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 DrainState getDrainState() const { return _drainState; } 208 209 protected: 210 void setDrainState(DrainState new_state) { _drainState = new_state; } 211 212 private: 213 DrainState _drainState; 214}; 215 216DrainManager *createDrainManager(); 217void cleanupDrainManager(DrainManager *drain_manager); 218 219#endif |