misc: Clean up and complete the gem5<->SystemC-TLM bridge [4/10]
authorChristian Menard <Christian.Menard@tu-dresden.de>
Fri, 10 Feb 2017 00:15:38 +0000 (19:15 -0500)
committerChristian Menard <Christian.Menard@tu-dresden.de>
Fri, 10 Feb 2017 00:15:38 +0000 (19:15 -0500)
The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
 * Move common code of the example to a common directory.  Move the cli
 * parsing from the SimControl module to a separate example object.  Add
 * comments describing the Gem5SimControl module.

Testing Done: Examples compile and run.

Reviewed at http://reviews.gem5.org/r/3695/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
util/tlm/examples/common/cli_parser.cc [new file with mode: 0644]
util/tlm/examples/common/cli_parser.hh [new file with mode: 0644]
util/tlm/examples/common/report_handler.cc [new file with mode: 0644]
util/tlm/examples/common/report_handler.hh [new file with mode: 0644]
util/tlm/examples/master_port/SConstruct
util/tlm/examples/master_port/main.cc
util/tlm/examples/slave_port/SConstruct
util/tlm/examples/slave_port/main.cc
util/tlm/sim_control.cc
util/tlm/sim_control.hh

diff --git a/util/tlm/examples/common/cli_parser.cc b/util/tlm/examples/common/cli_parser.cc
new file mode 100644 (file)
index 0000000..b86e99f
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016, Dresden University of Technology (TU Dresden)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder 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 HOLDER
+ * 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: Christian Menard
+ */
+
+#include <iostream>
+#include <sstream>
+
+#include "cli_parser.hh"
+#include "sim/cxx_manager.hh"
+
+void
+CliParser::usage(const std::string& prog_name)
+{
+    std::cerr
+      << "Usage: " << prog_name
+      << (" <config_file.ini> [ <option> ]\n\n"
+          "OPTIONS:\n"
+
+          "    -o <offset>                  -- set memory offset\n"
+          "    -d <flag>                    -- set a gem5 debug flag\n"
+          "                                    (-<flag> clears a flag)\n"
+          "    -v                           -- verbose output\n"
+          "    -e <ticks>                   -- end of simulation after a \n"
+          "                                    given number of ticks\n"
+          "\n");
+    std::exit(EXIT_FAILURE);
+}
+
+void
+CliParser::parse(int argc, char** argv)
+{
+    std::string prog_name(argv[0]);
+
+    unsigned int arg_ptr = 1;
+
+    if (argc == 1) {
+        usage(prog_name);
+    }
+
+    configFile = std::string(argv[arg_ptr]);
+    arg_ptr++;
+
+    // default values
+    verboseFlag = false;
+    simulationEnd = 0;
+    memoryOffset = 0;
+
+    try {
+        while (arg_ptr < argc) {
+            std::string option(argv[arg_ptr]);
+            arg_ptr++;
+            unsigned num_args = argc - arg_ptr;
+
+            if (option == "-d") {
+                if (num_args < 1) {
+                    usage(prog_name);
+                }
+                std::string flag(argv[arg_ptr]);
+                arg_ptr++;
+                debugFlags.push_back(flag);
+            } else if (option == "-e") {
+                if (num_args < 1) {
+                    usage(prog_name);
+                }
+                std::istringstream(argv[arg_ptr]) >> simulationEnd;
+                arg_ptr++;
+            } else if (option == "-v") {
+                verboseFlag = true;
+            } else if (option == "-o") {
+                if (num_args < 1) {
+                    usage(prog_name);
+                }
+                std::istringstream(argv[arg_ptr]) >> memoryOffset;
+                arg_ptr++;
+                /* code */
+            } else {
+                usage(prog_name);
+            }
+        }
+    } catch (CxxConfigManager::Exception &e) {
+        std::cerr << e.name << ": " << e.message << "\n";
+        std::exit(EXIT_FAILURE);
+    }
+
+    parsed = true;
+}
+
+std::string
+CliParser::getDebugFlags()
+{
+    std::stringstream ss;
+    for (auto& flag : debugFlags) {
+        ss << flag << ' ';
+    }
+    return ss.str();
+}
diff --git a/util/tlm/examples/common/cli_parser.hh b/util/tlm/examples/common/cli_parser.hh
new file mode 100644 (file)
index 0000000..3f89131
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016, Dresden University of Technology (TU Dresden)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder 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 HOLDER
+ * 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: Christian Menard
+ */
+
+#ifndef __CLI_PARSER_HH__
+#define __CLI_PARSER_HH__
+
+#include <cassert>
+#include <string>
+#include <vector>
+
+class CliParser
+{
+  private:
+    int argc;
+    char** argv;
+
+    bool parsed;
+
+    uint64_t memoryOffset;
+    uint64_t simulationEnd;
+    bool verboseFlag;
+    std::vector<std::string> debugFlags;
+    std::string configFile;
+
+    void usage(const std::string& prog_name);
+  public:
+
+    CliParser() : parsed(false) {}
+
+    void parse(int argc, char** argv);
+
+    uint64_t getMemoryOffset()  { assert(parsed); return memoryOffset; }
+    uint64_t getSimulationEnd() { assert(parsed); return simulationEnd; }
+    bool getVerboseFlag()       { assert(parsed); return verboseFlag; }
+    std::string getConfigFile() { assert(parsed); return configFile; }
+    std::string getDebugFlags();
+};
+
+#endif
diff --git a/util/tlm/examples/common/report_handler.cc b/util/tlm/examples/common/report_handler.cc
new file mode 100644 (file)
index 0000000..56a03ec
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2016, Dresden University of Technology (TU Dresden)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder 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 HOLDER
+ * 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: Christian Menard
+ */
+
+#include <iostream>
+#include <systemc>
+
+#include <sim/core.hh>
+#include <sim/simulate.hh>
+
+#include "report_handler.hh"
+
+using namespace sc_core;
+
+void
+reportHandler(const sc_report &report, const sc_actions &actions)
+{
+    uint64_t systemc_time = report.get_time().value();
+    uint64_t gem5_time = curTick();
+
+    if (actions & SC_DO_NOTHING)
+        return;
+
+    if (actions & SC_DISPLAY || actions & SC_LOG)
+    {
+        std::ostream& stream = actions & SC_DISPLAY ? std::cout : std::cerr;
+
+        stream << report.get_time();
+
+        if (gem5_time < systemc_time) {
+            stream << " (<) ";
+        } else if (gem5_time > systemc_time) {
+            stream << " (!) ";
+        } else {
+            stream << " (=) ";
+        }
+
+        stream << ": " << report.get_msg_type()
+               << ' ' << report.get_msg() << '\n';
+    }
+
+    if (actions & SC_THROW) {
+        std::cerr << "warning: the report handler ignored a SC_THROW action\n";
+    } else if (actions & SC_INTERRUPT) {
+        std::cerr << "warning: the report handler ignored a SC_INTERRUPT"
+                  << "action\n";
+    } else if (actions & SC_CACHE_REPORT) {
+        std::cerr << "warning: the report handler ignored a SC_CACHE_REPORT"
+                  << "action\n";
+    }
+
+    if (actions & SC_STOP)
+        sc_stop();
+
+    if (actions & SC_ABORT)
+        abort();
+}
diff --git a/util/tlm/examples/common/report_handler.hh b/util/tlm/examples/common/report_handler.hh
new file mode 100644 (file)
index 0000000..bd91b77
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Dresden University of Technology (TU Dresden)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder 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 HOLDER
+ * 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: Matthias Jung
+ *          Christian Menard
+ */
+
+#ifndef __REPORT_HANDLER_HH__
+#define __REPORT_HANDLER_HH__
+
+void reportHandler(const sc_core::sc_report &report,
+                   const sc_core::sc_actions &actions);
+
+#endif
index 8ca9959a0d649a607de64a46a9de5cea6a092a80..a896a34e44b5097fc9fc6e85e4cd3bf552fb4578 100644 (file)
@@ -54,7 +54,8 @@ env.ParseConfig('pkg-config --cflags --libs systemc')
 # add include dirs
 env.Append(CPPPATH=[gem5_root + '/build/' + gem5_arch,
                     gem5_root + '/util/systemc',
-                    gem5_root + '/util/tlm'])
+                    gem5_root + '/util/tlm',
+                    '../common'])
 
 env.Append(LIBS=['gem5_' + gem5_variant])
 env.Append(LIBPATH=[gem5_root + '/build/' + gem5_arch])
