sim_object.hh (9195:77fd8912c9d4) | sim_object.hh (9196:87967784f101) |
---|---|
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 --- 37 unchanged lines hidden (view full) --- 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 | 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 --- 37 unchanged lines hidden (view full) --- 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/* | 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.). | 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. |
|
58 */ 59class SimObject : public EventManager, public Serializable 60{ 61 public: | 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 */ |
|
62 enum State { | 138 enum State { |
63 Running, 64 Draining, 65 Drained | 139 Running, /** Running normally */ 140 Draining, /** Draining buffers pending serialization/handover */ 141 Drained /** Buffers drained, ready for serialization/handover */ |
66 }; 67 68 private: 69 State state; 70 71 protected: 72 void changeState(State new_state) { state = new_state; } 73 74 public: 75 State getState() { return state; } 76 77 private: 78 typedef std::vector<SimObject *> SimObjectList; 79 | 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 |
80 // list of all instantiated simulation objects | 156 /** List of all instantiated simulation objects. */ |
81 static SimObjectList simObjectList; 82 83 protected: | 157 static SimObjectList simObjectList; 158 159 protected: |
160 /** Cached copy of the object parameters. */ |
|
84 const SimObjectParams *_params; 85 86 public: 87 typedef SimObjectParams Params; 88 const Params *params() const { return _params; } 89 SimObject(const Params *_params); 90 virtual ~SimObject() {} 91 92 public: 93 94 virtual const std::string name() const { return params()->name; } 95 | 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 |
96 // The following SimObject initialization methods are called from 97 // the instantiate() method in src/python/m5/simulate.py. See 98 // that function for details on how/when these methods are 99 // invoked. 100 | |
101 /** 102 * init() is called after all C++ SimObjects have been created and 103 * all ports are connected. Initializations that are independent 104 * of unserialization but rely on a fully instantiated and 105 * connected SimObject graph should be done here. 106 */ 107 virtual void init(); 108 109 /** 110 * loadState() is called on each SimObject when restoring from a 111 * checkpoint. The default implementation simply calls 112 * unserialize() if there is a corresponding section in the 113 * checkpoint. However, objects can override loadState() to get 114 * other behaviors, e.g., doing other programmed initializations 115 * after unserialize(), or complaining if no checkpoint section is 116 * found. | 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. |
|
117 */ 118 virtual void loadState(Checkpoint *cp); 119 120 /** 121 * initState() is called on each SimObject when *not* restoring 122 * from a checkpoint. This provides a hook for state 123 * initializations that are only required for a "cold start". 124 */ 125 virtual void initState(); 126 | 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 |
127 // register statistics for this object | 201 /** 202 * Register statistics for this object. 203 */ |
128 virtual void regStats(); | 204 virtual void regStats(); |
205 206 /** 207 * Reset statistics associated with this object. 208 */ |
|
129 virtual void resetStats(); 130 131 /** 132 * startup() is the final initialization call before simulation. 133 * All state is initialized (including unserialized state, if any, 134 * such as the curTick() value), so this is the appropriate place to 135 * schedule initial event(s) for objects that need them. 136 */ 137 virtual void startup(); 138 | 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 |
139 // static: call nameOut() & serialize() on all SimObjects 140 static void serializeAll(std::ostream &); | 219 /** 220 * Serialize all SimObjects in the system. 221 */ 222 static void serializeAll(std::ostream &os); |
141 | 223 |
142 // Methods to drain objects in order to take checkpoints 143 // Or switch from timing -> atomic memory model 144 // Drain returns 0 if the simobject can drain immediately or 145 // the number of times the drain_event's process function will be called 146 // before the object will be done draining. Normally this should be 1 | 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 */ |
147 virtual unsigned int drain(Event *drain_event); | 251 virtual unsigned int drain(Event *drain_event); |
252 253 /** 254 * Switch an object in the Drained stated into the Running state. 255 */ |
|
148 virtual void resume(); | 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 */ |
|
149 virtual void setMemoryMode(Enums::MemoryMode new_mode); | 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 */ |
|
150 virtual void switchOut(); | 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 */ |
|
151 virtual void takeOverFrom(BaseCPU *cpu); 152 153#ifdef DEBUG 154 public: 155 bool doDebugBreak; 156 static void debugObjectBreak(const std::string &objs); 157#endif 158 159 /** 160 * Find the SimObject with the given name and return a pointer to 161 * it. Primarily used for interactive debugging. Argument is 162 * char* rather than std::string to make it callable from gdb. 163 */ 164 static SimObject *find(const char *name); 165}; 166 167#endif // __SIM_OBJECT_HH__ | 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__ |