misc: Merge branch 'release-staging-v21-2' into develop

Change-Id: Icc03e585d87cf89ed844a0249c365cc296fa2d14
diff --git a/configs/common/CacheConfig.py b/configs/common/CacheConfig.py
index 4979f7d..61c6a30 100644
--- a/configs/common/CacheConfig.py
+++ b/configs/common/CacheConfig.py
@@ -87,7 +87,7 @@
         dcache_class, icache_class, l2_cache_class, walk_cache_class = \
             core.O3_ARM_v7a_DCache, core.O3_ARM_v7a_ICache, \
             core.O3_ARM_v7aL2, \
-            core.O3_ARM_v7aWalkCache
+            None
     elif options.cpu_type == "HPI":
         try:
             import cores.arm.HPI as core
@@ -96,7 +96,7 @@
             sys.exit(1)
 
         dcache_class, icache_class, l2_cache_class, walk_cache_class = \
-            core.HPI_DCache, core.HPI_ICache, core.HPI_L2, core.HPI_WalkCache
+            core.HPI_DCache, core.HPI_ICache, core.HPI_L2, None
     else:
         dcache_class, icache_class, l2_cache_class, walk_cache_class = \
             L1_DCache, L1_ICache, L2Cache, None
diff --git a/configs/common/cores/arm/HPI.py b/configs/common/cores/arm/HPI.py
index 624c40c..620c01e 100644
--- a/configs/common/cores/arm/HPI.py
+++ b/configs/common/cores/arm/HPI.py
@@ -1332,16 +1332,6 @@
     itb = ArmTLB(entry_type="instruction", size=256)
     dtb = ArmTLB(entry_type="data", size=256)
 
-class HPI_WalkCache(Cache):
-    data_latency = 4
-    tag_latency = 4
-    response_latency = 4
-    mshrs = 6
-    tgts_per_mshr = 8
-    size = '1kB'
-    assoc = 8
-    write_buffers = 16
-
 class HPI_BP(TournamentBP):
     localPredictorSize = 64
     localCtrBits = 2
@@ -1442,7 +1432,7 @@
 
 __all__ = [
     "HPI_BP",
-    "HPI_ITB", "HPI_DTB", "HPI_WalkCache",
+    "HPI_ITB", "HPI_DTB",
     "HPI_ICache", "HPI_DCache", "HPI_L2",
     "HPI",
 ]
diff --git a/configs/common/cores/arm/O3_ARM_v7a.py b/configs/common/cores/arm/O3_ARM_v7a.py
index a402e5f..8cacc65 100644
--- a/configs/common/cores/arm/O3_ARM_v7a.py
+++ b/configs/common/cores/arm/O3_ARM_v7a.py
@@ -169,21 +169,6 @@
     # Consider the L2 a victim cache also for clean lines
     writeback_clean = True
 
-# TLB Cache
-# Use a cache as a L2 TLB
-class O3_ARM_v7aWalkCache(Cache):
-    tag_latency = 4
-    data_latency = 4
-    response_latency = 4
-    mshrs = 6
-    tgts_per_mshr = 8
-    size = '1kB'
-    assoc = 8
-    write_buffers = 16
-    is_read_only = True
-    # Writeback clean lines as well
-    writeback_clean = True
-
 # L2 Cache
 class O3_ARM_v7aL2(Cache):
     tag_latency = 12
diff --git a/configs/common/cores/arm/ex5_LITTLE.py b/configs/common/cores/arm/ex5_LITTLE.py
index b3f1ad5..bcbaa92 100644
--- a/configs/common/cores/arm/ex5_LITTLE.py
+++ b/configs/common/cores/arm/ex5_LITTLE.py
@@ -112,21 +112,6 @@
     assoc = 4
     write_buffers = 4
 
-# TLB Cache
-# Use a cache as a L2 TLB
-class WalkCache(Cache):
-    tag_latency = 2
-    data_latency = 2
-    response_latency = 2
-    mshrs = 6
-    tgts_per_mshr = 8
-    size = '1kB'
-    assoc = 2
-    write_buffers = 16
-    is_read_only = True
-    # Writeback clean lines as well
-    writeback_clean = True
-
 # L2 Cache
 class L2(Cache):
     tag_latency = 9
