110458Sandreas.hansson@arm.com/*
210458Sandreas.hansson@arm.com * Copyright (c) 2014 ARM Limited
310458Sandreas.hansson@arm.com * All rights reserved
410458Sandreas.hansson@arm.com *
510458Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
610458Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
710458Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
810458Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
910458Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
1010458Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
1110458Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
1210458Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
1310458Sandreas.hansson@arm.com *
1410458Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
1510458Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
1610458Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
1710458Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
1810458Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
1910458Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
2010458Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
2110458Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
2210458Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
2310458Sandreas.hansson@arm.com * this software without specific prior written permission.
2410458Sandreas.hansson@arm.com *
2510458Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610458Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710458Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810458Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910458Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010458Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110458Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210458Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310458Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410458Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510458Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610458Sandreas.hansson@arm.com *
3710458Sandreas.hansson@arm.com * Authors: Andrew Bardsley
3810458Sandreas.hansson@arm.com */
3910458Sandreas.hansson@arm.com
4010458Sandreas.hansson@arm.com/**
4110458Sandreas.hansson@arm.com * @file
4210458Sandreas.hansson@arm.com *
4310458Sandreas.hansson@arm.com *  C++-only configuration and instantiation support.  This allows a
4410458Sandreas.hansson@arm.com *  config to be read back from a config file and instantiated without
4510458Sandreas.hansson@arm.com *  Python.  Useful if you want to embed gem5 within a larger system
4610458Sandreas.hansson@arm.com *  without carrying the integration cost of the fully-featured
4710458Sandreas.hansson@arm.com *  configuration system.
4810458Sandreas.hansson@arm.com *
4910458Sandreas.hansson@arm.com *  This file contains the config loading/storing manager class
5010458Sandreas.hansson@arm.com */
5110458Sandreas.hansson@arm.com
5210458Sandreas.hansson@arm.com#ifndef __SIM_CXX_MANAGER_HH__
5310458Sandreas.hansson@arm.com#define __SIM_CXX_MANAGER_HH__
5410458Sandreas.hansson@arm.com
5510458Sandreas.hansson@arm.com#include <list>
5610458Sandreas.hansson@arm.com#include <map>
5710458Sandreas.hansson@arm.com#include <set>
5810458Sandreas.hansson@arm.com#include <string>
5910458Sandreas.hansson@arm.com#include <vector>
6010458Sandreas.hansson@arm.com
6110458Sandreas.hansson@arm.com#include "base/cprintf.hh"
6210458Sandreas.hansson@arm.com#include "sim/cxx_config.hh"
6310458Sandreas.hansson@arm.com
6410905Sandreas.sandberg@arm.comclass CheckpointIn;
6510458Sandreas.hansson@arm.com
6610458Sandreas.hansson@arm.com/** This class allows a config file to be read into gem5 (generating the
6710458Sandreas.hansson@arm.com *  appropriate SimObjects) from C++ */
6810458Sandreas.hansson@arm.comclass CxxConfigManager
6910458Sandreas.hansson@arm.com{
7010458Sandreas.hansson@arm.com  protected:
7110458Sandreas.hansson@arm.com    /** Configuration file being read */
7210458Sandreas.hansson@arm.com    CxxConfigFileBase &configFile;
7310458Sandreas.hansson@arm.com
7410458Sandreas.hansson@arm.com    /** Flags to pass to affect param setting */
7510458Sandreas.hansson@arm.com    CxxConfigParams::Flags flags;
7610458Sandreas.hansson@arm.com
7710458Sandreas.hansson@arm.com  public:
7810458Sandreas.hansson@arm.com    /** Exception for instantiate/post-instantiate errors */
7910458Sandreas.hansson@arm.com    class Exception : public std::exception
8010458Sandreas.hansson@arm.com    {
8110458Sandreas.hansson@arm.com      public:
8210458Sandreas.hansson@arm.com        std::string name;
8310458Sandreas.hansson@arm.com        std::string message;
8410458Sandreas.hansson@arm.com
8510458Sandreas.hansson@arm.com      public:
8610458Sandreas.hansson@arm.com        Exception(const std::string &name_, const std::string &message_) :
8710458Sandreas.hansson@arm.com            name(name_), message(message_)
8810458Sandreas.hansson@arm.com        { }
8910458Sandreas.hansson@arm.com
9010458Sandreas.hansson@arm.com        const char *what() const throw() { return message.c_str(); }
9110458Sandreas.hansson@arm.com
9210458Sandreas.hansson@arm.com        ~Exception() throw() { }
9310458Sandreas.hansson@arm.com    };
9410458Sandreas.hansson@arm.com
9510458Sandreas.hansson@arm.com    /** Name substitution when instantiating any object whose name starts
9610458Sandreas.hansson@arm.com     *  with fromPrefix.  Where both renamed and unrenamed names are used
9710458Sandreas.hansson@arm.com     *  in the code, `object' as part of a name usually refers to the
9810458Sandreas.hansson@arm.com     *  unrenamed name (the name as it appears in the config file) and
9910458Sandreas.hansson@arm.com     *  `instance' is part of the renamed name */
10010458Sandreas.hansson@arm.com    struct Renaming
10110458Sandreas.hansson@arm.com    {
10210458Sandreas.hansson@arm.com        std::string fromPrefix;
10310458Sandreas.hansson@arm.com        std::string toPrefix;
10410458Sandreas.hansson@arm.com
10510458Sandreas.hansson@arm.com        Renaming(const std::string &from_prefix,
10610458Sandreas.hansson@arm.com            const std::string &to_prefix) :
10710458Sandreas.hansson@arm.com            fromPrefix(from_prefix),
10810458Sandreas.hansson@arm.com            toPrefix(to_prefix)
10910458Sandreas.hansson@arm.com        { }
11010458Sandreas.hansson@arm.com    };
11110458Sandreas.hansson@arm.com
11210458Sandreas.hansson@arm.com  public:
11310458Sandreas.hansson@arm.com    /** SimObject indexed by name */
11410458Sandreas.hansson@arm.com    std::map<std::string, SimObject *> objectsByName;
11510458Sandreas.hansson@arm.com
11610458Sandreas.hansson@arm.com    /** ...Params objects created by this manager */
11710458Sandreas.hansson@arm.com    std::map<std::string, CxxConfigParams *> objectParamsByName;
11810458Sandreas.hansson@arm.com
11910458Sandreas.hansson@arm.com    /** SimObjects in order.  This is populated by findAllObjects */
12010458Sandreas.hansson@arm.com    std::list<SimObject *> objectsInOrder;
12110458Sandreas.hansson@arm.com
12210458Sandreas.hansson@arm.com  protected:
12310458Sandreas.hansson@arm.com    /** While configuring, inVisit contains names of SimObjects visited in
12410458Sandreas.hansson@arm.com     *  this recursive configuration walk */
12510458Sandreas.hansson@arm.com    std::set<std::string> inVisit;
12610458Sandreas.hansson@arm.com
12710458Sandreas.hansson@arm.com    /** All the renamings applicable when instantiating objects */
12810458Sandreas.hansson@arm.com    std::list<Renaming> renamings;
12910458Sandreas.hansson@arm.com
13010458Sandreas.hansson@arm.com    /** Bind a single connection between two objects' ports */
13110458Sandreas.hansson@arm.com    void bindPort(SimObject *masterObject, const std::string &masterPort,
13210458Sandreas.hansson@arm.com        PortID masterPortIndex, SimObject *slaveObject,
13310458Sandreas.hansson@arm.com        const std::string &slavePort, PortID slavePortIndex);
13410458Sandreas.hansson@arm.com
13510458Sandreas.hansson@arm.com    /** Bind a single (possibly vectored) master port to peers from the
13610458Sandreas.hansson@arm.com     *  unparsed list peers with elements in the .ini connection format:
13710458Sandreas.hansson@arm.com     *  path(.path)*.port[index] */
13810458Sandreas.hansson@arm.com    void bindMasterPort(SimObject *object,
13910458Sandreas.hansson@arm.com        const CxxConfigDirectoryEntry::PortDesc &port,
14010458Sandreas.hansson@arm.com        const std::vector<std::string> &peers);
14110458Sandreas.hansson@arm.com
14210458Sandreas.hansson@arm.com    /** Apply the first matching renaming in renamings to the given name */
14310458Sandreas.hansson@arm.com    std::string rename(const std::string &from_name);
14410458Sandreas.hansson@arm.com
14510458Sandreas.hansson@arm.com    /** Apply the first matching renaming in reverse (toPrefix -> fromPrefix
14610458Sandreas.hansson@arm.com     *  for the given name */
14710458Sandreas.hansson@arm.com    std::string unRename(const std::string &to_name);
14810458Sandreas.hansson@arm.com
14910458Sandreas.hansson@arm.com  protected:
15010458Sandreas.hansson@arm.com    /** Bind the ports of all the objects in objectInOrder order.
15110458Sandreas.hansson@arm.com     *  Also */
15210458Sandreas.hansson@arm.com    void bindAllPorts();
15310458Sandreas.hansson@arm.com
15410458Sandreas.hansson@arm.com    /** Class for resolving SimObject names to SimObjects usable by the
15510458Sandreas.hansson@arm.com     *  checkpoint restore mechanism */
15610458Sandreas.hansson@arm.com    class SimObjectResolver : public ::SimObjectResolver
15710458Sandreas.hansson@arm.com    {
15810458Sandreas.hansson@arm.com      protected:
15910458Sandreas.hansson@arm.com        CxxConfigManager &configManager;
16010458Sandreas.hansson@arm.com
16110458Sandreas.hansson@arm.com      public:
16210458Sandreas.hansson@arm.com        SimObjectResolver(CxxConfigManager &configManager_) :
16310458Sandreas.hansson@arm.com            configManager(configManager_)
16410458Sandreas.hansson@arm.com        { }
16510458Sandreas.hansson@arm.com
16610458Sandreas.hansson@arm.com        SimObject *resolveSimObject(const std::string &name)
16710458Sandreas.hansson@arm.com        { return &(configManager.getObject<SimObject>(name)); }
16810458Sandreas.hansson@arm.com    };
16910458Sandreas.hansson@arm.com
17010458Sandreas.hansson@arm.com    /** Singleton instance of SimObjectResolver */
17110458Sandreas.hansson@arm.com    SimObjectResolver simObjectResolver;
17210458Sandreas.hansson@arm.com
17310458Sandreas.hansson@arm.com  public:
17410458Sandreas.hansson@arm.com    CxxConfigManager(CxxConfigFileBase &configFile_);
17510458Sandreas.hansson@arm.com
17610458Sandreas.hansson@arm.com    /** Find the type field for a named object and return both the
17710458Sandreas.hansson@arm.com     *  name of the type to object_type and the object's directory
17810458Sandreas.hansson@arm.com     *  entry as the return value */
17910458Sandreas.hansson@arm.com    const CxxConfigDirectoryEntry &findObjectType(
18010458Sandreas.hansson@arm.com        const std::string &object_name, std::string &object_type);
18110458Sandreas.hansson@arm.com
18210458Sandreas.hansson@arm.com    /** Add a name prefix renaming to those currently applied.  Call this
18310458Sandreas.hansson@arm.com     *  before trying to instantiate any object as the name mappings are
18410458Sandreas.hansson@arm.com     *  not applied to the config tree read from the config file but are
18510458Sandreas.hansson@arm.com     *  applied while processing instantiations */
18610458Sandreas.hansson@arm.com    void addRenaming(const Renaming &renaming);
18710458Sandreas.hansson@arm.com
18810458Sandreas.hansson@arm.com  public:
18910458Sandreas.hansson@arm.com    /** Bind the ports of a single SimObject */
19010458Sandreas.hansson@arm.com    void bindObjectPorts(SimObject *object);
19110458Sandreas.hansson@arm.com
19210458Sandreas.hansson@arm.com    /** Walk the configuration starting with object object_name and fill
19310458Sandreas.hansson@arm.com     *  in all the elements of this object on the way.  This involves:
19410458Sandreas.hansson@arm.com     *  <ul>
19510458Sandreas.hansson@arm.com     *    <li>Calling findObjectParams to make the ...Params object
19610458Sandreas.hansson@arm.com     *      If findObjectParams has already been called for this object,
19710458Sandreas.hansson@arm.com     *      the ...Params object generated by that called (stored in
19810458Sandreas.hansson@arm.com     *      (objectParamsByName[object_name] will be used)</li>
19910458Sandreas.hansson@arm.com     *    <li>Populating the ...Params object references to other
20010458Sandreas.hansson@arm.com     *      SimObjects by recursively descending into the trees formed
20110458Sandreas.hansson@arm.com     *      by SimObject references</li>
20210458Sandreas.hansson@arm.com     *    <li>Building the final SimObject and adding it to
20310458Sandreas.hansson@arm.com     *      objectsByName</li>
20410458Sandreas.hansson@arm.com     *    <li>If visit_children is true, recursively visit all this
20510458Sandreas.hansson@arm.com     *      object's children and build/find them too</li>
20610458Sandreas.hansson@arm.com     *  </ul>
20710458Sandreas.hansson@arm.com     *  After the first call, this function will return
20810458Sandreas.hansson@arm.com     *  objectsByName[object_name] */
20910458Sandreas.hansson@arm.com    SimObject *findObject(const std::string &object_name,
21010458Sandreas.hansson@arm.com        bool visit_children = false);
21110458Sandreas.hansson@arm.com
21210458Sandreas.hansson@arm.com    /** Find the parameters for the named object.  Returns NULL if the
21310458Sandreas.hansson@arm.com     *  object isn't in the configuration.  For the first call with a
21410458Sandreas.hansson@arm.com     *  particular object name, a new CxxConfigParams descended object
21510458Sandreas.hansson@arm.com     *  is made with the configuration file contents for this object.
21610458Sandreas.hansson@arm.com     *  This involves populating that ...Params object with:
21710458Sandreas.hansson@arm.com     *  <ul>
21810458Sandreas.hansson@arm.com     *    <li>parameter values from the configuration file</li>
21910458Sandreas.hansson@arm.com     *    <li>port connection connection counts from the connection counts
22010458Sandreas.hansson@arm.com     *      indicated by the number of peer ports in the configuration
22110458Sandreas.hansson@arm.com     *      file</li>
22210458Sandreas.hansson@arm.com     *    <li>nulled (or vector<>::clear'ed) SimObject references for
22310458Sandreas.hansson@arm.com     *      SimObject-values parameters</li>
22410458Sandreas.hansson@arm.com     *  </ul>
22510458Sandreas.hansson@arm.com     *  The ...Params object is then added to objectParamsByName
22610458Sandreas.hansson@arm.com     *  After the first call, this function will return
22710458Sandreas.hansson@arm.com     *  objectParamsByName[object_name] */
22810458Sandreas.hansson@arm.com    CxxConfigParams *findObjectParams(const std::string &object_name);
22910458Sandreas.hansson@arm.com
23010458Sandreas.hansson@arm.com    /** Populate objectsInOrder with a preorder, depth first traversal from
23110458Sandreas.hansson@arm.com     *  the given object name down through all its children */
23210458Sandreas.hansson@arm.com    void findTraversalOrder(const std::string &object_name);
23310458Sandreas.hansson@arm.com
23410458Sandreas.hansson@arm.com    /** Find an object from objectsByName with a type-checking cast.
23510458Sandreas.hansson@arm.com     *  This function is provided for manipulating objects after
23610458Sandreas.hansson@arm.com     *  instantiate as it assumes the named object exists. */
23710458Sandreas.hansson@arm.com    template<typename SimObjectType>
23810458Sandreas.hansson@arm.com    SimObjectType &
23910458Sandreas.hansson@arm.com    getObject(const std::string &object_name)
24010458Sandreas.hansson@arm.com    {
24110458Sandreas.hansson@arm.com        if (objectsByName.find(object_name) == objectsByName.end()) {
24210458Sandreas.hansson@arm.com            throw Exception("", csprintf("No sim object named: %s",
24310458Sandreas.hansson@arm.com                object_name));
24410458Sandreas.hansson@arm.com        }
24510458Sandreas.hansson@arm.com
24610458Sandreas.hansson@arm.com        SimObjectType *object = dynamic_cast<SimObjectType *>(
24710458Sandreas.hansson@arm.com            objectsByName[object_name]);
24810458Sandreas.hansson@arm.com
24910458Sandreas.hansson@arm.com        if (!object) {
25010458Sandreas.hansson@arm.com            throw Exception("", csprintf("Sim object: %s  has the wrong"
25110458Sandreas.hansson@arm.com                " type", object_name));
25210458Sandreas.hansson@arm.com        }
25310458Sandreas.hansson@arm.com
25410458Sandreas.hansson@arm.com        return *object;
25510458Sandreas.hansson@arm.com    }
25610458Sandreas.hansson@arm.com
25710458Sandreas.hansson@arm.com    /** Perform mem_func on each SimObject */
25810458Sandreas.hansson@arm.com    void forEachObject(void (SimObject::*mem_func)());
25910458Sandreas.hansson@arm.com
26010458Sandreas.hansson@arm.com    /** Find all objects by iterating over the object names in the config
26110458Sandreas.hansson@arm.com     *  file with findObject.  Also populate the traversal order */
26210458Sandreas.hansson@arm.com    void findAllObjects();
26310458Sandreas.hansson@arm.com
26410458Sandreas.hansson@arm.com    /** Parse a port string of the form 'path(.path)*.port[index]' into
26510458Sandreas.hansson@arm.com     *  path, port and index */
26610458Sandreas.hansson@arm.com    static void parsePort(const std::string &inp,
26710458Sandreas.hansson@arm.com        std::string &path, std::string &port, unsigned int &index);
26810458Sandreas.hansson@arm.com
26910458Sandreas.hansson@arm.com    /** Build all objects (if build_all is true, otherwise objects must
27010458Sandreas.hansson@arm.com     *  have been individually findObject-ed and added to the traversal
27110458Sandreas.hansson@arm.com     *  order) and perform all the configuration specific actions up to,
27210458Sandreas.hansson@arm.com     *  but not including initState.
27310458Sandreas.hansson@arm.com     *
27410458Sandreas.hansson@arm.com     *  If you want to set some parameters before completing instantiation,
27510458Sandreas.hansson@arm.com     *  call findObjectParams on the objects you want to modify, then call
27610458Sandreas.hansson@arm.com     *  instantiate */
27710458Sandreas.hansson@arm.com    void instantiate(bool build_all = true);
27810458Sandreas.hansson@arm.com
27910458Sandreas.hansson@arm.com    /** Call initState on all objects */
28010458Sandreas.hansson@arm.com    void initState();
28110458Sandreas.hansson@arm.com
28210458Sandreas.hansson@arm.com    /** Call startup on all objects */
28310458Sandreas.hansson@arm.com    void startup();
28410458Sandreas.hansson@arm.com
28510458Sandreas.hansson@arm.com    /** Drain all objects */
28610912Sandreas.sandberg@arm.com    unsigned int drain();
28710458Sandreas.hansson@arm.com
28810458Sandreas.hansson@arm.com    /** Resume from drain */
28910458Sandreas.hansson@arm.com    void drainResume();
29010458Sandreas.hansson@arm.com
29110458Sandreas.hansson@arm.com    /** Serialize (checkpoint) all objects to the given stream */
29210458Sandreas.hansson@arm.com    void serialize(std::ostream &os);
29310458Sandreas.hansson@arm.com
29410458Sandreas.hansson@arm.com    /** Load all objects' state from the given Checkpoint */
29510905Sandreas.sandberg@arm.com    void loadState(CheckpointIn &checkpoint);
29610458Sandreas.hansson@arm.com
29710458Sandreas.hansson@arm.com    /** Delete all objects and clear objectsByName and objectsByOrder */
29810458Sandreas.hansson@arm.com    void deleteObjects();
29910458Sandreas.hansson@arm.com
30010458Sandreas.hansson@arm.com    /** Get the resolver used to map SimObject names to SimObjects for
30110458Sandreas.hansson@arm.com     *  checkpoint restore */
30210458Sandreas.hansson@arm.com    SimObjectResolver &getSimObjectResolver() { return simObjectResolver; }
30310458Sandreas.hansson@arm.com
30410458Sandreas.hansson@arm.com    /** Convenience functions for calling set... member functions on a
30510458Sandreas.hansson@arm.com     *  CxxConfigParams for an object.  These functions throw Exception
30610458Sandreas.hansson@arm.com     *  rather than return a bool on failure */
30710458Sandreas.hansson@arm.com    void setParam(const std::string &object_name,
30810458Sandreas.hansson@arm.com        const std::string &param_name, const std::string &param_value);
30910458Sandreas.hansson@arm.com    void setParamVector(const std::string &object_name,
31010458Sandreas.hansson@arm.com        const std::string &param_name,
31110458Sandreas.hansson@arm.com        const std::vector<std::string> &param_values);
31210458Sandreas.hansson@arm.com};
31310458Sandreas.hansson@arm.com
31410458Sandreas.hansson@arm.com#endif // __SIM_CXX_MANAGER_HH__
315