| /* |
| * 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 |
| */ |
| |
| #include <cstdlib> |
| #include <iostream> |
| #include <list> |
| |
| #include "base/statistics.hh" |
| #include "sc_gem5_control.hh" |
| #include "sc_logger.hh" |
| #include "sc_module.hh" |
| #include "sim/cxx_config_ini.hh" |
| #include "sim/cxx_manager.hh" |
| #include "sim/debug.hh" |
| #include "sim/init_signals.hh" |
| #include "sim/stat_control.hh" |
| #include "stats.hh" |
| |
| namespace Gem5SystemC |
| { |
| |
| /** This is the private side of Gem5Control */ |
| class Gem5TopLevelModule : public Gem5SystemC::Module |
| { |
| friend class Gem5Control; |
| |
| protected: |
| CxxConfigFileBase *config_file; |
| CxxConfigManager *root_manager; |
| Gem5SystemC::Logger logger; |
| |
| /** Things to do at end_of_elaborate */ |
| std::list<void (*)()> endOfElaborationFuncs; |
| |
| public: |
| SC_HAS_PROCESS(Gem5TopLevelModule); |
| |
| Gem5TopLevelModule(sc_core::sc_module_name name, |
| const std::string &config_filename); |
| ~Gem5TopLevelModule(); |
| |
| /** gem5 simulate. @todo for more interesting simulation control, |
| * this needs to be more complicated */ |
| void run(); |
| |
| /* Register an action to happen at the end of elaboration */ |
| void registerEndOfElaboration(void (*func)()) |
| { |
| endOfElaborationFuncs.push_back(func); |
| } |
| |
| /** SystemC startup */ |
| void end_of_elaboration(); |
| }; |
| |
| Gem5System::Gem5System(CxxConfigManager *manager_, |
| const std::string &system_name, const std::string &instance_name) : |
| manager(manager_), |
| systemName(system_name), |
| instanceName(instance_name) |
| { |
| manager->addRenaming(CxxConfigManager::Renaming( |
| system_name, instance_name)); |
| } |
| |
| Gem5System::~Gem5System() |
| { |
| delete manager; |
| } |
| |
| void |
| Gem5System::setParam(const std::string &object, |
| const std::string ¶m_name, const std::string ¶m_value) |
| { |
| manager->setParam(systemName + (object != "" ? "." + object : ""), |
| param_name, param_value); |
| } |
| |
| void |
| Gem5System::setParamVector(const std::string &object, |
| const std::string ¶m_name, |
| const std::vector<std::string> ¶m_values) |
| { |
| manager->setParamVector(systemName + |
| (object != "" ? "." + object : ""), param_name, param_values); |
| } |
| |
| void |
| Gem5System::instantiate() |
| { |
| try { |
| /* Make a new System */ |
| SimObject *obj = manager->findObject(systemName, true); |
| |
| /* Add the System's objects to the list of managed |
| * objects for initialisation */ |
| manager->findTraversalOrder(systemName); |
| |
| /* Bound ports *must* be internal to System */ |
| for (auto i = manager->objectsInOrder.begin(); |
| i != manager->objectsInOrder.end(); |
| ++ i) |
| { |
| manager->bindObjectPorts(*i); |
| } |
| |
| /* gem5 startup sequence */ |
| manager->instantiate(false); |
| manager->initState(); |
| manager->startup(); |
| } catch (CxxConfigManager::Exception &e) { |
| fatal("Config problem in Gem5System: %s: %s", |
| e.name, e.message); |
| } |
| } |
| |
| Gem5Control::Gem5Control(const std::string &config_filename) |
| { |
| module = new Gem5TopLevelModule("gem5", config_filename); |
| } |
| |
| Gem5Control::~Gem5Control() |
| { } |
| |
| void |
| Gem5Control::registerEndOfElaboration(void (*func)()) |
| { |
| module->registerEndOfElaboration(func); |
| } |
| |
| void |
| Gem5Control::setDebugFlag(const char *flag) |
| { |
| ::setDebugFlag(flag); |
| } |
| |
| void |
| Gem5Control::clearDebugFlag(const char *flag) |
| { |
| ::clearDebugFlag(flag); |
| } |
| |
| void |
| Gem5Control::setRemoteGDBPort(unsigned int port) |
| { |
| ::setRemoteGDBPort(port); |
| } |
| |
| Gem5System * |
| Gem5Control::makeSystem(const std::string &system_name, |
| const std::string &instance_name) |
| { |
| Gem5System *ret = new Gem5System( |
| new CxxConfigManager(*(module->config_file)), |
| system_name, instance_name); |
| |
| return ret; |
| } |
| |
| const std::string & |
| Gem5Control::getVersion() const |
| { |
| return version; |
| } |
| |
| void |
| Gem5Control::setVersion(const std::string &new_version) |
| { |
| if (version != "") |
| fatal("Gem5Control::setVersion called for a second time"); |
| |
| version = new_version; |
| } |
| |
| Gem5TopLevelModule::Gem5TopLevelModule(sc_core::sc_module_name name, |
| const std::string &config_filename) : |
| Gem5SystemC::Module(name), |
| config_file(NULL), |
| root_manager(NULL) |
| { |
| SC_THREAD(run); |
| |
| cxxConfigInit(); |
| |
| /* Pass DPRINTF messages to SystemC */ |
| Trace::setDebugLogger(&logger); |
| |
| /* @todo need this as an option */ |
| Gem5SystemC::setTickFrequency(); |
| |
| /* Make a SystemC-synchronising event queue and install it as the |
| * sole top level gem5 EventQueue */ |
| Gem5SystemC::Module::setupEventQueues(*this); |
| |
| if (sc_core::sc_get_time_resolution() != |
| sc_core::sc_time(1, sc_core::SC_PS)) |
| { |
| fatal("Time resolution must be set to 1 ps for gem5 to work"); |
| } |
| |
| /* Enable keyboard interrupt, async I/O etc. */ |
| initSignals(); |
| |
| /* Enable stats */ |
| Stats::initSimStats(); |
| Stats::registerHandlers(CxxConfig::statsReset, CxxConfig::statsDump); |
| |
| Trace::enable(); |
| |
| config_file = new CxxIniFile(); |
| |
| if (!config_file->load(config_filename)) { |
| fatal("Gem5TopLevelModule: Can't open config file: %s", |
| config_filename); |
| } |
| |
| root_manager = new CxxConfigManager(*config_file); |
| |
| CxxConfig::statsEnable(); |
| |
| /* Make the root object */ |
| try { |
| SimObject *root = root_manager->findObject("root", false); |
| |
| /* Make sure we don't traverse into root's children */ |
| root_manager->objectsInOrder.push_back(root); |
| |
| root_manager->instantiate(false); |
| root_manager->initState(); |
| root_manager->startup(); |
| } catch (CxxConfigManager::Exception &e) { |
| fatal("Config problem in Gem5TopLevelModule: %s: %s", |
| e.name, e.message); |
| } |
| } |
| |
| Gem5TopLevelModule::~Gem5TopLevelModule() |
| { |
| delete config_file; |
| delete root_manager; |
| } |
| |
| void |
| Gem5TopLevelModule::run() |
| { |
| GlobalSimLoopExitEvent *exit_event = NULL; |
| |
| exit_event = simulate(); |
| |
| std::cerr << "Exit at tick " << curTick() |
| << ", cause: " << exit_event->getCause() << '\n'; |
| |
| getEventQueue(0)->dump(); |
| } |
| |
| void |
| Gem5TopLevelModule::end_of_elaboration() |
| { |
| for (auto i = endOfElaborationFuncs.begin(); |
| i != endOfElaborationFuncs.end(); ++i) |
| { |
| (*i)(); |
| } |
| } |
| |
| } |
| |
| Gem5SystemC::Gem5Control * |
| makeGem5Control(const std::string &config_filename) |
| { |
| return new Gem5SystemC::Gem5Control(config_filename); |
| } |
| |