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