root.cc revision 8232
1695SN/A/*
21762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
3695SN/A * Copyright (c) 2011 Advanced Micro Devices
4695SN/A * All rights reserved.
5695SN/A *
6695SN/A * Redistribution and use in source and binary forms, with or without
7695SN/A * modification, are permitted provided that the following conditions are
8695SN/A * met: redistributions of source code must retain the above copyright
9695SN/A * notice, this list of conditions and the following disclaimer;
10695SN/A * redistributions in binary form must reproduce the above copyright
11695SN/A * notice, this list of conditions and the following disclaimer in the
12695SN/A * documentation and/or other materials provided with the distribution;
13695SN/A * neither the name of the copyright holders nor the names of its
14695SN/A * contributors may be used to endorse or promote products derived from
15695SN/A * this software without specific prior written permission.
16695SN/A *
17695SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18695SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19695SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20695SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21695SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22695SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23695SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24695SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25695SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26695SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272665Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665Ssaidi@eecs.umich.edu *
29695SN/A * Authors: Nathan Binkert
30695SN/A *          Steve Reinhardt
31873SN/A *          Gabe Black
32873SN/A */
33873SN/A
34873SN/A#include "base/misc.hh"
35695SN/A#include "debug/TimeSync.hh"
362621SN/A#include "sim/root.hh"
37695SN/A
38695SN/ARoot *Root::_root = NULL;
39695SN/A
40695SN/A/*
41695SN/A * This function is called periodically by an event in M5 and ensures that
42695SN/A * at least as much real time has passed between invocations as simulated time.
43695SN/A * If not, the function either sleeps, or if the difference is small enough
44695SN/A * spin waits.
45695SN/A */
46695SN/Avoid
47695SN/ARoot::timeSync()
48695SN/A{
49695SN/A    Time cur_time, diff, period = timeSyncPeriod();
50695SN/A
51695SN/A    do {
52695SN/A        cur_time.setTimer();
53695SN/A        diff = cur_time - lastTime;
54695SN/A        Time remainder = period - diff;
55695SN/A        if (diff < period && remainder > _spinThreshold) {
56695SN/A            DPRINTF(TimeSync, "Sleeping to sync with real time.\n");
57695SN/A            // Sleep until the end of the period, or until a signal.
58695SN/A            sleep(remainder);
59695SN/A            // Refresh the current time.
60695SN/A            cur_time.setTimer();
61695SN/A        }
62695SN/A    } while (diff < period);
63695SN/A    lastTime = cur_time;
64695SN/A    schedule(&syncEvent, curTick() + _periodTick);
65695SN/A}
66695SN/A
67695SN/Avoid
68695SN/ARoot::timeSyncEnable(bool en)
69695SN/A{
70729SN/A    if (en == _enabled)
71695SN/A        return;
72695SN/A    _enabled = en;
73695SN/A    if (_enabled) {
74695SN/A        // Get event going.
75695SN/A        Tick periods = ((curTick() + _periodTick - 1) / _periodTick);
76695SN/A        Tick nextPeriod = periods * _periodTick;
77695SN/A        schedule(&syncEvent, nextPeriod);
78695SN/A    } else {
79695SN/A        // Stop event.
80695SN/A        deschedule(&syncEvent);
81695SN/A    }
82695SN/A}
83695SN/A
84695SN/A/// Configure the period for time sync events.
85695SN/Avoid
86695SN/ARoot::timeSyncPeriod(Time newPeriod)
87695SN/A{
88695SN/A    bool en = timeSyncEnabled();
89695SN/A    _period = newPeriod;
90695SN/A    _periodTick = _period.getTick();
91695SN/A    timeSyncEnable(en);
92695SN/A}
93695SN/A
94695SN/A/// Set the threshold for time remaining to spin wait.
95695SN/Avoid
96695SN/ARoot::timeSyncSpinThreshold(Time newThreshold)
97695SN/A{
98695SN/A    bool en = timeSyncEnabled();
99695SN/A    _spinThreshold = newThreshold;
100695SN/A    timeSyncEnable(en);
101695SN/A}
102695SN/A
103695SN/ARoot::Root(RootParams *p) : SimObject(p), _enabled(false),
104695SN/A    _periodTick(p->time_sync_period), syncEvent(this)
105695SN/A{
106695SN/A    _period.setTick(p->time_sync_period);
107695SN/A    _spinThreshold.setTick(p->time_sync_spin_threshold);
108695SN/A
109695SN/A    assert(_root == NULL);
110695SN/A    _root = this;
111695SN/A    lastTime.setTimer();
112695SN/A}
113695SN/A
114695SN/Avoid
115695SN/ARoot::initState()
116695SN/A{
117695SN/A    timeSyncEnable(params()->time_sync_enable);
118695SN/A}
119695SN/A
120695SN/Avoid
121695SN/ARoot::loadState(Checkpoint *cp)
122695SN/A{
123695SN/A    timeSyncEnable(params()->time_sync_enable);
124695SN/A}
125695SN/A
126695SN/ARoot *
127695SN/ARootParams::create()
128695SN/A{
129695SN/A    static bool created = false;
130695SN/A    if (created)
131695SN/A        panic("only one root object allowed!");
1321395SN/A
133695SN/A    created = true;
134695SN/A
135695SN/A    return new Root(this);
136695SN/A}
137695SN/A