sim: Push the global frequency management code into C++.

That makes it available when python is left out, and makes it available
to c++ code without having to call back into python.

Change-Id: If82e7e8eff526f2b957f84afe046e1d56fed4aa2
Reviewed-on: https://gem5-review.googlesource.com/c/14055
Reviewed-by: Srikant Bharadwaj <srikant.bharadwaj@amd.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
diff --git a/src/python/m5/ticks.py b/src/python/m5/ticks.py
index 582c65c..fe25842 100644
--- a/src/python/m5/ticks.py
+++ b/src/python/m5/ticks.py
@@ -31,26 +31,14 @@
 import sys
 from m5.util import warn
 
-tps = 1.0e12         # default to 1 THz (1 Tick == 1 ps)
-tps_fixed = False    # once set to true, can't be changed
-
-# fix the global frequency and tell C++ about it
+# fix the global frequency
 def fixGlobalFrequency():
     import _m5.core
-    global tps, tps_fixed
-    if not tps_fixed:
-        tps_fixed = True
-        _m5.core.setClockFrequency(int(tps))
-        print("Global frequency set at %d ticks per second" % int(tps))
+    _m5.core.fixClockFrequency()
 
 def setGlobalFrequency(ticksPerSecond):
     from m5.util import convert
-
-    global tps, tps_fixed
-
-    if tps_fixed:
-        raise AttributeError, \
-              "Global frequency already fixed at %f ticks/s." % tps
+    import _m5.core
 
     if isinstance(ticksPerSecond, (int, long)):
         tps = ticksPerSecond
@@ -61,17 +49,20 @@
     else:
         raise TypeError, \
               "wrong type '%s' for ticksPerSecond" % type(ticksPerSecond)
+    _m5.core.setClockFrequency(tps)
 
 # how big does a rounding error need to be before we warn about it?
 frequency_tolerance = 0.001  # 0.1%
 
 def fromSeconds(value):
+    import _m5.core
+
     if not isinstance(value, float):
         raise TypeError, "can't convert '%s' to type tick" % type(value)
 
     # once someone needs to convert to seconds, the global frequency
     # had better be fixed
-    if not tps_fixed:
+    if not _m5.core.clockFrequencyFixed():
         raise AttributeError, \
               "In order to do conversions, the global frequency must be fixed"
 
@@ -79,7 +70,7 @@
         return 0
 
     # convert the value from time to ticks
-    value *= tps
+    value *= _m5.core.getClockFrequency()
 
     int_value = int(round(value))
     err = (value - int_value) / value
diff --git a/src/python/pybind11/core.cc b/src/python/pybind11/core.cc
index 41eeed2..57fcb94 100644
--- a/src/python/pybind11/core.cc
+++ b/src/python/pybind11/core.cc
@@ -245,7 +245,11 @@
         .def("seedRandom", [](uint64_t seed) { random_mt.init(seed); })
 
 
+        .def("fixClockFrequency", &fixClockFrequency)
+        .def("clockFrequencyFixed", &clockFrequencyFixed)
+
         .def("setClockFrequency", &setClockFrequency)
+        .def("getClockFrequency", &getClockFrequency)
         .def("curTick", curTick)
         ;
 
diff --git a/src/sim/core.cc b/src/sim/core.cc
index 514c4c5..cb9051f 100644
--- a/src/sim/core.cc
+++ b/src/sim/core.cc
@@ -37,6 +37,8 @@
 #include <string>
 
 #include "base/callback.hh"
+#include "base/cprintf.hh"
+#include "base/logging.hh"
 #include "base/output.hh"
 #include "sim/eventq.hh"
 
@@ -69,11 +71,23 @@
 
 } // namespace SimClock
 
+namespace {
+
+bool _clockFrequencyFixed = false;
+
+// Default to 1 THz (1 Tick == 1 ps)
+Tick _ticksPerSecond = 1e12;
+
+} // anonymous namespace
+
 void
-setClockFrequency(Tick ticksPerSecond)
+fixClockFrequency()
 {
+    if (_clockFrequencyFixed)
+        return;
+
     using namespace SimClock;
-    Frequency = ticksPerSecond;
+    Frequency = _ticksPerSecond;
     Float::s = static_cast<double>(Frequency);
     Float::ms = Float::s / 1.0e3;
     Float::us = Float::s / 1.0e6;
@@ -91,7 +105,20 @@
     Int::ns = Int::us / 1000;
     Int::ps = Int::ns / 1000;
 
+    cprintf("Global frequency set at %d ticks per second\n", _ticksPerSecond);
+
+    _clockFrequencyFixed = true;
 }
+bool clockFrequencyFixed() { return _clockFrequencyFixed; }
+
+void
+setClockFrequency(Tick tps)
+{
+    panic_if(_clockFrequencyFixed,
+            "Global frequency already fixed at %f ticks/s.", _ticksPerSecond);
+    _ticksPerSecond = tps;
+}
+Tick getClockFrequency() { return _ticksPerSecond; }
 
 void
 setOutputDir(const string &dir)
diff --git a/src/sim/core.hh b/src/sim/core.hh
index 281fe61..8e46454 100644
--- a/src/sim/core.hh
+++ b/src/sim/core.hh
@@ -91,7 +91,12 @@
 } // namespace Int
 } // namespace SimClock
 /** @} */
+
+void fixClockFrequency();
+bool clockFrequencyFixed();
+
 void setClockFrequency(Tick ticksPerSecond);
+Tick getClockFrequency(); // Ticks per second.
 
 void setOutputDir(const std::string &dir);