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>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
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.
206 *
207 *Check if any object still needs draining
208 * (DrainManager::tryDrain()), if so repeat the process above.
209 *
210 * <li>Serialize objects, switch CPU model, or change timing model.
211 *
212 * <li>Call DrainManager::resume(), which intern calls
213 * Drainable::drainResume() for all objects, and continue the
214 * simulation.
215 * </ol>
216 *
217 */
218class Drainable
219{
220 friend class DrainManager;
221
222 protected:
223 Drainable();
224 virtual ~Drainable();
225
226 /**
227 * Determine if an object needs draining and register a
228 * DrainManager.
229 *
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.
233 *
234 * @note An object that has entered the Drained state can be
235 * disturbed by other objects in the system and consequently be
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 *
241 * @return DrainState::Drained if the object is ready for
242 * serialization now, DrainState::Draining if it needs further
243 * simulation.
244 */
245 virtual DrainState drain() = 0;
246
247 /**
248 * Resume execution after a successful drain.
249 */
250 virtual void drainResume() {};
251
252 /**
253 * Signal that an object is drained
254 *
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.
259 */
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 }
271
272 public:
273 /** Return the current drain state of an object. */
274 DrainState drainState() const { return _drainState; }
275
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 */
283 DrainManager &_drainManager;
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;
291};
292
293#endif
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>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
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.
206 *
207 *
208 * (DrainManager::tryDrain()), if so repeat the process above.
209 *
210 * <li>Serialize objects, switch CPU model, or change timing model.
211 *
212 * <li>Call DrainManager::resume(), which intern calls
213 * Drainable::drainResume() for all objects, and continue the
214 * simulation.
215 * </ol>
216 *
217 */
218class Drainable
219{
220 friend class DrainManager;
221
222 protected:
223 Drainable();
224 virtual ~Drainable();
225
226 /**
227 * Determine if an object needs draining and register a
228 * DrainManager.
229 *
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.
233 *
234 * @note An object that has entered the Drained state can be
235 * disturbed by other objects in the system and consequently be
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 *
241 * @return DrainState::Drained if the object is ready for
242 * serialization now, DrainState::Draining if it needs further
243 * simulation.
244 */
245 virtual DrainState drain() = 0;
246
247 /**
248 * Resume execution after a successful drain.
249 */
250 virtual void drainResume() {};
251
252 /**
253 * Signal that an object is drained
254 *
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.
259 */
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 }
271
272 public:
273 /** Return the current drain state of an object. */
274 DrainState drainState() const { return _drainState; }
275
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 */
283 DrainManager &_drainManager;
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;
291};
292
293#endif