diff options
-rw-r--r-- | configs/example/fs.py | 7 | ||||
-rw-r--r-- | src/sim/Root.py | 7 | ||||
-rw-r--r-- | src/sim/SConscript | 1 | ||||
-rw-r--r-- | src/sim/root.cc | 89 | ||||
-rw-r--r-- | src/sim/root.hh | 101 |
5 files changed, 198 insertions, 7 deletions
diff --git a/configs/example/fs.py b/configs/example/fs.py index a45b48c76..e9bc9afb6 100644 --- a/configs/example/fs.py +++ b/configs/example/fs.py @@ -65,6 +65,10 @@ config_root = os.path.dirname(config_path) parser = optparse.OptionParser() +# Simulation options +parser.add_option("--timesync", action="store_true", + help="Prevent simulated time from getting ahead of real time") + # System options parser.add_option("--kernel", action="store", type="string") parser.add_option("--script", action="store", type="string") @@ -187,4 +191,7 @@ else: print "Error I don't know how to create more than 2 systems." sys.exit(1) +if options.timesync: + root.time_sync_enable = True + Simulation.run(options, root, test_sys, FutureClass) diff --git a/src/sim/Root.py b/src/sim/Root.py index 4edcffa2c..e15de1554 100644 --- a/src/sim/Root.py +++ b/src/sim/Root.py @@ -57,4 +57,9 @@ class Root(SimObject): return 'root' type = 'Root' - dummy = Param.Int(0, "We don't support objects without params") + + # Time syncing prevents the simulation from running faster than real time. + time_sync_enable = Param.Bool(False, "whether time syncing is enabled") + time_sync_period = Param.Clock("100ms", "how often to sync with real time") + time_sync_spin_threshold = \ + Param.Clock("100us", "when less than this much time is left, spin") diff --git a/src/sim/SConscript b/src/sim/SConscript index 97c6ddaae..f959870cd 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -73,6 +73,7 @@ TraceFlag('Interrupt') TraceFlag('Loader') TraceFlag('Stack') TraceFlag('SyscallVerbose') +TraceFlag('TimeSync') TraceFlag('TLB') TraceFlag('Thread') TraceFlag('Timer') 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() diff --git a/src/sim/root.hh b/src/sim/root.hh new file mode 100644 index 000000000..2beced9d4 --- /dev/null +++ b/src/sim/root.hh @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2011 Advanced Micro Devices + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +/** + * @file This file defines the Root simobject and the methods used to control + * the time syncing mechanism provided through it. + * + * Time syncing prevents simulated time from passing faster than real time. It + * works by scheduling a periodic event that checks to see if its simulated + * period is shorter than its real period. If it is, it stalls the simulation + * until they're equal. + */ + +#ifndef __SIM_ROOT_HH__ +#define __SIM_ROOT_HH__ + +#include "base/time.hh" +#include "params/Root.hh" +#include "sim/eventq.hh" +#include "sim/sim_object.hh" + +class Root : public SimObject +{ + private: + static Root *_root; + + protected: + bool _enabled; + Time _period; + Tick _periodTick; + Time _spinThreshold; + + Time lastTime; + + void timeSync(); + EventWrapper<Root, &Root::timeSync> syncEvent; + friend class EventWrapper<Root, &Root::timeSync>; + + public: + /** + * Use this function to get a pointer to the single Root object in the + * simulation. This function asserts that such an object has actual been + * constructed to avoid having to perform that check everywhere the root + * is used. This is to allow calling the functions below. + * + * @return Pointer to the single root object. + */ + static Root * + root() + { + assert(_root); + return _root; + } + + public: + + /// Check whether time syncing is enabled. + bool timeSyncEnabled() const { return _enabled; } + /// Retrieve the period for the sync event. + const Time timeSyncPeriod() const { return _period; } + /// Retrieve the threshold for time remaining to spin wait. + const Time timeSyncSpinThreshold() const { return _spinThreshold; } + + /// Enable or disable time syncing. + void timeSyncEnable(bool en); + /// Configure the period for time sync events. + void timeSyncPeriod(Time newPeriod); + /// Set the threshold for time remaining to spin wait. + void timeSyncSpinThreshold(Time newThreshold); + + Root(RootParams *p); +}; + +#endif // __SIM_ROOT_HH__ |