diff --git a/configs/common/cores/arm/ex5_big.py b/configs/common/cores/arm/ex5_big.py
index c734c62..eb5f53f 100644
--- a/configs/common/cores/arm/ex5_big.py
+++ b/configs/common/cores/arm/ex5_big.py
@@ -164,21 +164,6 @@
     assoc = 2
     write_buffers = 16
 
-# TLB Cache
-# Use a cache as a L2 TLB
-class WalkCache(Cache):
-    tag_latency = 4
-    data_latency = 4
-    response_latency = 4
-    mshrs = 6
-    tgts_per_mshr = 8
-    size = '1kB'
-    assoc = 8
-    write_buffers = 16
-    is_read_only = True
-    # Writeback clean lines as well
-    writeback_clean = True
-
 # L2 Cache
 class L2(Cache):
     tag_latency = 15
diff --git a/configs/example/arm/baremetal.py b/configs/example/arm/baremetal.py
index 9655bb1..0944344 100644
--- a/configs/example/arm/baremetal.py
+++ b/configs/example/arm/baremetal.py
@@ -61,14 +61,12 @@
 # the cache class may be 'None' if the particular cache is not present.
 cpu_types = {
 
-    "atomic" : ( AtomicSimpleCPU, None, None, None, None),
+    "atomic" : ( AtomicSimpleCPU, None, None, None),
     "minor" : (MinorCPU,
                devices.L1I, devices.L1D,
-               devices.WalkCache,
                devices.L2),
     "hpi" : ( HPI.HPI,
               HPI.HPI_ICache, HPI.HPI_DCache,
-              HPI.HPI_WalkCache,
               HPI.HPI_L2)
 }
 
diff --git a/configs/example/arm/devices.py b/configs/example/arm/devices.py
index 73aea59..9122e7c 100644
--- a/configs/example/arm/devices.py
+++ b/configs/example/arm/devices.py
@@ -65,17 +65,6 @@
     write_buffers = 16
 
 
-class WalkCache(PageTableWalkerCache):
-    tag_latency = 4
-    data_latency = 4
-    response_latency = 4
-    mshrs = 6
-    tgts_per_mshr = 8
-    size = '1kB'
-    assoc = 8
-    write_buffers = 16
-
-
 class L2(L2Cache):
     tag_latency = 12
     data_latency = 12
@@ -106,12 +95,11 @@
 
 class CpuCluster(SubSystem):
     def __init__(self, system,  num_cpus, cpu_clock, cpu_voltage,
-                 cpu_type, l1i_type, l1d_type, wcache_type, l2_type):
+                 cpu_type, l1i_type, l1d_type, l2_type):
         super(CpuCluster, self).__init__()
         self._cpu_type = cpu_type
         self._l1i_type = l1i_type
         self._l1d_type = l1d_type
-        self._wcache_type = wcache_type
         self._l2_type = l2_type
 
         assert num_cpus > 0
@@ -140,9 +128,7 @@
         for cpu in self.cpus:
             l1i = None if self._l1i_type is None else self._l1i_type()
             l1d = None if self._l1d_type is None else self._l1d_type()
-            iwc = None if self._wcache_type is None else self._wcache_type()
-            dwc = None if self._wcache_type is None else self._wcache_type()
-            cpu.addPrivateSplitL1Caches(l1i, l1d, iwc, dwc)
+            cpu.addPrivateSplitL1Caches(l1i, l1d)
 
     def addL2(self, clk_domain):
         if self._l2_type is None:
diff --git a/configs/example/arm/fs_bigLITTLE.py b/configs/example/arm/fs_bigLITTLE.py
index c590fe5..3f8b0cf 100644
--- a/configs/example/arm/fs_bigLITTLE.py
+++ b/configs/example/arm/fs_bigLITTLE.py
@@ -79,7 +79,7 @@
     def __init__(self, system, num_cpus, cpu_clock,
                  cpu_voltage="1.0V"):
         cpu_config = [ ObjectList.cpu_list.get("O3_ARM_v7a_3"),
-            devices.L1I, devices.L1D, devices.WalkCache, devices.L2 ]
+            devices.L1I, devices.L1D, devices.L2 ]
         super(BigCluster, self).__init__(system, num_cpus, cpu_clock,
                                          cpu_voltage, *cpu_config)
 
