drain.hh (10912:b99a6662d7c2) drain.hh (10913:38dbdeea7f1f)
1/*
2 * Copyright (c) 2012, 2015 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 178 unchanged lines hidden (view full) ---

187 * An object's internal state needs to be drained when creating a
188 * checkpoint, switching between CPU models, or switching between
189 * timing models. Once the internal state has been drained from
190 * <i>all</i> objects in the simulator, the objects are serialized to
191 * disc or the configuration change takes place. The process works as
192 * follows (see simulate.py for details):
193 *
194 * <ol>
1/*
2 * Copyright (c) 2012, 2015 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 178 unchanged lines hidden (view full) ---

187 * An object's internal state needs to be drained when creating a
188 * checkpoint, switching between CPU models, or switching between
189 * timing models. Once the internal state has been drained from
190 * <i>all</i> objects in the simulator, the objects are serialized to
191 * disc or the configuration change takes place. The process works as
192 * follows (see simulate.py for details):
193 *
194 * <ol>
195 * <li>Call Drainable::drain() for every object in the
196 * system. Draining has completed if all of them return
197 * zero. Otherwise, the sum of the return values is loaded into
198 * the counter of the DrainManager. A pointer to the drain
199 * manager is passed as an argument to the drain() method.
195 * <li>DrainManager::tryDrain() calls Drainable::drain() for every
196 * object in the system. Draining has completed if all of them
197 * return true. Otherwise, the drain manager keeps track of the
198 * objects that requested draining and waits for them to signal
199 * that they are done draining using the signalDrainDone() method.
200 *
201 * <li>Continue simulation. When an object has finished draining its
202 * internal state, it calls DrainManager::signalDrainDone() on the
200 *
201 * <li>Continue simulation. When an object has finished draining its
202 * internal state, it calls DrainManager::signalDrainDone() on the
203 * manager. When the counter in the manager reaches zero, the
204 * simulation stops.
203 * manager. The drain manager keeps track of the objects that
204 * haven't drained yet, simulation stops when the set of
205 * non-drained objects becomes empty.
205 *
206 *
206 * <li>Check if any object still needs draining, if so repeat the
207 * process above.
207 *
  • Check if any object still needs draining
    208 * (DrainManager::tryDrain()), if so repeat the process above.
  • 208 *
    209 * <li>Serialize objects, switch CPU model, or change timing model.
    210 *
    209 *
    210 * <li>Serialize objects, switch CPU model, or change timing model.
    211 *
    211 * <li>Call Drainable::drainResume() and continue the simulation.
    212 * <li>Call DrainManager::resume(), which intern calls
    213 * Drainable::drainResume() for all objects, and continue the
    214 * simulation.
    212 * </ol>
    213 *
    214 */
    215class Drainable
    216{
    217 friend class DrainManager;
    218
    215 * </ol>
    216 *
    217 */
    218class Drainable
    219{
    220 friend class DrainManager;
    221
    219 public:
    222 protected:
    220 Drainable();
    221 virtual ~Drainable();
    222
    223 /**
    224 * Determine if an object needs draining and register a
    225 * DrainManager.
    226 *
    223 Drainable();
    224 virtual ~Drainable();
    225
    226 /**
    227 * Determine if an object needs draining and register a
    228 * DrainManager.
    229 *
    227 * When draining the state of an object, the simulator calls drain
    228 * with a pointer to a drain manager. If the object does not need
    229 * further simulation to drain internal buffers, it switched to
    230 * the Drained state and returns 0, otherwise it switches to the
    231 * Draining state and returns the number of times that it will
    232 * call Event::process() on the drain event. Most objects are
    233 * expected to return either 0 or 1.
    230 * If the object does not need further simulation to drain
    231 * internal buffers, it returns true and automatically switches to
    232 * the Drained state, otherwise it switches to the Draining state.
    234 *
    235 * @note An object that has entered the Drained state can be
    236 * disturbed by other objects in the system and consequently be
    233 *
    234 * @note An object that has entered the Drained state can be
    235 * disturbed by other objects in the system and consequently be
    237 * forced to enter the Draining state again. The simulator
    238 * therefore repeats the draining process until all objects return
    239 * 0 on the first call to drain().
    236 * being drained. These perturbations are not visible in the
    237 * drain state. The simulator therefore repeats the draining
    238 * process until all objects return DrainState::Drained on the
    239 * first call to drain().
    240 *
    240 *
    241 * @param drainManager DrainManager to use to inform the simulator
    242 * when draining has completed.
    243 *
    244 * @return 0 if the object is ready for serialization now, >0 if
    245 * it needs further simulation.
    241 * @return DrainState::Drained if the object is ready for
    242 * serialization now, DrainState::Draining if it needs further
    243 * simulation.
    246 */
    244 */
    247 virtual unsigned int drain(DrainManager *drainManager) = 0;
    245 virtual DrainState drain() = 0;
    248
    249 /**
    250 * Resume execution after a successful drain.
    246
    247 /**
    248 * Resume execution after a successful drain.
    249 */
    250 virtual void drainResume() {};
    251
    252 /**
    253 * Signal that an object is drained
    251 *
    254 *
    252 * @note This method is normally only called from the simulation
    253 * scripts.
    255 * This method is designed to be called whenever an object enters
    256 * into a state where it is ready to be drained. The method is
    257 * safe to call multiple times and there is no need to check that
    258 * draining has been requested before calling this method.
    254 */
    259 */
    255 virtual void drainResume();
    260 void signalDrainDone() const {
    261 switch (_drainState) {
    262 case DrainState::Running:
    263 case DrainState::Drained:
    264 return;
    265 case DrainState::Draining:
    266 _drainState = DrainState::Drained;
    267 _drainManager.signalDrainDone();
    268 return;
    269 }
    270 }
    256
    271
    257 DrainState getDrainState() const { return _drainState; }
    272 public:
    273 /** Return the current drain state of an object. */
    274 DrainState drainState() const { return _drainState; }
    258
    275
    259 protected:
    260 void setDrainState(DrainState new_state) { _drainState = new_state; }
    261
    262 private:
    276 private:
    277 /** DrainManager interface to request a drain operation */
    278 DrainState dmDrain();
    279 /** DrainManager interface to request a resume operation */
    280 void dmDrainResume();
    281
    282 /** Convenience reference to the drain manager */
    263 DrainManager &_drainManager;
    283 DrainManager &_drainManager;
    264 DrainState _drainState;
    284
    285 /**
    286 * Current drain state of the object. Needs to be mutable since
    287 * objects need to be able to signal that they have transitioned
    288 * into a Drained state even if the calling method is const.
    289 */
    290 mutable DrainState _drainState;
    265};
    266
    267#endif
    291};
    292
    293#endif