/*
* 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 "sim/builder.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;
-// Dummy Object
-struct Root : public SimObject
+/*
+ * 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()
{
- Root(const std::string &name) : SimObject(name) {}
-};
+ Time cur_time, diff, period = timeSyncPeriod();
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(Root)
+ 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);
+}
- Param<int> dummy; // needed below
+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);
+ }
+}
-END_DECLARE_SIM_OBJECT_PARAMS(Root)
+/// Configure the period for time sync events.
+void
+Root::timeSyncPeriod(Time newPeriod)
+{
+ bool en = timeSyncEnabled();
+ _period = newPeriod;
+ _periodTick = _period.getTick();
+ timeSyncEnable(en);
+}
-BEGIN_INIT_SIM_OBJECT_PARAMS(Root)
+/// Set the threshold for time remaining to spin wait.
+void
+Root::timeSyncSpinThreshold(Time newThreshold)
+{
+ bool en = timeSyncEnabled();
+ _spinThreshold = newThreshold;
+ timeSyncEnable(en);
+}
- INIT_PARAM(dummy, "") // All SimObjects must have params
+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);
-END_INIT_SIM_OBJECT_PARAMS(Root)
+ assert(_root == NULL);
+ _root = this;
+ lastTime.setTimer();
+}
-CREATE_SIM_OBJECT(Root)
+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 §ion)
+{
+ 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()
{
static bool created = false;
if (created)
created = true;
- return new Root(getInstanceName());
-}
+ FullSystem = full_system;
+ FullSystemInt = full_system ? 1 : 0;
-REGISTER_SIM_OBJECT("Root", Root)
+ return new Root(this);
+}