sim_object.hh revision 9196
12SN/A/* 21762SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 37534Ssteve.reinhardt@amd.com * Copyright (c) 2010 Advanced Micro Devices, Inc. 42SN/A * All rights reserved. 52SN/A * 62SN/A * Redistribution and use in source and binary forms, with or without 72SN/A * modification, are permitted provided that the following conditions are 82SN/A * met: redistributions of source code must retain the above copyright 92SN/A * notice, this list of conditions and the following disclaimer; 102SN/A * redistributions in binary form must reproduce the above copyright 112SN/A * notice, this list of conditions and the following disclaimer in the 122SN/A * documentation and/or other materials provided with the distribution; 132SN/A * neither the name of the copyright holders nor the names of its 142SN/A * contributors may be used to endorse or promote products derived from 152SN/A * this software without specific prior written permission. 162SN/A * 172SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 182SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 192SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 202SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 212SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 222SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 232SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282665Ssaidi@eecs.umich.edu * 292665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 302665Ssaidi@eecs.umich.edu * Nathan Binkert 312SN/A */ 322SN/A 332SN/A/* @file 342SN/A * User Console Definitions 352SN/A */ 362SN/A 372SN/A#ifndef __SIM_OBJECT_HH__ 382SN/A#define __SIM_OBJECT_HH__ 392SN/A 405491Sgblack@eecs.umich.edu#include <iostream> 415491Sgblack@eecs.umich.edu#include <list> 422SN/A#include <map> 435491Sgblack@eecs.umich.edu#include <string> 442SN/A#include <vector> 452SN/A 468737Skoansin.tan@gmail.com#include "enums/MemoryMode.hh" 474762Snate@binkert.org#include "params/SimObject.hh" 485605Snate@binkert.org#include "sim/eventq.hh" 4956SN/A#include "sim/serialize.hh" 502SN/A 512797Sktlim@umich.educlass BaseCPU; 522797Sktlim@umich.educlass Event; 532609SN/A 549196SAndreas.Sandberg@arm.com/** 552SN/A * Abstract superclass for simulation objects. Represents things that 562SN/A * correspond to physical components and can be specified via the 572SN/A * config file (CPUs, caches, etc.). 589196SAndreas.Sandberg@arm.com * 599196SAndreas.Sandberg@arm.com * SimObject initialization is controlled by the instantiate method in 609196SAndreas.Sandberg@arm.com * src/python/m5/simulate.py. There are slightly different 619196SAndreas.Sandberg@arm.com * initialization paths when starting the simulation afresh and when 629196SAndreas.Sandberg@arm.com * loading from a checkpoint. After instantiation and connecting 639196SAndreas.Sandberg@arm.com * ports, simulate.py initializes the object using the following call 649196SAndreas.Sandberg@arm.com * sequence: 659196SAndreas.Sandberg@arm.com * 669196SAndreas.Sandberg@arm.com * <ol> 679196SAndreas.Sandberg@arm.com * <li>SimObject::init() 689196SAndreas.Sandberg@arm.com * <li>SimObject::regStats() 699196SAndreas.Sandberg@arm.com * <li><ul> 709196SAndreas.Sandberg@arm.com * <li>SimObject::initState() if starting afresh. 719196SAndreas.Sandberg@arm.com * <li>SimObject::loadState() if restoring from a checkpoint. 729196SAndreas.Sandberg@arm.com * </ul> 739196SAndreas.Sandberg@arm.com * <li>SimObject::resetStats() 749196SAndreas.Sandberg@arm.com * <li>SimObject::startup() 759196SAndreas.Sandberg@arm.com * <li>SimObject::resume() if resuming from a checkpoint. 769196SAndreas.Sandberg@arm.com * </ol> 779196SAndreas.Sandberg@arm.com * 789196SAndreas.Sandberg@arm.com * An object's internal state needs to be drained when creating a 799196SAndreas.Sandberg@arm.com * checkpoint, switching between CPU models, or switching between 809196SAndreas.Sandberg@arm.com * timing models. Once the internal state has been drained from 819196SAndreas.Sandberg@arm.com * <i>all</i> objects in the system, the objects are serialized to 829196SAndreas.Sandberg@arm.com * disc or the configuration change takes place. The process works as 839196SAndreas.Sandberg@arm.com * follows (see simulate.py for details): 849196SAndreas.Sandberg@arm.com * 859196SAndreas.Sandberg@arm.com * <ol> 869196SAndreas.Sandberg@arm.com * <li>An instance of a CountedDrainEvent is created to keep track of 879196SAndreas.Sandberg@arm.com * how many objects need to be drained. The object maintains an 889196SAndreas.Sandberg@arm.com * internal counter that is decreased every time its 899196SAndreas.Sandberg@arm.com * CountedDrainEvent::process() method is called. When the counter 909196SAndreas.Sandberg@arm.com * reaches zero, the simulation is stopped. 919196SAndreas.Sandberg@arm.com * 929196SAndreas.Sandberg@arm.com * <li>Call SimObject::drain() for every object in the 939196SAndreas.Sandberg@arm.com * system. Draining has completed if all of them return 949196SAndreas.Sandberg@arm.com * zero. Otherwise, the sum of the return values is loaded into 959196SAndreas.Sandberg@arm.com * the counter of the CountedDrainEvent. A pointer of the drain 969196SAndreas.Sandberg@arm.com * event is passed as an argument to the drain() method. 979196SAndreas.Sandberg@arm.com * 989196SAndreas.Sandberg@arm.com * <li>Continue simulation. When an object has finished draining its 999196SAndreas.Sandberg@arm.com * internal state, it calls CountedDrainEvent::process() on the 1009196SAndreas.Sandberg@arm.com * CountedDrainEvent. When counter in the CountedDrainEvent reaches 1019196SAndreas.Sandberg@arm.com * zero, the simulation stops. 1029196SAndreas.Sandberg@arm.com * 1039196SAndreas.Sandberg@arm.com * <li>Check if any object still needs draining, if so repeat the 1049196SAndreas.Sandberg@arm.com * process above. 1059196SAndreas.Sandberg@arm.com * 1069196SAndreas.Sandberg@arm.com * <li>Serialize objects, switch CPU model, or change timing model. 1079196SAndreas.Sandberg@arm.com * 1089196SAndreas.Sandberg@arm.com * <li>Call SimObject::resume() and continue the simulation. 1099196SAndreas.Sandberg@arm.com * </ol> 1109196SAndreas.Sandberg@arm.com * 1119196SAndreas.Sandberg@arm.com * @note Whenever a method is called on all objects in the simulator's 1129196SAndreas.Sandberg@arm.com * object tree (e.g., init(), startup(), or loadState()), a pre-order 1139196SAndreas.Sandberg@arm.com * depth-first traversal is performed (see descendants() in 1149196SAndreas.Sandberg@arm.com * SimObject.py). This has the effect of calling the method on the 1159196SAndreas.Sandberg@arm.com * parent node <i>before</i> its children. 1162SN/A */ 1177492Ssteve.reinhardt@amd.comclass SimObject : public EventManager, public Serializable 1182SN/A{ 1191553SN/A public: 1209196SAndreas.Sandberg@arm.com /** 1219196SAndreas.Sandberg@arm.com * Object drain/handover states 1229196SAndreas.Sandberg@arm.com * 1239196SAndreas.Sandberg@arm.com * An object starts out in the Running state. When the simulator 1249196SAndreas.Sandberg@arm.com * prepares to take a snapshot or prepares a CPU for handover, it 1259196SAndreas.Sandberg@arm.com * calls the drain() method to transfer the object into the 1269196SAndreas.Sandberg@arm.com * Draining or Drained state. If any object enters the Draining 1279196SAndreas.Sandberg@arm.com * state (drain() returning >0), simulation continues until it all 1289196SAndreas.Sandberg@arm.com * objects have entered the Drained. 1299196SAndreas.Sandberg@arm.com * 1309196SAndreas.Sandberg@arm.com * The before resuming simulation, the simulator calls resume() to 1319196SAndreas.Sandberg@arm.com * transfer the object to the Running state. 1329196SAndreas.Sandberg@arm.com * 1339196SAndreas.Sandberg@arm.com * \note Even though the state of an object (visible to the rest 1349196SAndreas.Sandberg@arm.com * of the world through getState()) could be used to determine if 1359196SAndreas.Sandberg@arm.com * all objects have entered the Drained state, the protocol is 1369196SAndreas.Sandberg@arm.com * actually a bit more elaborate. See drain() for details. 1379196SAndreas.Sandberg@arm.com */ 1382797Sktlim@umich.edu enum State { 1399196SAndreas.Sandberg@arm.com Running, /** Running normally */ 1409196SAndreas.Sandberg@arm.com Draining, /** Draining buffers pending serialization/handover */ 1419196SAndreas.Sandberg@arm.com Drained /** Buffers drained, ready for serialization/handover */ 1422797Sktlim@umich.edu }; 1433202Shsul@eecs.umich.edu 1442901Ssaidi@eecs.umich.edu private: 1452901Ssaidi@eecs.umich.edu State state; 1462797Sktlim@umich.edu 147265SN/A protected: 1482797Sktlim@umich.edu void changeState(State new_state) { state = new_state; } 1491553SN/A 1501553SN/A public: 1512797Sktlim@umich.edu State getState() { return state; } 1522797Sktlim@umich.edu 1532SN/A private: 1542SN/A typedef std::vector<SimObject *> SimObjectList; 1552SN/A 1569196SAndreas.Sandberg@arm.com /** List of all instantiated simulation objects. */ 1572SN/A static SimObjectList simObjectList; 1582SN/A 1594762Snate@binkert.org protected: 1609196SAndreas.Sandberg@arm.com /** Cached copy of the object parameters. */ 1614762Snate@binkert.org const SimObjectParams *_params; 1624762Snate@binkert.org 1632SN/A public: 1644762Snate@binkert.org typedef SimObjectParams Params; 1654762Snate@binkert.org const Params *params() const { return _params; } 1664762Snate@binkert.org SimObject(const Params *_params); 1672SN/A virtual ~SimObject() {} 1682SN/A 1695034Smilesck@eecs.umich.edu public: 1705034Smilesck@eecs.umich.edu 1711553SN/A virtual const std::string name() const { return params()->name; } 172265SN/A 1737532Ssteve.reinhardt@amd.com /** 1747532Ssteve.reinhardt@amd.com * init() is called after all C++ SimObjects have been created and 1757532Ssteve.reinhardt@amd.com * all ports are connected. Initializations that are independent 1767532Ssteve.reinhardt@amd.com * of unserialization but rely on a fully instantiated and 1777532Ssteve.reinhardt@amd.com * connected SimObject graph should be done here. 1787532Ssteve.reinhardt@amd.com */ 179465SN/A virtual void init(); 180465SN/A 1817532Ssteve.reinhardt@amd.com /** 1827532Ssteve.reinhardt@amd.com * loadState() is called on each SimObject when restoring from a 1837532Ssteve.reinhardt@amd.com * checkpoint. The default implementation simply calls 1847532Ssteve.reinhardt@amd.com * unserialize() if there is a corresponding section in the 1857532Ssteve.reinhardt@amd.com * checkpoint. However, objects can override loadState() to get 1867532Ssteve.reinhardt@amd.com * other behaviors, e.g., doing other programmed initializations 1877532Ssteve.reinhardt@amd.com * after unserialize(), or complaining if no checkpoint section is 1887532Ssteve.reinhardt@amd.com * found. 1899196SAndreas.Sandberg@arm.com * 1909196SAndreas.Sandberg@arm.com * @param cp Checkpoint to restore the state from. 1917532Ssteve.reinhardt@amd.com */ 1927532Ssteve.reinhardt@amd.com virtual void loadState(Checkpoint *cp); 1937532Ssteve.reinhardt@amd.com 1947532Ssteve.reinhardt@amd.com /** 1957532Ssteve.reinhardt@amd.com * initState() is called on each SimObject when *not* restoring 1967532Ssteve.reinhardt@amd.com * from a checkpoint. This provides a hook for state 1977532Ssteve.reinhardt@amd.com * initializations that are only required for a "cold start". 1987532Ssteve.reinhardt@amd.com */ 1997532Ssteve.reinhardt@amd.com virtual void initState(); 2007532Ssteve.reinhardt@amd.com 2019196SAndreas.Sandberg@arm.com /** 2029196SAndreas.Sandberg@arm.com * Register statistics for this object. 2039196SAndreas.Sandberg@arm.com */ 2042SN/A virtual void regStats(); 2059196SAndreas.Sandberg@arm.com 2069196SAndreas.Sandberg@arm.com /** 2079196SAndreas.Sandberg@arm.com * Reset statistics associated with this object. 2089196SAndreas.Sandberg@arm.com */ 209330SN/A virtual void resetStats(); 2102SN/A 2117532Ssteve.reinhardt@amd.com /** 2127532Ssteve.reinhardt@amd.com * startup() is the final initialization call before simulation. 2137532Ssteve.reinhardt@amd.com * All state is initialized (including unserialized state, if any, 2147823Ssteve.reinhardt@amd.com * such as the curTick() value), so this is the appropriate place to 2157532Ssteve.reinhardt@amd.com * schedule initial event(s) for objects that need them. 2167532Ssteve.reinhardt@amd.com */ 2177492Ssteve.reinhardt@amd.com virtual void startup(); 218330SN/A 2199196SAndreas.Sandberg@arm.com /** 2209196SAndreas.Sandberg@arm.com * Serialize all SimObjects in the system. 2219196SAndreas.Sandberg@arm.com */ 2229196SAndreas.Sandberg@arm.com static void serializeAll(std::ostream &os); 223938SN/A 2249196SAndreas.Sandberg@arm.com /** 2259196SAndreas.Sandberg@arm.com * Determine if an object needs draining and register a drain 2269196SAndreas.Sandberg@arm.com * event. 2279196SAndreas.Sandberg@arm.com * 2289196SAndreas.Sandberg@arm.com * When draining the state of an object, the simulator calls drain 2299196SAndreas.Sandberg@arm.com * with a pointer to a drain event. If the object does not need 2309196SAndreas.Sandberg@arm.com * further simulation to drain internal buffers, it switched to 2319196SAndreas.Sandberg@arm.com * the Drained state and returns 0, otherwise it switches to the 2329196SAndreas.Sandberg@arm.com * Draining state and returns the number of times that it will 2339196SAndreas.Sandberg@arm.com * call Event::process() on the drain event. Most objects are 2349196SAndreas.Sandberg@arm.com * expected to return either 0 or 1. 2359196SAndreas.Sandberg@arm.com * 2369196SAndreas.Sandberg@arm.com * The default implementation simply switches to the Drained state 2379196SAndreas.Sandberg@arm.com * and returns 0. 2389196SAndreas.Sandberg@arm.com * 2399196SAndreas.Sandberg@arm.com * @note An object that has entered the Drained state can be 2409196SAndreas.Sandberg@arm.com * disturbed by other objects in the system and consequently be 2419196SAndreas.Sandberg@arm.com * forced to enter the Draining state again. The simulator 2429196SAndreas.Sandberg@arm.com * therefore repeats the draining process until all objects return 2439196SAndreas.Sandberg@arm.com * 0 on the first call to drain(). 2449196SAndreas.Sandberg@arm.com * 2459196SAndreas.Sandberg@arm.com * @param drain_event Event to use to inform the simulator when 2469196SAndreas.Sandberg@arm.com * the draining has completed. 2479196SAndreas.Sandberg@arm.com * 2489196SAndreas.Sandberg@arm.com * @return 0 if the object is ready for serialization now, >0 if 2499196SAndreas.Sandberg@arm.com * it needs further simulation. 2509196SAndreas.Sandberg@arm.com */ 2512901Ssaidi@eecs.umich.edu virtual unsigned int drain(Event *drain_event); 2529196SAndreas.Sandberg@arm.com 2539196SAndreas.Sandberg@arm.com /** 2549196SAndreas.Sandberg@arm.com * Switch an object in the Drained stated into the Running state. 2559196SAndreas.Sandberg@arm.com */ 2562797Sktlim@umich.edu virtual void resume(); 2579196SAndreas.Sandberg@arm.com 2589196SAndreas.Sandberg@arm.com /** 2599196SAndreas.Sandberg@arm.com * Change the memory mode the simulator operates in. 2609196SAndreas.Sandberg@arm.com * 2619196SAndreas.Sandberg@arm.com * @note Should only be implemented in the System object. 2629196SAndreas.Sandberg@arm.com */ 2638737Skoansin.tan@gmail.com virtual void setMemoryMode(Enums::MemoryMode new_mode); 2649196SAndreas.Sandberg@arm.com 2659196SAndreas.Sandberg@arm.com /** 2669196SAndreas.Sandberg@arm.com * Prepare a CPU model to be switched out, invoked on active CPUs 2679196SAndreas.Sandberg@arm.com * that are about to be replaced. 2689196SAndreas.Sandberg@arm.com * 2699196SAndreas.Sandberg@arm.com * @note This should only be implemented in CPU models. 2709196SAndreas.Sandberg@arm.com */ 2712797Sktlim@umich.edu virtual void switchOut(); 2729196SAndreas.Sandberg@arm.com 2739196SAndreas.Sandberg@arm.com /** 2749196SAndreas.Sandberg@arm.com * Load the state of a CPU from the previous CPU object, invoked 2759196SAndreas.Sandberg@arm.com * on all new CPUs that are about to be switched in. 2769196SAndreas.Sandberg@arm.com * 2779196SAndreas.Sandberg@arm.com * A CPU model implementing this method is expected to initialize 2789196SAndreas.Sandberg@arm.com * its state from the old CPU and connect its memory (unless they 2799196SAndreas.Sandberg@arm.com * are already connected) to the memories connected to the old 2809196SAndreas.Sandberg@arm.com * CPU. 2819196SAndreas.Sandberg@arm.com * 2829196SAndreas.Sandberg@arm.com * @note This should only be implemented in CPU models. 2839196SAndreas.Sandberg@arm.com * 2849196SAndreas.Sandberg@arm.com * @param cpu CPU to initialize read state from. 2859196SAndreas.Sandberg@arm.com */ 2862797Sktlim@umich.edu virtual void takeOverFrom(BaseCPU *cpu); 2872609SN/A 2881031SN/A#ifdef DEBUG 2891031SN/A public: 2901031SN/A bool doDebugBreak; 2911031SN/A static void debugObjectBreak(const std::string &objs); 2921031SN/A#endif 2931031SN/A 2945314Sstever@gmail.com /** 2955314Sstever@gmail.com * Find the SimObject with the given name and return a pointer to 2965315Sstever@gmail.com * it. Primarily used for interactive debugging. Argument is 2975314Sstever@gmail.com * char* rather than std::string to make it callable from gdb. 2985314Sstever@gmail.com */ 2995314Sstever@gmail.com static SimObject *find(const char *name); 3002SN/A}; 3012SN/A 3022SN/A#endif // __SIM_OBJECT_HH__ 303