sc_time.cc revision 13247
112837Sgabeblack@google.com/*
212837Sgabeblack@google.com * Copyright 2018 Google, Inc.
312837Sgabeblack@google.com *
412837Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
512837Sgabeblack@google.com * modification, are permitted provided that the following conditions are
612837Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
712837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
812837Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
912837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1012837Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1112837Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1212837Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1312837Sgabeblack@google.com * this software without specific prior written permission.
1412837Sgabeblack@google.com *
1512837Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1612837Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1712837Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1812837Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1912837Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2012837Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2112837Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2212837Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2312837Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2412837Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2512837Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2612837Sgabeblack@google.com *
2712837Sgabeblack@google.com * Authors: Gabe Black
2812837Sgabeblack@google.com */
2912837Sgabeblack@google.com
3013177Sgabeblack@google.com#include <sstream>
3113039Sgabeblack@google.com#include <vector>
3213039Sgabeblack@google.com
3312837Sgabeblack@google.com#include "base/logging.hh"
3412989Sgabeblack@google.com#include "base/types.hh"
3512986Sgabeblack@google.com#include "python/pybind11/pybind.hh"
3613195Sgabeblack@google.com#include "sim/core.hh"
3713039Sgabeblack@google.com#include "systemc/core/python.hh"
3813149Sgabeblack@google.com#include "systemc/ext/core/sc_main.hh"
3912837Sgabeblack@google.com#include "systemc/ext/core/sc_time.hh"
4013149Sgabeblack@google.com#include "systemc/ext/utils/sc_report_handler.hh"
4112837Sgabeblack@google.com
4212837Sgabeblack@google.comnamespace sc_core
4312837Sgabeblack@google.com{
4412837Sgabeblack@google.com
4512983Sgabeblack@google.comnamespace
4612837Sgabeblack@google.com{
4712983Sgabeblack@google.com
4812983Sgabeblack@google.comconst char *TimeUnitNames[] = {
4912983Sgabeblack@google.com    [SC_FS] = "fs",
5012983Sgabeblack@google.com    [SC_PS] = "ps",
5112983Sgabeblack@google.com    [SC_NS] = "ns",
5212983Sgabeblack@google.com    [SC_US] = "us",
5312983Sgabeblack@google.com    [SC_MS] = "ms",
5412983Sgabeblack@google.com    [SC_SEC] = "s"
5512983Sgabeblack@google.com};
5612983Sgabeblack@google.com
5712983Sgabeblack@google.comdouble TimeUnitScale[] = {
5812983Sgabeblack@google.com    [SC_FS] = 1.0e-15,
5912983Sgabeblack@google.com    [SC_PS] = 1.0e-12,
6012983Sgabeblack@google.com    [SC_NS] = 1.0e-9,
6112983Sgabeblack@google.com    [SC_US] = 1.0e-6,
6212983Sgabeblack@google.com    [SC_MS] = 1.0e-3,
6312983Sgabeblack@google.com    [SC_SEC] = 1.0
6412983Sgabeblack@google.com};
6512983Sgabeblack@google.com
6613195Sgabeblack@google.comTick TimeUnitFrequency[] = {
6713195Sgabeblack@google.com    [SC_FS] = 1ULL * 1000 * 1000 * 1000 * 1000 * 1000,
6813195Sgabeblack@google.com    [SC_PS] = 1ULL * 1000 * 1000 * 1000 * 1000,
6913195Sgabeblack@google.com    [SC_NS] = 1ULL * 1000 * 1000 * 1000,
7013195Sgabeblack@google.com    [SC_US] = 1ULL * 1000 * 1000,
7113195Sgabeblack@google.com    [SC_MS] = 1ULL * 1000,
7213195Sgabeblack@google.com    [SC_SEC] = 1ULL
7313195Sgabeblack@google.com};
7413195Sgabeblack@google.com
7513039Sgabeblack@google.combool timeFixed = false;
7613039Sgabeblack@google.combool pythonReady = false;
7713039Sgabeblack@google.com
7813039Sgabeblack@google.comstruct SetInfo
7913039Sgabeblack@google.com{
8013039Sgabeblack@google.com    SetInfo(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu) :
8113039Sgabeblack@google.com        time(time), d(d), tu(tu)
8213039Sgabeblack@google.com    {}
8313039Sgabeblack@google.com
8413039Sgabeblack@google.com    ::sc_core::sc_time *time;
8513039Sgabeblack@google.com    double d;
8613039Sgabeblack@google.com    ::sc_core::sc_time_unit tu;
8713039Sgabeblack@google.com};
8813039Sgabeblack@google.comstd::vector<SetInfo> toSet;
8913039Sgabeblack@google.com
9012986Sgabeblack@google.comvoid
9113039Sgabeblack@google.comsetWork(sc_time *time, double d, ::sc_core::sc_time_unit tu)
9212986Sgabeblack@google.com{
9313195Sgabeblack@google.com    double scale = TimeUnitScale[tu] * SimClock::Float::s;
9413039Sgabeblack@google.com    // Accellera claims there is a linux bug, and that these next two
9513039Sgabeblack@google.com    // lines work around them.
9613039Sgabeblack@google.com    volatile double tmp = d * scale + 0.5;
9713039Sgabeblack@google.com    *time = sc_time::from_value(static_cast<uint64_t>(tmp));
9813039Sgabeblack@google.com}
9912986Sgabeblack@google.com
10013039Sgabeblack@google.comvoid
10113039Sgabeblack@google.comfixTime()
10213039Sgabeblack@google.com{
10312986Sgabeblack@google.com    auto ticks = pybind11::module::import("m5.ticks");
10412986Sgabeblack@google.com    auto fix_global_frequency = ticks.attr("fixGlobalFrequency");
10512986Sgabeblack@google.com    fix_global_frequency();
10613039Sgabeblack@google.com
10713039Sgabeblack@google.com    for (auto &t: toSet)
10813039Sgabeblack@google.com        setWork(t.time, t.d, t.tu);
10913039Sgabeblack@google.com    toSet.clear();
11012986Sgabeblack@google.com}
11112986Sgabeblack@google.com
11213039Sgabeblack@google.comvoid
11313195Sgabeblack@google.comattemptToFixTime()
11413195Sgabeblack@google.com{
11513195Sgabeblack@google.com    // Only fix time once.
11613195Sgabeblack@google.com    if (!timeFixed) {
11713195Sgabeblack@google.com        timeFixed = true;
11813195Sgabeblack@google.com
11913195Sgabeblack@google.com        // If we've run, python is working and we haven't fixed time yet.
12013195Sgabeblack@google.com        if (pythonReady)
12113195Sgabeblack@google.com            fixTime();
12213195Sgabeblack@google.com    }
12313195Sgabeblack@google.com}
12413195Sgabeblack@google.com
12513195Sgabeblack@google.comvoid
12613149Sgabeblack@google.comsetGlobalFrequency(Tick ticks_per_second)
12713149Sgabeblack@google.com{
12813149Sgabeblack@google.com    auto ticks = pybind11::module::import("m5.ticks");
12913149Sgabeblack@google.com    auto set_global_frequency = ticks.attr("setGlobalFrequency");
13013149Sgabeblack@google.com    set_global_frequency(ticks_per_second);
13113149Sgabeblack@google.com    fixTime();
13213149Sgabeblack@google.com}
13313149Sgabeblack@google.com
13413149Sgabeblack@google.comvoid
13513039Sgabeblack@google.comset(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu)
13613039Sgabeblack@google.com{
13713195Sgabeblack@google.com    if (d != 0)
13813195Sgabeblack@google.com        attemptToFixTime();
13913039Sgabeblack@google.com    if (pythonReady) {
14013039Sgabeblack@google.com        // Time should be working. Set up this sc_time.
14113039Sgabeblack@google.com        setWork(time, d, tu);
14213039Sgabeblack@google.com    } else {
14313039Sgabeblack@google.com        // Time isn't set up yet. Defer setting up this sc_time.
14413039Sgabeblack@google.com        toSet.emplace_back(time, d, tu);
14513039Sgabeblack@google.com    }
14613039Sgabeblack@google.com}
14713039Sgabeblack@google.com
14813039Sgabeblack@google.comclass TimeSetter : public ::sc_gem5::PythonReadyFunc
14913039Sgabeblack@google.com{
15013039Sgabeblack@google.com  public:
15113039Sgabeblack@google.com    TimeSetter() : ::sc_gem5::PythonReadyFunc() {}
15213039Sgabeblack@google.com
15313039Sgabeblack@google.com    void
15413039Sgabeblack@google.com    run() override
15513039Sgabeblack@google.com    {
15613039Sgabeblack@google.com        // Record that we've run and python/pybind should be usable.
15713039Sgabeblack@google.com        pythonReady = true;
15813039Sgabeblack@google.com
15913039Sgabeblack@google.com        // If time is already fixed, let python know.
16013039Sgabeblack@google.com        if (timeFixed)
16113039Sgabeblack@google.com            fixTime();
16213039Sgabeblack@google.com    }
16313039Sgabeblack@google.com} timeSetter;
16413039Sgabeblack@google.com
16513124Sgabeblack@google.comdouble defaultUnit = 1.0e-9;
16613124Sgabeblack@google.com
16712983Sgabeblack@google.com} // anonymous namespace
16812983Sgabeblack@google.com
16912983Sgabeblack@google.comsc_time::sc_time() : val(0) {}
17012983Sgabeblack@google.com
17112983Sgabeblack@google.comsc_time::sc_time(double d, sc_time_unit tu)
17212983Sgabeblack@google.com{
17312983Sgabeblack@google.com    val = 0;
17413195Sgabeblack@google.com    set(this, d, tu);
17512837Sgabeblack@google.com}
17612837Sgabeblack@google.com
17712983Sgabeblack@google.comsc_time::sc_time(const sc_time &t)
17812837Sgabeblack@google.com{
17912983Sgabeblack@google.com    val = t.val;
18012837Sgabeblack@google.com}
18112837Sgabeblack@google.com
18213057Sgabeblack@google.comsc_time::sc_time(double d, bool scale)
18312925Sgabeblack@google.com{
18413195Sgabeblack@google.com    double scaler = scale ? defaultUnit : SimClock::Float::Hz;
18513195Sgabeblack@google.com    set(this, d * scaler, SC_SEC);
18612925Sgabeblack@google.com}
18712925Sgabeblack@google.com
18813057Sgabeblack@google.comsc_time::sc_time(sc_dt::uint64 v, bool scale)
18912925Sgabeblack@google.com{
19013195Sgabeblack@google.com    double scaler = scale ? defaultUnit : SimClock::Float::Hz;
19113195Sgabeblack@google.com    set(this, static_cast<double>(v) * scaler, SC_SEC);
19212925Sgabeblack@google.com}
19312925Sgabeblack@google.com
19412837Sgabeblack@google.comsc_time &
19512983Sgabeblack@google.comsc_time::operator = (const sc_time &t)
19612837Sgabeblack@google.com{
19712983Sgabeblack@google.com    val = t.val;
19812837Sgabeblack@google.com    return *this;
19912837Sgabeblack@google.com}
20012837Sgabeblack@google.com
20112837Sgabeblack@google.comsc_dt::uint64
20212837Sgabeblack@google.comsc_time::value() const
20312837Sgabeblack@google.com{
20412983Sgabeblack@google.com    return val;
20512837Sgabeblack@google.com}
20612837Sgabeblack@google.com
20712837Sgabeblack@google.comdouble
20812837Sgabeblack@google.comsc_time::to_double() const
20912837Sgabeblack@google.com{
21013040Sgabeblack@google.com    return static_cast<double>(val);
21112837Sgabeblack@google.com}
21212837Sgabeblack@google.comdouble
21312837Sgabeblack@google.comsc_time::to_seconds() const
21412837Sgabeblack@google.com{
21513195Sgabeblack@google.com    return to_double() * SimClock::Float::Hz;
21612837Sgabeblack@google.com}
21712837Sgabeblack@google.com
21812837Sgabeblack@google.comconst std::string
21912837Sgabeblack@google.comsc_time::to_string() const
22012837Sgabeblack@google.com{
22113177Sgabeblack@google.com    std::ostringstream ss;
22213177Sgabeblack@google.com    print(ss);
22313177Sgabeblack@google.com    return ss.str();
22412837Sgabeblack@google.com}
22512837Sgabeblack@google.com
22612837Sgabeblack@google.combool
22712983Sgabeblack@google.comsc_time::operator == (const sc_time &t) const
22812837Sgabeblack@google.com{
22912983Sgabeblack@google.com    return val == t.val;
23012837Sgabeblack@google.com}
23112837Sgabeblack@google.com
23212837Sgabeblack@google.combool
23312983Sgabeblack@google.comsc_time::operator != (const sc_time &t) const
23412837Sgabeblack@google.com{
23512983Sgabeblack@google.com    return val != t.val;
23612837Sgabeblack@google.com}
23712837Sgabeblack@google.com
23812837Sgabeblack@google.combool
23912983Sgabeblack@google.comsc_time::operator < (const sc_time &t) const
24012837Sgabeblack@google.com{
24112983Sgabeblack@google.com    return val < t.val;
24212837Sgabeblack@google.com}
24312837Sgabeblack@google.com
24412837Sgabeblack@google.combool
24512983Sgabeblack@google.comsc_time::operator <= (const sc_time &t) const
24612837Sgabeblack@google.com{
24712983Sgabeblack@google.com    return val <= t.val;
24812837Sgabeblack@google.com}
24912837Sgabeblack@google.com
25012837Sgabeblack@google.combool
25112983Sgabeblack@google.comsc_time::operator > (const sc_time &t) const
25212837Sgabeblack@google.com{
25312983Sgabeblack@google.com    return val > t.val;
25412837Sgabeblack@google.com}
25512837Sgabeblack@google.com
25612837Sgabeblack@google.combool
25712983Sgabeblack@google.comsc_time::operator >= (const sc_time &t) const
25812837Sgabeblack@google.com{
25912983Sgabeblack@google.com    return val >= t.val;
26012837Sgabeblack@google.com}
26112837Sgabeblack@google.com
26212837Sgabeblack@google.comsc_time &
26312983Sgabeblack@google.comsc_time::operator += (const sc_time &t)
26412837Sgabeblack@google.com{
26512983Sgabeblack@google.com    val += t.val;
26612837Sgabeblack@google.com    return *this;
26712837Sgabeblack@google.com}
26812837Sgabeblack@google.com
26912837Sgabeblack@google.comsc_time &
27012983Sgabeblack@google.comsc_time::operator -= (const sc_time &t)
27112837Sgabeblack@google.com{
27212983Sgabeblack@google.com    val -= t.val;
27312837Sgabeblack@google.com    return *this;
27412837Sgabeblack@google.com}
27512837Sgabeblack@google.com
27612837Sgabeblack@google.comsc_time &
27713040Sgabeblack@google.comsc_time::operator *= (double d)
27812837Sgabeblack@google.com{
27913040Sgabeblack@google.com    val = static_cast<int64_t>(static_cast<double>(val) * d + 0.5);
28012837Sgabeblack@google.com    return *this;
28112837Sgabeblack@google.com}
28212837Sgabeblack@google.com
28312837Sgabeblack@google.comsc_time &
28413040Sgabeblack@google.comsc_time::operator /= (double d)
28512837Sgabeblack@google.com{
28613040Sgabeblack@google.com    val = static_cast<int64_t>(static_cast<double>(val) / d + 0.5);
28712837Sgabeblack@google.com    return *this;
28812837Sgabeblack@google.com}
28912837Sgabeblack@google.com
29012837Sgabeblack@google.comvoid
29112983Sgabeblack@google.comsc_time::print(std::ostream &os) const
29212837Sgabeblack@google.com{
29312983Sgabeblack@google.com    if (val == 0) {
29412983Sgabeblack@google.com        os << "0 s";
29512983Sgabeblack@google.com    } else {
29613195Sgabeblack@google.com        Tick frequency = SimClock::Frequency;
29713195Sgabeblack@google.com
29813195Sgabeblack@google.com        // Shrink the frequency by scaling down the time period, ie converting
29913195Sgabeblack@google.com        // it from cycles per second to cycles per millisecond, etc.
30013195Sgabeblack@google.com        sc_time_unit tu = SC_SEC;
30113195Sgabeblack@google.com        while (tu > 1 && (frequency % 1000 == 0)) {
30213195Sgabeblack@google.com            tu = (sc_time_unit)((int)tu - 1);
30313195Sgabeblack@google.com            frequency /= 1000;
30413195Sgabeblack@google.com        }
30513195Sgabeblack@google.com
30613195Sgabeblack@google.com        // Convert the frequency into a period.
30713195Sgabeblack@google.com        Tick period;
30813195Sgabeblack@google.com        if (frequency > 1) {
30913195Sgabeblack@google.com            tu = (sc_time_unit)((int)tu - 1);
31013195Sgabeblack@google.com            period = 1000 / frequency;
31113195Sgabeblack@google.com        } else {
31213195Sgabeblack@google.com            period = frequency;
31313195Sgabeblack@google.com        }
31413195Sgabeblack@google.com
31513195Sgabeblack@google.com        // Scale our integer value by the period.
31613195Sgabeblack@google.com        uint64_t scaled = val * period;
31713195Sgabeblack@google.com
31813195Sgabeblack@google.com        // Shrink the scaled time value by increasing the size of the units
31913195Sgabeblack@google.com        // it's measured by, avoiding fractional parts.
32012983Sgabeblack@google.com        while (tu < SC_SEC && (scaled % 1000) == 0) {
32112983Sgabeblack@google.com            tu = (sc_time_unit)((int)tu + 1);
32212983Sgabeblack@google.com            scaled /= 1000;
32312983Sgabeblack@google.com        }
32412983Sgabeblack@google.com
32512983Sgabeblack@google.com        os << scaled << ' ' << TimeUnitNames[tu];
32612983Sgabeblack@google.com    }
32712837Sgabeblack@google.com}
32812837Sgabeblack@google.com
32912923Sgabeblack@google.comsc_time
33012983Sgabeblack@google.comsc_time::from_value(sc_dt::uint64 u)
33112923Sgabeblack@google.com{
33213195Sgabeblack@google.com    if (u)
33313195Sgabeblack@google.com        attemptToFixTime();
33412983Sgabeblack@google.com    sc_time t;
33512983Sgabeblack@google.com    t.val = u;
33612983Sgabeblack@google.com    return t;
33712923Sgabeblack@google.com}
33812923Sgabeblack@google.com
33912923Sgabeblack@google.comsc_time
34013057Sgabeblack@google.comsc_time::from_seconds(double d)
34112923Sgabeblack@google.com{
34213057Sgabeblack@google.com    sc_time t;
34313057Sgabeblack@google.com    set(&t, d, SC_SEC);
34413057Sgabeblack@google.com    return t;
34512923Sgabeblack@google.com}
34612923Sgabeblack@google.com
34712923Sgabeblack@google.comsc_time
34812923Sgabeblack@google.comsc_time::from_string(const char *str)
34912923Sgabeblack@google.com{
35012923Sgabeblack@google.com    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
35112923Sgabeblack@google.com    return sc_time();
35212923Sgabeblack@google.com}
35312923Sgabeblack@google.com
35412837Sgabeblack@google.comconst sc_time
35512989Sgabeblack@google.comoperator + (const sc_time &a, const sc_time &b)
35612837Sgabeblack@google.com{
35712989Sgabeblack@google.com    return sc_time::from_value(a.value() + b.value());
35812837Sgabeblack@google.com}
35912837Sgabeblack@google.com
36012837Sgabeblack@google.comconst sc_time
36112989Sgabeblack@google.comoperator - (const sc_time &a, const sc_time &b)
36212837Sgabeblack@google.com{
36312989Sgabeblack@google.com    return sc_time::from_value(a.value() - b.value());
36412837Sgabeblack@google.com}
36512837Sgabeblack@google.com
36612837Sgabeblack@google.comconst sc_time
36713040Sgabeblack@google.comoperator * (const sc_time &t, double d)
36812837Sgabeblack@google.com{
36913040Sgabeblack@google.com    volatile double tmp = static_cast<double>(t.value()) * d + 0.5;
37013040Sgabeblack@google.com    return sc_time::from_value(static_cast<int64_t>(tmp));
37112837Sgabeblack@google.com}
37212837Sgabeblack@google.com
37312837Sgabeblack@google.comconst sc_time
37413040Sgabeblack@google.comoperator * (double d, const sc_time &t)
37512837Sgabeblack@google.com{
37613040Sgabeblack@google.com    volatile double tmp = d * static_cast<double>(t.value()) + 0.5;
37713040Sgabeblack@google.com    return sc_time::from_value(static_cast<int64_t>(tmp));
37812837Sgabeblack@google.com}
37912837Sgabeblack@google.com
38012837Sgabeblack@google.comconst sc_time
38113040Sgabeblack@google.comoperator / (const sc_time &t, double d)
38212837Sgabeblack@google.com{
38313040Sgabeblack@google.com    volatile double tmp = static_cast<double>(t.value()) / d + 0.5;
38413040Sgabeblack@google.com    return sc_time::from_value(static_cast<int64_t>(tmp));
38512837Sgabeblack@google.com}
38612837Sgabeblack@google.com
38712837Sgabeblack@google.comdouble
38813040Sgabeblack@google.comoperator / (const sc_time &t1, const sc_time &t2)
38912837Sgabeblack@google.com{
39013040Sgabeblack@google.com    return t1.to_double() / t2.to_double();
39112837Sgabeblack@google.com}
39212837Sgabeblack@google.com
39312837Sgabeblack@google.comstd::ostream &
39412983Sgabeblack@google.comoperator << (std::ostream &os, const sc_time &t)
39512837Sgabeblack@google.com{
39612983Sgabeblack@google.com    t.print(os);
39712837Sgabeblack@google.com    return os;
39812837Sgabeblack@google.com}
39912837Sgabeblack@google.com
40012837Sgabeblack@google.comconst sc_time SC_ZERO_TIME;
40112837Sgabeblack@google.com
40212837Sgabeblack@google.comvoid
40313149Sgabeblack@google.comsc_set_time_resolution(double d, sc_time_unit tu)
40412837Sgabeblack@google.com{
40513151Sgabeblack@google.com    if (d <= 0.0) {
40613149Sgabeblack@google.com        SC_REPORT_ERROR("(E514) set time resolution failed",
40713149Sgabeblack@google.com                "value not positive");
40813149Sgabeblack@google.com    }
40913149Sgabeblack@google.com    double dummy;
41013149Sgabeblack@google.com    if (modf(log10(d), &dummy) != 0.0) {
41113149Sgabeblack@google.com        SC_REPORT_ERROR("(E514) set time resolution failed",
41213149Sgabeblack@google.com                "value not a power of ten");
41313149Sgabeblack@google.com    }
41413149Sgabeblack@google.com    if (sc_is_running()) {
41513149Sgabeblack@google.com        SC_REPORT_ERROR("(E514) set time resolution failed",
41613149Sgabeblack@google.com                "simulation running");
41713149Sgabeblack@google.com    }
41813149Sgabeblack@google.com    static bool specified = false;
41913149Sgabeblack@google.com    if (specified) {
42013149Sgabeblack@google.com        SC_REPORT_ERROR("(E514) set time resolution failed",
42113149Sgabeblack@google.com                "already specified");
42213149Sgabeblack@google.com    }
42313149Sgabeblack@google.com    // This won't detect the timescale being fixed outside of systemc, but
42413149Sgabeblack@google.com    // it's at least some protection.
42513149Sgabeblack@google.com    if (timeFixed) {
42613149Sgabeblack@google.com        SC_REPORT_ERROR("(E514) set time resolution failed",
42713149Sgabeblack@google.com                "sc_time object(s) constructed");
42813149Sgabeblack@google.com    }
42913149Sgabeblack@google.com
43013195Sgabeblack@google.com    double seconds = d * TimeUnitScale[tu];
43113195Sgabeblack@google.com    if (seconds < TimeUnitScale[SC_FS]) {
43213149Sgabeblack@google.com        SC_REPORT_ERROR("(E514) set time resolution failed",
43313149Sgabeblack@google.com                "value smaller than 1 fs");
43413149Sgabeblack@google.com    }
43513195Sgabeblack@google.com
43613195Sgabeblack@google.com    if (seconds > defaultUnit) {
43713195Sgabeblack@google.com        SC_REPORT_WARNING(
43813195Sgabeblack@google.com                "(W516) default time unit changed to time resolution", "");
43913195Sgabeblack@google.com        defaultUnit = seconds;
44013195Sgabeblack@google.com    }
44113195Sgabeblack@google.com
44213195Sgabeblack@google.com    // Get rid of fractional parts of d.
44313195Sgabeblack@google.com    while (d < 1.0 && tu > SC_FS) {
44413195Sgabeblack@google.com        d *= 1000;
44513195Sgabeblack@google.com        tu = (sc_time_unit)(tu - 1);
44613195Sgabeblack@google.com    }
44713195Sgabeblack@google.com
44813195Sgabeblack@google.com    Tick ticks_per_second = TimeUnitFrequency[tu] / static_cast<Tick>(d);
44913149Sgabeblack@google.com    setGlobalFrequency(ticks_per_second);
45013149Sgabeblack@google.com    specified = true;
45112837Sgabeblack@google.com}
45212837Sgabeblack@google.com
45312837Sgabeblack@google.comsc_time
45412837Sgabeblack@google.comsc_get_time_resolution()
45512837Sgabeblack@google.com{
45613149Sgabeblack@google.com    return sc_time::from_value(1);
45712837Sgabeblack@google.com}
45812837Sgabeblack@google.com
45912837Sgabeblack@google.comconst sc_time &
46012837Sgabeblack@google.comsc_max_time()
46112837Sgabeblack@google.com{
46212989Sgabeblack@google.com    static const sc_time MaxScTime = sc_time::from_value(MaxTick);
46312989Sgabeblack@google.com    return MaxScTime;
46412837Sgabeblack@google.com}
46512837Sgabeblack@google.com
46612916Sgabeblack@google.comvoid
46713124Sgabeblack@google.comsc_set_default_time_unit(double d, sc_time_unit tu)
46812916Sgabeblack@google.com{
46913151Sgabeblack@google.com    if (d < 0.0) {
47013151Sgabeblack@google.com        SC_REPORT_ERROR("(E515) set default time unit failed",
47113151Sgabeblack@google.com                "value not positive");
47213151Sgabeblack@google.com    }
47313151Sgabeblack@google.com    double dummy;
47413151Sgabeblack@google.com    if (modf(log10(d), &dummy) != 0.0) {
47513151Sgabeblack@google.com        SC_REPORT_ERROR("(E515) set default time unit failed",
47613151Sgabeblack@google.com                "value not a power of ten");
47713151Sgabeblack@google.com    }
47813151Sgabeblack@google.com    if (sc_is_running()) {
47913151Sgabeblack@google.com        SC_REPORT_ERROR("(E515) set default time unit failed",
48013151Sgabeblack@google.com                "simulation running");
48113151Sgabeblack@google.com    }
48213151Sgabeblack@google.com    static bool specified = false;
48313151Sgabeblack@google.com    if (specified) {
48413151Sgabeblack@google.com        SC_REPORT_ERROR("(E515) set default time unit failed",
48513151Sgabeblack@google.com                "already specified");
48613151Sgabeblack@google.com    }
48713151Sgabeblack@google.com    // This won't detect the timescale being fixed outside of systemc, but
48813151Sgabeblack@google.com    // it's at least some protection.
48913151Sgabeblack@google.com    if (timeFixed) {
49013151Sgabeblack@google.com        SC_REPORT_ERROR("(E515) set default time unit failed",
49113151Sgabeblack@google.com                "sc_time object(s) constructed");
49213151Sgabeblack@google.com    }
49313151Sgabeblack@google.com
49413151Sgabeblack@google.com    // Normalize d to seconds.
49513124Sgabeblack@google.com    defaultUnit = d * TimeUnitScale[tu];
49613151Sgabeblack@google.com    specified = true;
49713247Sgabeblack@google.com
49813247Sgabeblack@google.com    double resolution = SimClock::Float::Hz;
49913247Sgabeblack@google.com    if (resolution == 0.0)
50013247Sgabeblack@google.com        resolution = TimeUnitScale[SC_PS];
50113247Sgabeblack@google.com    if (defaultUnit < resolution) {
50213247Sgabeblack@google.com        SC_REPORT_ERROR("(E515) set default time unit failed",
50313247Sgabeblack@google.com                "value smaller than time resolution");
50413247Sgabeblack@google.com    }
50512916Sgabeblack@google.com}
50612916Sgabeblack@google.com
50712916Sgabeblack@google.comsc_time
50812916Sgabeblack@google.comsc_get_default_time_unit()
50912916Sgabeblack@google.com{
51013124Sgabeblack@google.com    return sc_time(defaultUnit, SC_SEC);
51112916Sgabeblack@google.com}
51212916Sgabeblack@google.com
51312927Sgabeblack@google.comsc_time_tuple::sc_time_tuple(const sc_time &)
51412927Sgabeblack@google.com{
51512927Sgabeblack@google.com    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
51612927Sgabeblack@google.com}
51712927Sgabeblack@google.com
51812927Sgabeblack@google.combool
51912927Sgabeblack@google.comsc_time_tuple::has_value() const
52012927Sgabeblack@google.com{
52112927Sgabeblack@google.com    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
52212927Sgabeblack@google.com    return false;
52312927Sgabeblack@google.com}
52412927Sgabeblack@google.com
52512927Sgabeblack@google.comsc_dt::uint64
52612927Sgabeblack@google.comsc_time_tuple::value() const
52712927Sgabeblack@google.com{
52812927Sgabeblack@google.com    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
52912927Sgabeblack@google.com    return 0;
53012927Sgabeblack@google.com}
53112927Sgabeblack@google.com
53212927Sgabeblack@google.comconst char *
53312927Sgabeblack@google.comsc_time_tuple::unit_symbol() const
53412927Sgabeblack@google.com{
53512927Sgabeblack@google.com    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
53612927Sgabeblack@google.com    return "";
53712927Sgabeblack@google.com}
53812927Sgabeblack@google.com
53912927Sgabeblack@google.comdouble
54012927Sgabeblack@google.comsc_time_tuple::to_double() const
54112927Sgabeblack@google.com{
54212927Sgabeblack@google.com    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
54312927Sgabeblack@google.com    return 0.0;
54412927Sgabeblack@google.com}
54512927Sgabeblack@google.com
54612927Sgabeblack@google.comstd::string
54712927Sgabeblack@google.comsc_time_tuple::to_string() const
54812927Sgabeblack@google.com{
54912927Sgabeblack@google.com    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
55012927Sgabeblack@google.com    return "";
55112927Sgabeblack@google.com}
55212927Sgabeblack@google.com
55312837Sgabeblack@google.com} // namespace sc_core
554