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