sc_time.cc revision 13317
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"
3813252Sgabeblack@google.com#include "systemc/core/time.hh"
3913317Sgabeblack@google.com#include "systemc/ext/core/messages.hh"
4013149Sgabeblack@google.com#include "systemc/ext/core/sc_main.hh"
4112837Sgabeblack@google.com#include "systemc/ext/core/sc_time.hh"
4213149Sgabeblack@google.com#include "systemc/ext/utils/sc_report_handler.hh"
4312837Sgabeblack@google.com
4412837Sgabeblack@google.comnamespace sc_core
4512837Sgabeblack@google.com{
4612837Sgabeblack@google.com
4712983Sgabeblack@google.comnamespace
4812837Sgabeblack@google.com{
4912983Sgabeblack@google.com
5013039Sgabeblack@google.combool timeFixed = false;
5113039Sgabeblack@google.combool pythonReady = false;
5213039Sgabeblack@google.com
5313039Sgabeblack@google.comstruct SetInfo
5413039Sgabeblack@google.com{
5513039Sgabeblack@google.com    SetInfo(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu) :
5613039Sgabeblack@google.com        time(time), d(d), tu(tu)
5713039Sgabeblack@google.com    {}
5813039Sgabeblack@google.com
5913039Sgabeblack@google.com    ::sc_core::sc_time *time;
6013039Sgabeblack@google.com    double d;
6113039Sgabeblack@google.com    ::sc_core::sc_time_unit tu;
6213039Sgabeblack@google.com};
6313039Sgabeblack@google.comstd::vector<SetInfo> toSet;
6413039Sgabeblack@google.com
6512986Sgabeblack@google.comvoid
6613039Sgabeblack@google.comsetWork(sc_time *time, double d, ::sc_core::sc_time_unit tu)
6712986Sgabeblack@google.com{
6813252Sgabeblack@google.com    double scale = sc_gem5::TimeUnitScale[tu] * SimClock::Float::s;
6913039Sgabeblack@google.com    // Accellera claims there is a linux bug, and that these next two
7013039Sgabeblack@google.com    // lines work around them.
7113039Sgabeblack@google.com    volatile double tmp = d * scale + 0.5;
7213039Sgabeblack@google.com    *time = sc_time::from_value(static_cast<uint64_t>(tmp));
7313039Sgabeblack@google.com}
7412986Sgabeblack@google.com
7513039Sgabeblack@google.comvoid
7613039Sgabeblack@google.comfixTime()
7713039Sgabeblack@google.com{
7812986Sgabeblack@google.com    auto ticks = pybind11::module::import("m5.ticks");
7912986Sgabeblack@google.com    auto fix_global_frequency = ticks.attr("fixGlobalFrequency");
8012986Sgabeblack@google.com    fix_global_frequency();
8113039Sgabeblack@google.com
8213039Sgabeblack@google.com    for (auto &t: toSet)
8313039Sgabeblack@google.com        setWork(t.time, t.d, t.tu);
8413039Sgabeblack@google.com    toSet.clear();
8512986Sgabeblack@google.com}
8612986Sgabeblack@google.com
8713039Sgabeblack@google.comvoid
8813195Sgabeblack@google.comattemptToFixTime()
8913195Sgabeblack@google.com{
9013195Sgabeblack@google.com    // Only fix time once.
9113195Sgabeblack@google.com    if (!timeFixed) {
9213195Sgabeblack@google.com        timeFixed = true;
9313195Sgabeblack@google.com
9413195Sgabeblack@google.com        // If we've run, python is working and we haven't fixed time yet.
9513195Sgabeblack@google.com        if (pythonReady)
9613195Sgabeblack@google.com            fixTime();
9713195Sgabeblack@google.com    }
9813195Sgabeblack@google.com}
9913195Sgabeblack@google.com
10013195Sgabeblack@google.comvoid
10113149Sgabeblack@google.comsetGlobalFrequency(Tick ticks_per_second)
10213149Sgabeblack@google.com{
10313149Sgabeblack@google.com    auto ticks = pybind11::module::import("m5.ticks");
10413149Sgabeblack@google.com    auto set_global_frequency = ticks.attr("setGlobalFrequency");
10513149Sgabeblack@google.com    set_global_frequency(ticks_per_second);
10613149Sgabeblack@google.com    fixTime();
10713149Sgabeblack@google.com}
10813149Sgabeblack@google.com
10913149Sgabeblack@google.comvoid
11013039Sgabeblack@google.comset(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu)
11113039Sgabeblack@google.com{
11213195Sgabeblack@google.com    if (d != 0)
11313195Sgabeblack@google.com        attemptToFixTime();
11413039Sgabeblack@google.com    if (pythonReady) {
11513039Sgabeblack@google.com        // Time should be working. Set up this sc_time.
11613039Sgabeblack@google.com        setWork(time, d, tu);
11713039Sgabeblack@google.com    } else {
11813039Sgabeblack@google.com        // Time isn't set up yet. Defer setting up this sc_time.
11913039Sgabeblack@google.com        toSet.emplace_back(time, d, tu);
12013039Sgabeblack@google.com    }
12113039Sgabeblack@google.com}
12213039Sgabeblack@google.com
12313039Sgabeblack@google.comclass TimeSetter : public ::sc_gem5::PythonReadyFunc
12413039Sgabeblack@google.com{
12513039Sgabeblack@google.com  public:
12613039Sgabeblack@google.com    TimeSetter() : ::sc_gem5::PythonReadyFunc() {}
12713039Sgabeblack@google.com
12813039Sgabeblack@google.com    void
12913039Sgabeblack@google.com    run() override
13013039Sgabeblack@google.com    {
13113039Sgabeblack@google.com        // Record that we've run and python/pybind should be usable.
13213039Sgabeblack@google.com        pythonReady = true;
13313039Sgabeblack@google.com
13413039Sgabeblack@google.com        // If time is already fixed, let python know.
13513039Sgabeblack@google.com        if (timeFixed)
13613039Sgabeblack@google.com            fixTime();
13713039Sgabeblack@google.com    }
13813039Sgabeblack@google.com} timeSetter;
13913039Sgabeblack@google.com
14013124Sgabeblack@google.comdouble defaultUnit = 1.0e-9;
14113124Sgabeblack@google.com
14212983Sgabeblack@google.com} // anonymous namespace
14312983Sgabeblack@google.com
14412983Sgabeblack@google.comsc_time::sc_time() : val(0) {}
14512983Sgabeblack@google.com
14612983Sgabeblack@google.comsc_time::sc_time(double d, sc_time_unit tu)
14712983Sgabeblack@google.com{
14812983Sgabeblack@google.com    val = 0;
14913195Sgabeblack@google.com    set(this, d, tu);
15012837Sgabeblack@google.com}
15112837Sgabeblack@google.com
15212983Sgabeblack@google.comsc_time::sc_time(const sc_time &t)
15312837Sgabeblack@google.com{
15412983Sgabeblack@google.com    val = t.val;
15512837Sgabeblack@google.com}
15612837Sgabeblack@google.com
15713265Sgabeblack@google.comsc_time::sc_time(double d, const char *unit)
15813265Sgabeblack@google.com{
15913265Sgabeblack@google.com    sc_time_unit tu;
16013265Sgabeblack@google.com    for (tu = SC_FS; tu <= SC_SEC; tu = (sc_time_unit)(tu + 1)) {
16113265Sgabeblack@google.com        if (strcmp(unit, sc_gem5::TimeUnitNames[tu]) == 0 ||
16213265Sgabeblack@google.com            strcmp(unit, sc_gem5::TimeUnitConstantNames[tu]) == 0) {
16313265Sgabeblack@google.com            break;
16413265Sgabeblack@google.com        }
16513265Sgabeblack@google.com    }
16613265Sgabeblack@google.com
16713265Sgabeblack@google.com    if (tu > SC_SEC) {
16813317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_TIME_CONVERSION_FAILED_,"invalid unit given");
16913265Sgabeblack@google.com        val = 0;
17013265Sgabeblack@google.com        return;
17113265Sgabeblack@google.com    }
17213265Sgabeblack@google.com    set(this, d, tu);
17313265Sgabeblack@google.com}
17413265Sgabeblack@google.com
17513057Sgabeblack@google.comsc_time::sc_time(double d, bool scale)
17612925Sgabeblack@google.com{
17713195Sgabeblack@google.com    double scaler = scale ? defaultUnit : SimClock::Float::Hz;
17813195Sgabeblack@google.com    set(this, d * scaler, SC_SEC);
17912925Sgabeblack@google.com}
18012925Sgabeblack@google.com
18113057Sgabeblack@google.comsc_time::sc_time(sc_dt::uint64 v, bool scale)
18212925Sgabeblack@google.com{
18313195Sgabeblack@google.com    double scaler = scale ? defaultUnit : SimClock::Float::Hz;
18413195Sgabeblack@google.com    set(this, static_cast<double>(v) * scaler, SC_SEC);
18512925Sgabeblack@google.com}
18612925Sgabeblack@google.com
18712837Sgabeblack@google.comsc_time &
18812983Sgabeblack@google.comsc_time::operator = (const sc_time &t)
18912837Sgabeblack@google.com{
19012983Sgabeblack@google.com    val = t.val;
19112837Sgabeblack@google.com    return *this;
19212837Sgabeblack@google.com}
19312837Sgabeblack@google.com
19412837Sgabeblack@google.comsc_dt::uint64
19512837Sgabeblack@google.comsc_time::value() const
19612837Sgabeblack@google.com{
19712983Sgabeblack@google.com    return val;
19812837Sgabeblack@google.com}
19912837Sgabeblack@google.com
20012837Sgabeblack@google.comdouble
20112837Sgabeblack@google.comsc_time::to_double() const
20212837Sgabeblack@google.com{
20313040Sgabeblack@google.com    return static_cast<double>(val);
20412837Sgabeblack@google.com}
20512837Sgabeblack@google.comdouble
20612837Sgabeblack@google.comsc_time::to_seconds() const
20712837Sgabeblack@google.com{
20813195Sgabeblack@google.com    return to_double() * SimClock::Float::Hz;
20912837Sgabeblack@google.com}
21012837Sgabeblack@google.com
21112837Sgabeblack@google.comconst std::string
21212837Sgabeblack@google.comsc_time::to_string() const
21312837Sgabeblack@google.com{
21413177Sgabeblack@google.com    std::ostringstream ss;
21513177Sgabeblack@google.com    print(ss);
21613177Sgabeblack@google.com    return ss.str();
21712837Sgabeblack@google.com}
21812837Sgabeblack@google.com
21912837Sgabeblack@google.combool
22012983Sgabeblack@google.comsc_time::operator == (const sc_time &t) const
22112837Sgabeblack@google.com{
22212983Sgabeblack@google.com    return val == t.val;
22312837Sgabeblack@google.com}
22412837Sgabeblack@google.com
22512837Sgabeblack@google.combool
22612983Sgabeblack@google.comsc_time::operator != (const sc_time &t) const
22712837Sgabeblack@google.com{
22812983Sgabeblack@google.com    return val != t.val;
22912837Sgabeblack@google.com}
23012837Sgabeblack@google.com
23112837Sgabeblack@google.combool
23212983Sgabeblack@google.comsc_time::operator < (const sc_time &t) const
23312837Sgabeblack@google.com{
23412983Sgabeblack@google.com    return val < t.val;
23512837Sgabeblack@google.com}
23612837Sgabeblack@google.com
23712837Sgabeblack@google.combool
23812983Sgabeblack@google.comsc_time::operator <= (const sc_time &t) const
23912837Sgabeblack@google.com{
24012983Sgabeblack@google.com    return val <= t.val;
24112837Sgabeblack@google.com}
24212837Sgabeblack@google.com
24312837Sgabeblack@google.combool
24412983Sgabeblack@google.comsc_time::operator > (const sc_time &t) const
24512837Sgabeblack@google.com{
24612983Sgabeblack@google.com    return val > t.val;
24712837Sgabeblack@google.com}
24812837Sgabeblack@google.com
24912837Sgabeblack@google.combool
25012983Sgabeblack@google.comsc_time::operator >= (const sc_time &t) const
25112837Sgabeblack@google.com{
25212983Sgabeblack@google.com    return val >= t.val;
25312837Sgabeblack@google.com}
25412837Sgabeblack@google.com
25512837Sgabeblack@google.comsc_time &
25612983Sgabeblack@google.comsc_time::operator += (const sc_time &t)
25712837Sgabeblack@google.com{
25812983Sgabeblack@google.com    val += t.val;
25912837Sgabeblack@google.com    return *this;
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 &
27013040Sgabeblack@google.comsc_time::operator *= (double d)
27112837Sgabeblack@google.com{
27213040Sgabeblack@google.com    val = static_cast<int64_t>(static_cast<double>(val) * d + 0.5);
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.comvoid
28412983Sgabeblack@google.comsc_time::print(std::ostream &os) const
28512837Sgabeblack@google.com{
28613263Sgabeblack@google.com    os << sc_time_tuple(*this).to_string();
28712837Sgabeblack@google.com}
28812837Sgabeblack@google.com
28912923Sgabeblack@google.comsc_time
29012983Sgabeblack@google.comsc_time::from_value(sc_dt::uint64 u)
29112923Sgabeblack@google.com{
29213195Sgabeblack@google.com    if (u)
29313195Sgabeblack@google.com        attemptToFixTime();
29412983Sgabeblack@google.com    sc_time t;
29512983Sgabeblack@google.com    t.val = u;
29612983Sgabeblack@google.com    return t;
29712923Sgabeblack@google.com}
29812923Sgabeblack@google.com
29912923Sgabeblack@google.comsc_time
30013057Sgabeblack@google.comsc_time::from_seconds(double d)
30112923Sgabeblack@google.com{
30213057Sgabeblack@google.com    sc_time t;
30313057Sgabeblack@google.com    set(&t, d, SC_SEC);
30413057Sgabeblack@google.com    return t;
30512923Sgabeblack@google.com}
30612923Sgabeblack@google.com
30712923Sgabeblack@google.comsc_time
30812923Sgabeblack@google.comsc_time::from_string(const char *str)
30912923Sgabeblack@google.com{
31013265Sgabeblack@google.com    char *end = nullptr;
31113265Sgabeblack@google.com
31213265Sgabeblack@google.com    double d = str ? std::strtod(str, &end) : 0.0;
31313265Sgabeblack@google.com    if (str == end || d < 0.0) {
31413317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_TIME_CONVERSION_FAILED_, "invalid value given");
31513265Sgabeblack@google.com        return SC_ZERO_TIME;
31613265Sgabeblack@google.com    }
31713265Sgabeblack@google.com
31813265Sgabeblack@google.com    while (*end && std::isspace(*end))
31913265Sgabeblack@google.com        end++;
32013265Sgabeblack@google.com
32113265Sgabeblack@google.com    return sc_time(d, end);
32212923Sgabeblack@google.com}
32312923Sgabeblack@google.com
32412837Sgabeblack@google.comconst sc_time
32512989Sgabeblack@google.comoperator + (const sc_time &a, const sc_time &b)
32612837Sgabeblack@google.com{
32712989Sgabeblack@google.com    return sc_time::from_value(a.value() + b.value());
32812837Sgabeblack@google.com}
32912837Sgabeblack@google.com
33012837Sgabeblack@google.comconst sc_time
33112989Sgabeblack@google.comoperator - (const sc_time &a, const sc_time &b)
33212837Sgabeblack@google.com{
33312989Sgabeblack@google.com    return sc_time::from_value(a.value() - b.value());
33412837Sgabeblack@google.com}
33512837Sgabeblack@google.com
33612837Sgabeblack@google.comconst sc_time
33713040Sgabeblack@google.comoperator * (const sc_time &t, double d)
33812837Sgabeblack@google.com{
33913040Sgabeblack@google.com    volatile double tmp = static_cast<double>(t.value()) * d + 0.5;
34013040Sgabeblack@google.com    return sc_time::from_value(static_cast<int64_t>(tmp));
34112837Sgabeblack@google.com}
34212837Sgabeblack@google.com
34312837Sgabeblack@google.comconst sc_time
34413040Sgabeblack@google.comoperator * (double d, const sc_time &t)
34512837Sgabeblack@google.com{
34613040Sgabeblack@google.com    volatile double tmp = d * static_cast<double>(t.value()) + 0.5;
34713040Sgabeblack@google.com    return sc_time::from_value(static_cast<int64_t>(tmp));
34812837Sgabeblack@google.com}
34912837Sgabeblack@google.com
35012837Sgabeblack@google.comconst sc_time
35113040Sgabeblack@google.comoperator / (const sc_time &t, double d)
35212837Sgabeblack@google.com{
35313040Sgabeblack@google.com    volatile double tmp = static_cast<double>(t.value()) / d + 0.5;
35413040Sgabeblack@google.com    return sc_time::from_value(static_cast<int64_t>(tmp));
35512837Sgabeblack@google.com}
35612837Sgabeblack@google.com
35712837Sgabeblack@google.comdouble
35813040Sgabeblack@google.comoperator / (const sc_time &t1, const sc_time &t2)
35912837Sgabeblack@google.com{
36013040Sgabeblack@google.com    return t1.to_double() / t2.to_double();
36112837Sgabeblack@google.com}
36212837Sgabeblack@google.com
36312837Sgabeblack@google.comstd::ostream &
36412983Sgabeblack@google.comoperator << (std::ostream &os, const sc_time &t)
36512837Sgabeblack@google.com{
36612983Sgabeblack@google.com    t.print(os);
36712837Sgabeblack@google.com    return os;
36812837Sgabeblack@google.com}
36912837Sgabeblack@google.com
37012837Sgabeblack@google.comconst sc_time SC_ZERO_TIME;
37112837Sgabeblack@google.com
37212837Sgabeblack@google.comvoid
37313149Sgabeblack@google.comsc_set_time_resolution(double d, sc_time_unit tu)
37412837Sgabeblack@google.com{
37513317Sgabeblack@google.com    if (d <= 0.0)
37613317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "value not positive");
37713317Sgabeblack@google.com
37813149Sgabeblack@google.com    double dummy;
37913149Sgabeblack@google.com    if (modf(log10(d), &dummy) != 0.0) {
38013317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_,
38113149Sgabeblack@google.com                "value not a power of ten");
38213149Sgabeblack@google.com    }
38313317Sgabeblack@google.com    if (sc_is_running())
38413317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "simulation running");
38513317Sgabeblack@google.com
38613149Sgabeblack@google.com    static bool specified = false;
38713317Sgabeblack@google.com    if (specified)
38813317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "already specified");
38913317Sgabeblack@google.com
39013149Sgabeblack@google.com    // This won't detect the timescale being fixed outside of systemc, but
39113149Sgabeblack@google.com    // it's at least some protection.
39213149Sgabeblack@google.com    if (timeFixed) {
39313317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_,
39413149Sgabeblack@google.com                "sc_time object(s) constructed");
39513149Sgabeblack@google.com    }
39613149Sgabeblack@google.com
39713252Sgabeblack@google.com    double seconds = d * sc_gem5::TimeUnitScale[tu];
39813317Sgabeblack@google.com    if (seconds < sc_gem5::TimeUnitScale[SC_FS])
39913317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "value smaller than 1 fs");
40013195Sgabeblack@google.com
40113195Sgabeblack@google.com    if (seconds > defaultUnit) {
40213317Sgabeblack@google.com        SC_REPORT_WARNING(SC_ID_DEFAULT_TIME_UNIT_CHANGED_, "");
40313195Sgabeblack@google.com        defaultUnit = seconds;
40413195Sgabeblack@google.com    }
40513195Sgabeblack@google.com
40613195Sgabeblack@google.com    // Get rid of fractional parts of d.
40713195Sgabeblack@google.com    while (d < 1.0 && tu > SC_FS) {
40813195Sgabeblack@google.com        d *= 1000;
40913195Sgabeblack@google.com        tu = (sc_time_unit)(tu - 1);
41013195Sgabeblack@google.com    }
41113195Sgabeblack@google.com
41213252Sgabeblack@google.com    Tick ticks_per_second =
41313252Sgabeblack@google.com        sc_gem5::TimeUnitFrequency[tu] / static_cast<Tick>(d);
41413149Sgabeblack@google.com    setGlobalFrequency(ticks_per_second);
41513149Sgabeblack@google.com    specified = true;
41612837Sgabeblack@google.com}
41712837Sgabeblack@google.com
41812837Sgabeblack@google.comsc_time
41912837Sgabeblack@google.comsc_get_time_resolution()
42012837Sgabeblack@google.com{
42113149Sgabeblack@google.com    return sc_time::from_value(1);
42212837Sgabeblack@google.com}
42312837Sgabeblack@google.com
42412837Sgabeblack@google.comconst sc_time &
42512837Sgabeblack@google.comsc_max_time()
42612837Sgabeblack@google.com{
42712989Sgabeblack@google.com    static const sc_time MaxScTime = sc_time::from_value(MaxTick);
42812989Sgabeblack@google.com    return MaxScTime;
42912837Sgabeblack@google.com}
43012837Sgabeblack@google.com
43112916Sgabeblack@google.comvoid
43213124Sgabeblack@google.comsc_set_default_time_unit(double d, sc_time_unit tu)
43312916Sgabeblack@google.com{
43413317Sgabeblack@google.com    if (d < 0.0)
43513317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_, "value not positive");
43613317Sgabeblack@google.com
43713151Sgabeblack@google.com    double dummy;
43813151Sgabeblack@google.com    if (modf(log10(d), &dummy) != 0.0) {
43913317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_,
44013151Sgabeblack@google.com                "value not a power of ten");
44113151Sgabeblack@google.com    }
44213317Sgabeblack@google.com    if (sc_is_running())
44313317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_, "simulation running");
44413317Sgabeblack@google.com
44513151Sgabeblack@google.com    static bool specified = false;
44613151Sgabeblack@google.com    if (specified) {
44713317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_, "already specified");
44813151Sgabeblack@google.com    }
44913151Sgabeblack@google.com    // This won't detect the timescale being fixed outside of systemc, but
45013151Sgabeblack@google.com    // it's at least some protection.
45113151Sgabeblack@google.com    if (timeFixed) {
45213317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_,
45313151Sgabeblack@google.com                "sc_time object(s) constructed");
45413151Sgabeblack@google.com    }
45513151Sgabeblack@google.com
45613151Sgabeblack@google.com    // Normalize d to seconds.
45713252Sgabeblack@google.com    defaultUnit = d * sc_gem5::TimeUnitScale[tu];
45813151Sgabeblack@google.com    specified = true;
45913247Sgabeblack@google.com
46013247Sgabeblack@google.com    double resolution = SimClock::Float::Hz;
46113247Sgabeblack@google.com    if (resolution == 0.0)
46213252Sgabeblack@google.com        resolution = sc_gem5::TimeUnitScale[SC_PS];
46313247Sgabeblack@google.com    if (defaultUnit < resolution) {
46413317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_,
46513247Sgabeblack@google.com                "value smaller than time resolution");
46613247Sgabeblack@google.com    }
46712916Sgabeblack@google.com}
46812916Sgabeblack@google.com
46912916Sgabeblack@google.comsc_time
47012916Sgabeblack@google.comsc_get_default_time_unit()
47112916Sgabeblack@google.com{
47213124Sgabeblack@google.com    return sc_time(defaultUnit, SC_SEC);
47312916Sgabeblack@google.com}
47412916Sgabeblack@google.com
47513263Sgabeblack@google.comsc_time_tuple::sc_time_tuple(const sc_time &t) :
47613263Sgabeblack@google.com    _value(), _unit(SC_SEC), _set(true)
47712927Sgabeblack@google.com{
47813263Sgabeblack@google.com    if (!t.value())
47913263Sgabeblack@google.com        return;
48013263Sgabeblack@google.com
48113263Sgabeblack@google.com    Tick frequency = SimClock::Frequency;
48213263Sgabeblack@google.com
48313263Sgabeblack@google.com    // Shrink the frequency by scaling down the time period, ie converting
48413263Sgabeblack@google.com    // it from cycles per second to cycles per millisecond, etc.
48513263Sgabeblack@google.com    while (_unit > 1 && (frequency % 1000 == 0)) {
48613263Sgabeblack@google.com        _unit = (sc_time_unit)((int)_unit - 1);
48713263Sgabeblack@google.com        frequency /= 1000;
48813263Sgabeblack@google.com    }
48913263Sgabeblack@google.com
49013263Sgabeblack@google.com    // Convert the frequency into a period.
49113263Sgabeblack@google.com    Tick period;
49213263Sgabeblack@google.com    if (frequency > 1) {
49313263Sgabeblack@google.com        _unit = (sc_time_unit)((int)_unit - 1);
49413263Sgabeblack@google.com        period = 1000 / frequency;
49513263Sgabeblack@google.com    } else {
49613263Sgabeblack@google.com        period = frequency;
49713263Sgabeblack@google.com    }
49813263Sgabeblack@google.com
49913263Sgabeblack@google.com    // Scale our integer value by the period.
50013263Sgabeblack@google.com    _value = t.value() * period;
50113263Sgabeblack@google.com
50213263Sgabeblack@google.com    // Shrink the scaled time value by increasing the size of the units
50313263Sgabeblack@google.com    // it's measured by, avoiding fractional parts.
50413263Sgabeblack@google.com    while (_unit < SC_SEC && (_value % 1000) == 0) {
50513263Sgabeblack@google.com        _unit = (sc_time_unit)((int)_unit + 1);
50613263Sgabeblack@google.com        _value /= 1000;
50713263Sgabeblack@google.com    }
50812927Sgabeblack@google.com}
50912927Sgabeblack@google.com
51012927Sgabeblack@google.combool
51112927Sgabeblack@google.comsc_time_tuple::has_value() const
51212927Sgabeblack@google.com{
51313263Sgabeblack@google.com    return _set;
51412927Sgabeblack@google.com}
51512927Sgabeblack@google.com
51613263Sgabeblack@google.comsc_dt::uint64 sc_time_tuple::value() const { return _value; }
51712927Sgabeblack@google.com
51812927Sgabeblack@google.comconst char *
51912927Sgabeblack@google.comsc_time_tuple::unit_symbol() const
52012927Sgabeblack@google.com{
52113263Sgabeblack@google.com    return sc_gem5::TimeUnitNames[_unit];
52212927Sgabeblack@google.com}
52312927Sgabeblack@google.com
52413263Sgabeblack@google.comdouble sc_time_tuple::to_double() const { return static_cast<double>(_value); }
52512927Sgabeblack@google.com
52612927Sgabeblack@google.comstd::string
52712927Sgabeblack@google.comsc_time_tuple::to_string() const
52812927Sgabeblack@google.com{
52913263Sgabeblack@google.com    std::ostringstream ss;
53013263Sgabeblack@google.com    ss << _value << ' ' << unit_symbol();
53113263Sgabeblack@google.com    return ss.str();
53212927Sgabeblack@google.com}
53312927Sgabeblack@google.com
53412837Sgabeblack@google.com} // namespace sc_core
535