sim_object.hh revision 9196
1/* 2 * Copyright (c) 2001-2005 The Regents of The University of Michigan 3 * Copyright (c) 2010 Advanced Micro Devices, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Steve Reinhardt 30 * Nathan Binkert 31 */ 32 33/* @file 34 * User Console Definitions 35 */ 36 37#ifndef __SIM_OBJECT_HH__ 38#define __SIM_OBJECT_HH__ 39 40#include <iostream> 41#include <list> 42#include <map> 43#include <string> 44#include <vector> 45 46#include "enums/MemoryMode.hh" 47#include "params/SimObject.hh" 48#include "sim/eventq.hh" 49#include "sim/serialize.hh" 50 51class BaseCPU; 52class Event; 53 54/** 55 * Abstract superclass for simulation objects. Represents things that 56 * correspond to physical components and can be specified via the 57 * config file (CPUs, caches, etc.). 58 * 59 * SimObject initialization is controlled by the instantiate method in 60 * src/python/m5/simulate.py. There are slightly different 61 * initialization paths when starting the simulation afresh and when 62 * loading from a checkpoint. After instantiation and connecting 63 * ports, simulate.py initializes the object using the following call 64 * sequence: 65 * 66 * <ol> 67 * <li>SimObject::init() 68 * <li>SimObject::regStats() 69 * <li><ul> 70 * <li>SimObject::initState() if starting afresh. 71 * <li>SimObject::loadState() if restoring from a checkpoint. 72 * </ul> 73 * <li>SimObject::resetStats() 74 * <li>SimObject::startup() 75 * <li>SimObject::resume() if resuming from a checkpoint. 76 * </ol> 77 * 78 * An object's internal state needs to be drained when creating a 79 * checkpoint, switching between CPU models, or switching between 80 * timing models. Once the internal state has been drained from 81 * <i>all</i> objects in the system, the objects are serialized to 82 * disc or the configuration change takes place. The process works as 83 * follows (see simulate.py for details): 84 * 85 * <ol> 86 * <li>An instance of a CountedDrainEvent is created to keep track of 87 * how many objects need to be drained. The object maintains an 88 * internal counter that is decreased every time its 89 * CountedDrainEvent::process() method is called. When the counter 90 * reaches zero, the simulation is stopped. 91 * 92 * <li>Call SimObject::drain() for every object in the 93 * system. Draining has completed if all of them return 94 * zero. Otherwise, the sum of the return values is loaded into 95 * the counter of the CountedDrainEvent. A pointer of the drain 96 * event is passed as an argument to the drain() method. 97 * 98 * <li>Continue simulation. When an object has finished draining its 99 * internal state, it calls CountedDrainEvent::process() on the 100 * CountedDrainEvent. When counter in the CountedDrainEvent reaches 101 * zero, the simulation stops. 102 * 103 * <li>Check if any object still needs draining, if so repeat the 104 * process above. 105 * 106 * <li>Serialize objects, switch CPU model, or change timing model. 107 * 108 * <li>Call SimObject::resume() and continue the simulation. 109 * </ol> 110 * 111 * @note Whenever a method is called on all objects in the simulator's 112 * object tree (e.g., init(), startup(), or loadState()), a pre-order 113 * depth-first traversal is performed (see descendants() in 114 * SimObject.py). This has the effect of calling the method on the 115 * parent node <i>before</i> its children. 116 */ 117class SimObject : public EventManager, public Serializable 118{ 119 public: 120 /** 121 * Object drain/handover states 122 * 123 * An object starts out in the Running state. When the simulator 124 * prepares to take a snapshot or prepares a CPU for handover, it 125 * calls the drain() method to transfer the object into the 126 * Draining or Drained state. If any object enters the Draining 127 * state (drain() returning >0), simulation continues until it all 128 * objects have entered the Drained. 129 * 130 * The before resuming simulation, the simulator calls resume() to 131 * transfer the object to the Running state. 132 * 133 * \note Even though the state of an object (visible to the rest 134 * of the world through getState()) could be used to determine if 135 * all objects have entered the Drained state, the protocol is 136 * actually a bit more elaborate. See drain() for details. 137 */ 138 enum State { 139 Running, /** Running normally */ 140 Draining, /** Draining buffers pending serialization/handover */ 141 Drained /** Buffers drained, ready for serialization/handover */ 142 }; 143 144 private: 145 State state; 146 147 protected: 148 void changeState(State new_state) { state = new_state; } 149 150 public: 151 State getState() { return state; } 152 153 private: 154 typedef std::vector<SimObject *> SimObjectList; 155 156 /** List of all instantiated simulation objects. */ 157 static SimObjectList simObjectList; 158 159 protected: 160 /** Cached copy of the object parameters. */ 161 const SimObjectParams *_params; 162 163 public: 164 typedef SimObjectParams Params; 165 const Params *params() const { return _params; } 166 SimObject(const Params *_params); 167 virtual ~SimObject() {} 168 169 public: 170 171 virtual const std::string name() const { return params()->name; } 172 173 /** 174 * init() is called after all C++ SimObjects have been created and 175 * all ports are connected. Initializations that are independent 176 * of unserialization but rely on a fully instantiated and 177 * connected SimObject graph should be done here. 178 */ 179 virtual void init(); 180 181 /** 182 * loadState() is called on each SimObject when restoring from a 183 * checkpoint. The default implementation simply calls 184 * unserialize() if there is a corresponding section in the 185 * checkpoint. However, objects can override loadState() to get 186 * other behaviors, e.g., doing other programmed initializations 187 * after unserialize(), or complaining if no checkpoint section is 188 * found. 189 * 190 * @param cp Checkpoint to restore the state from. 191 */ 192 virtual void loadState(Checkpoint *cp); 193 194 /** 195 * initState() is called on each SimObject when *not* restoring 196 * from a checkpoint. This provides a hook for state 197 * initializations that are only required for a "cold start". 198 */ 199 virtual void initState(); 200 201 /** 202 * Register statistics for this object. 203 */ 204 virtual void regStats(); 205 206 /** 207 * Reset statistics associated with this object. 208 */ 209 virtual void resetStats(); 210 211 /** 212 * startup() is the final initialization call before simulation. 213 * All state is initialized (including unserialized state, if any, 214 * such as the curTick() value), so this is the appropriate place to 215 * schedule initial event(s) for objects that need them. 216 */ 217 virtual void startup(); 218 219 /** 220 * Serialize all SimObjects in the system. 221 */ 222 static void serializeAll(std::ostream &os); 223 224 /** 225 * Determine if an object needs draining and register a drain 226 * event. 227 * 228 * When draining the state of an object, the simulator calls drain 229 * with a pointer to a drain event. If the object does not need 230 * further simulation to drain internal buffers, it switched to 231 * the Drained state and returns 0, otherwise it switches to the 232 * Draining state and returns the number of times that it will 233 * call Event::process() on the drain event. Most objects are 234 * expected to return either 0 or 1. 235 * 236 * The default implementation simply switches to the Drained state 237 * and returns 0. 238 * 239 * @note An object that has entered the Drained state can be 240 * disturbed by other objects in the system and consequently be 241 * forced to enter the Draining state again. The simulator 242 * therefore repeats the draining process until all objects return 243 * 0 on the first call to drain(). 244 * 245 * @param drain_event Event to use to inform the simulator when 246 * the draining has completed. 247 * 248 * @return 0 if the object is ready for serialization now, >0 if 249 * it needs further simulation. 250 */ 251 virtual unsigned int drain(Event *drain_event); 252 253 /** 254 * Switch an object in the Drained stated into the Running state. 255 */ 256 virtual void resume(); 257 258 /** 259 * Change the memory mode the simulator operates in. 260 * 261 * @note Should only be implemented in the System object. 262 */ 263 virtual void setMemoryMode(Enums::MemoryMode new_mode); 264 265 /** 266 * Prepare a CPU model to be switched out, invoked on active CPUs 267 * that are about to be replaced. 268 * 269 * @note This should only be implemented in CPU models. 270 */ 271 virtual void switchOut(); 272 273 /** 274 * Load the state of a CPU from the previous CPU object, invoked 275 * on all new CPUs that are about to be switched in. 276 * 277 * A CPU model implementing this method is expected to initialize 278 * its state from the old CPU and connect its memory (unless they 279 * are already connected) to the memories connected to the old 280 * CPU. 281 * 282 * @note This should only be implemented in CPU models. 283 * 284 * @param cpu CPU to initialize read state from. 285 */ 286 virtual void takeOverFrom(BaseCPU *cpu); 287 288#ifdef DEBUG 289 public: 290 bool doDebugBreak; 291 static void debugObjectBreak(const std::string &objs); 292#endif 293 294 /** 295 * Find the SimObject with the given name and return a pointer to 296 * it. Primarily used for interactive debugging. Argument is 297 * char* rather than std::string to make it callable from gdb. 298 */ 299 static SimObject *find(const char *name); 300}; 301 302#endif // __SIM_OBJECT_HH__ 303