drain.hh revision 10910
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
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 Drainable;
49
50#ifndef SWIG // SWIG doesn't support strongly typed enums
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/**
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:
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
230    DrainState getDrainState() const { return _drainState; }
231
232  protected:
233    void setDrainState(DrainState new_state) { _drainState = new_state; }
234
235  private:
236    DrainState _drainState;
237};
238
239DrainManager *createDrainManager();
240void cleanupDrainManager(DrainManager *drain_manager);
241
242#endif
243