1/* 2 * Copyright (c) 2014 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Andrew Bardsley 38 */ 39 40/** 41 * @file 42 * 43 * C++-only configuration and instantiation support. This allows a 44 * config to be read back from a config file and instantiated without 45 * Python. Useful if you want to embed gem5 within a larger system 46 * without carrying the integration cost of the fully-featured 47 * configuration system. 48 * 49 * This file contains the config loading/storing manager class 50 */ 51 52#ifndef __SIM_CXX_MANAGER_HH__ 53#define __SIM_CXX_MANAGER_HH__ 54 55#include <list> 56#include <map> 57#include <set> 58#include <string> 59#include <vector> 60 61#include "base/cprintf.hh" 62#include "sim/cxx_config.hh" 63 64class CheckpointIn; 65 66/** This class allows a config file to be read into gem5 (generating the 67 * appropriate SimObjects) from C++ */ 68class CxxConfigManager 69{ 70 protected: 71 /** Configuration file being read */ 72 CxxConfigFileBase &configFile; 73 74 /** Flags to pass to affect param setting */ 75 CxxConfigParams::Flags flags; 76 77 public: 78 /** Exception for instantiate/post-instantiate errors */ 79 class Exception : public std::exception 80 { 81 public: 82 std::string name; 83 std::string message; 84 85 public: 86 Exception(const std::string &name_, const std::string &message_) : 87 name(name_), message(message_) 88 { } 89 90 const char *what() const throw() { return message.c_str(); } 91 92 ~Exception() throw() { } 93 }; 94 95 /** Name substitution when instantiating any object whose name starts 96 * with fromPrefix. Where both renamed and unrenamed names are used 97 * in the code, `object' as part of a name usually refers to the 98 * unrenamed name (the name as it appears in the config file) and 99 * `instance' is part of the renamed name */ 100 struct Renaming 101 { 102 std::string fromPrefix; 103 std::string toPrefix; 104 105 Renaming(const std::string &from_prefix, 106 const std::string &to_prefix) : 107 fromPrefix(from_prefix), 108 toPrefix(to_prefix) 109 { } 110 }; 111 112 public: 113 /** SimObject indexed by name */ 114 std::map<std::string, SimObject *> objectsByName; 115 116 /** ...Params objects created by this manager */ 117 std::map<std::string, CxxConfigParams *> objectParamsByName; 118 119 /** SimObjects in order. This is populated by findAllObjects */ 120 std::list<SimObject *> objectsInOrder; 121 122 protected: 123 /** While configuring, inVisit contains names of SimObjects visited in 124 * this recursive configuration walk */ 125 std::set<std::string> inVisit; 126 127 /** All the renamings applicable when instantiating objects */ 128 std::list<Renaming> renamings; 129 130 /** Bind a single connection between two objects' ports */ 131 void bindPort(SimObject *masterObject, const std::string &masterPort, 132 PortID masterPortIndex, SimObject *slaveObject, 133 const std::string &slavePort, PortID slavePortIndex); 134 135 /** Bind a single (possibly vectored) master port to peers from the 136 * unparsed list peers with elements in the .ini connection format: 137 * path(.path)*.port[index] */ 138 void bindMasterPort(SimObject *object, 139 const CxxConfigDirectoryEntry::PortDesc &port, 140 const std::vector<std::string> &peers); 141 142 /** Apply the first matching renaming in renamings to the given name */ 143 std::string rename(const std::string &from_name); 144 145 /** Apply the first matching renaming in reverse (toPrefix -> fromPrefix 146 * for the given name */ 147 std::string unRename(const std::string &to_name); 148 149 protected: 150 /** Bind the ports of all the objects in objectInOrder order. 151 * Also */ 152 void bindAllPorts(); 153 154 /** Class for resolving SimObject names to SimObjects usable by the 155 * checkpoint restore mechanism */ 156 class SimObjectResolver : public ::SimObjectResolver 157 { 158 protected: 159 CxxConfigManager &configManager; 160 161 public: 162 SimObjectResolver(CxxConfigManager &configManager_) : 163 configManager(configManager_) 164 { } 165 166 SimObject *resolveSimObject(const std::string &name) 167 { return &(configManager.getObject<SimObject>(name)); } 168 }; 169 170 /** Singleton instance of SimObjectResolver */ 171 SimObjectResolver simObjectResolver; 172 173 public: 174 CxxConfigManager(CxxConfigFileBase &configFile_); 175 176 /** Find the type field for a named object and return both the 177 * name of the type to object_type and the object's directory 178 * entry as the return value */ 179 const CxxConfigDirectoryEntry &findObjectType( 180 const std::string &object_name, std::string &object_type); 181 182 /** Add a name prefix renaming to those currently applied. Call this 183 * before trying to instantiate any object as the name mappings are 184 * not applied to the config tree read from the config file but are 185 * applied while processing instantiations */ 186 void addRenaming(const Renaming &renaming); 187 188 public: 189 /** Bind the ports of a single SimObject */ 190 void bindObjectPorts(SimObject *object); 191 192 /** Walk the configuration starting with object object_name and fill 193 * in all the elements of this object on the way. This involves: 194 * <ul> 195 * <li>Calling findObjectParams to make the ...Params object 196 * If findObjectParams has already been called for this object, 197 * the ...Params object generated by that called (stored in 198 * (objectParamsByName[object_name] will be used)</li> 199 * <li>Populating the ...Params object references to other 200 * SimObjects by recursively descending into the trees formed 201 * by SimObject references</li> 202 * <li>Building the final SimObject and adding it to 203 * objectsByName</li> 204 * <li>If visit_children is true, recursively visit all this 205 * object's children and build/find them too</li> 206 * </ul> 207 * After the first call, this function will return 208 * objectsByName[object_name] */ 209 SimObject *findObject(const std::string &object_name, 210 bool visit_children = false); 211 212 /** Find the parameters for the named object. Returns NULL if the 213 * object isn't in the configuration. For the first call with a 214 * particular object name, a new CxxConfigParams descended object 215 * is made with the configuration file contents for this object. 216 * This involves populating that ...Params object with: 217 * <ul> 218 * <li>parameter values from the configuration file</li> 219 * <li>port connection connection counts from the connection counts 220 * indicated by the number of peer ports in the configuration 221 * file</li> 222 * <li>nulled (or vector<>::clear'ed) SimObject references for 223 * SimObject-values parameters</li> 224 * </ul> 225 * The ...Params object is then added to objectParamsByName 226 * After the first call, this function will return 227 * objectParamsByName[object_name] */ 228 CxxConfigParams *findObjectParams(const std::string &object_name); 229 230 /** Populate objectsInOrder with a preorder, depth first traversal from 231 * the given object name down through all its children */ 232 void findTraversalOrder(const std::string &object_name); 233 234 /** Find an object from objectsByName with a type-checking cast. 235 * This function is provided for manipulating objects after 236 * instantiate as it assumes the named object exists. */ 237 template<typename SimObjectType> 238 SimObjectType & 239 getObject(const std::string &object_name) 240 { 241 if (objectsByName.find(object_name) == objectsByName.end()) { 242 throw Exception("", csprintf("No sim object named: %s", 243 object_name)); 244 } 245 246 SimObjectType *object = dynamic_cast<SimObjectType *>( 247 objectsByName[object_name]); 248 249 if (!object) { 250 throw Exception("", csprintf("Sim object: %s has the wrong" 251 " type", object_name)); 252 } 253 254 return *object; 255 } 256 257 /** Perform mem_func on each SimObject */ 258 void forEachObject(void (SimObject::*mem_func)()); 259 260 /** Find all objects by iterating over the object names in the config 261 * file with findObject. Also populate the traversal order */ 262 void findAllObjects(); 263 264 /** Parse a port string of the form 'path(.path)*.port[index]' into 265 * path, port and index */ 266 static void parsePort(const std::string &inp, 267 std::string &path, std::string &port, unsigned int &index); 268 269 /** Build all objects (if build_all is true, otherwise objects must 270 * have been individually findObject-ed and added to the traversal 271 * order) and perform all the configuration specific actions up to, 272 * but not including initState. 273 * 274 * If you want to set some parameters before completing instantiation, 275 * call findObjectParams on the objects you want to modify, then call 276 * instantiate */ 277 void instantiate(bool build_all = true); 278 279 /** Call initState on all objects */ 280 void initState(); 281 282 /** Call startup on all objects */ 283 void startup(); 284 285 /** Drain all objects */ 286 unsigned int drain(); 287 288 /** Resume from drain */ 289 void drainResume(); 290 291 /** Serialize (checkpoint) all objects to the given stream */ 292 void serialize(std::ostream &os); 293 294 /** Load all objects' state from the given Checkpoint */ 295 void loadState(CheckpointIn &checkpoint); 296 297 /** Delete all objects and clear objectsByName and objectsByOrder */ 298 void deleteObjects(); 299 300 /** Get the resolver used to map SimObject names to SimObjects for 301 * checkpoint restore */ 302 SimObjectResolver &getSimObjectResolver() { return simObjectResolver; } 303 304 /** Convenience functions for calling set... member functions on a 305 * CxxConfigParams for an object. These functions throw Exception 306 * rather than return a bool on failure */ 307 void setParam(const std::string &object_name, 308 const std::string ¶m_name, const std::string ¶m_value); 309 void setParamVector(const std::string &object_name, 310 const std::string ¶m_name, 311 const std::vector<std::string> ¶m_values); 312}; 313 314#endif // __SIM_CXX_MANAGER_HH__ 315