summaryrefslogtreecommitdiff
path: root/src/sim/root.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim/root.cc')
-rw-r--r--src/sim/root.cc89
1 files changed, 83 insertions, 6 deletions
diff --git a/src/sim/root.cc b/src/sim/root.cc
index 2e5c070c8..d44c72f4d 100644
--- a/src/sim/root.cc
+++ b/src/sim/root.cc
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2011 Advanced Micro Devices
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,17 +28,93 @@
*
* Authors: Nathan Binkert
* Steve Reinhardt
+ * Gabe Black
*/
#include "base/misc.hh"
-#include "params/Root.hh"
-#include "sim/sim_object.hh"
+#include "sim/core.hh"
+#include "sim/root.hh"
-// Dummy Object
-struct Root : public SimObject
+Root *Root::_root = NULL;
+
+/*
+ * This function is called periodically by an event in M5 and ensures that
+ * at least as much real time has passed between invocations as simulated time.
+ * If not, the function either sleeps, or if the difference is small enough
+ * spin waits.
+ */
+void
+Root::timeSync()
+{
+ Time cur_time, diff, period = timeSyncPeriod();
+
+ do {
+ cur_time.setTimer();
+ diff = cur_time - lastTime;
+ Time remainder = period - diff;
+ if (diff < period && remainder > _spinThreshold) {
+ DPRINTF(TimeSync, "Sleeping to sync with real time.\n");
+ // Sleep until the end of the period, or until a signal.
+ sleep(remainder);
+ // Refresh the current time.
+ cur_time.setTimer();
+ }
+ } while (diff < period);
+ lastTime = cur_time;
+ schedule(&syncEvent, curTick() + _periodTick);
+}
+
+void
+Root::timeSyncEnable(bool en)
+{
+ if (en == _enabled)
+ return;
+ _enabled = en;
+ if (_enabled) {
+ // Get event going.
+ Tick periods = ((curTick() + _periodTick - 1) / _periodTick);
+ Tick nextPeriod = periods * _periodTick;
+ schedule(&syncEvent, nextPeriod);
+ } else {
+ // Stop event.
+ deschedule(&syncEvent);
+ }
+}
+
+/// Configure the period for time sync events.
+void
+Root::timeSyncPeriod(Time newPeriod)
{
- Root(RootParams *params) : SimObject(params) {}
-};
+ bool en = timeSyncEnabled();
+ _period = newPeriod;
+ _periodTick = _period.nsec() * SimClock::Int::ns +
+ _period.sec() * SimClock::Int::s;
+ timeSyncEnable(en);
+}
+
+/// Set the threshold for time remaining to spin wait.
+void
+Root::timeSyncSpinThreshold(Time newThreshold)
+{
+ bool en = timeSyncEnabled();
+ _spinThreshold = newThreshold;
+ timeSyncEnable(en);
+}
+
+Root::Root(RootParams *p) : SimObject(p), _enabled(false),
+ _periodTick(p->time_sync_period), syncEvent(this)
+{
+ uint64_t nsecs = p->time_sync_period / SimClock::Int::ns;
+ _period.set(nsecs / Time::NSEC_PER_SEC, nsecs % Time::NSEC_PER_SEC);
+ nsecs = p->time_sync_spin_threshold / SimClock::Int::ns;
+ _spinThreshold.set(nsecs / Time::NSEC_PER_SEC,
+ nsecs % Time::NSEC_PER_SEC);
+
+ assert(_root == NULL);
+ _root = this;
+ lastTime.setTimer();
+ timeSyncEnable(p->time_sync_enable);
+}
Root *
RootParams::create()