drain.hh (10911:0ca18446a5bb) | drain.hh (10912:b99a6662d7c2) |
---|---|
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 --- 26 unchanged lines hidden (view full) --- 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Andreas Sandberg 38 */ 39 40#ifndef __SIM_DRAIN_HH__ 41#define __SIM_DRAIN_HH__ 42 | 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 --- 26 unchanged lines hidden (view full) --- 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Andreas Sandberg 38 */ 39 40#ifndef __SIM_DRAIN_HH__ 41#define __SIM_DRAIN_HH__ 42 |
43#include <cassert> 44#include <vector> | 43#include <atomic> 44#include <mutex> 45#include <unordered_set> |
45 46#include "base/flags.hh" 47 48class Drainable; 49 50#ifndef SWIG // SWIG doesn't support strongly typed enums 51/** 52 * Object drain/handover states --- 18 unchanged lines hidden (view full) --- 71 Draining, /** Draining buffers pending serialization/handover */ 72 Drained /** Buffers drained, ready for serialization/handover */ 73}; 74#endif 75 76/** 77 * This class coordinates draining of a System. 78 * | 46 47#include "base/flags.hh" 48 49class Drainable; 50 51#ifndef SWIG // SWIG doesn't support strongly typed enums 52/** 53 * Object drain/handover states --- 18 unchanged lines hidden (view full) --- 72 Draining, /** Draining buffers pending serialization/handover */ 73 Drained /** Buffers drained, ready for serialization/handover */ 74}; 75#endif 76 77/** 78 * This class coordinates draining of a System. 79 * |
79 * When draining a System, we need to make sure that all SimObjects in 80 * that system have drained their state before declaring the operation 81 * to be successful. This class keeps track of how many objects are 82 * still in the process of draining their state. Once it determines 83 * that all objects have drained their state, it exits the simulation 84 * loop. | 80 * When draining the simulator, we need to make sure that all 81 * Drainable objects within the system have ended up in the drained 82 * state before declaring the operation to be successful. This class 83 * keeps track of how many objects are still in the process of 84 * draining. Once it determines that all objects have drained their 85 * state, it exits the simulation loop. |
85 * 86 * @note A System might not be completely drained even though the 87 * DrainManager has caused the simulation loop to exit. Draining needs 88 * to be restarted until all Drainable objects declare that they don't 89 * need further simulation to be completely drained. See Drainable for 90 * more information. 91 */ 92class DrainManager 93{ | 86 * 87 * @note A System might not be completely drained even though the 88 * DrainManager has caused the simulation loop to exit. Draining needs 89 * to be restarted until all Drainable objects declare that they don't 90 * need further simulation to be completely drained. See Drainable for 91 * more information. 92 */ 93class DrainManager 94{ |
94 public: | 95 private: |
95 DrainManager(); | 96 DrainManager(); |
96 virtual ~DrainManager(); | 97#ifndef SWIG 98 DrainManager(DrainManager &) = delete; 99#endif 100 ~DrainManager(); |
97 | 101 |
102 public: 103 /** Get the singleton DrainManager instance */ 104 static DrainManager &instance() { return _instance; } 105 |
|
98 /** | 106 /** |
99 * Get the number of objects registered with this DrainManager 100 * that are currently draining their state. | 107 * Try to drain the system. |
101 * | 108 * |
102 * @return Number of objects currently draining. | 109 * Try to drain the system and return true if all objects are in a 110 * the Drained state at which point the whole simulator is in a 111 * consistent state and ready for checkpointing or CPU 112 * handover. The simulation script must continue simulating until 113 * the simulation loop returns "Finished drain", at which point 114 * this method should be called again. This cycle should continue 115 * until this method returns true. 116 * 117 * @return true if all objects were drained successfully, false if 118 * more simulation is needed. |
103 */ | 119 */ |
104 unsigned int getCount() const { return _count; } | 120 bool tryDrain(); |
105 | 121 |
106 void setCount(int count) { _count = count; } | 122 /** 123 * Resume normal simulation in a Drained system. 124 */ 125 void resume(); |
107 108 /** | 126 127 /** |
128 * Run state fixups before a checkpoint restore operation 129 * 130 * The drain state of an object isn't stored in a checkpoint since 131 * the whole system is always going to be in the Drained state 132 * when the checkpoint is created. When the checkpoint is restored 133 * at a later stage, recreated objects will be in the Running 134 * state since the state isn't stored in checkpoints. This method 135 * performs state fixups on all Drainable objects and the 136 * DrainManager itself. 137 */ 138 void preCheckpointRestore(); 139 140 /** Check if the system is drained */ 141 bool isDrained() { return _state == DrainState::Drained; } 142 143 /** Get the simulators global drain state */ 144 DrainState state() { return _state; } 145 146 /** |
|
109 * Notify the DrainManager that a Drainable object has finished 110 * draining. 111 */ | 147 * Notify the DrainManager that a Drainable object has finished 148 * draining. 149 */ |
112 void signalDrainDone() { 113 assert(_count > 0); 114 if (--_count == 0) 115 drainCycleDone(); 116 } | 150 void signalDrainDone(); |
117 | 151 |
118 protected: | 152 public: 153 void registerDrainable(Drainable *obj); 154 void unregisterDrainable(Drainable *obj); 155 156 private: |
119 /** | 157 /** |
120 * Callback when all registered Drainable objects have completed a 121 * drain cycle. | 158 * Thread-safe helper function to get the number of Drainable 159 * objects in a system. |
122 */ | 160 */ |
123 virtual void drainCycleDone(); | 161 size_t drainableCount() const; |
124 | 162 |
125 /** Number of objects still draining. */ 126 unsigned int _count; | 163 /** Lock protecting the set of drainable objects */ 164 mutable std::mutex globalLock; 165 166 /** Set of all drainable objects */ 167 std::unordered_set<Drainable *> _allDrainable; 168 169 /** 170 * Number of objects still draining. This is flagged atomic since 171 * it can be manipulated by SimObjects living in different 172 * threads. 173 */ 174 std::atomic_uint _count; 175 176 /** Global simulator drain state */ 177 DrainState _state; 178 179 /** Singleton instance of the drain manager */ 180 static DrainManager _instance; |
127}; 128 129/** 130 * Interface for objects that might require draining before 131 * checkpointing. 132 * 133 * An object's internal state needs to be drained when creating a 134 * checkpoint, switching between CPU models, or switching between 135 * timing models. Once the internal state has been drained from | 181}; 182 183/** 184 * Interface for objects that might require draining before 185 * checkpointing. 186 * 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 |
136 * <i>all</i> objects in the system, the objects are serialized to | 190 * <i>all</i> objects in the simulator, the objects are serialized to |
137 * disc or the configuration change takes place. The process works as 138 * follows (see simulate.py for details): 139 * 140 * <ol> | 191 * disc or the configuration change takes place. The process works as 192 * follows (see simulate.py for details): 193 * 194 * <ol> |
141 * <li>An instance of a DrainManager is created to keep track of how 142 * many objects need to be drained. The object maintains an 143 * internal counter that is decreased every time its 144 * CountedDrainEvent::signalDrainDone() method is called. When the 145 * counter reaches zero, the simulation is stopped. 146 * | |
147 * <li>Call Drainable::drain() for every object in the 148 * system. Draining has completed if all of them return 149 * zero. Otherwise, the sum of the return values is loaded into 150 * the counter of the DrainManager. A pointer to the drain 151 * manager is passed as an argument to the drain() method. 152 * 153 * <li>Continue simulation. When an object has finished draining its | 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. 200 * 201 * <li>Continue simulation. When an object has finished draining its |
154 * internal state, it calls CountedDrainEvent::signalDrainDone() 155 * on the manager. When the counter in the manager reaches zero, 156 * the simulation stops. | 202 * internal state, it calls DrainManager::signalDrainDone() on the 203 * manager. When the counter in the manager reaches zero, the 204 * simulation stops. |
157 * 158 * <li>Check if any object still needs draining, if so repeat the 159 * process above. 160 * 161 * <li>Serialize objects, switch CPU model, or change timing model. 162 * 163 * <li>Call Drainable::drainResume() and continue the simulation. 164 * </ol> 165 * 166 */ 167class Drainable 168{ | 205 * 206 * <li>Check if any object still needs draining, if so repeat the 207 * process above. 208 * 209 * <li>Serialize objects, switch CPU model, or change timing model. 210 * 211 * <li>Call Drainable::drainResume() and continue the simulation. 212 * </ol> 213 * 214 */ 215class Drainable 216{ |
217 friend class DrainManager; 218 |
|
169 public: 170 Drainable(); 171 virtual ~Drainable(); 172 173 /** 174 * Determine if an object needs draining and register a 175 * DrainManager. 176 * --- 28 unchanged lines hidden (view full) --- 205 virtual void drainResume(); 206 207 DrainState getDrainState() const { return _drainState; } 208 209 protected: 210 void setDrainState(DrainState new_state) { _drainState = new_state; } 211 212 private: | 219 public: 220 Drainable(); 221 virtual ~Drainable(); 222 223 /** 224 * Determine if an object needs draining and register a 225 * DrainManager. 226 * --- 28 unchanged lines hidden (view full) --- 255 virtual void drainResume(); 256 257 DrainState getDrainState() const { return _drainState; } 258 259 protected: 260 void setDrainState(DrainState new_state) { _drainState = new_state; } 261 262 private: |
263 DrainManager &_drainManager; |
|
213 DrainState _drainState; 214}; 215 | 264 DrainState _drainState; 265}; 266 |
216DrainManager *createDrainManager(); 217void cleanupDrainManager(DrainManager *drain_manager); 218 | |
219#endif | 267#endif |