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 * 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 |