summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util/systemc/Makefile69
-rw-r--r--util/systemc/README59
-rw-r--r--util/systemc/main.cc379
-rw-r--r--util/systemc/sc_gem5_control.cc248
-rw-r--r--util/systemc/sc_gem5_control.hh154
-rw-r--r--util/systemc/sc_logger.cc152
-rw-r--r--util/systemc/sc_logger.hh80
-rw-r--r--util/systemc/sc_module.cc231
-rw-r--r--util/systemc/sc_module.hh152
-rw-r--r--util/systemc/stats.cc115
-rw-r--r--util/systemc/stats.hh61
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 &param_name, const std::string &param_value)
+{
+ manager->setParam(systemName + (object != "" ? "." + object : ""),
+ param_name, param_value);
+}
+
+void Gem5System::setParamVector(const std::string &object,
+ const std::string &param_name,
+ const std::vector<std::string> &param_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 &param_name, const std::string &param_value);
+
+ virtual void setParamVector(const std::string &system_name,
+ const std::string &param_name,
+ const std::vector<std::string> &param_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__