systemc: Use the new python interface to delay fixing the timescale.

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>
This commit is contained in:
Gabe Black
2018-08-07 03:54:08 -07:00
parent 33e3365bf9
commit 88be5e34f6

View File

@@ -27,9 +27,12 @@
* 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
};
void
fixTimeResolution()
{
static bool fixed = false;
if (fixed)
return;
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
setWork(sc_time *time, double d, ::sc_core::sc_time_unit tu)
{
//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)