@@ -72,6 +73,6 @@ src_systemc = [gem5_root + '/util/systemc/sc_gem5_control.cc',
                gem5_root + '/util/systemc/stats.cc']
 
 src_tlm     = Glob(gem5_root + '/util/tlm/*.cc')
-src_main    = Glob('*.cc')
+src_main    = Glob('*.cc') + Glob('../common/*.cc')
 
 main = env.Program(target, src_systemc + src_tlm + src_main)
index 205e430aefcd8c14b44dbb111758dd3b1fa102c7..588d8115635b5646105584bf15e99492fe987378 100644 (file)
 #include <systemc>
 #include <tlm>
 
+#include "cli_parser.hh"
+#include "report_handler.hh"
 #include "sc_master_port.hh"
 #include "sim_control.hh"
 #include "stats.hh"
 #include "traffic_generator.hh"
 
-// Defining global string variable decalred in stats.hh
-std::string filename;
-
-void
-reportHandler(const sc_core::sc_report& report,
-              const sc_core::sc_actions& actions)
-{
-    uint64_t systemc_time = report.get_time().value();
-    uint64_t gem5_time = curTick();
-
-    std::cerr << report.get_time();
-
-    if (gem5_time < systemc_time) {
-        std::cerr << " (<) ";
-    } else if (gem5_time > systemc_time) {
-        std::cerr << " (!) ";
-    } else {
-        std::cerr << " (=) ";
-    }
-
-    std::cerr << ": " << report.get_msg_type() << ' ' << report.get_msg()
-              << '\n';
-}
-
 int
 sc_main(int argc, char** argv)
 {
+    CliParser parser;
+    parser.parse(argc, argv);
+
     sc_core::sc_report_handler::set_handler(reportHandler);
 
-    SimControl simControl("gem5", argc, argv);
-    TrafficGenerator trafficGenerator("traffic_generator");
+    Gem5SystemC::Gem5SimControl simControl("gem5",
+                                           parser.getConfigFile(),
+                                           parser.getSimulationEnd(),
+                                           parser.getDebugFlags());
 
-    filename = "m5out/stats-systemc.txt";
+    TrafficGenerator trafficGenerator("traffic_generator");
 
     tlm::tlm_target_socket<>* mem_port =
       dynamic_cast<tlm::tlm_target_socket<>*>(
@@ -86,7 +69,7 @@ sc_main(int argc, char** argv)
         std::exit(EXIT_FAILURE);
     }
 
-    std::cout << "Starting sc_main" << std::endl;
+    SC_REPORT_INFO("sc_main", "Start of Simulation");
 
     sc_core::sc_start(); // Run to end of simulation
 
index 8ca9959a0d649a607de64a46a9de5cea6a092a80..a896a34e44b5097fc9fc6e85e4cd3bf552fb4578 100644 (file)
@@ -54,7 +54,8 @@ env.ParseConfig('pkg-config --cflags --libs systemc')
 # add include dirs
 env.Append(CPPPATH=[gem5_root + '/build/' + gem5_arch,
                     gem5_root + '/util/systemc',
-                    gem5_root + '/util/tlm'])
+                    gem5_root + '/util/tlm',
+                    '../common'])
 
 env.Append(LIBS=['gem5_' + gem5_variant])
 env.Append(LIBPATH=[gem5_root + '/build/' + gem5_arch])
