/* * 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. * * Authors: Andrew Bardsley */ /** * @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 #include #include #include #include #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 objectsByName; /** ...Params objects created by this manager */ std::map objectParamsByName; /** SimObjects in order. This is populated by findAllObjects */ std::list objectsInOrder; protected: /** While configuring, inVisit contains names of SimObjects visited in * this recursive configuration walk */ std::set inVisit; /** All the renamings applicable when instantiating objects */ std::list 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 &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(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: *
    *
  • 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)
  • *
  • Populating the ...Params object references to other * SimObjects by recursively descending into the trees formed * by SimObject references
  • *
  • Building the final SimObject and adding it to * objectsByName
  • *
  • If visit_children is true, recursively visit all this * object's children and build/find them too
  • *
* 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: *
    *
  • parameter values from the configuration file
  • *
  • port connection connection counts from the connection counts * indicated by the number of peer ports in the configuration * file
  • *
  • nulled (or vector<>::clear'ed) SimObject references for * SimObject-values parameters
  • *
* 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 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( 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(DrainManager *drain_manager); /** 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 ¶m_values); }; #endif // __SIM_CXX_MANAGER_HH__