drain.hh (9554:406fbcf60223) drain.hh (10910:32f3d1c454ec)
1/*
1/*
2 * Copyright (c) 2012 ARM Limited
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
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
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>
45
46#include "base/flags.hh"
47
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
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
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>
45
46#include "base/flags.hh"
47
48class Event;
48class Drainable;
49
49
50#ifndef SWIG // SWIG doesn't support strongly typed enums
50/**
51/**
52 * Object drain/handover states
53 *
54 * An object starts out in the Running state. When the simulator
55 * prepares to take a snapshot or prepares a CPU for handover, it
56 * calls the drain() method to transfer the object into the Draining
57 * or Drained state. If any object enters the Draining state
58 * (Drainable::drain() returning >0), simulation continues until it
59 * all objects have entered the Drained state.
60 *
61 * Before resuming simulation, the simulator calls resume() to
62 * transfer the object to the Running state.
63 *
64 * \note Even though the state of an object (visible to the rest of
65 * the world through Drainable::getState()) could be used to determine
66 * if all objects have entered the Drained state, the protocol is
67 * actually a bit more elaborate. See Drainable::drain() for details.
68 */
69enum class DrainState {
70 Running, /** Running normally */
71 Draining, /** Draining buffers pending serialization/handover */
72 Drained /** Buffers drained, ready for serialization/handover */
73};
74#endif
75
76/**
51 * This class coordinates draining of a System.
52 *
53 * When draining a System, we need to make sure that all SimObjects in
54 * that system have drained their state before declaring the operation
55 * to be successful. This class keeps track of how many objects are
56 * still in the process of draining their state. Once it determines
57 * that all objects have drained their state, it exits the simulation
58 * loop.
59 *
60 * @note A System might not be completely drained even though the
61 * DrainManager has caused the simulation loop to exit. Draining needs
62 * to be restarted until all Drainable objects declare that they don't
63 * need further simulation to be completely drained. See Drainable for
64 * more information.
65 */
66class DrainManager
67{
68 public:
69 DrainManager();
70 virtual ~DrainManager();
71
72 /**
73 * Get the number of objects registered with this DrainManager
74 * that are currently draining their state.
75 *
76 * @return Number of objects currently draining.
77 */
78 unsigned int getCount() const { return _count; }
79
80 void setCount(int count) { _count = count; }
81
82 /**
83 * Notify the DrainManager that a Drainable object has finished
84 * draining.
85 */
86 void signalDrainDone() {
87 assert(_count > 0);
88 if (--_count == 0)
89 drainCycleDone();
90 }
91
92 protected:
93 /**
94 * Callback when all registered Drainable objects have completed a
95 * drain cycle.
96 */
97 virtual void drainCycleDone();
98
99 /** Number of objects still draining. */
100 unsigned int _count;
101};
102
103/**
104 * Interface for objects that might require draining before
105 * checkpointing.
106 *
107 * An object's internal state needs to be drained when creating a
108 * checkpoint, switching between CPU models, or switching between
109 * timing models. Once the internal state has been drained from
110 * <i>all</i> objects in the system, the objects are serialized to
111 * disc or the configuration change takes place. The process works as
112 * follows (see simulate.py for details):
113 *
114 * <ol>
115 * <li>An instance of a DrainManager is created to keep track of how
116 * many objects need to be drained. The object maintains an
117 * internal counter that is decreased every time its
118 * CountedDrainEvent::signalDrainDone() method is called. When the
119 * counter reaches zero, the simulation is stopped.
120 *
121 * <li>Call Drainable::drain() for every object in the
122 * system. Draining has completed if all of them return
123 * zero. Otherwise, the sum of the return values is loaded into
124 * the counter of the DrainManager. A pointer to the drain
125 * manager is passed as an argument to the drain() method.
126 *
127 * <li>Continue simulation. When an object has finished draining its
128 * internal state, it calls CountedDrainEvent::signalDrainDone()
129 * on the manager. When the counter in the manager reaches zero,
130 * the simulation stops.
131 *
132 * <li>Check if any object still needs draining, if so repeat the
133 * process above.
134 *
135 * <li>Serialize objects, switch CPU model, or change timing model.
136 *
137 * <li>Call Drainable::drainResume() and continue the simulation.
138 * </ol>
139 *
140 */
141class Drainable
142{
143 public:
77 * This class coordinates draining of a System.
78 *
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.
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{
94 public:
95 DrainManager();
96 virtual ~DrainManager();
97
98 /**
99 * Get the number of objects registered with this DrainManager
100 * that are currently draining their state.
101 *
102 * @return Number of objects currently draining.
103 */
104 unsigned int getCount() const { return _count; }
105
106 void setCount(int count) { _count = count; }
107
108 /**
109 * Notify the DrainManager that a Drainable object has finished
110 * draining.
111 */
112 void signalDrainDone() {
113 assert(_count > 0);
114 if (--_count == 0)
115 drainCycleDone();
116 }
117
118 protected:
119 /**
120 * Callback when all registered Drainable objects have completed a
121 * drain cycle.
122 */
123 virtual void drainCycleDone();
124
125 /** Number of objects still draining. */
126 unsigned int _count;
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
136 * <i>all</i> objects in the system, 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>
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
154 * internal state, it calls CountedDrainEvent::signalDrainDone()
155 * on the manager. When the counter in the manager reaches zero,
156 * the 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{
169 public:
144 /**
145 * Object drain/handover states
146 *
147 * An object starts out in the Running state. When the simulator
148 * prepares to take a snapshot or prepares a CPU for handover, it
149 * calls the drain() method to transfer the object into the
150 * Draining or Drained state. If any object enters the Draining
151 * state (drain() returning >0), simulation continues until it all
152 * objects have entered the Drained state.
153 *
154 * Before resuming simulation, the simulator calls resume() to
155 * transfer the object to the Running state.
156 *
157 * \note Even though the state of an object (visible to the rest
158 * of the world through getState()) could be used to determine if
159 * all objects have entered the Drained state, the protocol is
160 * actually a bit more elaborate. See drain() for details.
161 */
162 enum State {
163 Running, /** Running normally */
164 Draining, /** Draining buffers pending serialization/handover */
165 Drained /** Buffers drained, ready for serialization/handover */
166 };
167
168 Drainable();
169 virtual ~Drainable();
170
171 /**
172 * Determine if an object needs draining and register a
173 * DrainManager.
174 *
175 * When draining the state of an object, the simulator calls drain
176 * with a pointer to a drain manager. If the object does not need
177 * further simulation to drain internal buffers, it switched to
178 * the Drained state and returns 0, otherwise it switches to the
179 * Draining state and returns the number of times that it will
180 * call Event::process() on the drain event. Most objects are
181 * expected to return either 0 or 1.
182 *
183 * @note An object that has entered the Drained state can be
184 * disturbed by other objects in the system and consequently be
185 * forced to enter the Draining state again. The simulator
186 * therefore repeats the draining process until all objects return
187 * 0 on the first call to drain().
188 *
189 * @param drainManager DrainManager to use to inform the simulator
190 * when draining has completed.
191 *
192 * @return 0 if the object is ready for serialization now, >0 if
193 * it needs further simulation.
194 */
195 virtual unsigned int drain(DrainManager *drainManager) = 0;
196
197 /**
198 * Resume execution after a successful drain.
199 *
200 * @note This method is normally only called from the simulation
201 * scripts.
202 */
203 virtual void drainResume();
204
205 /**
206 * Write back dirty buffers to memory using functional writes.
207 *
208 * After returning, an object implementing this method should have
209 * written all its dirty data back to memory. This method is
210 * typically used to prepare a system with caches for
211 * checkpointing.
212 */
213 virtual void memWriteback() {};
214
215 /**
216 * Invalidate the contents of memory buffers.
217 *
218 * When the switching to hardware virtualized CPU models, we need
219 * to make sure that we don't have any cached state in the system
220 * that might become stale when we return. This method is used to
221 * flush all such state back to main memory.
222 *
223 * @warn This does <i>not</i> cause any dirty state to be written
224 * back to memory.
225 */
226 virtual void memInvalidate() {};
227
170 Drainable();
171 virtual ~Drainable();
172
173 /**
174 * Determine if an object needs draining and register a
175 * DrainManager.
176 *
177 * When draining the state of an object, the simulator calls drain
178 * with a pointer to a drain manager. If the object does not need
179 * further simulation to drain internal buffers, it switched to
180 * the Drained state and returns 0, otherwise it switches to the
181 * Draining state and returns the number of times that it will
182 * call Event::process() on the drain event. Most objects are
183 * expected to return either 0 or 1.
184 *
185 * @note An object that has entered the Drained state can be
186 * disturbed by other objects in the system and consequently be
187 * forced to enter the Draining state again. The simulator
188 * therefore repeats the draining process until all objects return
189 * 0 on the first call to drain().
190 *
191 * @param drainManager DrainManager to use to inform the simulator
192 * when draining has completed.
193 *
194 * @return 0 if the object is ready for serialization now, >0 if
195 * it needs further simulation.
196 */
197 virtual unsigned int drain(DrainManager *drainManager) = 0;
198
199 /**
200 * Resume execution after a successful drain.
201 *
202 * @note This method is normally only called from the simulation
203 * scripts.
204 */
205 virtual void drainResume();
206
207 /**
208 * Write back dirty buffers to memory using functional writes.
209 *
210 * After returning, an object implementing this method should have
211 * written all its dirty data back to memory. This method is
212 * typically used to prepare a system with caches for
213 * checkpointing.
214 */
215 virtual void memWriteback() {};
216
217 /**
218 * Invalidate the contents of memory buffers.
219 *
220 * When the switching to hardware virtualized CPU models, we need
221 * to make sure that we don't have any cached state in the system
222 * that might become stale when we return. This method is used to
223 * flush all such state back to main memory.
224 *
225 * @warn This does <i>not</i> cause any dirty state to be written
226 * back to memory.
227 */
228 virtual void memInvalidate() {};
229
228 State getDrainState() const { return _drainState; }
230 DrainState getDrainState() const { return _drainState; }
229
230 protected:
231
232 protected:
231 void setDrainState(State new_state) { _drainState = new_state; }
233 void setDrainState(DrainState new_state) { _drainState = new_state; }
232
234
233
234 private:
235 private:
235 State _drainState;
236
236 DrainState _drainState;
237};
238
239DrainManager *createDrainManager();
240void cleanupDrainManager(DrainManager *drain_manager);
241
242#endif
237};
238
239DrainManager *createDrainManager();
240void cleanupDrainManager(DrainManager *drain_manager);
241
242#endif