| /* |
| * Copyright (c) 2014 ARM Limited |
| * All rights reserved |
| * |
| * The license below extends only to copyright in the software and shall |
| * not be construed as granting a license to any other intellectual |
| * property including but not limited to intellectual property relating |
| * to a hardware implementation of the functionality of the software |
| * licensed hereunder. You may use the software subject to the license |
| * terms below provided that you ensure that this notice is replicated |
| * unmodified and in its entirety in all distributions of the software, |
| * modified or unmodified, in source code or in binary form. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer; |
| * redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution; |
| * neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** |
| * @file |
| * |
| * C++-only configuration and instantiation support. This allows a |
| * config to be read back from a config file and instantiated without |
| * Python. Useful if you want to embed gem5 within a larger system |
| * without carrying the integration cost of the fully-featured |
| * configuration system. |
| * |
| * This file contains the config loading/storing manager class |
| */ |
| |
| #ifndef __SIM_CXX_MANAGER_HH__ |
| #define __SIM_CXX_MANAGER_HH__ |
| |
| #include <list> |
| #include <map> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/cprintf.hh" |
| #include "sim/cxx_config.hh" |
| |
| class CheckpointIn; |
| |
| /** This class allows a config file to be read into gem5 (generating the |
| * appropriate SimObjects) from C++ */ |
| class CxxConfigManager |
| { |
| protected: |
| /** Configuration file being read */ |
| CxxConfigFileBase &configFile; |
| |
| /** Flags to pass to affect param setting */ |
| CxxConfigParams::Flags flags; |
| |
| public: |
| /** Exception for instantiate/post-instantiate errors */ |
| class Exception : public std::exception |
| { |
| public: |
| std::string name; |
| std::string message; |
| |
| public: |
| Exception(const std::string &name_, const std::string &message_) : |
| name(name_), message(message_) |
| { } |
| |
| const char *what() const throw() { return message.c_str(); } |
| |
| ~Exception() throw() { } |
| }; |
| |
| /** Name substitution when instantiating any object whose name starts |
| * with fromPrefix. Where both renamed and unrenamed names are used |
| * in the code, `object' as part of a name usually refers to the |
| * unrenamed name (the name as it appears in the config file) and |
| * `instance' is part of the renamed name */ |
| struct Renaming |
| { |
| std::string fromPrefix; |
| std::string toPrefix; |
| |
| Renaming(const std::string &from_prefix, |
| const std::string &to_prefix) : |
| fromPrefix(from_prefix), |
| toPrefix(to_prefix) |
| { } |
| }; |
| |
| public: |
| /** SimObject indexed by name */ |
| std::map<std::string, SimObject *> objectsByName; |
| |
| /** ...Params objects created by this manager */ |
| std::map<std::string, CxxConfigParams *> objectParamsByName; |
| |
| /** SimObjects in order. This is populated by findAllObjects */ |
| std::list<SimObject *> objectsInOrder; |
| |
| protected: |
| /** While configuring, inVisit contains names of SimObjects visited in |
| * this recursive configuration walk */ |
| std::set<std::string> inVisit; |
| |
| /** All the renamings applicable when instantiating objects */ |
| std::list<Renaming> renamings; |
| |
| /** Bind a single connection between two objects' ports */ |
| void bindPort(SimObject *masterObject, const std::string &masterPort, |
| PortID masterPortIndex, SimObject *slaveObject, |
| const std::string &slavePort, PortID slavePortIndex); |
| |
| /** Bind a single (possibly vectored) master port to peers from the |
| * unparsed list peers with elements in the .ini connection format: |
| * path(.path)*.port[index] */ |
| void bindMasterPort(SimObject *object, |
| const CxxConfigDirectoryEntry::PortDesc &port, |
| const std::vector<std::string> &peers); |
| |
| /** Apply the first matching renaming in renamings to the given name */ |
| std::string rename(const std::string &from_name); |
| |
| /** Apply the first matching renaming in reverse (toPrefix -> fromPrefix |
| * for the given name */ |
| std::string unRename(const std::string &to_name); |
| |
| protected: |
| /** Bind the ports of all the objects in objectInOrder order. |
| * Also */ |
| void bindAllPorts(); |
| |
| /** Class for resolving SimObject names to SimObjects usable by the |
| * checkpoint restore mechanism */ |
| class SimObjectResolver : public ::SimObjectResolver |
| { |
| protected: |
| CxxConfigManager &configManager; |
| |
| public: |
| SimObjectResolver(CxxConfigManager &configManager_) : |
| configManager(configManager_) |
| { } |
| |
| SimObject *resolveSimObject(const std::string &name) |
| { return &(configManager.getObject<SimObject>(name)); } |
| }; |
| |
| /** Singleton instance of SimObjectResolver */ |
| SimObjectResolver simObjectResolver; |
| |
| public: |
| CxxConfigManager(CxxConfigFileBase &configFile_); |
| |
| /** Find the type field for a named object and return both the |
| * name of the type to object_type and the object's directory |
| * entry as the return value */ |
| const CxxConfigDirectoryEntry &findObjectType( |
| const std::string &object_name, std::string &object_type); |
| |
| /** Add a name prefix renaming to those currently applied. Call this |
| * before trying to instantiate any object as the name mappings are |
| * not applied to the config tree read from the config file but are |
| * applied while processing instantiations */ |
| void addRenaming(const Renaming &renaming); |
| |
| public: |
| /** Bind the ports of a single SimObject */ |
| void bindObjectPorts(SimObject *object); |
| |
| /** Walk the configuration starting with object object_name and fill |
| * in all the elements of this object on the way. This involves: |
| * <ul> |
| * <li>Calling findObjectParams to make the ...Params object |
| * If findObjectParams has already been called for this object, |
| * the ...Params object generated by that called (stored in |
| * (objectParamsByName[object_name] will be used)</li> |
| * <li>Populating the ...Params object references to other |
| * SimObjects by recursively descending into the trees formed |
| * by SimObject references</li> |
| * <li>Building the final SimObject and adding it to |
| * objectsByName</li> |
| * <li>If visit_children is true, recursively visit all this |
| * object's children and build/find them too</li> |
| * </ul> |
| * After the first call, this function will return |
| * objectsByName[object_name] */ |
| SimObject *findObject(const std::string &object_name, |
| bool visit_children = false); |
| |
| /** Find the parameters for the named object. Returns NULL if the |
| * object isn't in the configuration. For the first call with a |
| * particular object name, a new CxxConfigParams descended object |
| * is made with the configuration file contents for this object. |
| * This involves populating that ...Params object with: |
| * <ul> |
| * <li>parameter values from the configuration file</li> |
| * <li>port connection connection counts from the connection counts |
| * indicated by the number of peer ports in the configuration |
| * file</li> |
| * <li>nulled (or vector<>::clear'ed) SimObject references for |
| * SimObject-values parameters</li> |
| * </ul> |
| * The ...Params object is then added to objectParamsByName |
| * After the first call, this function will return |
| * objectParamsByName[object_name] */ |
| CxxConfigParams *findObjectParams(const std::string &object_name); |
| |
| /** Populate objectsInOrder with a preorder, depth first traversal from |
| * the given object name down through all its children */ |
| void findTraversalOrder(const std::string &object_name); |
| |
| /** Find an object from objectsByName with a type-checking cast. |
| * This function is provided for manipulating objects after |
| * instantiate as it assumes the named object exists. */ |
| template<typename SimObjectType> |
| SimObjectType & |
| getObject(const std::string &object_name) |
| { |
| if (objectsByName.find(object_name) == objectsByName.end()) { |
| throw Exception("", csprintf("No sim object named: %s", |
| object_name)); |
| } |
| |
| SimObjectType *object = dynamic_cast<SimObjectType *>( |
| objectsByName[object_name]); |
| |
| if (!object) { |
| throw Exception("", csprintf("Sim object: %s has the wrong" |
| " type", object_name)); |
| } |
| |
| return *object; |
| } |
| |
| /** Perform mem_func on each SimObject */ |
| void forEachObject(void (SimObject::*mem_func)()); |
| |
| /** Find all objects by iterating over the object names in the config |
| * file with findObject. Also populate the traversal order */ |
| void findAllObjects(); |
| |
| /** Parse a port string of the form 'path(.path)*.port[index]' into |
| * path, port and index */ |
| static void parsePort(const std::string &inp, |
| std::string &path, std::string &port, unsigned int &index); |
| |
| /** Build all objects (if build_all is true, otherwise objects must |
| * have been individually findObject-ed and added to the traversal |
| * order) and perform all the configuration specific actions up to, |
| * but not including initState. |
| * |
| * If you want to set some parameters before completing instantiation, |
| * call findObjectParams on the objects you want to modify, then call |
| * instantiate */ |
| void instantiate(bool build_all = true); |
| |
| /** Call initState on all objects */ |
| void initState(); |
| |
| /** Call startup on all objects */ |
| void startup(); |
| |
| /** Drain all objects */ |
| unsigned int drain(); |
| |
| /** Resume from drain */ |
| void drainResume(); |
| |
| /** Serialize (checkpoint) all objects to the given stream */ |
| void serialize(std::ostream &os); |
| |
| /** Load all objects' state from the given Checkpoint */ |
| void loadState(CheckpointIn &checkpoint); |
| |
| /** Delete all objects and clear objectsByName and objectsByOrder */ |
| void deleteObjects(); |
| |
| /** Get the resolver used to map SimObject names to SimObjects for |
| * checkpoint restore */ |
| SimObjectResolver &getSimObjectResolver() { return simObjectResolver; } |
| |
| /** Convenience functions for calling set... member functions on a |
| * CxxConfigParams for an object. These functions throw Exception |
| * rather than return a bool on failure */ |
| void setParam(const std::string &object_name, |
| const std::string ¶m_name, const std::string ¶m_value); |
| void setParamVector(const std::string &object_name, |
| const std::string ¶m_name, |
| const std::vector<std::string> ¶m_values); |
| }; |
| |
| #endif // __SIM_CXX_MANAGER_HH__ |