mem: Make the XBar responsible for tracking response routing
[gem5.git] / src / sim / root.cc
index 15f73b15bed2c386c22321a38e805570a1505d94..9bb8b4f05cba5fcf886869915fa71e3a3b3e5518 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2011 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *
  * Authors: Nathan Binkert
  *          Steve Reinhardt
+ *          Gabe Black
  */
 
-#include <cstring>
-#include <fstream>
-#include <list>
-#include <string>
-#include <vector>
-
 #include "base/misc.hh"
-#include "params/Root.hh"
-#include "sim/sim_object.hh"
+#include "base/trace.hh"
+#include "config/the_isa.hh"
+#include "debug/TimeSync.hh"
+#include "sim/full_system.hh"
+#include "sim/root.hh"
+
+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)
+{
+    bool en = timeSyncEnabled();
+    _period = newPeriod;
+    _periodTick = _period.getTick();
+    timeSyncEnable(en);
+}
 
-// Dummy Object
-struct Root : public SimObject
+/// Set the threshold for time remaining to spin wait.
+void
+Root::timeSyncSpinThreshold(Time newThreshold)
 {
-    Root(RootParams *params) : SimObject(params) {}
-};
+    bool en = timeSyncEnabled();
+    _spinThreshold = newThreshold;
+    timeSyncEnable(en);
+}
+
+Root::Root(RootParams *p) : SimObject(p), _enabled(false),
+    _periodTick(p->time_sync_period), syncEvent(this)
+{
+    _period.setTick(p->time_sync_period);
+    _spinThreshold.setTick(p->time_sync_spin_threshold);
+
+    assert(_root == NULL);
+    _root = this;
+    lastTime.setTimer();
+
+    simQuantum = p->sim_quantum;
+}
+
+void
+Root::initState()
+{
+    timeSyncEnable(params()->time_sync_enable);
+}
+
+void
+Root::loadState(Checkpoint *cp)
+{
+    SimObject::loadState(cp);
+    timeSyncEnable(params()->time_sync_enable);
+}
+
+void
+Root::serialize(std::ostream &os)
+{
+    uint64_t cpt_ver = gem5CheckpointVersion;
+    SERIALIZE_SCALAR(cpt_ver);
+    SERIALIZE_SCALAR(FullSystem);
+    std::string isa = THE_ISA_STR;
+    SERIALIZE_SCALAR(isa);
+}
+
+void
+Root::unserialize(Checkpoint *cp, const std::string &section)
+{
+    uint64_t cpt_ver = 0;
+    UNSERIALIZE_OPT_SCALAR(cpt_ver);
+    if (cpt_ver < gem5CheckpointVersion) {
+        warn("**********************************************************\n");
+        warn("!!!! Checkpoint ver %#x is older than current ver %#x !!!!\n",
+                cpt_ver, gem5CheckpointVersion);
+        warn("You might experience some issues when restoring and should run "
+             "the checkpoint upgrader (util/cpt_upgrader.py) on your "
+             "checkpoint\n");
+        warn("**********************************************************\n");
+    } else if (cpt_ver > gem5CheckpointVersion) {
+        warn("**********************************************************\n");
+        warn("!!!! Checkpoint ver %#x is newer than current ver %#x !!!!\n",
+                cpt_ver, gem5CheckpointVersion);
+        warn("Running a new checkpoint with an older version of gem5 is not "
+             "supported. While it might work, you may experience incorrect "
+             "behavior or crashes.\n");
+        warn("**********************************************************\n");
+     }
+}
+
+
+bool FullSystem;
+unsigned int FullSystemInt;
 
 Root *
 RootParams::create()
@@ -54,5 +176,8 @@ RootParams::create()
 
     created = true;
 
+    FullSystem = full_system;
+    FullSystemInt = full_system ? 1 : 0;
+
     return new Root(this);
 }