@@ -87,7 +87,7 @@
     def __init__(self, system, num_cpus, cpu_clock,
                  cpu_voltage="1.0V"):
         cpu_config = [ ObjectList.cpu_list.get("MinorCPU"), devices.L1I,
-            devices.L1D, devices.WalkCache, devices.L2 ]
+            devices.L1D, devices.L2 ]
         super(LittleCluster, self).__init__(system, num_cpus, cpu_clock,
                                          cpu_voltage, *cpu_config)
 
@@ -95,7 +95,7 @@
     def __init__(self, system, num_cpus, cpu_clock,
                  cpu_voltage="1.0V"):
         cpu_config = [ ObjectList.cpu_list.get("ex5_big"), ex5_big.L1I,
-            ex5_big.L1D, ex5_big.WalkCache, ex5_big.L2 ]
+            ex5_big.L1D, ex5_big.L2 ]
         super(Ex5BigCluster, self).__init__(system, num_cpus, cpu_clock,
                                          cpu_voltage, *cpu_config)
 
@@ -103,7 +103,7 @@
     def __init__(self, system, num_cpus, cpu_clock,
                  cpu_voltage="1.0V"):
         cpu_config = [ ObjectList.cpu_list.get("ex5_LITTLE"),
-            ex5_LITTLE.L1I, ex5_LITTLE.L1D, ex5_LITTLE.WalkCache,
+            ex5_LITTLE.L1I, ex5_LITTLE.L1D,
             ex5_LITTLE.L2 ]
         super(Ex5LittleCluster, self).__init__(system, num_cpus, cpu_clock,
                                          cpu_voltage, *cpu_config)
diff --git a/configs/example/arm/ruby_fs.py b/configs/example/arm/ruby_fs.py
index 3783f33..d820f86 100644
--- a/configs/example/arm/ruby_fs.py
+++ b/configs/example/arm/ruby_fs.py
@@ -62,14 +62,12 @@
 # the cache class may be 'None' if the particular cache is not present.
 cpu_types = {
 
-    "noncaching" : ( NonCachingSimpleCPU, None, None, None, None),
+    "noncaching" : ( NonCachingSimpleCPU, None, None, None),
     "minor" : (MinorCPU,
                devices.L1I, devices.L1D,
-               devices.WalkCache,
                devices.L2),
     "hpi" : ( HPI.HPI,
               HPI.HPI_ICache, HPI.HPI_DCache,
-              HPI.HPI_WalkCache,
               HPI.HPI_L2)
 }
 
diff --git a/configs/example/arm/starter_fs.py b/configs/example/arm/starter_fs.py
index 11190db..40e645b 100644
--- a/configs/example/arm/starter_fs.py
+++ b/configs/example/arm/starter_fs.py
@@ -65,14 +65,12 @@
 # the cache class may be 'None' if the particular cache is not present.
 cpu_types = {
 
-    "atomic" : ( AtomicSimpleCPU, None, None, None, None),
+    "atomic" : ( AtomicSimpleCPU, None, None, None),
     "minor" : (MinorCPU,
                devices.L1I, devices.L1D,
-               devices.WalkCache,
                devices.L2),
     "hpi" : ( HPI.HPI,
               HPI.HPI_ICache, HPI.HPI_DCache,
-              HPI.HPI_WalkCache,
               HPI.HPI_L2)
 }
 
