summaryrefslogtreecommitdiff
path: root/util/systemc/gem5_within_systemc
diff options
context:
space:
mode:
Diffstat (limited to 'util/systemc/gem5_within_systemc')
-rw-r--r--util/systemc/gem5_within_systemc/Makefile70
-rw-r--r--util/systemc/gem5_within_systemc/README83
-rw-r--r--util/systemc/gem5_within_systemc/main.cc446
-rw-r--r--util/systemc/gem5_within_systemc/sc_gem5_control.cc309
-rw-r--r--util/systemc/gem5_within_systemc/sc_gem5_control.hh168
-rw-r--r--util/systemc/gem5_within_systemc/sc_logger.cc152
-rw-r--r--util/systemc/gem5_within_systemc/sc_logger.hh80
-rw-r--r--util/systemc/gem5_within_systemc/sc_module.cc300
-rw-r--r--util/systemc/gem5_within_systemc/sc_module.hh165
-rw-r--r--util/systemc/gem5_within_systemc/stats.cc159
-rw-r--r--util/systemc/gem5_within_systemc/stats.hh65
11 files changed, 1997 insertions, 0 deletions
diff --git a/util/systemc/gem5_within_systemc/Makefile b/util/systemc/gem5_within_systemc/Makefile
new file mode 100644
index 000000000..100402c15
--- /dev/null
+++ b/util/systemc/gem5_within_systemc/Makefile
@@ -0,0 +1,70 @@
+# 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) *.o
+ $(RM) -r m5out
diff --git a/util/systemc/gem5_within_systemc/README b/util/systemc/gem5_within_systemc/README
new file mode 100644
index 000000000..9ee1103a8
--- /dev/null
+++ b/util/systemc/gem5_within_systemc/README
@@ -0,0 +1,83 @@
+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/systemc
+
+Note: For MAC / OSX this command should be used:
+> scons --with-cxx-config --without-python build/ARM/libgem5_opt.dylib
+
+Set a proper LD_LIBRARY_PATH e.g. for bash:
+> export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/path/to/gem5/build/ARM/"
+
+or for MAC / OSX:
+> export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:/path/to/gem5/build/ARM/"
+
+
+Then edit the Makefile to set the paths for SystemC, e.g:
+
+ Linux:
+ SYSTEMC_INC = /opt/systemc/include
+ SYSTEMC_LIB = /opt/systemc/lib-linux64
+
+ MAC / OSX:
+ SYSTEMC_INC = /opt/systemc/include
+ SYSTEMC_LIB = /opt/systemc/lib-macosx64
+
+Then 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
+
+If you are interested in SystemC Transaction Level Modeling (TLM2) please have
+a look into /util/tlm.
diff --git a/util/systemc/gem5_within_systemc/main.cc b/util/systemc/gem5_within_systemc/main.cc
new file mode 100644
index 000000000..9d88b63cb
--- /dev/null
+++ b/util/systemc/gem5_within_systemc/main.cc
@@ -0,0 +1,446 @@
+/*
+ * 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
+ * Abdul Mutaal Ahmad
+ */
+
+/**
+ * @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 "sc_logger.hh"
+#include "sc_module.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 "stats.hh"
+
+// Defining global string variable decalred in stats.hh
+std::string filename;
+
+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 <#cpus> the number of cpus to switch\n"
+ " (appended to 'to' and 'from'"
+ " cpus above)\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;
+ unsigned num_switch_cpus;
+
+ public:
+ SC_HAS_PROCESS(SimControl);
+
+ SimControl(sc_core::sc_module_name name, int argc_, char **argv_);
+
+ void run();
+ private:
+ /**
+ * Switch a single CPU
+ *
+ * If numTotalCpus is greater than 1, the CPU index will be appended to
+ * the object name when searching config manager for the CPU name
+ *
+ * @param The CPU number to switch
+ * @param The total number of CPUs in the system
+ */
+ void switchCpu(unsigned cpuNum, unsigned numTotalCpus);
+
+};
+
+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();
+
+ /* Pass DPRINTF messages to SystemC */
+ Trace::setDebugLogger(&logger);
+
+ /* @todo need this as an option */
+ Gem5SystemC::setTickFrequency();
+
+ /* Make a SystemC-synchronising event queue and install it as the
+ * sole top level gem5 EventQueue */
+ Gem5SystemC::Module::setupEventQueues(*this);
+
+ if (sc_core::sc_get_time_resolution() !=
+ sc_core::sc_time(1, sc_core::SC_PS))
+ {
+ fatal("Time resolution must be set to 1 ps for gem5 to work");
+ }
+
+ /* Enable keyboard interrupt, async I/O etc. */
+ initSignals();
+
+ /* Enable stats */
+ Stats::initSimStats();
+ Stats::registerHandlers(CxxConfig::statsReset, CxxConfig::statsDump);
+
+ Trace::enable();
+ 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;
+ num_switch_cpus = 1;
+
+ const std::string config_file(argv[arg_ptr]);
+
+ CxxConfigFileBase *conf = new CxxIniFile();
+
+ if (!conf->load(config_file.c_str()))
+ fatal("Can't open config file: %s", config_file);
+
+ 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 if (option == "-n") {
+ if (num_args < 1)
+ usage(prog_name);
+ std::istringstream(argv[arg_ptr]) >> num_switch_cpus;
+ arg_ptr++;
+ } else {
+ usage(prog_name);
+ }
+ }
+ } catch (CxxConfigManager::Exception &e) {
+ fatal("Config problem in sim object %s: %s", e.name, e.message);
+ }
+
+ if (checkpoint_save && checkpoint_restore) {
+ fatal("Don't try to save and restore a checkpoint in the same"
+ "run");
+ }
+
+ CxxConfig::statsEnable();
+ getEventQueue(0)->dump();
+
+ try {
+ config_manager->instantiate();
+ } catch (CxxConfigManager::Exception &e) {
+ fatal("Config problem in sim object %s: %s", e.name, e.message);
+ }
+}
+
+void SimControl::run()
+{
+ EventQueue *eventq = getEventQueue(0);
+ GlobalSimLoopExitEvent *exit_event = NULL;
+
+ /* There *must* be no scheduled events yet */
+ fatal_if(!eventq->empty(), "There must be no posted events"
+ " before SimControl::run");
+
+ try {
+ if (checkpoint_restore) {
+ std::cerr << "Restoring checkpoint\n";
+
+ CheckpointIn *checkpoint = new CheckpointIn(checkpoint_dir,
+ config_manager->getSimObjectResolver());
+
+ /* Catch SystemC up with gem5 after checkpoint restore.
+ * Note that gem5 leading SystemC is always a violation of the
+ * required relationship between the two, hence this careful
+ * catchup */
+
+ DrainManager::instance().preCheckpointRestore();
+ Serializable::unserializeGlobals(*checkpoint);
+
+ 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::from_value(wait_period));
+ }
+
+ config_manager->loadState(*checkpoint);
+ config_manager->startup();
+ config_manager->drainResume();
+
+ std::cerr << "Restored from Checkpoint\n";
+ } else {
+ config_manager->initState();
+ config_manager->startup();
+ }
+ } catch (CxxConfigManager::Exception &e) {
+ fatal("Config problem in sim object %s: %s", e.name, e.message);
+ }
+
+ fatal_if(eventq->empty(), "No events to process after system startup");
+
+ if (checkpoint_save) {
+ exit_event = simulate(pre_run_time);
+
+ unsigned int drain_count = 1;
+ do {
+ drain_count = config_manager->drain();
+
+ std::cerr << "Draining " << drain_count << '\n';
+
+ if (drain_count > 0) {
+ 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 (switch_cpus) {
+ exit_event = simulate(pre_switch_time);
+
+ unsigned int drain_count = 1;
+ do {
+ drain_count = config_manager->drain();
+
+ std::cerr << "Draining " << drain_count << '\n';
+
+ if (drain_count > 0) {
+ exit_event = simulate();
+ }
+ } while (drain_count > 0);
+
+ for (unsigned cpu_num = 0; cpu_num < num_switch_cpus; ++cpu_num) {
+ switchCpu(cpu_num, num_switch_cpus);
+ }
+
+ config_manager->drainResume();
+
+ }
+
+ 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);
+
+ filename = "m5out/stats-systemc.txt";
+
+ sc_core::sc_start();
+
+ CxxConfig::statsDump();
+
+ return EXIT_SUCCESS;
+}
+
+void
+SimControl::switchCpu(unsigned cpuNum, unsigned numTotalCpus) {
+ assert(cpuNum < numTotalCpus);
+ std::ostringstream from_cpu_name;
+ std::ostringstream to_cpu_name;
+
+ from_cpu_name << from_cpu;
+ to_cpu_name << to_cpu;
+
+ if (numTotalCpus > 1) {
+ from_cpu_name << cpuNum;
+ to_cpu_name << cpuNum;
+ }
+
+ std::cerr << "Switching CPU "<< cpuNum << "(from='" << from_cpu_name.str()
+ <<"' to '"<< to_cpu_name.str() << "')\n";
+
+ /* Assume the system is called system */
+ System &system = config_manager->getObject<System>("system");
+ BaseCPU &old_cpu = config_manager->getObject<BaseCPU>(from_cpu_name.str());
+ BaseCPU &new_cpu = config_manager->getObject<BaseCPU>(to_cpu_name.str());
+
+ old_cpu.switchOut();
+
+ // I'm not sure if this can be called before old_cpu.switchOut(). If so,
+ // it is best to just move this call before the switchCpu loop in run()
+ // where it previously was
+ if (cpuNum == 0)
+ system.setMemoryMode(Enums::timing);
+
+ new_cpu.takeOverFrom(&old_cpu);
+
+
+ std::cerr << "Switched CPU"<<cpuNum<<"\n";
+}
diff --git a/util/systemc/gem5_within_systemc/sc_gem5_control.cc b/util/systemc/gem5_within_systemc/sc_gem5_control.cc
new file mode 100644
index 000000000..ae3dc241f
--- /dev/null
+++ b/util/systemc/gem5_within_systemc/sc_gem5_control.cc
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2014 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Andrew Bardsley
+ */
+
+#include <cstdlib>
+#include <iostream>
+#include <list>
+
+#include "base/statistics.hh"
+#include "sc_gem5_control.hh"
+#include "sc_logger.hh"
+#include "sc_module.hh"
+#include "sim/cxx_config_ini.hh"
+#include "sim/cxx_manager.hh"
+#include "sim/debug.hh"
+#include "sim/init_signals.hh"
+#include "sim/stat_control.hh"
+#include "stats.hh"
+
+namespace Gem5SystemC
+{
+
+/** This is the private side of Gem5Control */
+class Gem5TopLevelModule : public Gem5SystemC::Module
+{
+ friend class Gem5Control;
+
+ protected:
+ CxxConfigFileBase *config_file;
+ CxxConfigManager *root_manager;
+ Gem5SystemC::Logger logger;
+
+ /** Things to do at end_of_elaborate */
+ std::list<void (*)()> endOfElaborationFuncs;
+
+ public:
+ SC_HAS_PROCESS(Gem5TopLevelModule);
+
+ Gem5TopLevelModule(sc_core::sc_module_name name,
+ const std::string &config_filename);
+ ~Gem5TopLevelModule();
+
+ /** gem5 simulate. @todo for more interesting simulation control,
+ * this needs to be more complicated */
+ void run();
+
+ /* Register an action to happen at the end of elaboration */
+ void registerEndOfElaboration(void (*func)())
+ {
+ endOfElaborationFuncs.push_back(func);
+ }
+
+ /** SystemC startup */
+ void end_of_elaboration();
+};
+
+Gem5System::Gem5System(CxxConfigManager *manager_,
+ const std::string &system_name, const std::string &instance_name) :
+ manager(manager_),
+ systemName(system_name),
+ instanceName(instance_name)
+{
+ manager->addRenaming(CxxConfigManager::Renaming(
+ system_name, instance_name));
+}
+
+Gem5System::~Gem5System()
+{
+ delete manager;
+}
+
+void
+Gem5System::setParam(const std::string &object,
+ const std::string &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::registerEndOfElaboration(void (*func)())
+{
+ module->registerEndOfElaboration(func);
+}
+
+void
+Gem5Control::setDebugFlag(const char *flag)
+{
+ ::setDebugFlag(flag);
+}
+
+void
+Gem5Control::clearDebugFlag(const char *flag)
+{
+ ::clearDebugFlag(flag);
+}
+
+void
+Gem5Control::setRemoteGDBPort(unsigned int port)
+{
+ ::setRemoteGDBPort(port);
+}
+
+Gem5System *
+Gem5Control::makeSystem(const std::string &system_name,
+ const std::string &instance_name)
+{
+ Gem5System *ret = new Gem5System(
+ new CxxConfigManager(*(module->config_file)),
+ system_name, instance_name);
+
+ return ret;
+}
+
+const std::string &
+Gem5Control::getVersion() const
+{
+ return version;
+}
+
+void
+Gem5Control::setVersion(const std::string &new_version)
+{
+ if (version != "")
+ fatal("Gem5Control::setVersion called for a second time");
+
+ version = new_version;
+}
+
+Gem5TopLevelModule::Gem5TopLevelModule(sc_core::sc_module_name name,
+ const std::string &config_filename) :
+ Gem5SystemC::Module(name),
+ config_file(NULL),
+ root_manager(NULL)
+{
+ SC_THREAD(run);
+
+ cxxConfigInit();
+
+ /* Pass DPRINTF messages to SystemC */
+ Trace::setDebugLogger(&logger);
+
+ /* @todo need this as an option */
+ Gem5SystemC::setTickFrequency();
+
+ /* Make a SystemC-synchronising event queue and install it as the
+ * sole top level gem5 EventQueue */
+ Gem5SystemC::Module::setupEventQueues(*this);
+
+ if (sc_core::sc_get_time_resolution() !=
+ sc_core::sc_time(1, sc_core::SC_PS))
+ {
+ fatal("Time resolution must be set to 1 ps for gem5 to work");
+ }
+
+ /* Enable keyboard interrupt, async I/O etc. */
+ initSignals();
+
+ /* Enable stats */
+ Stats::initSimStats();
+ Stats::registerHandlers(CxxConfig::statsReset, CxxConfig::statsDump);
+
+ Trace::enable();
+
+ config_file = new CxxIniFile();
+
+ if (!config_file->load(config_filename)) {
+ fatal("Gem5TopLevelModule: Can't open config file: %s",
+ config_filename);
+ }
+
+ root_manager = new CxxConfigManager(*config_file);
+
+ CxxConfig::statsEnable();
+
+ /* Make the root object */
+ try {
+ SimObject *root = root_manager->findObject("root", false);
+
+ /* Make sure we don't traverse into root's children */
+ root_manager->objectsInOrder.push_back(root);
+
+ root_manager->instantiate(false);
+ root_manager->initState();
+ root_manager->startup();
+ } catch (CxxConfigManager::Exception &e) {
+ fatal("Config problem in Gem5TopLevelModule: %s: %s",
+ e.name, e.message);
+ }
+}
+
+Gem5TopLevelModule::~Gem5TopLevelModule()
+{
+ delete config_file;
+ delete root_manager;
+}
+
+void
+Gem5TopLevelModule::run()
+{
+ GlobalSimLoopExitEvent *exit_event = NULL;
+
+ exit_event = simulate();
+
+ std::cerr << "Exit at tick " << curTick()
+ << ", cause: " << exit_event->getCause() << '\n';
+
+ getEventQueue(0)->dump();
+}
+
+void
+Gem5TopLevelModule::end_of_elaboration()
+{
+ for (auto i = endOfElaborationFuncs.begin();
+ i != endOfElaborationFuncs.end(); ++i)
+ {
+ (*i)();
+ }
+}
+
+}
+
+Gem5SystemC::Gem5Control *
+makeGem5Control(const std::string &config_filename)
+{
+ return new Gem5SystemC::Gem5Control(config_filename);
+}
+
diff --git a/util/systemc/gem5_within_systemc/sc_gem5_control.hh b/util/systemc/gem5_within_systemc/sc_gem5_control.hh
new file mode 100644
index 000000000..a5a372344
--- /dev/null
+++ b/util/systemc/gem5_within_systemc/sc_gem5_control.hh
@@ -0,0 +1,168 @@
+/*
+ * 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;
+
+ /** One-time-settable version string */
+ std::string version;
+
+ 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);
+
+ /** Choose a base port number for GDB to connect to the model
+ * (0 disables connections) */
+ virtual void setRemoteGDBPort(unsigned int port);
+
+ /* Register an action to happen at the end of elaboration */
+ virtual void registerEndOfElaboration(void (*func)());
+
+ /** 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);
+
+ /** set/get version string */
+ virtual const std::string &getVersion() const;
+ virtual void setVersion(const std::string &new_version);
+};
+
+}
+
+/** 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/gem5_within_systemc/sc_logger.cc b/util/systemc/gem5_within_systemc/sc_logger.cc
new file mode 100644
index 000000000..a8b9020f4
--- /dev/null
+++ b/util/systemc/gem5_within_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/gem5_within_systemc/sc_logger.hh b/util/systemc/gem5_within_systemc/sc_logger.hh
new file mode 100644
index 000000000..4143f8bb8
--- /dev/null
+++ b/util/systemc/gem5_within_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/gem5_within_systemc/sc_module.cc b/util/systemc/gem5_within_systemc/sc_module.cc
new file mode 100644
index 000000000..dafa80ee9
--- /dev/null
+++ b/util/systemc/gem5_within_systemc/sc_module.cc
@@ -0,0 +1,300 @@
+/*
+ * 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
+ * Matthias Jung
+ * Christian Menard
+ */
+
+/**
+ * @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/logging.hh"
+#include "base/pollevent.hh"
+#include "base/trace.hh"
+#include "debug/Event.hh"
+#include "sc_module.hh"
+#include "sim/async.hh"
+#include "sim/core.hh"
+#include "sim/eventq.hh"
+#include "sim/sim_exit.hh"
+#include "sim/stat_control.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_channel(name),
+ in_simulate(false)
+{
+ SC_METHOD(eventLoop);
+ sensitive << eventLoopEnterEvent;
+ dont_initialize();
+
+ SC_METHOD(serviceExternalEvent);
+ 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)
+{
+ fatal_if(mainEventQueue.size() != 0,
+ "Gem5SystemC::Module::setupEventQueues must be called"
+ " before any gem5 event queues are set up");
+
+ numMainEventQueues = 1;
+ mainEventQueue.push_back(new SCEventQueue("events", module));
+ curEventQueue(getEventQueue(0));
+}
+
+void
+Module::catchup()
+{
+ EventQueue *eventq = getEventQueue(0);
+ Tick systemc_time = sc_core::sc_time_stamp().value();
+ Tick gem5_time = curTick();
+
+ /* gem5 time *must* lag SystemC as SystemC is the master */
+ fatal_if(gem5_time > systemc_time, "gem5 time must lag SystemC time"
+ " gem5: %d SystemC: %d", gem5_time, systemc_time);
+
+ eventq->setCurTick(systemc_time);
+
+ if (!eventq->empty()) {
+ Tick next_event_time M5_VAR_USED = eventq->nextTick();
+
+ fatal_if(gem5_time > next_event_time,
+ "Missed an event at time %d gem5: %d, SystemC: %d",
+ next_event_time, gem5_time, systemc_time);
+ }
+}
+
+void
+Module::notify(sc_core::sc_time time_from_now)
+{
+ externalSchedulingEvent.notify(time_from_now);
+}
+
+void
+Module::serviceAsyncEvent()
+{
+ EventQueue *eventq = getEventQueue(0);
+ std::lock_guard<EventQueue> lock(*eventq);
+
+ assert(async_event);
+
+ /* Catch up gem5 time with SystemC time so that any event here won't
+ * be in the past relative to the current time */
+ Tick systemc_time = sc_core::sc_time_stamp().value();
+
+ /* Move time on to match SystemC */
+ catchup();
+
+ 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::serviceExternalEvent()
+{
+ EventQueue *eventq = getEventQueue(0);
+
+ if (!in_simulate && !async_event)
+ warn("Gem5SystemC external event received while not in simulate");
+
+ if (async_event)
+ serviceAsyncEvent();
+
+ if (in_simulate && !eventq->empty())
+ eventLoop();
+}
+
+void
+Module::eventLoop()
+{
+ EventQueue *eventq = getEventQueue(0);
+
+ fatal_if(!in_simulate, "Gem5SystemC event loop entered while"
+ " outside Gem5SystemC::Module::simulate");
+
+ if (async_event)
+ serviceAsyncEvent();
+
+ while (!eventq->empty()) {
+ Tick next_event_time = eventq->nextTick();
+
+ /* Move time on to match SystemC */
+ catchup();
+
+ 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::from_value(
+ sc_dt::uint64(wait_period)));
+
+ return;
+ } else if (gem5_time > next_event_time) {
+ Tick systemc_time = sc_core::sc_time_stamp().value();
+
+ /* 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(sc_core::SC_ZERO_TIME);
+ return;
+ }
+ }
+ }
+
+ fatal("Ran out of events without seeing exit event");
+}
+
+GlobalSimLoopExitEvent *
+Module::simulate(Tick num_cycles)
+{
+ inform("Entering event queue @ %d. Starting simulation...", 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;
+
+ /* Cancel any outstanding events */
+ eventLoopExitEvent.cancel();
+ externalSchedulingEvent.cancel();
+
+ in_simulate = true;
+ 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);
+
+ /* Cancel any outstanding event loop entries */
+ eventLoopEnterEvent.cancel();
+ in_simulate = false;
+
+ /* 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/gem5_within_systemc/sc_module.hh b/util/systemc/gem5_within_systemc/sc_module.hh
new file mode 100644
index 000000000..ff4e56e53
--- /dev/null
+++ b/util/systemc/gem5_within_systemc/sc_module.hh
@@ -0,0 +1,165 @@
+/*
+ * 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
+ * Christian Menard
+ */
+
+/**
+ * @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_channel
+{
+ 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;
+
+ /** Are we in Module::simulate? Used to mask events when not inside
+ * the simulate loop */
+ bool in_simulate;
+
+ /** 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);
+
+ /** Catch gem5 time up with SystemC */
+ void catchup();
+
+ /** 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 an event triggered by externalSchedulingEvent and also
+ * call eventLoop (to try and mop up any events at this time) if there
+ * are any scheduled events */
+ void serviceExternalEvent();
+
+ /** 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/gem5_within_systemc/stats.cc b/util/systemc/gem5_within_systemc/stats.cc
new file mode 100644
index 000000000..54d149474
--- /dev/null
+++ b/util/systemc/gem5_within_systemc/stats.cc
@@ -0,0 +1,159 @@
+/*
+ * 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
+ * Matthias Jung
+ * Abdul Mutaal Ahmad
+ */
+
+/**
+ * @file
+ *
+ * C++-only configuration stats handling example
+ *
+ * Register with: Stats::registerHandlers(statsReset, statsDump)
+ */
+
+#include "base/output.hh"
+#include "base/statistics.hh"
+#include "base/stats/text.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){
+ Stats::Info *stat = *i;
+ Stats::VectorInfo *vector = dynamic_cast<Stats::VectorInfo *>(stat);
+ if (vector){
+ (dynamic_cast<Stats::VectorInfo *>(*i))->prepare();
+ }
+ else {
+ (*i)->prepare();
+ }
+
+ }
+}
+
+void statsDump()
+{
+ bool desc = true;
+ Stats::Output *output = Stats::initText(filename, desc);
+
+ Stats::processDumpQueue();
+
+ std::list<Stats::Info *> stats = Stats::statsList();
+
+ statsEnable();
+ statsPrepare();
+
+ output->begin();
+ /* gather_stats -> convert_value */
+ for (auto i = stats.begin(); i != stats.end(); ++i) {
+ Stats::Info *stat = *i;
+
+ const Stats::ScalarInfo *scalar = dynamic_cast<Stats::ScalarInfo
+ *>(stat);
+ Stats::VectorInfo *vector = dynamic_cast<Stats::VectorInfo *>(stat);
+ const Stats::Vector2dInfo *vector2d = dynamic_cast<Stats::Vector2dInfo
+ *>(vector);
+ const Stats::DistInfo *dist = dynamic_cast<Stats::DistInfo *>(stat);
+ const Stats::VectorDistInfo *vectordist =
+ dynamic_cast<Stats::VectorDistInfo *>(stat);
+ const Stats::SparseHistInfo *sparse =
+ dynamic_cast<Stats::SparseHistInfo *>(stat);
+ const Stats::InfoProxy <Stats::Vector2d,Stats::Vector2dInfo> *info =
+ dynamic_cast<Stats::InfoProxy
+ <Stats::Vector2d,Stats::Vector2dInfo>*>(stat);
+
+ if (vector) {
+ const Stats::FormulaInfo *formula = dynamic_cast<Stats::FormulaInfo
+ *>(vector);
+ if (formula){
+ output->visit(*formula);
+ } else {
+ const Stats::VectorInfo *vector1 = vector;
+ output->visit(*vector1);
+ }
+ } else if (vector2d) {
+ output->visit(*vector2d);
+ } else if (info){
+ output->visit(*info);
+ } else if (vectordist){
+ output->visit(*vectordist);
+ } else if (dist) {
+ output->visit(*dist);
+ } else if (sparse) {
+ output->visit(*sparse);
+ } else if (scalar) {
+ output->visit(*scalar);
+ } else {
+ warn("Stat not dumped: %s\n", stat->name);
+ }
+ }
+ output->end();
+}
+
+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){
+ Stats::Info *stat = *i;
+ Stats::VectorInfo *vector = dynamic_cast<Stats::VectorInfo *>(stat);
+ if (vector){
+ (dynamic_cast<Stats::VectorInfo *>(*i))->enable();
+ }
+ else {
+ (*i)->enable();
+ }
+
+ }
+}
+
+}
diff --git a/util/systemc/gem5_within_systemc/stats.hh b/util/systemc/gem5_within_systemc/stats.hh
new file mode 100644
index 000000000..9dac960ee
--- /dev/null
+++ b/util/systemc/gem5_within_systemc/stats.hh
@@ -0,0 +1,65 @@
+/*
+ * 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
+ * Matthias Jung
+ * Abdul Mutaal Ahmad
+ */
+
+/**
+ * @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__
+
+extern std::string filename;
+
+namespace CxxConfig
+{
+
+void statsDump();
+void statsReset();
+void statsEnable();
+void statsPrepare();
+
+}
+
+#endif // __UTIL_CXX_CONFIG_STATS_H__