systemc: Use the new python interface to delay fixing the timescale.
authorGabe Black <gabeblack@google.com>
Tue, 7 Aug 2018 10:54:08 +0000 (03:54 -0700)
committerGabe Black <gabeblack@google.com>
Thu, 20 Sep 2018 01:40:30 +0000 (01:40 +0000)
This is necessary if an sc_time object is constructed globally, either
directly or indirectly, before python is available to fix the
timescale. The call will be deferred until the interpretter is up and
ready.

Change-Id: I486c0a90d44a0e0f0ad8c530b7148e1cff04a5cc
Reviewed-on: https://gem5-review.googlesource.com/12070
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/systemc/core/sc_time.cc

index 43d39008d53325284ce8910518d60fd35c4cab65..93150aacee081462f3aa94133ce0732e4717d4a6 100644 (file)
  * Authors: Gabe Black
  */
 
+#include <vector>
+
 #include "base/logging.hh"
 #include "base/types.hh"
 #include "python/pybind11/pybind.hh"
+#include "systemc/core/python.hh"
 #include "systemc/ext/core/sc_time.hh"
 
 namespace sc_core
@@ -56,19 +59,81 @@ double TimeUnitScale[] = {
     [SC_SEC] = 1.0
 };
 
+bool timeFixed = false;
+bool pythonReady = false;
+
+struct SetInfo
+{
+    SetInfo(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu) :
+        time(time), d(d), tu(tu)
+    {}
+
+    ::sc_core::sc_time *time;
+    double d;
+    ::sc_core::sc_time_unit tu;
+};
+std::vector<SetInfo> toSet;
+
 void
-fixTimeResolution()
+setWork(sc_time *time, double d, ::sc_core::sc_time_unit tu)
 {
-    static bool fixed = false;
-    if (fixed)
-        return;
+    //XXX Assuming the time resolution is 1ps.
+    double scale = TimeUnitScale[tu] / TimeUnitScale[SC_PS];
+    // Accellera claims there is a linux bug, and that these next two
+    // lines work around them.
+    volatile double tmp = d * scale + 0.5;
+    *time = sc_time::from_value(static_cast<uint64_t>(tmp));
+}
 
+void
+fixTime()
+{
     auto ticks = pybind11::module::import("m5.ticks");
     auto fix_global_frequency = ticks.attr("fixGlobalFrequency");
     fix_global_frequency();
-    fixed = true;
+
+    for (auto &t: toSet)
+        setWork(t.time, t.d, t.tu);
+    toSet.clear();
 }
 
+void
+set(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu)
+{
+    // Only fix time once.
+    if (!timeFixed) {
+        timeFixed = true;
+
+        // If we've run, python is working and we haven't fixed time yet.
+        if (pythonReady)
+            fixTime();
+    }
+    if (pythonReady) {
+        // Time should be working. Set up this sc_time.
+        setWork(time, d, tu);
+    } else {
+        // Time isn't set up yet. Defer setting up this sc_time.
+        toSet.emplace_back(time, d, tu);
+    }
+}
+
+class TimeSetter : public ::sc_gem5::PythonReadyFunc
+{
+  public:
+    TimeSetter() : ::sc_gem5::PythonReadyFunc() {}
+
+    void
+    run() override
+    {
+        // Record that we've run and python/pybind should be usable.
+        pythonReady = true;
+
+        // If time is already fixed, let python know.
+        if (timeFixed)
+            fixTime();
+    }
+} timeSetter;
+
 } // anonymous namespace
 
 sc_time::sc_time() : val(0) {}
@@ -76,15 +141,8 @@ sc_time::sc_time() : val(0) {}
 sc_time::sc_time(double d, sc_time_unit tu)
 {
     val = 0;
-    if (d != 0) {
-        fixTimeResolution();
-        //XXX Assuming the time resolution is 1ps.
-        double scale = TimeUnitScale[tu] / TimeUnitScale[SC_PS];
-        // Accellera claims there is a linux bug, and that these next two
-        // lines work around them.
-        volatile double tmp = d * scale + 0.5;
-        val = static_cast<uint64_t>(tmp);
-    }
+    if (d != 0)
+        set(this, d, tu);
 }
 
 sc_time::sc_time(const sc_time &t)