diff --git a/configs/example/arm/starter_se.py b/configs/example/arm/starter_se.py
index 82fc49e..d80f749 100644
--- a/configs/example/arm/starter_se.py
+++ b/configs/example/arm/starter_se.py
@@ -59,14 +59,12 @@
 # l1_icache_class, l1_dcache_class, walk_cache_class, l2_Cache_class). Any of
 # the cache class may be 'None' if the particular cache is not present.
 cpu_types = {
-    "atomic" : ( AtomicSimpleCPU, None, None, None, None),
+    "atomic" : ( AtomicSimpleCPU, None, None, None),
     "minor" : (MinorCPU,
                devices.L1I, devices.L1D,
-               devices.WalkCache,
                devices.L2),
     "hpi" : ( HPI.HPI,
               HPI.HPI_ICache, HPI.HPI_DCache,
-              HPI.HPI_WalkCache,
               HPI.HPI_L2)
 }
 
diff --git a/ext/sst/gem5.cc b/ext/sst/gem5.cc
index 1d90bc5..7af0eed 100644
--- a/ext/sst/gem5.cc
+++ b/ext/sst/gem5.cc
@@ -194,6 +194,7 @@
         initPython(args.size(), &args[0]);
 
         const std::vector<std::string> m5_instantiate_commands = {
+            "import m5",
             "m5.instantiate()"
         };
         execPythonCommands(m5_instantiate_commands);
@@ -201,7 +202,10 @@
         // calling SimObject.startup()
         const std::vector<std::string> simobject_setup_commands = {
             "import atexit",
-            "import _m5",
+            "import _m5.core",
+            "import m5",
+            "import m5.stats",
+            "import m5.objects.Root",
             "root = m5.objects.Root.getInstance()",
             "for obj in root.descendants(): obj.startup()",
             "atexit.register(m5.stats.dump)",
@@ -258,6 +262,7 @@
         );
         // output gem5 stats
         const std::vector<std::string> output_stats_commands = {
+            "import m5.stats",
             "m5.stats.dump()"
         };
         execPythonCommands(output_stats_commands);