@@ -72,6 +73,6 @@ src_systemc = [gem5_root + '/util/systemc/sc_gem5_control.cc',
                gem5_root + '/util/systemc/stats.cc']
 
 src_tlm     = Glob(gem5_root + '/util/tlm/*.cc')
-src_main    = Glob('*.cc')
+src_main    = Glob('*.cc') + Glob('../common/*.cc')
 
 main = env.Program(target, src_systemc + src_tlm + src_main)
index 256a99d1b6f6e16b68f113d8f1bdf2a1eb8bffed..9f1cadc8d954393601771b4c5fabf133ab25e2cf 100644 (file)
  *
  */
 
-#include <tlm_utils/simple_target_socket.h>
-
 #include <systemc>
 #include <tlm>
 
+#include "cli_parser.hh"
+#include "report_handler.hh"
 #include "sc_target.hh"
 #include "sim_control.hh"
 #include "stats.hh"
 
-// Defining global string variable decalred in stats.hh
-std::string filename;
-
-void
-reportHandler(const sc_core::sc_report &report,
-              const sc_core::sc_actions &actions)
-{
-    uint64_t systemc_time = report.get_time().value();
-    uint64_t gem5_time = curTick();
-
-    std::cerr << report.get_time();
-
-    if (gem5_time < systemc_time) {
-        std::cerr << " (<) ";
-    } else if (gem5_time > systemc_time) {
-        std::cerr << " (!) ";
-    } else {
-        std::cerr << " (=) ";
-    }
-
-    std::cerr << ": " << report.get_msg_type()
-              << ' ' << report.get_msg() << '\n';
-}
-
 int
 sc_main(int argc, char **argv)
 {
+    CliParser parser;
+    parser.parse(argc, argv);
+
     sc_core::sc_report_handler::set_handler(reportHandler);
 
-    SimControl sim_control("gem5", argc, argv);
+    Gem5SystemC::Gem5SimControl simControl("gem5",
+                                           parser.getConfigFile(),
+                                           parser.getSimulationEnd(),
+                                           parser.getDebugFlags());
     Target *memory;
 
-    filename = "m5out/stats-systemc.txt";
+    unsigned long long int memorySize = 512*1024*1024ULL;
 
     tlm::tlm_initiator_socket <> *mem_port =
         dynamic_cast<tlm::tlm_initiator_socket<> *>(
@@ -93,11 +75,10 @@ sc_main(int argc, char **argv)
 
     if (mem_port) {
         SC_REPORT_INFO("sc_main", "Port Found");
-        unsigned long long int size = 512*1024*1024ULL;
         memory = new Target("memory",
-                            sim_control.getDebugFlag(),
-                            size,
-                            sim_control.getOffset());
+                            parser.getVerboseFlag(),
+                            memorySize,
+                            parser.getMemoryOffset());
 
         memory->socket.bind(*mem_port);
     } else {
@@ -105,6 +86,8 @@ sc_main(int argc, char **argv)
         std::exit(EXIT_FAILURE);
     }
 
+    SC_REPORT_INFO("sc_main", "Start of Simulation");
+
     sc_core::sc_start();
 
     SC_REPORT_INFO("sc_main", "End of Simulation");
index 2423f1fb6d509df4063a2729ec67f16f51d5ea22..d6bedc80ba709371a6f9db5a8a7d8da5a207a391 100644 (file)
 #include "sim_control.hh"
 #include "stats.hh"
 
-void
-usage(const std::string& prog_name)
+// Define global string variable decalred in stats.hh
+std::string filename = "m5out/stats-systemc.txt";
+
+namespace Gem5SystemC
 {
-    std::cerr
-      << "Usage: " << prog_name
-      << (" <config_file.ini> [ <option> ]\n\n"
-          "OPTIONS:\n"
-
-          "    -o <offset>                  -- set memory offset\n"
-          "    -p <object> <param> <value>  -- set a parameter\n"
-          "    -v <object> <param> <values> -- set a vector parameter from a\n"
-          "                                    comma separated values string\n"
-          "    -d <flag>                    -- set a debug flag\n"
-          "                                    (-<flag> clear a flag)\n"
-          "    -D                           -- debug on\n"
-          "    -e <ticks>                   -- end of simulation after a \n"
-          "                                    given number of ticks\n"
-          "\n");
-    std::exit(EXIT_FAILURE);
-}
 
-SimControl::SimControl(sc_core::sc_module_name name, int argc_, char** argv_)
+Gem5SimControl* Gem5SimControl::instance = nullptr;
+
+Gem5SimControl::Gem5SimControl(sc_core::sc_module_name name,
+                               const std::string& configFile,
+                               uint64_t simulationEnd,
+                               const std::string& gem5DebugFlags)
   : Gem5SystemC::Module(name),
-    argc(argc_),
-    argv(argv_)
+    simulationEnd(simulationEnd)
 {
     SC_THREAD(run);
 
-    std::string prog_name(argv[0]);
-    unsigned int arg_ptr = 1;
-
-    if (argc == 1) {
-        usage(prog_name);
+    if (instance != nullptr) {
+        panic("Tried to instantiate Gem5SimControl more than once!\n");
     }
+    instance = this;
 
     cxxConfigInit();
     Gem5SystemC::SCSlavePort::registerPortHandler();
@@ -106,79 +93,32 @@ SimControl::SimControl(sc_core::sc_module_name name, int argc_, char** argv_)
 
     Trace::enable();
 
-    sim_end = 0;
-    debug = false;
-    offset = 0;
-
-    const std::string config_file(argv[arg_ptr]);
+    CxxConfigFileBase* conf = new CxxIniFile();
 
-    CxxConfigFileBase *conf = new CxxIniFile();
+    if (configFile.empty()) {
+        std::cerr << "No gem5 config file specified!\n";
+        std::exit(EXIT_FAILURE);
+    }
 
-    if (!conf->load(config_file.c_str())) {
-        std::cerr << "Can't open config file: " << config_file << '\n';
+    if (!conf->load(configFile.c_str())) {
+        std::cerr << "Can't open config file: " << configFile << '\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 == "-e") {
-                if (num_args < 1) {
-                    usage(prog_name);
-                }
-                std::istringstream(argv[arg_ptr]) >> sim_end;
-                arg_ptr++;
-            } else if (option == "-D") {
-                debug = true;
-            } else if (option == "-o") {
-                if (num_args < 1) {
-                    usage(prog_name);
-                }
-                std::istringstream(argv[arg_ptr]) >> offset;
-                arg_ptr++;
-                /* code */
-            } else {
-                usage(prog_name);
-            }
+    // parse debug flags string and clear/set flags accordingly
+    std::stringstream ss;
+    ss.str(gem5DebugFlags);
+    std::string flag;
+    while (std::getline(ss, flag, ' ')) {
+        if (flag.at(0) == '-') {
+            flag.erase(0, 1); // remove the '-'
+            clearDebugFlag(flag.c_str());
+        }
+        else {
+            setDebugFlag(flag.c_str());
         }
-    } catch (CxxConfigManager::Exception &e) {
-        std::cerr << e.name << ": " << e.message << "\n";
-        std::exit(EXIT_FAILURE);
     }
 
     CxxConfig::statsEnable();
@@ -194,7 +134,7 @@ SimControl::SimControl(sc_core::sc_module_name name, int argc_, char** argv_)
 }
 
 void
-SimControl::before_end_of_elaboration()
+Gem5SimControl::before_end_of_elaboration()
 {
     try {
         config_manager->initState();
@@ -207,14 +147,14 @@ SimControl::before_end_of_elaboration()
 }
 
 void
-SimControl::run()
+Gem5SimControl::run()
 {
     GlobalSimLoopExitEvent *exit_event = NULL;
 
-    if (sim_end == 0) {
+    if (simulationEnd == 0) {
         exit_event = simulate();
     } else {
-        exit_event = simulate(sim_end);
+        exit_event = simulate(simulationEnd);
     }
 
     std::cerr << "Exit at tick " << curTick()
@@ -226,3 +166,5 @@ SimControl::run()
     config_manager->deleteObjects();
 #endif
 }
+
+}
index 52bfa64d41c46216dc8d2fd9044baaedfc132fd7..d210d76dd6237b7006675e4ce556dba043d91cec 100644 (file)
 #include "sim/cxx_manager.hh"
 #include "sim/system.hh"
 
-class SimControl : public Gem5SystemC::Module
+namespace Gem5SystemC
+{
+
+/**
+ * This is the central SystemC module that orchestrates the gem5 simulation.
+ *
+ * The module is responsible for loading the configuration file, setting up and
+ * maintaining the event queues, as well as starting and ending the simulation.
+ * While it is mandatory to have one instance of this class for running a gem5
+ * simulation in SystemC, it is not allowed to have multiple instances!
+ */
+class Gem5SimControl : public Gem5SystemC::Module
 {
   protected:
-    int argc;
-    char** argv;
     CxxConfigManager* config_manager;
     Gem5SystemC::Logger logger;
 
-    Tick sim_end;
-    bool debug;
-    unsigned int offset;
+    Tick simulationEnd;
+
+    /// Pointer to a previously created instance.
+    static Gem5SimControl* instance;
 
   public:
-    SC_HAS_PROCESS(SimControl);
+    SC_HAS_PROCESS(Gem5SimControl);
 
-    SimControl(sc_core::sc_module_name name, int argc_, char** argv_);
+    /**
+     * Constructor.
+     *
+     * This class has a public constructor although the class is actually a
+     * singleton. The public constructor is required to ensure compatibility
+     * to external SystemC based tools. For the same reason, the constructor
+     * parameters are basic types (int, string).
+     *
+     * @param configFile     location of the gem5 configuration file
+     * @param simulationEnd  number of ticks to simulate
+     * @param gem5DebugFlags a space separated list of gem5 debug flags to be
+     *                       set, a prepended '-' clears the flag
+     */
+    Gem5SimControl(sc_core::sc_module_name name,
+                   const std::string& configFile,
+                   uint64_t simulationEnd,
+                   const std::string& gem5DebugFlags);
 
     void before_end_of_elaboration();
 
-    bool getDebugFlag() { return debug; }
-
-    unsigned int getOffset() { return offset; }
-
     void run();
 };
 
+}
+
 #endif