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#include <cstdlib> 41#include <iostream> 42#include <list> 43 44#include "base/statistics.hh" 45#include "sc_gem5_control.hh" 46#include "sc_logger.hh" 47#include "sc_module.hh" 48#include "sim/cxx_config_ini.hh" 49#include "sim/cxx_manager.hh" 50#include "sim/debug.hh" 51#include "sim/init_signals.hh" 52#include "sim/stat_control.hh" 53#include "stats.hh" 54 55namespace Gem5SystemC 56{ 57 58/** This is the private side of Gem5Control */ 59class Gem5TopLevelModule : public Gem5SystemC::Module 60{ 61 friend class Gem5Control; 62 63 protected: 64 CxxConfigFileBase *config_file; 65 CxxConfigManager *root_manager; 66 Gem5SystemC::Logger logger; 67 68 /** Things to do at end_of_elaborate */ 69 std::list<void (*)()> endOfElaborationFuncs; 70 71 public: 72 SC_HAS_PROCESS(Gem5TopLevelModule); 73 74 Gem5TopLevelModule(sc_core::sc_module_name name, 75 const std::string &config_filename); 76 ~Gem5TopLevelModule(); 77 78 /** gem5 simulate. @todo for more interesting simulation control, 79 * this needs to be more complicated */ 80 void run(); 81 82 /* Register an action to happen at the end of elaboration */ 83 void registerEndOfElaboration(void (*func)()) 84 { 85 endOfElaborationFuncs.push_back(func); 86 } 87 88 /** SystemC startup */ 89 void end_of_elaboration(); 90}; 91 92Gem5System::Gem5System(CxxConfigManager *manager_, 93 const std::string &system_name, const std::string &instance_name) : 94 manager(manager_), 95 systemName(system_name), 96 instanceName(instance_name) 97{ 98 manager->addRenaming(CxxConfigManager::Renaming( 99 system_name, instance_name)); 100} 101 102Gem5System::~Gem5System() 103{ 104 delete manager; 105} 106 107void 108Gem5System::setParam(const std::string &object, 109 const std::string ¶m_name, const std::string ¶m_value) 110{ 111 manager->setParam(systemName + (object != "" ? "." + object : ""), 112 param_name, param_value); 113} 114 115void 116Gem5System::setParamVector(const std::string &object, 117 const std::string ¶m_name, 118 const std::vector<std::string> ¶m_values) 119{ 120 manager->setParamVector(systemName + 121 (object != "" ? "." + object : ""), param_name, param_values); 122} 123 124void 125Gem5System::instantiate() 126{ 127 try { 128 /* Make a new System */ 129 SimObject *obj = manager->findObject(systemName, true); 130 131 /* Add the System's objects to the list of managed 132 * objects for initialisation */ 133 manager->findTraversalOrder(systemName); 134 135 /* Bound ports *must* be internal to System */ 136 for (auto i = manager->objectsInOrder.begin(); 137 i != manager->objectsInOrder.end(); 138 ++ i) 139 { 140 manager->bindObjectPorts(*i); 141 } 142 143 /* gem5 startup sequence */ 144 manager->instantiate(false); 145 manager->initState(); 146 manager->startup(); 147 } catch (CxxConfigManager::Exception &e) { 148 fatal("Config problem in Gem5System: %s: %s", 149 e.name, e.message); 150 } 151} 152 153Gem5Control::Gem5Control(const std::string &config_filename) 154{ 155 module = new Gem5TopLevelModule("gem5", config_filename); 156} 157 158Gem5Control::~Gem5Control() 159{ } 160 161void 162Gem5Control::registerEndOfElaboration(void (*func)()) 163{ 164 module->registerEndOfElaboration(func); 165} 166 167void 168Gem5Control::setDebugFlag(const char *flag) 169{ 170 ::setDebugFlag(flag); 171} 172 173void 174Gem5Control::clearDebugFlag(const char *flag) 175{ 176 ::clearDebugFlag(flag); 177} 178 179void 180Gem5Control::setRemoteGDBPort(unsigned int port) 181{ 182 ::setRemoteGDBPort(port); 183} 184 185Gem5System * 186Gem5Control::makeSystem(const std::string &system_name, 187 const std::string &instance_name) 188{ 189 Gem5System *ret = new Gem5System( 190 new CxxConfigManager(*(module->config_file)), 191 system_name, instance_name); 192 193 return ret; 194} 195 196const std::string & 197Gem5Control::getVersion() const 198{ 199 return version; 200} 201 202void 203Gem5Control::setVersion(const std::string &new_version) 204{ 205 if (version != "") 206 fatal("Gem5Control::setVersion called for a second time"); 207 208 version = new_version; 209} 210 211Gem5TopLevelModule::Gem5TopLevelModule(sc_core::sc_module_name name, 212 const std::string &config_filename) : 213 Gem5SystemC::Module(name), 214 config_file(NULL), 215 root_manager(NULL) 216{ 217 SC_THREAD(run); 218 219 cxxConfigInit(); 220 221 /* Pass DPRINTF messages to SystemC */ 222 Trace::setDebugLogger(&logger); 223 224 /* @todo need this as an option */ 225 Gem5SystemC::setTickFrequency(); 226 227 /* Make a SystemC-synchronising event queue and install it as the 228 * sole top level gem5 EventQueue */ 229 Gem5SystemC::Module::setupEventQueues(*this); 230 231 if (sc_core::sc_get_time_resolution() != 232 sc_core::sc_time(1, sc_core::SC_PS)) 233 { 234 fatal("Time resolution must be set to 1 ps for gem5 to work"); 235 } 236 237 /* Enable keyboard interrupt, async I/O etc. */ 238 initSignals(); 239 240 /* Enable stats */ 241 Stats::initSimStats(); 242 Stats::registerHandlers(CxxConfig::statsReset, CxxConfig::statsDump); 243 244 Trace::enable(); 245 246 config_file = new CxxIniFile(); 247 248 if (!config_file->load(config_filename)) { 249 fatal("Gem5TopLevelModule: Can't open config file: %s", 250 config_filename); 251 } 252 253 root_manager = new CxxConfigManager(*config_file); 254 255 CxxConfig::statsEnable(); 256 257 /* Make the root object */ 258 try { 259 SimObject *root = root_manager->findObject("root", false); 260 261 /* Make sure we don't traverse into root's children */ 262 root_manager->objectsInOrder.push_back(root); 263 264 root_manager->instantiate(false); 265 root_manager->initState(); 266 root_manager->startup(); 267 } catch (CxxConfigManager::Exception &e) { 268 fatal("Config problem in Gem5TopLevelModule: %s: %s", 269 e.name, e.message); 270 } 271} 272 273Gem5TopLevelModule::~Gem5TopLevelModule() 274{ 275 delete config_file; 276 delete root_manager; 277} 278 279void 280Gem5TopLevelModule::run() 281{ 282 GlobalSimLoopExitEvent *exit_event = NULL; 283 284 exit_event = simulate(); 285 286 std::cerr << "Exit at tick " << curTick() 287 << ", cause: " << exit_event->getCause() << '\n'; 288 289 getEventQueue(0)->dump(); 290} 291 292void 293Gem5TopLevelModule::end_of_elaboration() 294{ 295 for (auto i = endOfElaborationFuncs.begin(); 296 i != endOfElaborationFuncs.end(); ++i) 297 { 298 (*i)(); 299 } 300} 301 302} 303 304Gem5SystemC::Gem5Control * 305makeGem5Control(const std::string &config_filename) 306{ 307 return new Gem5SystemC::Gem5Control(config_filename); 308} 309 310