@@ -355,7 +360,8 @@
 int
 gem5Component::execPythonCommands(const std::vector<std::string>& commands)
 {
-    PyObject *dict = PyModule_GetDict(pythonMain);
+    static PyObject *dict =
+        py::module_::import("__main__").attr("__dict__").ptr();
 
     PyObject *result;
 
@@ -376,8 +382,27 @@
     // Initialize gem5 special signal handling.
     gem5::initSignals();
 
-    if (!Py_IsInitialized())
-        py::initialize_interpreter(false, argc, _argv);
+    if (!Py_IsInitialized()) {
+        py::initialize_interpreter(true, argc, _argv);
+    } else {
+        // pybind doesn't provide a way to set sys.argv if not initializing the
+        // interpreter, so we have to do that manually if it's already running.
+        py::list py_argv;
+        auto sys = py::module::import("sys");
+        if (py::hasattr(sys, "argv")) {
+            // sys.argv already exists, so grab that.
+            py_argv = sys.attr("argv");
+        } else {
+            // sys.argv doesn't exist, so create it.
+            sys.add_object("argv", py_argv);
+        }
+        // Clear out argv just in case it has something in it.
+        py_argv.attr("clear")();
+
+        // Fill it with our argvs.
+        for (int i = 0; i < argc; i++)
+            py_argv.append(_argv[i]);
+    }
 
     auto importer = py::module_::import("importer");
     importer.attr("install")();
diff --git a/ext/sst/gem5.hh b/ext/sst/gem5.hh
index 2712411..447c68c 100644
--- a/ext/sst/gem5.hh
+++ b/ext/sst/gem5.hh
@@ -104,7 +104,6 @@
 
   // stuff needed for gem5 sim
   public:
-    PyObject *pythonMain;
     int execPythonCommands(const std::vector<std::string>& commands);
 
   private:
diff --git a/src/SConscript b/src/SConscript
index 7eb810a..e40262a 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -149,13 +149,21 @@
     enums = dict()
     tags = dict()
 
-    def __init__(self, source, *, sim_objects=[], enums=[],
+    def __init__(self, source, *, sim_objects=None, enums=None,
             tags=None, add_tags=None):
         '''Specify the source file and any tags (automatically in
         the m5.objects package)'''
+        if sim_objects is None:
+            if enums is None:
+                error(f"SimObject({source}...) must list c++ sim_objects or "
+                      "enums (set either to [] if there are none).")
+            sim_objects = []
+        if enums is None:
+            enums = []
+
         super().__init__('m5.objects', source, tags, add_tags)
         if self.fixed:
-            raise AttributeError("Too late to call SimObject now.")
+            error("Too late to call SimObject now.")
 
         SimObject.sim_objects[self.modpath] = sim_objects
         SimObject.enums[self.modpath] = enums
diff --git a/src/cpu/o3/SConscript b/src/cpu/o3/SConscript
index a20e30d..ba021a8 100755
--- a/src/cpu/o3/SConscript
+++ b/src/cpu/o3/SConscript
@@ -32,7 +32,7 @@
 
 if 'O3CPU' in env['CPU_MODELS']:
     SimObject('FUPool.py', sim_objects=['FUPool'])
-    SimObject('FuncUnitConfig.py')
+    SimObject('FuncUnitConfig.py', sim_objects=[])
     SimObject('O3CPU.py', sim_objects=['O3CPU'], enums=[
         'SMTFetchPolicy', 'SMTQueuePolicy', 'CommitPolicy'])
 
diff --git a/src/dev/SConscript b/src/dev/SConscript
index db3163e..755ddb5 100644
--- a/src/dev/SConscript
+++ b/src/dev/SConscript
@@ -35,7 +35,7 @@
 Source('dma_device.cc')
 Source('dma_virt_device.cc')
 
-SimObject('IntPin.py')
+SimObject('IntPin.py', sim_objects=[])
 Source('intpin.cc')
 
 DebugFlag('IsaFake')
diff --git a/src/sim/main.cc b/src/sim/main.cc
index c44531e..81a691d 100644
--- a/src/sim/main.cc
+++ b/src/sim/main.cc
@@ -60,28 +60,11 @@
     // It's probably not necessary, but is mostly harmless and might be useful.
     Py_SetProgramName(program.get());
 
-    py::scoped_interpreter guard;
+    py::scoped_interpreter guard(true, argc, argv);
 
     auto importer = py::module_::import("importer");
     importer.attr("install")();
 
-    // Embedded python doesn't set up sys.argv, so we'll do that ourselves.
-    py::list py_argv;
-    auto sys = py::module::import("sys");
-    if (py::hasattr(sys, "argv")) {
-        // sys.argv already exists, so grab that.
-        py_argv = sys.attr("argv");
-    } else {
-        // sys.argv doesn't exist, so create it.
-        sys.add_object("argv", py_argv);
-    }
-    // Clear out argv just in case it has something in it.
-    py_argv.attr("clear")();
-
-    // Fill it with our argvs.
-    for (int i = 0; i < argc; i++)
-        py_argv.append(argv[i]);
-
     try {
         py::module_::import("m5").attr("main")();
     } catch (py::error_already_set &e) {
diff --git a/src/systemc/SConscript b/src/systemc/SConscript
index ef7e79b..57cb1d9 100644
--- a/src/systemc/SConscript
+++ b/src/systemc/SConscript
@@ -32,4 +32,4 @@
 
 env.Append(CPPPATH=Dir('ext'))
 
-SimObject('Tlm.py')
+SimObject('Tlm.py', sim_objects=[])
diff --git a/src/systemc/core/SystemC.py b/src/systemc/core/SystemC.py
index 6828175..592b950 100644
--- a/src/systemc/core/SystemC.py
+++ b/src/systemc/core/SystemC.py
@@ -63,11 +63,3 @@
     @cxxMethod(return_value_policy="reference", cxx_name="gem5_getPort")
     def getPort(self, if_name, iex):
         return None
-
-try:
-    import _m5
-except:
-    pass
-else:
-    import _m5.systemc
-    _m5.systemc.python_ready()
diff --git a/src/systemc/core/python.cc b/src/systemc/core/python.cc
index 8f2d56b..472a050 100644
--- a/src/systemc/core/python.cc
+++ b/src/systemc/core/python.cc
@@ -38,13 +38,6 @@
 namespace
 {
 
-PythonReadyFunc *&
-firstReadyFunc()
-{
-    static PythonReadyFunc *first = nullptr;
-    return first;
-}
-
 PythonInitFunc *&
 firstInitFunc()
 {
@@ -52,33 +45,31 @@
     return first;
 }
 
-void
-python_ready(pybind11::args args)
-{
-    for (auto ptr = firstReadyFunc(); ptr; ptr = ptr->next)
-        ptr->run();
-}
+bool python_initialized = false;
 
 void
 systemc_pybind(pybind11::module_ &m_internal)
 {
     pybind11::module_ m = m_internal.def_submodule("systemc");
-    m.def("python_ready", &python_ready);
     for (auto ptr = firstInitFunc(); ptr; ptr = ptr->next)
-        ptr->run(m);
+        ptr->callback(m);
+
+    python_initialized = true;
 }
 gem5::EmbeddedPyBind embed_("systemc", &systemc_pybind);
 
 } // anonymous namespace
 
-PythonReadyFunc::PythonReadyFunc() : next(firstReadyFunc())
-{
-    firstReadyFunc() = this;
-}
-
-PythonInitFunc::PythonInitFunc() : next(firstInitFunc())
+PythonInitFunc::PythonInitFunc(Callback run) :
+    callback(run), next(firstInitFunc())
 {
     firstInitFunc() = this;
+
+    // If the python was already initialized, run the callback immediately.
+    if (python_initialized) {
+        auto systemc_module = pybind11::module_::import("_m5.systemc");
+        callback(systemc_module);
+    }
 }
 
 } // namespace sc_gem5
diff --git a/src/systemc/core/python.hh b/src/systemc/core/python.hh
index 61c9c80..3c563db 100644
--- a/src/systemc/core/python.hh
+++ b/src/systemc/core/python.hh
@@ -33,22 +33,14 @@
 namespace sc_gem5
 {
 
-struct PythonReadyFunc
-{
-    PythonReadyFunc *next;
-
-    PythonReadyFunc();
-    ~PythonReadyFunc() {}
-    virtual void run() = 0;
-};
-
 struct PythonInitFunc
 {
+    using Callback = void(*)(pybind11::module_ &systemc);
+    Callback callback;
+
     PythonInitFunc *next;
 
-    PythonInitFunc();
-    ~PythonInitFunc() {}
-    virtual void run(pybind11::module_ &systemc) = 0;
+    PythonInitFunc(Callback run);
 };
 
 } // namespace sc_gem5
diff --git a/src/systemc/core/sc_main_python.cc b/src/systemc/core/sc_main_python.cc
index 1697efe..8d2542e 100644
--- a/src/systemc/core/sc_main_python.cc
+++ b/src/systemc/core/sc_main_python.cc
@@ -92,15 +92,10 @@
 // Make our sc_main wrapper available in the internal _m5 python module under
 // the systemc submodule.
 
-struct InstallScMain : public ::sc_gem5::PythonInitFunc
-{
-    void
-    run(pybind11::module_ &systemc) override
-    {
-        systemc.def("sc_main", &sc_main);
-        systemc.def("sc_main_result_code", &sc_main_result_code);
-        systemc.def("sc_main_result_str", &sc_main_result_str);
-    }
-} installScMain;
+::sc_gem5::PythonInitFunc installScMain([](pybind11::module_ &systemc) {
+    systemc.def("sc_main", &sc_main);
+    systemc.def("sc_main_result_code", &sc_main_result_code);
+    systemc.def("sc_main_result_str", &sc_main_result_str);
+});
 
 } // anonymous namespace
diff --git a/src/systemc/core/sc_time_python.cc b/src/systemc/core/sc_time_python.cc
index 58fa65f..be383bc 100644
--- a/src/systemc/core/sc_time_python.cc
+++ b/src/systemc/core/sc_time_python.cc
@@ -33,48 +33,43 @@
 namespace
 {
 
-struct InstallScTime : public ::sc_gem5::PythonInitFunc
-{
-    void
-    run(pybind11::module_ &systemc) override
-    {
-        pybind11::class_<sc_core::sc_time> sc_time(systemc, "sc_time");
-        sc_time
-            // Constructors (omitting nonstandard and deprecated)
-            .def(pybind11::init<>())
-            .def(pybind11::init<double, sc_core::sc_time_unit>())
-            .def(pybind11::init<const sc_core::sc_time &>())
+::sc_gem5::PythonInitFunc installScTime([](pybind11::module_ &systemc) {
+    pybind11::class_<sc_core::sc_time> sc_time(systemc, "sc_time");
+    sc_time
+        // Constructors (omitting nonstandard and deprecated)
+        .def(pybind11::init<>())
+        .def(pybind11::init<double, sc_core::sc_time_unit>())
+        .def(pybind11::init<const sc_core::sc_time &>())
 
-            // Converters.
-            .def("value", &sc_core::sc_time::value)
-            .def("to_double", &sc_core::sc_time::to_double)
-            .def("to_seconds", &sc_core::sc_time::to_seconds)
-            .def("to_string", &sc_core::sc_time::to_string)
-            .def("__str__", &sc_core::sc_time::to_string)
+        // Converters.
+        .def("value", &sc_core::sc_time::value)
+        .def("to_double", &sc_core::sc_time::to_double)
+        .def("to_seconds", &sc_core::sc_time::to_seconds)
+        .def("to_string", &sc_core::sc_time::to_string)
+        .def("__str__", &sc_core::sc_time::to_string)
 
-            // Operators.
-            .def(pybind11::self == pybind11::self)
-            .def(pybind11::self != pybind11::self)
-            .def(pybind11::self < pybind11::self)
-            .def(pybind11::self <= pybind11::self)
-            .def(pybind11::self > pybind11::self)
-            .def(pybind11::self >= pybind11::self)
-            .def(pybind11::self += pybind11::self)
-            .def(pybind11::self -= pybind11::self)
-            .def(pybind11::self *= double())
-            .def(pybind11::self /= double())
-            ;
+        // Operators.
+        .def(pybind11::self == pybind11::self)
+        .def(pybind11::self != pybind11::self)
+        .def(pybind11::self < pybind11::self)
+        .def(pybind11::self <= pybind11::self)
+        .def(pybind11::self > pybind11::self)
+        .def(pybind11::self >= pybind11::self)
+        .def(pybind11::self += pybind11::self)
+        .def(pybind11::self -= pybind11::self)
+        .def(pybind11::self *= double())
+        .def(pybind11::self /= double())
+        ;
 
-        pybind11::enum_<sc_core::sc_time_unit>(sc_time, "sc_time_unit")
-            .value("SC_FS", sc_core::SC_FS)
-            .value("SC_PS", sc_core::SC_PS)
-            .value("SC_NS", sc_core::SC_NS)
-            .value("SC_US", sc_core::SC_US)
-            .value("SC_MS", sc_core::SC_MS)
-            .value("SC_SEC", sc_core::SC_SEC)
-            .export_values()
-            ;
-    }
-} installScTime;
+    pybind11::enum_<sc_core::sc_time_unit>(sc_time, "sc_time_unit")
+        .value("SC_FS", sc_core::SC_FS)
+        .value("SC_PS", sc_core::SC_PS)
+        .value("SC_NS", sc_core::SC_NS)
+        .value("SC_US", sc_core::SC_US)
+        .value("SC_MS", sc_core::SC_MS)
+        .value("SC_SEC", sc_core::SC_SEC)
+        .export_values()
+        ;
+});
 
 } // anonymous namespace
diff --git a/src/systemc/tests/SConscript b/src/systemc/tests/SConscript
index 7d544f2..fb916d2 100644
--- a/src/systemc/tests/SConscript
+++ b/src/systemc/tests/SConscript
@@ -63,7 +63,8 @@
     test_dir = Dir('.')
     class SystemCTestBin(Executable):
         def __init__(self, test):
-            super().__init__(test.target, *test.sources)
+            all_sources = test.sources + [with_tag('main')]
+            super().__init__(test.target, *all_sources)
             self.reldir = test.reldir
             self.test_deps = test.deps
 
@@ -78,26 +79,16 @@
 
             env.Append(CPPPATH=test_dir.Dir('include'))
 
-            shared_lib_path = env['SHARED_LIB'][0].abspath
-            sl_dir, sl_base = os.path.split(shared_lib_path)
-            env.Append(LIBPATH=[sl_dir], LIBS=[sl_base])
+            env.Append(LIBPATH=['${BUILDDIR}'], LIBS=['gem5_${ENV_LABEL}'])
+            env.AddLocalRPATH('${BUILDDIR}')
+
+            env['OBJSUFFIX'] = '.sc' + env['OBJSUFFIX'][1:]
+            env['SHOBJSUFFIX'] = '.sc' + env['OBJSUFFIX'][1:]
 
             super().declare_all(env)
 
         def declare(self, env):
-            env = env.Clone()
-            sources = list(self.sources)
-            for f in self.filters:
-                sources += Source.all.apply_filter(f)
-            objs = self.srcs_to_objs(env, sources)
-            objs = objs + env['MAIN_OBJS']
-            relpath = os.path.relpath(
-                    env['SHARED_LIB'][0].dir.abspath,
-                    self.path(env).dir.abspath)
-            env.Append(LINKFLAGS=Split('-z origin'))
-            env.Append(RPATH=[
-                    env.Literal(os.path.join('\\$$ORIGIN', relpath))])
-            test_bin = super().declare(env, objs)
+            test_bin, _u = super().declare(env)
             test_dir = self.dir.Dir(self.reldir)
             for dep in self.test_deps:
                 env.Depends(test_bin, test_dir.File(dep))
diff --git a/src/systemc/tests/verify.py b/src/systemc/tests/verify.py
index 54b4633..818855a 100755
--- a/src/systemc/tests/verify.py
+++ b/src/systemc/tests/verify.py
@@ -277,9 +277,9 @@
     test_filt = merge_filts(
         r'^/.*:\d+: ',
         r'^Global frequency set at \d* ticks per second\n',
-        r'info: Entering event queue @ \d*\.  Starting simulation\.\.\.\n',
-        r'warn: Ignoring request to set stack size\.\n',
-        r'^warn: No dot file generated. Please install pydot ' +
+        r'.*info: Entering event queue @ \d*\.  Starting simulation\.\.\.\n',
+        r'.*warn: Ignoring request to set stack size\.\n',
+        r'^.*warn: No dot file generated. Please install pydot ' +
         r'to generate the dot file and pdf.\n',
         info_filt(804),
         in_file_filt,
diff --git a/src/systemc/tlm_core/2/quantum/global_quantum_python.cc b/src/systemc/tlm_core/2/quantum/global_quantum_python.cc
index c29a232..a00db0c 100644
--- a/src/systemc/tlm_core/2/quantum/global_quantum_python.cc
+++ b/src/systemc/tlm_core/2/quantum/global_quantum_python.cc
@@ -31,21 +31,17 @@
 namespace
 {
 
-struct InstallTlmGlobalQuantum : public ::sc_gem5::PythonInitFunc
-{
-    void
-    run(pybind11::module_ &systemc) override
-    {
-        pybind11::class_<tlm::tlm_global_quantum>(
-                systemc, "tlm_global_quantum")
-            .def_static("instance", &tlm::tlm_global_quantum::instance,
-                        pybind11::return_value_policy::reference)
-            .def("set", &tlm::tlm_global_quantum::set)
-            .def("get", &tlm::tlm_global_quantum::get)
-            .def("compute_local_quantum",
-                    &tlm::tlm_global_quantum::compute_local_quantum)
-            ;
-    }
-} installTlmGlobalQuantum;
+::sc_gem5::PythonInitFunc installTlmGlobalQuantum(
+        [](pybind11::module_ &systemc) {
+    pybind11::class_<tlm::tlm_global_quantum>(
+            systemc, "tlm_global_quantum")
+        .def_static("instance", &tlm::tlm_global_quantum::instance,
+                    pybind11::return_value_policy::reference)
+        .def("set", &tlm::tlm_global_quantum::set)
+        .def("get", &tlm::tlm_global_quantum::get)
+        .def("compute_local_quantum",
+                &tlm::tlm_global_quantum::compute_local_quantum)
+        ;
+});
 
 } // anonymous namespace