diff options
-rw-r--r-- | util/systemc/Makefile | 69 | ||||
-rw-r--r-- | util/systemc/README | 59 | ||||
-rw-r--r-- | util/systemc/main.cc | 379 | ||||
-rw-r--r-- | util/systemc/sc_gem5_control.cc | 248 | ||||
-rw-r--r-- | util/systemc/sc_gem5_control.hh | 154 | ||||
-rw-r--r-- | util/systemc/sc_logger.cc | 152 | ||||
-rw-r--r-- | util/systemc/sc_logger.hh | 80 | ||||
-rw-r--r-- | util/systemc/sc_module.cc | 231 | ||||
-rw-r--r-- | util/systemc/sc_module.hh | 152 | ||||
-rw-r--r-- | util/systemc/stats.cc | 115 | ||||
-rw-r--r-- | util/systemc/stats.hh | 61 |
11 files changed, 1700 insertions, 0 deletions
diff --git a/util/systemc/Makefile b/util/systemc/Makefile new file mode 100644 index 000000000..da9b28866 --- /dev/null +++ b/util/systemc/Makefile @@ -0,0 +1,69 @@ +# Copyright (c) 2012-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 + +ARCH = ARM +VARIANT = opt + +SYSTEMC_INC = ./systemc/include +SYSTEMC_LIB = ./systemc/lib-linux64 + +CXXFLAGS = -I../../build/$(ARCH) -L../../build/$(ARCH) +CXXFLAGS += -I$(SYSTEMC_INC) -L$(SYSTEMC_LIB) +CXXFLAGS += -std=c++0x +CXXFLAGS += -g +LIBS = -lgem5_$(VARIANT) -lsystemc + +ALL = gem5.$(VARIANT).sc + +all: $(ALL) + +.cc.o: + $(CXX) $(CXXFLAGS) -c -o $@ $< + +sc_gem5_control.o: sc_gem5_control.cc sc_gem5_control.hh +sc_logger.o: sc_logger.cc sc_logger.hh +sc_module.o: sc_module.cc sc_module.hh +stats.o: stats.cc stats.hh +main.o: main.cc sc_logger.hh sc_module.hh stats.hh + +gem5.$(VARIANT).sc: main.o stats.o \ + sc_gem5_control.o sc_logger.o sc_module.o + $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) + +clean: + $(RM) $(ALL) + $(RM) -r m5out diff --git a/util/systemc/README b/util/systemc/README new file mode 100644 index 000000000..a886e0220 --- /dev/null +++ b/util/systemc/README @@ -0,0 +1,59 @@ +This directory contains a demo of C++ configuration of gem5. The intention +is to provide a mechanism to allow pre-generated config.ini files generated +by Python-based gem5 to be reloaded in library-base versions of gem5 +embedded in other systems using C++ calls for simulation control. + +This directory contain a demo of hosting a C++ configured version of gem5 +onto SystemC's event loop. The hosting is achieved by replacing 'simulate' +with a SystemC object which implements an event loop using SystemC scheduler +mechanisms. + +The sc_... files here should probably be hosted in a diferent directory and +buildable as a library. + +Files: + + main.cc -- demonstration top level + sc_logger.{cc,hh} -- rehosting of DPRINTF onto SC_REPORT + sc_module.{cc,hh} -- SystemC simulation loop base class + sc_gem5_control.{cc,hh} -- Alternative extra wrapping to allow gem5 + Systems to be instantiated as single + sc_module objects. + stats.{cc,hh} -- Stats dumping (copied from util/cxx_config) + +Read main.cc for more details of the implementation and sc_... files for + +To build: + +First build gem5 as a library with cxx-config support and (optionally) +without python. Also build a normal gem5 (cxx-config not needed, Python +needed): + +> cd ../.. +> scons build/ARM/gem5.opt +> scons --with-cxx-config --without-python build/ARM/libgem5_opt.so +> cd util/cxx_config + +Then edit Makefile to set the paths for SystemC and run make + +> make + +Make a config file for the C++-configured gem5 using normal gem5 + +> ../../build/ARM/gem5.opt ../../configs/example/se.py -c \ +> ../../tests/test-progs/hello/bin/arm/linux/hello + +The binary 'gem5.opt.cxx' can now be used to load in the generated config +file from the previous normal gem5 run. + +Try: + +> ./gem5.opt.cxx m5out/config.ini + +This should print: + +> Hello world! + +The .ini file can also be read by the Python .ini file reader example: + +> ../../build/ARM/gem5.opt ../../configs/example/read_ini.py m5out/config.ini diff --git a/util/systemc/main.cc b/util/systemc/main.cc new file mode 100644 index 000000000..6ffaeb6da --- /dev/null +++ b/util/systemc/main.cc @@ -0,0 +1,379 @@ +/* + * 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 + * + * Example top level file for SystemC integration with C++-only + * instantiation. + * + * Build with something like: + * + * scons --without-python build/ARM/libgem5_opt.so + * + * g++ -std=c++0x -Ibuild/ARM -Isrc -DTRACING_ON \ + * -o gem5cxx.opt -Lbuild/ARM -lgem5_opt \ + * src/sim/sc_main_cxx.cc src/sim/cxx_stats.cc \ + * src/sim/sc_module.cc src/sim/sc_logger.cc + */ + +#include <cstdlib> +#include <iostream> +#include <sstream> +#include <systemc> + +#include "base/statistics.hh" +#include "base/str.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "sim/cxx_config_ini.hh" +#include "sim/cxx_manager.hh" +#include "sim/init_signals.hh" +#include "sim/serialize.hh" +#include "sim/simulate.hh" +#include "sim/stat_control.hh" +#include "sim/system.hh" +#include "sc_logger.hh" +#include "sc_module.hh" +#include "stats.hh" + +void +usage(const std::string &prog_name) +{ + std::cerr << "Usage: " << prog_name << ( + " <config_file.ini> [ <option> ]\n\n" + "OPTIONS:\n" + " -p <object> <param> <value> -- set a parameter\n" + " -v <object> <param> <values> -- set a vector parameter from" + " a comma\n" + " separated values string\n" + " -d <flag> -- set a debug flag (-<flag>\n" + " clear a flag)\n" + " -s <dir> <ticks> -- save checkpoint to dir after" + " the given\n" + " number of ticks\n" + " -r <dir> -- restore checkpoint to dir\n" + " -c <from> <to> <ticks> -- switch from cpu 'from' to cpu" + " 'to' after\n" + " the given number of ticks\n" + "\n" + ); + + std::exit(EXIT_FAILURE); +} + +class SimControl : public Gem5SystemC::Module +{ + protected: + int argc; + char **argv; + CxxConfigManager *config_manager; + Gem5SystemC::Logger logger; + + bool checkpoint_restore; + bool checkpoint_save; + bool switch_cpus; + std::string checkpoint_dir; + std::string from_cpu; + std::string to_cpu; + Tick pre_run_time; + Tick pre_switch_time; + + public: + SC_HAS_PROCESS(SimControl); + + SimControl(sc_core::sc_module_name name, int argc_, char **argv_); + + void before_end_of_elaboration(); + + void run(); +}; + +SimControl::SimControl(sc_core::sc_module_name name, + int argc_, char **argv_) : + Gem5SystemC::Module(name), + argc(argc_), + argv(argv_) +{ + SC_THREAD(run); + + std::string prog_name(argv[0]); + unsigned int arg_ptr = 1; + + if (argc == 1) + usage(prog_name); + + cxxConfigInit(); + + Trace::setDebugLogger(&logger); + + Gem5SystemC::setTickFrequency(); + sc_core::sc_set_time_resolution(1, sc_core::SC_PS); + + Gem5SystemC::Module::setupEventQueues(*this); + initSignals(); + + Stats::initSimStats(); + Stats::registerHandlers(CxxConfig::statsReset, CxxConfig::statsDump); + + Trace::enabled = true; + setDebugFlag("Terminal"); + + checkpoint_restore = false; + checkpoint_save = false; + switch_cpus = false; + checkpoint_dir = ""; + from_cpu = ""; + to_cpu = ""; + pre_run_time = 1000000; + pre_switch_time = 1000000; + + const std::string config_file(argv[arg_ptr]); + + CxxConfigFileBase *conf = new CxxIniFile(); + + if (!conf->load(config_file.c_str())) { + std::cerr << "Can't open config file: " << config_file << '\n'; + std::exit(EXIT_FAILURE); + } + arg_ptr++; + + config_manager = new CxxConfigManager(*conf); + + try { + while (arg_ptr < argc) { + std::string option(argv[arg_ptr]); + arg_ptr++; + unsigned num_args = argc - arg_ptr; + + if (option == "-p") { + if (num_args < 3) + usage(prog_name); + config_manager->setParam(argv[arg_ptr], argv[arg_ptr + 1], + argv[arg_ptr + 2]); + arg_ptr += 3; + } else if (option == "-v") { + std::vector<std::string> values; + + if (num_args < 3) + usage(prog_name); + tokenize(values, argv[2], ','); + config_manager->setParamVector(argv[arg_ptr], + argv[arg_ptr], values); + arg_ptr += 3; + } else if (option == "-d") { + if (num_args < 1) + usage(prog_name); + if (argv[arg_ptr][0] == '-') + clearDebugFlag(argv[arg_ptr] + 1); + else + setDebugFlag(argv[arg_ptr]); + arg_ptr++; + } else if (option == "-r") { + if (num_args < 1) + usage(prog_name); + checkpoint_dir = argv[arg_ptr]; + checkpoint_restore = true; + arg_ptr++; + } else if (option == "-s") { + if (num_args < 2) + usage(prog_name); + checkpoint_dir = argv[arg_ptr]; + std::istringstream(argv[arg_ptr + 1]) >> pre_run_time; + checkpoint_save = true; + arg_ptr += 2; + } else if (option == "-c") { + if (num_args < 3) + usage(prog_name); + switch_cpus = true; + from_cpu = argv[arg_ptr]; + to_cpu = argv[arg_ptr + 1]; + std::istringstream(argv[arg_ptr + 2]) >> pre_switch_time; + arg_ptr += 3; + } else { + usage(prog_name); + } + } + } catch (CxxConfigManager::Exception &e) { + std::cerr << e.name << ": " << e.message << "\n"; + std::exit(EXIT_FAILURE); + } + + CxxConfig::statsEnable(); + getEventQueue(0)->dump(); + + try { + config_manager->instantiate(); + } catch (CxxConfigManager::Exception &e) { + std::cerr << "Config problem in sim object " << e.name + << ": " << e.message << "\n"; + + std::exit(EXIT_FAILURE); + } +} + +void SimControl::before_end_of_elaboration() +{ + if (!checkpoint_restore) { + try { + config_manager->initState(); + config_manager->startup(); + } catch (CxxConfigManager::Exception &e) { + std::cerr << "Config problem in sim object " << e.name + << ": " << e.message << "\n"; + + std::exit(EXIT_FAILURE); + } + } +} + +void SimControl::run() +{ + GlobalSimLoopExitEvent *exit_event = NULL; + + if (checkpoint_save) { + exit_event = simulate(pre_run_time); + + DrainManager drain_manager; + + unsigned int drain_count = 1; + do { + drain_count = config_manager->drain(&drain_manager); + + std::cerr << "Draining " << drain_count << '\n'; + + if (drain_count > 0) { + drain_manager.setCount(drain_count); + exit_event = simulate(); + } + } while (drain_count > 0); + + std::cerr << "Simulation stop at tick " << curTick() + << ", cause: " << exit_event->getCause() << '\n'; + + std::cerr << "Checkpointing\n"; + + /* FIXME, this should really be serialising just for + * config_manager rather than using serializeAll's ugly + * SimObject static object list */ + Serializable::serializeAll(checkpoint_dir); + + std::cerr << "Completed checkpoint\n"; + + config_manager->drainResume(); + } + + if (checkpoint_restore) { + std::cerr << "Restoring checkpoint\n"; + + Checkpoint *checkpoint = new Checkpoint(checkpoint_dir, + config_manager->getSimObjectResolver()); + + Serializable::unserializeGlobals(checkpoint); + + /* gem5 time can have changed, so lets wait until SystemC + * catches up */ + Tick systemc_time = sc_core::sc_time_stamp().value(); + if (curTick() > systemc_time) { + Tick wait_period = curTick() - systemc_time; + + std::cerr << "Waiting for " << wait_period << "ps for" + " SystemC to catch up to gem5\n"; + wait(sc_core::sc_time(wait_period, sc_core::SC_PS)); + } + + config_manager->loadState(checkpoint); + + config_manager->drainResume(); + + std::cerr << "Restored from checkpoint\n"; + } + + if (switch_cpus) { + exit_event = simulate(pre_switch_time); + + std::cerr << "Switching CPU\n"; + + /* Assume the system is called system */ + System &system = config_manager->getObject<System>("system"); + BaseCPU &old_cpu = config_manager->getObject<BaseCPU>(from_cpu); + BaseCPU &new_cpu = config_manager->getObject<BaseCPU>(to_cpu); + + DrainManager drain_manager; + unsigned int drain_count = 1; + do { + drain_count = config_manager->drain(&drain_manager); + + std::cerr << "Draining " << drain_count << '\n'; + + if (drain_count > 0) { + drain_manager.setCount(drain_count); + exit_event = simulate(); + } + } while (drain_count > 0); + + old_cpu.switchOut(); + system.setMemoryMode(Enums::timing); + new_cpu.takeOverFrom(&old_cpu); + config_manager->drainResume(); + + std::cerr << "Switched CPU\n"; + } + + exit_event = simulate(); + + std::cerr << "Exit at tick " << curTick() + << ", cause: " << exit_event->getCause() << '\n'; + + getEventQueue(0)->dump(); + +#if TRY_CLEAN_DELETE + config_manager->deleteObjects(); +#endif +} + +int +sc_main(int argc, char **argv) +{ + SimControl sim_control("gem5", argc, argv); + + sc_core::sc_start(); + + return EXIT_SUCCESS; +} diff --git a/util/systemc/sc_gem5_control.cc b/util/systemc/sc_gem5_control.cc new file mode 100644 index 000000000..09a1be995 --- /dev/null +++ b/util/systemc/sc_gem5_control.cc @@ -0,0 +1,248 @@ +/* + * 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 "base/statistics.hh" +#include "sim/cxx_config_ini.hh" +#include "sim/cxx_manager.hh" +#include "sim/init_signals.hh" +#include "sim/stat_control.hh" +#include "sc_gem5_control.hh" +#include "sc_logger.hh" +#include "sc_module.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; + + 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(); +}; + +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::setDebugFlag(const char *flag) +{ + ::setDebugFlag(flag); +} + +void +Gem5Control::clearDebugFlag(const char *flag) +{ + ::clearDebugFlag(flag); +} + +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; +} + +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(); + sc_core::sc_set_time_resolution(1, sc_core::SC_PS); + + /* Make a SystemC-synchronising event queue and install it as the + * sole top level gem5 EventQueue */ + Gem5SystemC::Module::setupEventQueues(*this); + + /* Enable keyboard interrupt, async I/O etc. */ + initSignals(); + + /* Enable stats */ + Stats::initSimStats(); + Stats::registerHandlers(CxxConfig::statsReset, CxxConfig::statsDump); + + Trace::enabled = true; + + 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(); +} + +} + +Gem5SystemC::Gem5Control *makeGem5Control(const std::string &config_filename) +{ + return new Gem5SystemC::Gem5Control(config_filename); +} + diff --git a/util/systemc/sc_gem5_control.hh b/util/systemc/sc_gem5_control.hh new file mode 100644 index 000000000..e08ec3cc8 --- /dev/null +++ b/util/systemc/sc_gem5_control.hh @@ -0,0 +1,154 @@ +/* + * 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 + * + * Top level definitions for exporting gem5 across a dlopen interface. + * + * Gem5Control should be instantiated once to build the gem5 root. + * Systems from that root's config file can then be instantiated as + * Gem5System's using Gem5Control::makeSystem. + * + * Gem5Control contains a Gem5TopLevelModule which is a SystemC + * module providing the gem5 `simulate' function as its sole + * thread action. + */ + +#ifndef __SIM_SC_GEM5_CONTROL_HH__ +#define __SIM_SC_GEM5_CONTROL_HH__ + +#include <string> +#include <vector> + +class CxxConfigManager; + +namespace Gem5SystemC +{ + +class Gem5TopLevelModule; +class Gem5Control; + +/** Gem5System's wrap CxxConfigManager's instantiating a gem5 System + * object (and its children). New Gem5Systems are created by + * Gem5Control::makeSystem. A new system can have its parameters + * tweaked using setParam{,Vector} before being instantiated using + * Gem5System::instantiate. After instantiation, any external ports + * declared by the system should be visible in SystemC. + * + * It is recommended that a SystemC wrapper sc_module is declared to + * own each Gem5System with the call to Gem5System::instantiate being + * made in that wrapper's constructor + * + * Note that *every* `normal' member function in this class *must* + * be virtual to ensure that references to the functions go through + * the pointer acquired using makeSystem and not looked up as + * name-mangled symbols + * + * */ +class Gem5System +{ + private: + /** Config management for *just* this system's objects (notably + * excluding root */ + CxxConfigManager *manager; + + /** The config file prototype for the system */ + std::string systemName; + + /** The instantiated (in gem5) name of the system */ + std::string instanceName; + + public: + /** A constructor only used by Gem5Control */ + Gem5System(CxxConfigManager *manager_, + const std::string &system_name, const std::string &instance_name); + + virtual ~Gem5System(); + + /** Parameter setting functions callable before instantiate */ + virtual void setParam(const std::string &object, + const std::string ¶m_name, const std::string ¶m_value); + + virtual void setParamVector(const std::string &system_name, + const std::string ¶m_name, + const std::vector<std::string> ¶m_values); + + /** Build the system's gem5 infrastructure, bind its ports (note + * that all ports *must* be internal to the system), init and + * SimObject::startup the system */ + virtual void instantiate(); +}; + +/** Singleton class containing gem5 simulation control. + * + * Note that *every* `normal' member function in this class *must* + * be virtual to ensure that references to the functions go through + * the pointer acquired using makeGem5Control and not looked up as + * name-mangled symbols + */ +class Gem5Control +{ + private: + /** Private SystemC module containing top level simulation control */ + Gem5TopLevelModule *module; + + public: + Gem5Control(const std::string &config_filename); + + virtual ~Gem5Control(); + + /** Set/clear a gem5 debug flag */ + virtual void setDebugFlag(const char *flag); + virtual void clearDebugFlag(const char *flag); + + /** Make a System from the config file description for system + * system_name and call it instance_name in gem5 */ + virtual Gem5System *makeSystem(const std::string &system_name, + const std::string &top_instance); +}; + +} + +/** Instantiate a Gem5Control. This can be called using dlopen/dlsym + * to kick-start gem5 */ +extern "C" Gem5SystemC::Gem5Control *makeGem5Control( + const std::string &config_filename); + +#endif // __SIM_SC_GEM5_CONTROL_HH__ diff --git a/util/systemc/sc_logger.cc b/util/systemc/sc_logger.cc new file mode 100644 index 000000000..8f8abaeb6 --- /dev/null +++ b/util/systemc/sc_logger.cc @@ -0,0 +1,152 @@ +/* + * 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 + * + * A logger to allow SystemC to capture DPRINTF messages (and similar things) + * using sc_report + */ + +#include <cstdlib> +#include <cstring> +#include <sstream> + +#include "sc_logger.hh" + +namespace Gem5SystemC +{ + +/** Class to act as a streambuf for std::ostream which cuts output strings + * into lines and offers them to a logger */ +class CuttingStreambuf : public std::streambuf +{ + public: + /** Accumulate line so far */ + std::ostringstream line; + + /** Logger to send complete lines to */ + Trace::Logger *logger; + + CuttingStreambuf(Trace::Logger *logger_) : logger(logger_) + { } + + /** Accumulate to line up to \n and then emit */ + int overflow(int i); + int sync(); + + /** Push a line out to the logger */ + void outputLine(); + + ~CuttingStreambuf(); +}; + +void CuttingStreambuf::outputLine() +{ + logger->logMessage((Tick)-1, "gem5", line.str()); + line.clear(); + line.str(""); +} + +/** This is pretty much the least efficient way of doing this, but it has the + * advantage of having very few corners to get wrong. + * + * A newly allocated streambuf will have no buffer to serve to its [oi]stream. + * It will, therefore, call overflow for every character it wants to insert + * into the output stream. Those characters are captured one by one here and + * added to this->line. */ +int +CuttingStreambuf::overflow(int chr) +{ + if (chr == '\n') + outputLine(); + else if (chr != EOF) + line << (char) chr; + + /* Always succeeds */ + return 0; +} + +int +CuttingStreambuf::sync() +{ + if (!line.str().empty()) + outputLine(); + + /* Always succeeds */ + return 0; +} + +CuttingStreambuf::~CuttingStreambuf() +{ + sync(); +} + +Logger::Logger() : + cuttingStreambuf(new CuttingStreambuf(this)), + stream(cuttingStreambuf) +{ +} + +Logger::~Logger() +{ + stream.flush(); + delete cuttingStreambuf; +} + +/** Log a single message as a single sc_report call */ +void +Logger::logMessage(Tick when, const std::string &name, + const std::string &message) +{ + /* Need to chop the newline off the message */ + std::string message_without_nl = message; + message_without_nl.erase( + message_without_nl.find_last_not_of(" \n\r") + 1); + + SC_REPORT_INFO(name.c_str(), message_without_nl.c_str()); +} + +std::ostream & +Logger::getOstream() +{ + return stream; +} + +} diff --git a/util/systemc/sc_logger.hh b/util/systemc/sc_logger.hh new file mode 100644 index 000000000..4143f8bb8 --- /dev/null +++ b/util/systemc/sc_logger.hh @@ -0,0 +1,80 @@ +/* + * 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 + * + * A logger to allow SystemC to capture DPRINTF messages (and similar things) + * using sc_report + */ + +#ifndef __SIM_SC_LOGGER_H__ +#define __SIM_SC_LOGGER_H__ + +#include <systemc> + +#include "base/trace.hh" + +namespace Gem5SystemC +{ + +/** sc_report logging class */ +class Logger : public Trace::Logger +{ + protected: + /** Stream to offer getOstream. This will cut messages up newlines and + * offer them to logMessage */ + std::streambuf *cuttingStreambuf; + std::ostream stream; + + public: + Logger(); + + ~Logger(); + + /** Log a single message as a single sc_report call */ + void logMessage(Tick when, const std::string &name, + const std::string &message); + + std::ostream &getOstream(); +}; + +} + +#endif // __SIM_SC_LOGGER_H__ diff --git a/util/systemc/sc_module.cc b/util/systemc/sc_module.cc new file mode 100644 index 000000000..d9e049607 --- /dev/null +++ b/util/systemc/sc_module.cc @@ -0,0 +1,231 @@ +/* + * 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. + * + * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. + * Copyright (c) 2013 Mark D. Hill and David A. Wood + * All rights reserved. + * + * 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: Nathan Binkert + * Steve Reinhardt + * Andrew Bardsley + */ + +/** + * @file + * + * Defines an sc_module type to wrap a gem5 simulation. The 'evaluate' + * thread on that module implements the gem5 event loop. + * + * This currently only supports a single event queue and strictly + * cooperatively threaded SystemC threads and so there should be at + * most one Gem5Module instantiated in any simulation. + */ + +#include "base/pollevent.hh" +#include "base/trace.hh" +#include "debug/Event.hh" +#include "sim/async.hh" +#include "sim/core.hh" +#include "sim/eventq.hh" +#include "sim/sim_exit.hh" +#include "sim/stat_control.hh" +#include "sc_module.hh" + +namespace Gem5SystemC +{ + +/** There are assumptions throughout Gem5SystemC file that a tick is 1ps. + * Make this the case */ +void +setTickFrequency() +{ + ::setClockFrequency(1000000000000); +} + +Module::Module(sc_core::sc_module_name name) : sc_core::sc_module(name) +{ + SC_METHOD(eventLoop); + sensitive << eventLoopEnterEvent; + sensitive << externalSchedulingEvent; + dont_initialize(); +} + +void +Module::SCEventQueue::wakeup(Tick when) +{ + DPRINTF(Event, "waking up SCEventQueue\n"); + /* Don't bother to use 'when' for now */ + module.notify(); +} + +void +Module::setupEventQueues(Module &module) +{ + numMainEventQueues = 1; + mainEventQueue.push_back(new SCEventQueue("events", module)); + curEventQueue(getEventQueue(0)); +} + +void +Module::notify(sc_core::sc_time time_from_now) +{ + externalSchedulingEvent.notify(time_from_now); +} + +void +Module::serviceAsyncEvent() +{ + assert(async_event); + + async_event = false; + if (async_statdump || async_statreset) { + Stats::schedStatEvent(async_statdump, async_statreset); + async_statdump = false; + async_statreset = false; + } + + if (async_exit) { + async_exit = false; + exitSimLoop("user interrupt received"); + } + + if (async_io) { + async_io = false; + pollQueue.service(); + } + + if (async_exception) + fatal("received async_exception, shouldn't be possible"); +} + +void +Module::eventLoop() +{ + EventQueue *eventq = getEventQueue(0); + + if (async_event) + serviceAsyncEvent(); + + while (!eventq->empty()) { + Tick next_event_time = eventq->nextTick(); + Tick systemc_time = sc_core::sc_time_stamp().value(); + + /* gem5 time *must* lag SystemC as SystemC is the master */ + assert(curTick() <= systemc_time); + + /* Move time on to match SystemC */ + eventq->setCurTick(systemc_time); + Tick gem5_time = curTick(); + + /* Woken up early */ + if (wait_exit_time > sc_core::sc_time_stamp().value()) { + DPRINTF(Event, "Woken up early\n"); + wait_exit_time = sc_core::sc_time_stamp().value(); + } + + if (gem5_time < next_event_time) { + Tick wait_period = next_event_time - gem5_time; + wait_exit_time = gem5_time + wait_period; + + DPRINTF(Event, "Waiting for %d ticks for next gem5 event\n", + wait_period); + + /* The next event is scheduled in the future, wait until + * then or until externalSchedulingEvent */ + eventLoopEnterEvent.notify(sc_core::sc_time( + sc_dt::uint64(wait_period), 0)); + + return; + } else if (gem5_time > next_event_time) { + /* Missed event, for some reason the above test didn't work + * or an event was scheduled in the past */ + fatal("Missed an event at time %d gem5: %d, SystemC: %d", + next_event_time, gem5_time, systemc_time); + } else { + /* Service an event */ + exitEvent = eventq->serviceOne(); + + if (exitEvent) { + eventLoopExitEvent.notify(); + return; + } + } + } + + fatal("Ran out of events without seeing exit event"); +} + +GlobalSimLoopExitEvent * +Module::simulate(Tick num_cycles) +{ + inform("Entering event queue @ %d. Starting simulation...\n", curTick()); + + if (num_cycles < MaxTick - curTick()) + num_cycles = curTick() + num_cycles; + else /* counter would roll over or be set to MaxTick anyhow */ + num_cycles = MaxTick; + + GlobalEvent *limit_event = new GlobalSimLoopExitEvent(num_cycles, + "simulate() limit reached", 0, 0); + + exitEvent = NULL; + + eventLoopEnterEvent.notify(sc_core::SC_ZERO_TIME); + + /* Wait for event queue to exit, guarded by exitEvent just incase + * it already has exited and we don't want to completely rely + * on notify semantics */ + if (!exitEvent) + wait(eventLoopExitEvent); + + /* Locate the global exit event */ + BaseGlobalEvent *global_event = exitEvent->globalEvent(); + assert(global_event != NULL); + + GlobalSimLoopExitEvent *global_exit_event = + dynamic_cast<GlobalSimLoopExitEvent *>(global_event); + assert(global_exit_event != NULL); + + if (global_exit_event != limit_event) { + limit_event->deschedule(); + delete limit_event; + } + + return global_exit_event; +} + +} diff --git a/util/systemc/sc_module.hh b/util/systemc/sc_module.hh new file mode 100644 index 000000000..c9ad94429 --- /dev/null +++ b/util/systemc/sc_module.hh @@ -0,0 +1,152 @@ +/* + * 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. + * + * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. + * Copyright (c) 2013 Mark D. Hill and David A. Wood + * All rights reserved. + * + * 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: Nathan Binkert + * Steve Reinhardt + * Andrew Bardsley + */ + +/** + * @file + * + * Defines an sc_module type to wrap a gem5 simulation. The 'evaluate' + * thread on that module implements the gem5 event loop. + * + * This currently only supports a single event queue and strictly + * cooperatively threaded SystemC threads and so there should be at + * most one Gem5Module instantiated in any simulation. + */ + +#ifndef __SIM_SC_MODULE_HH__ +#define __SIM_SC_MODULE_HH__ + +#include <systemc> + +#include "sim/eventq.hh" +#include "sim/sim_events.hh" + +namespace Gem5SystemC +{ + +/** A SystemC module implementing the gem5 event queue. This object + * doesn't actually own any of the simulation SimObjects (those need + * to be administered separately) but it does control the event + * queue. + * + * The event loop here services gem5 events in order at the current time + * and then yielding to another SystemC thread. gem5 events are not + * individually scheduled in SystemC. For this reason, asynchronous events + * and function interaction (for example TLM) with gem5 from SystemC must + * notify the module so that the yielding 'wait' can be interrupted. + * From the point of view of another SystemC module calling into gem5, + * curTick can lag SystemC time, be exactly the same time but *never* + * lead SystemC time. + * + * This functionality is wrapped in an sc_module as its intended that + * the a class representing top level simulation control should be derived + * from this class. */ +class Module : public sc_core::sc_module +{ + protected: + /** Event to trigger (via. ::notify) for event scheduling from + * outside gem5 */ + sc_core::sc_event externalSchedulingEvent; + + /** Event to trigger on exit of eventLoop */ + sc_core::sc_event eventLoopExitEvent; + + /** Event to trigger to enter eventLoop */ + sc_core::sc_event eventLoopEnterEvent; + + /** Expected exit time of last eventLoop sleep */ + Tick wait_exit_time; + + /** Placeholder base class for a variant event queue if this becomes + * useful */ + class SCEventQueue : public EventQueue + { + protected: + Module &module; + + public: + SCEventQueue(const std::string &name, + Module &module_) : EventQueue(name), module(module_) + { } + + /** Signal module to wakeup */ + void wakeup(Tick when); + }; + + /** Service any async event marked up in the globals event_... */ + void serviceAsyncEvent(); + + public: + /** Simulate is a process */ + SC_HAS_PROCESS(Module); + + Module(sc_core::sc_module_name name); + + /** Last exitEvent from eventLoop */ + Event *exitEvent; + + /** Setup global event queues. Call this before any other event queues + * are created */ + static void setupEventQueues(Module &module); + + /** Notify an externalSchedulingEvent at the given time from the + * current SystemC time */ + void notify(sc_core::sc_time time_from_now = sc_core::SC_ZERO_TIME); + + /** Process gem5 events up until an exit event or there are no events + * left. */ + void eventLoop(); + + /** Run eventLoop up to num_cycles and return the final event */ + GlobalSimLoopExitEvent *simulate(Tick num_cycles = MaxTick); +}; + +/** There are assumptions throughout Gem5SystemC file that a tick is 1ps. + * Make this the case */ +void setTickFrequency(); + +} + +#endif // __SIM_SC_MODULE_HH__ diff --git a/util/systemc/stats.cc b/util/systemc/stats.cc new file mode 100644 index 000000000..ef5d9b5d3 --- /dev/null +++ b/util/systemc/stats.cc @@ -0,0 +1,115 @@ +/* + * 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 stats handling example + * + * Register with: Stats::registerHandlers(statsReset, statsDump) + */ + +#include "base/statistics.hh" +#include "stats.hh" + +namespace CxxConfig +{ + +void statsPrepare() +{ + std::list<Stats::Info *> stats = Stats::statsList(); + + /* gather_stats -> prepare */ + for (auto i = stats.begin(); i != stats.end(); ++i) + (*i)->prepare(); +} + +void statsDump() +{ + std::cerr << "Stats dump\n"; + + Stats::processDumpQueue(); + + std::list<Stats::Info *> stats = Stats::statsList(); + + statsPrepare(); + + /* gather_stats -> convert_value */ + for (auto i = stats.begin(); i != stats.end(); ++i) { + Stats::Info *stat = *i; + + Stats::ScalarInfo *scalar = dynamic_cast<Stats::ScalarInfo *>(stat); + Stats::VectorInfo *vector = dynamic_cast<Stats::VectorInfo *>(stat); + + if (scalar) { + std::cerr << "SCALAR " << stat->name << ' ' + << scalar->value() << '\n'; + } else if (vector) { + Stats::VResult results = vector->value(); + + unsigned int index = 0; + for (auto e = results.begin(); e != results.end(); ++e) { + std::cerr << "VECTOR " << stat->name << '[' << index + << "] " << (*e) << '\n'; + index++; + } + std::cerr << "VTOTAL " << stat->name << ' ' + << vector->total() << '\n'; + } else { + std::cerr << "?????? " << stat->name << '\n'; + } + } +} + +void statsReset() +{ + std::cerr << "Stats reset\n"; + + Stats::processResetQueue(); +} + +void statsEnable() +{ + std::list<Stats::Info *> stats = Stats::statsList(); + + for (auto i = stats.begin(); i != stats.end(); ++i) + (*i)->enable(); +} + +} diff --git a/util/systemc/stats.hh b/util/systemc/stats.hh new file mode 100644 index 000000000..360cb6293 --- /dev/null +++ b/util/systemc/stats.hh @@ -0,0 +1,61 @@ +/* + * 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 stats handling example + * + * Register with: Stats::registerHandlers(statsReset, statsDump) + */ + +#ifndef __UTIL_CXX_CONFIG_STATS_H__ +#define __UTIL_CXX_CONFIG_STATS_H__ + +namespace CxxConfig +{ + +void statsDump(); +void statsReset(); +void statsEnable(); +void statsPrepare(); + +} + +#endif // __UTIL_CXX_CONFIG_STATS_H__ |