diff options
Diffstat (limited to 'src/sim/drain.hh')
-rw-r--r-- | src/sim/drain.hh | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/sim/drain.hh b/src/sim/drain.hh new file mode 100644 index 000000000..252022bc7 --- /dev/null +++ b/src/sim/drain.hh @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2012 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Andreas Sandberg + */ + +#ifndef __SIM_DRAIN_HH__ +#define __SIM_DRAIN_HH__ + +#include <cassert> +#include <vector> + +#include "base/flags.hh" + +class Event; + +/** + * This class coordinates draining of a System. + * + * When draining a System, we need to make sure that all SimObjects in + * that system have drained their state before declaring the operation + * to be successful. This class keeps track of how many objects are + * still in the process of draining their state. Once it determines + * that all objects have drained their state, it exits the simulation + * loop. + * + * @note A System might not be completely drained even though the + * DrainManager has caused the simulation loop to exit. Draining needs + * to be restarted until all Drainable objects declare that they don't + * need further simulation to be completely drained. See Drainable for + * more information. + */ +class DrainManager +{ + public: + DrainManager(); + virtual ~DrainManager(); + + /** + * Get the number of objects registered with this DrainManager + * that are currently draining their state. + * + * @return Number of objects currently draining. + */ + unsigned int getCount() const { return _count; } + + void setCount(int count) { _count = count; } + + /** + * Notify the DrainManager that a Drainable object has finished + * draining. + */ + void signalDrainDone() { + assert(_count > 0); + if (--_count == 0) + drainCycleDone(); + } + + protected: + /** + * Callback when all registered Drainable objects have completed a + * drain cycle. + */ + virtual void drainCycleDone(); + + /** Number of objects still draining. */ + unsigned int _count; +}; + +/** + * Interface for objects that might require draining before + * checkpointing. + * + * An object's internal state needs to be drained when creating a + * checkpoint, switching between CPU models, or switching between + * timing models. Once the internal state has been drained from + * <i>all</i> objects in the system, the objects are serialized to + * disc or the configuration change takes place. The process works as + * follows (see simulate.py for details): + * + * <ol> + * <li>An instance of a DrainManager is created to keep track of how + * many objects need to be drained. The object maintains an + * internal counter that is decreased every time its + * CountedDrainEvent::signalDrainDone() method is called. When the + * counter reaches zero, the simulation is stopped. + * + * <li>Call Drainable::drain() for every object in the + * system. Draining has completed if all of them return + * zero. Otherwise, the sum of the return values is loaded into + * the counter of the DrainManager. A pointer to the drain + * manager is passed as an argument to the drain() method. + * + * <li>Continue simulation. When an object has finished draining its + * internal state, it calls CountedDrainEvent::signalDrainDone() + * on the manager. When the counter in the manager reaches zero, + * the simulation stops. + * + * <li>Check if any object still needs draining, if so repeat the + * process above. + * + * <li>Serialize objects, switch CPU model, or change timing model. + * + * <li>Call Drainable::drainResume() and continue the simulation. + * </ol> + * + */ +class Drainable +{ + public: + /** + * Object drain/handover states + * + * An object starts out in the Running state. When the simulator + * prepares to take a snapshot or prepares a CPU for handover, it + * calls the drain() method to transfer the object into the + * Draining or Drained state. If any object enters the Draining + * state (drain() returning >0), simulation continues until it all + * objects have entered the Drained state. + * + * Before resuming simulation, the simulator calls resume() to + * transfer the object to the Running state. + * + * \note Even though the state of an object (visible to the rest + * of the world through getState()) could be used to determine if + * all objects have entered the Drained state, the protocol is + * actually a bit more elaborate. See drain() for details. + */ + enum State { + Running, /** Running normally */ + Draining, /** Draining buffers pending serialization/handover */ + Drained /** Buffers drained, ready for serialization/handover */ + }; + + Drainable(); + virtual ~Drainable(); + + /** + * Determine if an object needs draining and register a + * DrainManager. + * + * When draining the state of an object, the simulator calls drain + * with a pointer to a drain manager. If the object does not need + * further simulation to drain internal buffers, it switched to + * the Drained state and returns 0, otherwise it switches to the + * Draining state and returns the number of times that it will + * call Event::process() on the drain event. Most objects are + * expected to return either 0 or 1. + * + * @note An object that has entered the Drained state can be + * disturbed by other objects in the system and consequently be + * forced to enter the Draining state again. The simulator + * therefore repeats the draining process until all objects return + * 0 on the first call to drain(). + * + * @param drainManager DrainManager to use to inform the simulator + * when draining has completed. + * + * @return 0 if the object is ready for serialization now, >0 if + * it needs further simulation. + */ + virtual unsigned int drain(DrainManager *drainManager) = 0; + + /** + * Resume execution after a successful drain. + * + * @note This method is normally only called from the simulation + * scripts. + */ + virtual void drainResume(); + + State getDrainState() const { return _drainState; } + + protected: + void setDrainState(State new_state) { _drainState = new_state; } + + + private: + State _drainState; + +}; + +#endif |