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
3013410Sgabeblack@google.com#include <cmath>
3113410Sgabeblack@google.com#include <cstring>
3213177Sgabeblack@google.com#include <sstream>
3313039Sgabeblack@google.com#include <vector>
3413039Sgabeblack@google.com
3512989Sgabeblack@google.com#include "base/types.hh"
3613195Sgabeblack@google.com#include "sim/core.hh"
3713252Sgabeblack@google.com#include "systemc/core/time.hh"
3813317Sgabeblack@google.com#include "systemc/ext/core/messages.hh"
3913149Sgabeblack@google.com#include "systemc/ext/core/sc_main.hh"
4012837Sgabeblack@google.com#include "systemc/ext/core/sc_time.hh"
4113149Sgabeblack@google.com#include "systemc/ext/utils/sc_report_handler.hh"
4212837Sgabeblack@google.com
4312837Sgabeblack@google.comnamespace sc_core
4412837Sgabeblack@google.com{
4512837Sgabeblack@google.com
4612983Sgabeblack@google.comnamespace
4712837Sgabeblack@google.com{
4812983Sgabeblack@google.com
4913410Sgabeblack@google.comvoid
5013410Sgabeblack@google.comset(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu)
5113410Sgabeblack@google.com{
5213410Sgabeblack@google.com    if (d != 0)
5313410Sgabeblack@google.com        fixClockFrequency();
5413039Sgabeblack@google.com
5513252Sgabeblack@google.com    double scale = sc_gem5::TimeUnitScale[tu] * SimClock::Float::s;
5613039Sgabeblack@google.com    // Accellera claims there is a linux bug, and that these next two
5713039Sgabeblack@google.com    // lines work around them.
5813039Sgabeblack@google.com    volatile double tmp = d * scale + 0.5;
5913039Sgabeblack@google.com    *time = sc_time::from_value(static_cast<uint64_t>(tmp));
6013039Sgabeblack@google.com}
6112986Sgabeblack@google.com
6213124Sgabeblack@google.comdouble defaultUnit = 1.0e-9;
6313124Sgabeblack@google.com
6412983Sgabeblack@google.com} // anonymous namespace
6512983Sgabeblack@google.com
6612983Sgabeblack@google.comsc_time::sc_time() : val(0) {}
6712983Sgabeblack@google.com
6812983Sgabeblack@google.comsc_time::sc_time(double d, sc_time_unit tu)
6912983Sgabeblack@google.com{
7012983Sgabeblack@google.com    val = 0;
7113195Sgabeblack@google.com    set(this, d, tu);
7212837Sgabeblack@google.com}
7312837Sgabeblack@google.com
7412983Sgabeblack@google.comsc_time::sc_time(const sc_time &t)
7512837Sgabeblack@google.com{
7612983Sgabeblack@google.com    val = t.val;
7712837Sgabeblack@google.com}
7812837Sgabeblack@google.com
7913265Sgabeblack@google.comsc_time::sc_time(double d, const char *unit)
8013265Sgabeblack@google.com{
8113265Sgabeblack@google.com    sc_time_unit tu;
8213265Sgabeblack@google.com    for (tu = SC_FS; tu <= SC_SEC; tu = (sc_time_unit)(tu + 1)) {
8313265Sgabeblack@google.com        if (strcmp(unit, sc_gem5::TimeUnitNames[tu]) == 0 ||
8413265Sgabeblack@google.com            strcmp(unit, sc_gem5::TimeUnitConstantNames[tu]) == 0) {
8513265Sgabeblack@google.com            break;
8613265Sgabeblack@google.com        }
8713265Sgabeblack@google.com    }
8813265Sgabeblack@google.com
8913265Sgabeblack@google.com    if (tu > SC_SEC) {
9013317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_TIME_CONVERSION_FAILED_,"invalid unit given");
9113265Sgabeblack@google.com        val = 0;
9213265Sgabeblack@google.com        return;
9313265Sgabeblack@google.com    }
9413265Sgabeblack@google.com    set(this, d, tu);
9513265Sgabeblack@google.com}
9613265Sgabeblack@google.com
9713057Sgabeblack@google.comsc_time::sc_time(double d, bool scale)
9812925Sgabeblack@google.com{
9913195Sgabeblack@google.com    double scaler = scale ? defaultUnit : SimClock::Float::Hz;
10013195Sgabeblack@google.com    set(this, d * scaler, SC_SEC);
10112925Sgabeblack@google.com}
10212925Sgabeblack@google.com
10313057Sgabeblack@google.comsc_time::sc_time(sc_dt::uint64 v, bool scale)
10412925Sgabeblack@google.com{
10513195Sgabeblack@google.com    double scaler = scale ? defaultUnit : SimClock::Float::Hz;
10613195Sgabeblack@google.com    set(this, static_cast<double>(v) * scaler, SC_SEC);
10712925Sgabeblack@google.com}
10812925Sgabeblack@google.com
10912837Sgabeblack@google.comsc_time &
11012983Sgabeblack@google.comsc_time::operator = (const sc_time &t)
11112837Sgabeblack@google.com{
11212983Sgabeblack@google.com    val = t.val;
11312837Sgabeblack@google.com    return *this;
11412837Sgabeblack@google.com}
11512837Sgabeblack@google.com
11612837Sgabeblack@google.comsc_dt::uint64
11712837Sgabeblack@google.comsc_time::value() const
11812837Sgabeblack@google.com{
11912983Sgabeblack@google.com    return val;
12012837Sgabeblack@google.com}
12112837Sgabeblack@google.com
12212837Sgabeblack@google.comdouble
12312837Sgabeblack@google.comsc_time::to_double() const
12412837Sgabeblack@google.com{
12513040Sgabeblack@google.com    return static_cast<double>(val);
12612837Sgabeblack@google.com}
12712837Sgabeblack@google.comdouble
12812837Sgabeblack@google.comsc_time::to_seconds() const
12912837Sgabeblack@google.com{
13013195Sgabeblack@google.com    return to_double() * SimClock::Float::Hz;
13112837Sgabeblack@google.com}
13212837Sgabeblack@google.com
13312837Sgabeblack@google.comconst std::string
13412837Sgabeblack@google.comsc_time::to_string() const
13512837Sgabeblack@google.com{
13613177Sgabeblack@google.com    std::ostringstream ss;
13713177Sgabeblack@google.com    print(ss);
13813177Sgabeblack@google.com    return ss.str();
13912837Sgabeblack@google.com}
14012837Sgabeblack@google.com
14112837Sgabeblack@google.combool
14212983Sgabeblack@google.comsc_time::operator == (const sc_time &t) const
14312837Sgabeblack@google.com{
14412983Sgabeblack@google.com    return val == t.val;
14512837Sgabeblack@google.com}
14612837Sgabeblack@google.com
14712837Sgabeblack@google.combool
14812983Sgabeblack@google.comsc_time::operator != (const sc_time &t) const
14912837Sgabeblack@google.com{
15012983Sgabeblack@google.com    return val != t.val;
15112837Sgabeblack@google.com}
15212837Sgabeblack@google.com
15312837Sgabeblack@google.combool
15412983Sgabeblack@google.comsc_time::operator < (const sc_time &t) const
15512837Sgabeblack@google.com{
15612983Sgabeblack@google.com    return val < t.val;
15712837Sgabeblack@google.com}
15812837Sgabeblack@google.com
15912837Sgabeblack@google.combool
16012983Sgabeblack@google.comsc_time::operator <= (const sc_time &t) const
16112837Sgabeblack@google.com{
16212983Sgabeblack@google.com    return val <= t.val;
16312837Sgabeblack@google.com}
16412837Sgabeblack@google.com
16512837Sgabeblack@google.combool
16612983Sgabeblack@google.comsc_time::operator > (const sc_time &t) const
16712837Sgabeblack@google.com{
16812983Sgabeblack@google.com    return val > t.val;
16912837Sgabeblack@google.com}
17012837Sgabeblack@google.com
17112837Sgabeblack@google.combool
17212983Sgabeblack@google.comsc_time::operator >= (const sc_time &t) const
17312837Sgabeblack@google.com{
17412983Sgabeblack@google.com    return val >= t.val;
17512837Sgabeblack@google.com}
17612837Sgabeblack@google.com
17712837Sgabeblack@google.comsc_time &
17812983Sgabeblack@google.comsc_time::operator += (const sc_time &t)
17912837Sgabeblack@google.com{
18012983Sgabeblack@google.com    val += t.val;
18112837Sgabeblack@google.com    return *this;
18212837Sgabeblack@google.com}
18312837Sgabeblack@google.com
18412837Sgabeblack@google.comsc_time &
18512983Sgabeblack@google.comsc_time::operator -= (const sc_time &t)
18612837Sgabeblack@google.com{
18712983Sgabeblack@google.com    val -= t.val;
18812837Sgabeblack@google.com    return *this;
18912837Sgabeblack@google.com}
19012837Sgabeblack@google.com
19112837Sgabeblack@google.comsc_time &
19213040Sgabeblack@google.comsc_time::operator *= (double d)
19312837Sgabeblack@google.com{
19413040Sgabeblack@google.com    val = static_cast<int64_t>(static_cast<double>(val) * d + 0.5);
19512837Sgabeblack@google.com    return *this;
19612837Sgabeblack@google.com}
19712837Sgabeblack@google.com
19812837Sgabeblack@google.comsc_time &
19913040Sgabeblack@google.comsc_time::operator /= (double d)
20012837Sgabeblack@google.com{
20113040Sgabeblack@google.com    val = static_cast<int64_t>(static_cast<double>(val) / d + 0.5);
20212837Sgabeblack@google.com    return *this;
20312837Sgabeblack@google.com}
20412837Sgabeblack@google.com
20512837Sgabeblack@google.comvoid
20612983Sgabeblack@google.comsc_time::print(std::ostream &os) const
20712837Sgabeblack@google.com{
20813263Sgabeblack@google.com    os << sc_time_tuple(*this).to_string();
20912837Sgabeblack@google.com}
21012837Sgabeblack@google.com
21112923Sgabeblack@google.comsc_time
21212983Sgabeblack@google.comsc_time::from_value(sc_dt::uint64 u)
21312923Sgabeblack@google.com{
21413195Sgabeblack@google.com    if (u)
21513410Sgabeblack@google.com        fixClockFrequency();
21612983Sgabeblack@google.com    sc_time t;
21712983Sgabeblack@google.com    t.val = u;
21812983Sgabeblack@google.com    return t;
21912923Sgabeblack@google.com}
22012923Sgabeblack@google.com
22112923Sgabeblack@google.comsc_time
22213057Sgabeblack@google.comsc_time::from_seconds(double d)
22312923Sgabeblack@google.com{
22413057Sgabeblack@google.com    sc_time t;
22513057Sgabeblack@google.com    set(&t, d, SC_SEC);
22613057Sgabeblack@google.com    return t;
22712923Sgabeblack@google.com}
22812923Sgabeblack@google.com
22912923Sgabeblack@google.comsc_time
23012923Sgabeblack@google.comsc_time::from_string(const char *str)
23112923Sgabeblack@google.com{
23213265Sgabeblack@google.com    char *end = nullptr;
23313265Sgabeblack@google.com
23413265Sgabeblack@google.com    double d = str ? std::strtod(str, &end) : 0.0;
23513265Sgabeblack@google.com    if (str == end || d < 0.0) {
23613317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_TIME_CONVERSION_FAILED_, "invalid value given");
23713265Sgabeblack@google.com        return SC_ZERO_TIME;
23813265Sgabeblack@google.com    }
23913265Sgabeblack@google.com
24013265Sgabeblack@google.com    while (*end && std::isspace(*end))
24113265Sgabeblack@google.com        end++;
24213265Sgabeblack@google.com
24313265Sgabeblack@google.com    return sc_time(d, end);
24412923Sgabeblack@google.com}
24512923Sgabeblack@google.com
24612837Sgabeblack@google.comconst sc_time
24712989Sgabeblack@google.comoperator + (const sc_time &a, const sc_time &b)
24812837Sgabeblack@google.com{
24912989Sgabeblack@google.com    return sc_time::from_value(a.value() + b.value());
25012837Sgabeblack@google.com}
25112837Sgabeblack@google.com
25212837Sgabeblack@google.comconst sc_time
25312989Sgabeblack@google.comoperator - (const sc_time &a, const sc_time &b)
25412837Sgabeblack@google.com{
25512989Sgabeblack@google.com    return sc_time::from_value(a.value() - b.value());
25612837Sgabeblack@google.com}
25712837Sgabeblack@google.com
25812837Sgabeblack@google.comconst sc_time
25913040Sgabeblack@google.comoperator * (const sc_time &t, double d)
26012837Sgabeblack@google.com{
26113040Sgabeblack@google.com    volatile double tmp = static_cast<double>(t.value()) * d + 0.5;
26213040Sgabeblack@google.com    return sc_time::from_value(static_cast<int64_t>(tmp));
26312837Sgabeblack@google.com}
26412837Sgabeblack@google.com
26512837Sgabeblack@google.comconst sc_time
26613040Sgabeblack@google.comoperator * (double d, const sc_time &t)
26712837Sgabeblack@google.com{
26813040Sgabeblack@google.com    volatile double tmp = d * static_cast<double>(t.value()) + 0.5;
26913040Sgabeblack@google.com    return sc_time::from_value(static_cast<int64_t>(tmp));
27012837Sgabeblack@google.com}
27112837Sgabeblack@google.com
27212837Sgabeblack@google.comconst sc_time
27313040Sgabeblack@google.comoperator / (const sc_time &t, double d)
27412837Sgabeblack@google.com{
27513040Sgabeblack@google.com    volatile double tmp = static_cast<double>(t.value()) / d + 0.5;
27613040Sgabeblack@google.com    return sc_time::from_value(static_cast<int64_t>(tmp));
27712837Sgabeblack@google.com}
27812837Sgabeblack@google.com
27912837Sgabeblack@google.comdouble
28013040Sgabeblack@google.comoperator / (const sc_time &t1, const sc_time &t2)
28112837Sgabeblack@google.com{
28213040Sgabeblack@google.com    return t1.to_double() / t2.to_double();
28312837Sgabeblack@google.com}
28412837Sgabeblack@google.com
28512837Sgabeblack@google.comstd::ostream &
28612983Sgabeblack@google.comoperator << (std::ostream &os, const sc_time &t)
28712837Sgabeblack@google.com{
28812983Sgabeblack@google.com    t.print(os);
28912837Sgabeblack@google.com    return os;
29012837Sgabeblack@google.com}
29112837Sgabeblack@google.com
29212837Sgabeblack@google.comconst sc_time SC_ZERO_TIME;
29312837Sgabeblack@google.com
29412837Sgabeblack@google.comvoid
29513149Sgabeblack@google.comsc_set_time_resolution(double d, sc_time_unit tu)
29612837Sgabeblack@google.com{
29713317Sgabeblack@google.com    if (d <= 0.0)
29813317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "value not positive");
29913317Sgabeblack@google.com
30013149Sgabeblack@google.com    double dummy;
30113149Sgabeblack@google.com    if (modf(log10(d), &dummy) != 0.0) {
30213317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_,
30313149Sgabeblack@google.com                "value not a power of ten");
30413149Sgabeblack@google.com    }
30513317Sgabeblack@google.com    if (sc_is_running())
30613317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "simulation running");
30713317Sgabeblack@google.com
30813149Sgabeblack@google.com    static bool specified = false;
30913317Sgabeblack@google.com    if (specified)
31013317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "already specified");
31113317Sgabeblack@google.com
31213149Sgabeblack@google.com    // This won't detect the timescale being fixed outside of systemc, but
31313149Sgabeblack@google.com    // it's at least some protection.
31413410Sgabeblack@google.com    if (clockFrequencyFixed()) {
31513317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_,
31613149Sgabeblack@google.com                "sc_time object(s) constructed");
31713149Sgabeblack@google.com    }
31813149Sgabeblack@google.com
31913252Sgabeblack@google.com    double seconds = d * sc_gem5::TimeUnitScale[tu];
32013317Sgabeblack@google.com    if (seconds < sc_gem5::TimeUnitScale[SC_FS])
32113317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "value smaller than 1 fs");
32213195Sgabeblack@google.com
32313195Sgabeblack@google.com    if (seconds > defaultUnit) {
32413317Sgabeblack@google.com        SC_REPORT_WARNING(SC_ID_DEFAULT_TIME_UNIT_CHANGED_, "");
32513195Sgabeblack@google.com        defaultUnit = seconds;
32613195Sgabeblack@google.com    }
32713195Sgabeblack@google.com
32813195Sgabeblack@google.com    // Get rid of fractional parts of d.
32913195Sgabeblack@google.com    while (d < 1.0 && tu > SC_FS) {
33013195Sgabeblack@google.com        d *= 1000;
33113195Sgabeblack@google.com        tu = (sc_time_unit)(tu - 1);
33213195Sgabeblack@google.com    }
33313195Sgabeblack@google.com
33413252Sgabeblack@google.com    Tick ticks_per_second =
33513252Sgabeblack@google.com        sc_gem5::TimeUnitFrequency[tu] / static_cast<Tick>(d);
33613410Sgabeblack@google.com    setClockFrequency(ticks_per_second);
33713149Sgabeblack@google.com    specified = true;
33812837Sgabeblack@google.com}
33912837Sgabeblack@google.com
34012837Sgabeblack@google.comsc_time
34112837Sgabeblack@google.comsc_get_time_resolution()
34212837Sgabeblack@google.com{
34313149Sgabeblack@google.com    return sc_time::from_value(1);
34412837Sgabeblack@google.com}
34512837Sgabeblack@google.com
34612837Sgabeblack@google.comconst sc_time &
34712837Sgabeblack@google.comsc_max_time()
34812837Sgabeblack@google.com{
34912989Sgabeblack@google.com    static const sc_time MaxScTime = sc_time::from_value(MaxTick);
35012989Sgabeblack@google.com    return MaxScTime;
35112837Sgabeblack@google.com}
35212837Sgabeblack@google.com
35312916Sgabeblack@google.comvoid
35413124Sgabeblack@google.comsc_set_default_time_unit(double d, sc_time_unit tu)
35512916Sgabeblack@google.com{
35613317Sgabeblack@google.com    if (d < 0.0)
35713317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_, "value not positive");
35813317Sgabeblack@google.com
35913151Sgabeblack@google.com    double dummy;
36013151Sgabeblack@google.com    if (modf(log10(d), &dummy) != 0.0) {
36113317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_,
36213151Sgabeblack@google.com                "value not a power of ten");
36313151Sgabeblack@google.com    }
36413317Sgabeblack@google.com    if (sc_is_running())
36513317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_, "simulation running");
36613317Sgabeblack@google.com
36713151Sgabeblack@google.com    static bool specified = false;
36813151Sgabeblack@google.com    if (specified) {
36913317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_, "already specified");
37013151Sgabeblack@google.com    }
37113151Sgabeblack@google.com    // This won't detect the timescale being fixed outside of systemc, but
37213151Sgabeblack@google.com    // it's at least some protection.
37313410Sgabeblack@google.com    if (clockFrequencyFixed()) {
37413317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_,
37513151Sgabeblack@google.com                "sc_time object(s) constructed");
37613151Sgabeblack@google.com    }
37713151Sgabeblack@google.com
37813151Sgabeblack@google.com    // Normalize d to seconds.
37913252Sgabeblack@google.com    defaultUnit = d * sc_gem5::TimeUnitScale[tu];
38013151Sgabeblack@google.com    specified = true;
38113247Sgabeblack@google.com
38213247Sgabeblack@google.com    double resolution = SimClock::Float::Hz;
38313247Sgabeblack@google.com    if (resolution == 0.0)
38413252Sgabeblack@google.com        resolution = sc_gem5::TimeUnitScale[SC_PS];
38513247Sgabeblack@google.com    if (defaultUnit < resolution) {
38613317Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_,
38713247Sgabeblack@google.com                "value smaller than time resolution");
38813247Sgabeblack@google.com    }
38912916Sgabeblack@google.com}
39012916Sgabeblack@google.com
39112916Sgabeblack@google.comsc_time
39212916Sgabeblack@google.comsc_get_default_time_unit()
39312916Sgabeblack@google.com{
39413124Sgabeblack@google.com    return sc_time(defaultUnit, SC_SEC);
39512916Sgabeblack@google.com}
39612916Sgabeblack@google.com
39713263Sgabeblack@google.comsc_time_tuple::sc_time_tuple(const sc_time &t) :
39813263Sgabeblack@google.com    _value(), _unit(SC_SEC), _set(true)
39912927Sgabeblack@google.com{
40013263Sgabeblack@google.com    if (!t.value())
40113263Sgabeblack@google.com        return;
40213263Sgabeblack@google.com
40313263Sgabeblack@google.com    Tick frequency = SimClock::Frequency;
40413263Sgabeblack@google.com
40513263Sgabeblack@google.com    // Shrink the frequency by scaling down the time period, ie converting
40613263Sgabeblack@google.com    // it from cycles per second to cycles per millisecond, etc.
40713263Sgabeblack@google.com    while (_unit > 1 && (frequency % 1000 == 0)) {
40813263Sgabeblack@google.com        _unit = (sc_time_unit)((int)_unit - 1);
40913263Sgabeblack@google.com        frequency /= 1000;
41013263Sgabeblack@google.com    }
41113263Sgabeblack@google.com
41213263Sgabeblack@google.com    // Convert the frequency into a period.
41313263Sgabeblack@google.com    Tick period;
41413263Sgabeblack@google.com    if (frequency > 1) {
41513263Sgabeblack@google.com        _unit = (sc_time_unit)((int)_unit - 1);
41613263Sgabeblack@google.com        period = 1000 / frequency;
41713263Sgabeblack@google.com    } else {
41813263Sgabeblack@google.com        period = frequency;
41913263Sgabeblack@google.com    }
42013263Sgabeblack@google.com
42113263Sgabeblack@google.com    // Scale our integer value by the period.
42213263Sgabeblack@google.com    _value = t.value() * period;
42313263Sgabeblack@google.com
42413263Sgabeblack@google.com    // Shrink the scaled time value by increasing the size of the units
42513263Sgabeblack@google.com    // it's measured by, avoiding fractional parts.
42613263Sgabeblack@google.com    while (_unit < SC_SEC && (_value % 1000) == 0) {
42713263Sgabeblack@google.com        _unit = (sc_time_unit)((int)_unit + 1);
42813263Sgabeblack@google.com        _value /= 1000;
42913263Sgabeblack@google.com    }
43012927Sgabeblack@google.com}
43112927Sgabeblack@google.com
43212927Sgabeblack@google.combool
43312927Sgabeblack@google.comsc_time_tuple::has_value() const
43412927Sgabeblack@google.com{
43513263Sgabeblack@google.com    return _set;
43612927Sgabeblack@google.com}
43712927Sgabeblack@google.com
43813263Sgabeblack@google.comsc_dt::uint64 sc_time_tuple::value() const { return _value; }
43912927Sgabeblack@google.com
44012927Sgabeblack@google.comconst char *
44112927Sgabeblack@google.comsc_time_tuple::unit_symbol() const
44212927Sgabeblack@google.com{
44313263Sgabeblack@google.com    return sc_gem5::TimeUnitNames[_unit];
44412927Sgabeblack@google.com}
44512927Sgabeblack@google.com
44613263Sgabeblack@google.comdouble sc_time_tuple::to_double() const { return static_cast<double>(_value); }
44712927Sgabeblack@google.com
44812927Sgabeblack@google.comstd::string
44912927Sgabeblack@google.comsc_time_tuple::to_string() const
45012927Sgabeblack@google.com{
45113263Sgabeblack@google.com    std::ostringstream ss;
45213263Sgabeblack@google.com    ss << _value << ' ' << unit_symbol();
45313263Sgabeblack@google.com    return ss.str();
45412927Sgabeblack@google.com}
45512927Sgabeblack@google.com
45612837Sgabeblack@google.com} // namespace sc_core
457