drain.hh revision 9342
1/* 2 * Copyright (c) 2012 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 Event; 49 50/** 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: 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 State getDrainState() const { return _drainState; } 206 207 protected: 208 void setDrainState(State new_state) { _drainState = new_state; } 209 210 211 private: 212 State _drainState; 213 214}; 215 216#endif 217