sc_time.cc revision 13124:538eff58fb30
12SN/A/*
22188SN/A * Copyright 2018 Google, Inc.
32SN/A *
42SN/A * Redistribution and use in source and binary forms, with or without
52SN/A * modification, are permitted provided that the following conditions are
62SN/A * met: redistributions of source code must retain the above copyright
72SN/A * notice, this list of conditions and the following disclaimer;
82SN/A * redistributions in binary form must reproduce the above copyright
92SN/A * notice, this list of conditions and the following disclaimer in the
102SN/A * documentation and/or other materials provided with the distribution;
112SN/A * neither the name of the copyright holders nor the names of its
122SN/A * contributors may be used to endorse or promote products derived from
132SN/A * this software without specific prior written permission.
142SN/A *
152SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
182SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
192SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
202SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
212SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
252SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262SN/A *
272665SN/A * Authors: Gabe Black
282665SN/A */
292665SN/A
302SN/A#include <vector>
312SN/A
322683Sktlim@umich.edu#include "base/logging.hh"
332683Sktlim@umich.edu#include "base/types.hh"
342SN/A#include "python/pybind11/pybind.hh"
356313Sgblack@eecs.umich.edu#include "systemc/core/python.hh"
362190SN/A#include "systemc/ext/core/sc_time.hh"
373776Sgblack@eecs.umich.edu
384997Sgblack@eecs.umich.edunamespace sc_core
396316Sgblack@eecs.umich.edu{
406216Snate@binkert.org
411858SN/Anamespace
422680SN/A{
432683Sktlim@umich.edu
442395SN/Aconst char *TimeUnitNames[] = {
452190SN/A    [SC_FS] = "fs",
462188SN/A    [SC_PS] = "ps",
47217SN/A    [SC_NS] = "ns",
482SN/A    [SC_US] = "us",
492SN/A    [SC_MS] = "ms",
502SN/A    [SC_SEC] = "s"
511858SN/A};
522SN/A
531070SN/Adouble TimeUnitScale[] = {
541070SN/A    [SC_FS] = 1.0e-15,
551917SN/A    [SC_PS] = 1.0e-12,
561917SN/A    [SC_NS] = 1.0e-9,
572521SN/A    [SC_US] = 1.0e-6,
582521SN/A    [SC_MS] = 1.0e-3,
592521SN/A    [SC_SEC] = 1.0
603548Sgblack@eecs.umich.edu};
613548Sgblack@eecs.umich.edu
623548Sgblack@eecs.umich.edubool timeFixed = false;
633548Sgblack@eecs.umich.edubool pythonReady = false;
642330SN/A
652330SN/Astruct SetInfo
662SN/A{
672SN/A    SetInfo(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu) :
68360SN/A        time(time), d(d), tu(tu)
692462SN/A    {}
702420SN/A
712SN/A    ::sc_core::sc_time *time;
722SN/A    double d;
732SN/A    ::sc_core::sc_time_unit tu;
742683Sktlim@umich.edu};
752683Sktlim@umich.edustd::vector<SetInfo> toSet;
762683Sktlim@umich.edu
772683Sktlim@umich.eduvoid
782683Sktlim@umich.edusetWork(sc_time *time, double d, ::sc_core::sc_time_unit tu)
792683Sktlim@umich.edu{
802683Sktlim@umich.edu    //XXX Assuming the time resolution is 1ps.
812683Sktlim@umich.edu    double scale = TimeUnitScale[tu] / TimeUnitScale[SC_PS];
822683Sktlim@umich.edu    // Accellera claims there is a linux bug, and that these next two
832683Sktlim@umich.edu    // lines work around them.
842683Sktlim@umich.edu    volatile double tmp = d * scale + 0.5;
852683Sktlim@umich.edu    *time = sc_time::from_value(static_cast<uint64_t>(tmp));
862683Sktlim@umich.edu}
872683Sktlim@umich.edu
882683Sktlim@umich.eduvoid
892SN/AfixTime()
902683Sktlim@umich.edu{
912SN/A    auto ticks = pybind11::module::import("m5.ticks");
922107SN/A    auto fix_global_frequency = ticks.attr("fixGlobalFrequency");
932107SN/A    fix_global_frequency();
942107SN/A
952159SN/A    for (auto &t: toSet)
962455SN/A        setWork(t.time, t.d, t.tu);
972455SN/A    toSet.clear();
982SN/A}
992680SN/A
1002SN/Avoid
1012190SN/Aset(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu)
1025543Ssaidi@eecs.umich.edu{
1036315Sgblack@eecs.umich.edu    // Only fix time once.
1046315Sgblack@eecs.umich.edu    if (!timeFixed) {
1056315Sgblack@eecs.umich.edu        timeFixed = true;
1066315Sgblack@eecs.umich.edu
1076316Sgblack@eecs.umich.edu        // If we've run, python is working and we haven't fixed time yet.
1086313Sgblack@eecs.umich.edu        if (pythonReady)
1092SN/A            fixTime();
1102190SN/A    }
1112683Sktlim@umich.edu    if (pythonReady) {
1122SN/A        // Time should be working. Set up this sc_time.
1132SN/A        setWork(time, d, tu);
1142683Sktlim@umich.edu    } else {
1152188SN/A        // Time isn't set up yet. Defer setting up this sc_time.
1162378SN/A        toSet.emplace_back(time, d, tu);
1172400SN/A    }
1186022Sgblack@eecs.umich.edu}
1196022Sgblack@eecs.umich.edu
1202SN/Aclass TimeSetter : public ::sc_gem5::PythonReadyFunc
1212683Sktlim@umich.edu{
1221858SN/A  public:
1232683Sktlim@umich.edu    TimeSetter() : ::sc_gem5::PythonReadyFunc() {}
1246022Sgblack@eecs.umich.edu
1252683Sktlim@umich.edu    void
1262SN/A    run() override
1274997Sgblack@eecs.umich.edu    {
1286022Sgblack@eecs.umich.edu        // Record that we've run and python/pybind should be usable.
1292SN/A        pythonReady = true;
1302862Sktlim@umich.edu
1312864Sktlim@umich.edu        // If time is already fixed, let python know.
1322862Sktlim@umich.edu        if (timeFixed)
1332683Sktlim@umich.edu            fixTime();
1342SN/A    }
1352680SN/A} timeSetter;
136180SN/A
1372SN/Adouble defaultUnit = 1.0e-9;
1382SN/A
1392864Sktlim@umich.edu} // anonymous namespace
1402864Sktlim@umich.edu
1412862Sktlim@umich.edusc_time::sc_time() : val(0) {}
1422862Sktlim@umich.edu
143217SN/Asc_time::sc_time(double d, sc_time_unit tu)
144237SN/A{
145217SN/A    val = 0;
1462683Sktlim@umich.edu    if (d != 0)
1472683Sktlim@umich.edu        set(this, d, tu);
1485891Sgblack@eecs.umich.edu}
1492683Sktlim@umich.edu
1502190SN/Asc_time::sc_time(const sc_time &t)
1512683Sktlim@umich.edu{
1522683Sktlim@umich.edu    val = t.val;
1532683Sktlim@umich.edu}
1542683Sktlim@umich.edu
1552680SN/Asc_time::sc_time(double d, bool scale)
1562190SN/A{
1575358Sgblack@eecs.umich.edu    //XXX Assuming the time resolution is 1ps.
1585358Sgblack@eecs.umich.edu    if (scale)
1595358Sgblack@eecs.umich.edu        set(this, d * defaultUnit, SC_SEC);
1605358Sgblack@eecs.umich.edu    else
1615358Sgblack@eecs.umich.edu        set(this, d, SC_PS);
1625358Sgblack@eecs.umich.edu}
1635358Sgblack@eecs.umich.edu
1645358Sgblack@eecs.umich.edusc_time::sc_time(sc_dt::uint64 v, bool scale)
1655358Sgblack@eecs.umich.edu{
1665358Sgblack@eecs.umich.edu    //XXX Assuming the time resolution is 1ps.
1675358Sgblack@eecs.umich.edu    if (scale)
1685358Sgblack@eecs.umich.edu        set(this, static_cast<double>(v) * defaultUnit, SC_SEC);
1695358Sgblack@eecs.umich.edu    else
1705358Sgblack@eecs.umich.edu        set(this, static_cast<double>(v), SC_PS);
1715358Sgblack@eecs.umich.edu}
1725358Sgblack@eecs.umich.edu
1734997Sgblack@eecs.umich.edusc_time &
1746313Sgblack@eecs.umich.edusc_time::operator = (const sc_time &t)
1756313Sgblack@eecs.umich.edu{
1764997Sgblack@eecs.umich.edu    val = t.val;
1772683Sktlim@umich.edu    return *this;
1782521SN/A}
1795702Ssaidi@eecs.umich.edu
1805702Ssaidi@eecs.umich.edusc_dt::uint64
1815702Ssaidi@eecs.umich.edusc_time::value() const
1825702Ssaidi@eecs.umich.edu{
1832683Sktlim@umich.edu    return val;
1842SN/A}
1852683Sktlim@umich.edu
1862683Sktlim@umich.edudouble
1872683Sktlim@umich.edusc_time::to_double() const
1882683Sktlim@umich.edu{
1892683Sktlim@umich.edu    return static_cast<double>(val);
1902683Sktlim@umich.edu}
1916022Sgblack@eecs.umich.edudouble
1922683Sktlim@umich.edusc_time::to_seconds() const
1936022Sgblack@eecs.umich.edu{
1942683Sktlim@umich.edu    double d = to_double();
1954997Sgblack@eecs.umich.edu    //XXX Assuming the time resolution is 1ps.
1964997Sgblack@eecs.umich.edu    double scale = TimeUnitScale[SC_PS] / TimeUnitScale[SC_SEC];
1975803Snate@binkert.org    return d * scale;
1982683Sktlim@umich.edu}
1992683Sktlim@umich.edu
2005499Ssaidi@eecs.umich.educonst std::string
2015499Ssaidi@eecs.umich.edusc_time::to_string() const
2025499Ssaidi@eecs.umich.edu{
2035499Ssaidi@eecs.umich.edu    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
2045499Ssaidi@eecs.umich.edu    return "";
2052SN/A}
2062SN/A
2072683Sktlim@umich.edubool
2082683Sktlim@umich.edusc_time::operator == (const sc_time &t) const
2092683Sktlim@umich.edu{
2102683Sktlim@umich.edu    return val == t.val;
2112683Sktlim@umich.edu}
2122683Sktlim@umich.edu
2132683Sktlim@umich.edubool
2142683Sktlim@umich.edusc_time::operator != (const sc_time &t) const
2152683Sktlim@umich.edu{
2162683Sktlim@umich.edu    return val != t.val;
2172683Sktlim@umich.edu}
2182683Sktlim@umich.edu
2192683Sktlim@umich.edubool
2202683Sktlim@umich.edusc_time::operator < (const sc_time &t) const
2212SN/A{
2222SN/A    return val < t.val;
2232532SN/A}
224716SN/A
2252378SN/Abool
2262378SN/Asc_time::operator <= (const sc_time &t) const
2272423SN/A{
228716SN/A    return val <= t.val;
229716SN/A}
2302683Sktlim@umich.edu
2312190SN/Abool
2326315Sgblack@eecs.umich.edusc_time::operator > (const sc_time &t) const
2336315Sgblack@eecs.umich.edu{
2346315Sgblack@eecs.umich.edu    return val > t.val;
2356316Sgblack@eecs.umich.edu}
2366315Sgblack@eecs.umich.edu
2376315Sgblack@eecs.umich.edubool
2382190SN/Asc_time::operator >= (const sc_time &t) const
2392SN/A{
2402SN/A    return val >= t.val;
2412SN/A}
2422SN/A
2432SN/Asc_time &
2446313Sgblack@eecs.umich.edusc_time::operator += (const sc_time &t)
2456323Sgblack@eecs.umich.edu{
2466316Sgblack@eecs.umich.edu    val += t.val;
2472SN/A    return *this;
2482SN/A}
2492455SN/A
2502SN/Asc_time &
2516313Sgblack@eecs.umich.edusc_time::operator -= (const sc_time &t)
2526323Sgblack@eecs.umich.edu{
2536315Sgblack@eecs.umich.edu    val -= t.val;
2542SN/A    return *this;
2552SN/A}
2562455SN/A
2572455SN/Asc_time &
2586313Sgblack@eecs.umich.edusc_time::operator *= (double d)
2596323Sgblack@eecs.umich.edu{
2606315Sgblack@eecs.umich.edu    val = static_cast<int64_t>(static_cast<double>(val) * d + 0.5);
2612SN/A    return *this;
2622SN/A}
2632SN/A
2642SN/Asc_time &
2656313Sgblack@eecs.umich.edusc_time::operator /= (double d)
2666323Sgblack@eecs.umich.edu{
2676316Sgblack@eecs.umich.edu    val = static_cast<int64_t>(static_cast<double>(val) / d + 0.5);
2682SN/A    return *this;
2692SN/A}
2702455SN/A
2712SN/Avoid
2726313Sgblack@eecs.umich.edusc_time::print(std::ostream &os) const
2736323Sgblack@eecs.umich.edu{
2746315Sgblack@eecs.umich.edu    if (val == 0) {
2752SN/A        os << "0 s";
2762SN/A    } else {
2772455SN/A        //XXX Assuming the time resolution is 1ps.
2782455SN/A        sc_time_unit tu = SC_PS;
2796313Sgblack@eecs.umich.edu        uint64_t scaled = val;
2806323Sgblack@eecs.umich.edu        while (tu < SC_SEC && (scaled % 1000) == 0) {
2816315Sgblack@eecs.umich.edu            tu = (sc_time_unit)((int)tu + 1);
2822SN/A            scaled /= 1000;
2832SN/A        }
2842SN/A
2852SN/A        os << scaled << ' ' << TimeUnitNames[tu];
2862525SN/A    }
2872SN/A}
2882SN/A
2892190SN/Asc_time
2902190SN/Asc_time::from_value(sc_dt::uint64 u)
2912525SN/A{
2922190SN/A    sc_time t;
2932190SN/A    t.val = u;
2943276Sgblack@eecs.umich.edu    return t;
2953276Sgblack@eecs.umich.edu}
2963276Sgblack@eecs.umich.edu
2973276Sgblack@eecs.umich.edusc_time
2983276Sgblack@eecs.umich.edusc_time::from_seconds(double d)
2993276Sgblack@eecs.umich.edu{
3003276Sgblack@eecs.umich.edu    sc_time t;
3013276Sgblack@eecs.umich.edu    set(&t, d, SC_SEC);
3023276Sgblack@eecs.umich.edu    return t;
3033276Sgblack@eecs.umich.edu}
3042190SN/A
3052190SN/Asc_time
3062525SN/Asc_time::from_string(const char *str)
3072190SN/A{
3082190SN/A    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
3092SN/A    return sc_time();
3102SN/A}
3112525SN/A
3122SN/Aconst sc_time
3132SN/Aoperator + (const sc_time &a, const sc_time &b)
3143276Sgblack@eecs.umich.edu{
3153276Sgblack@eecs.umich.edu    return sc_time::from_value(a.value() + b.value());
3163276Sgblack@eecs.umich.edu}
3173276Sgblack@eecs.umich.edu
3183276Sgblack@eecs.umich.educonst sc_time
3193276Sgblack@eecs.umich.eduoperator - (const sc_time &a, const sc_time &b)
3203276Sgblack@eecs.umich.edu{
3213276Sgblack@eecs.umich.edu    return sc_time::from_value(a.value() - b.value());
3223276Sgblack@eecs.umich.edu}
3233276Sgblack@eecs.umich.edu
3242252SN/Aconst sc_time
3252252SN/Aoperator * (const sc_time &t, double d)
3262525SN/A{
3272252SN/A    volatile double tmp = static_cast<double>(t.value()) * d + 0.5;
3282252SN/A    return sc_time::from_value(static_cast<int64_t>(tmp));
3292251SN/A}
3302251SN/A
3312525SN/Aconst sc_time
3322251SN/Aoperator * (double d, const sc_time &t)
3332251SN/A{
3346221Snate@binkert.org    volatile double tmp = d * static_cast<double>(t.value()) + 0.5;
3356221Snate@binkert.org    return sc_time::from_value(static_cast<int64_t>(tmp));
3364172Ssaidi@eecs.umich.edu}
3376313Sgblack@eecs.umich.edu
3384172Ssaidi@eecs.umich.educonst sc_time
3394172Ssaidi@eecs.umich.eduoperator / (const sc_time &t, double d)
3406221Snate@binkert.org{
3416221Snate@binkert.org    volatile double tmp = static_cast<double>(t.value()) / d + 0.5;
3422SN/A    return sc_time::from_value(static_cast<int64_t>(tmp));
3436313Sgblack@eecs.umich.edu}
3442SN/A
3452SN/Adouble
3466221Snate@binkert.orgoperator / (const sc_time &t1, const sc_time &t2)
3476221Snate@binkert.org{
3482SN/A    return t1.to_double() / t2.to_double();
3496313Sgblack@eecs.umich.edu}
3502SN/A
3512SN/Astd::ostream &
3526221Snate@binkert.orgoperator << (std::ostream &os, const sc_time &t)
3536221Snate@binkert.org{
3542SN/A    t.print(os);
3556313Sgblack@eecs.umich.edu    return os;
3566313Sgblack@eecs.umich.edu}
3576313Sgblack@eecs.umich.edu
3586313Sgblack@eecs.umich.educonst sc_time SC_ZERO_TIME;
3596313Sgblack@eecs.umich.edu
3606313Sgblack@eecs.umich.eduvoid
3616313Sgblack@eecs.umich.edusc_set_time_resolution(double, sc_time_unit)
3626313Sgblack@eecs.umich.edu{
3636313Sgblack@eecs.umich.edu    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
3646313Sgblack@eecs.umich.edu}
3656313Sgblack@eecs.umich.edu
3666313Sgblack@eecs.umich.edusc_time
3676313Sgblack@eecs.umich.edusc_get_time_resolution()
3682SN/A{
3692SN/A    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
3702190SN/A    return sc_time();
3712190SN/A}
3722190SN/A
3732190SN/Aconst sc_time &
3742190SN/Asc_max_time()
3751858SN/A{
3762561SN/A    static const sc_time MaxScTime = sc_time::from_value(MaxTick);
3772SN/A    return MaxScTime;
3782680SN/A}
3792SN/A
3802SN/Avoid
3812SN/Asc_set_default_time_unit(double d, sc_time_unit tu)
3822SN/A{
3832SN/A    defaultUnit = d * TimeUnitScale[tu];
3842SN/A}
3852SN/A
3862683Sktlim@umich.edusc_time
3872SN/Asc_get_default_time_unit()
3882SN/A{
3892SN/A    return sc_time(defaultUnit, SC_SEC);
3902SN/A}
3912190SN/A
392sc_time_tuple::sc_time_tuple(const sc_time &)
393{
394    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
395}
396
397bool
398sc_time_tuple::has_value() const
399{
400    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
401    return false;
402}
403
404sc_dt::uint64
405sc_time_tuple::value() const
406{
407    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
408    return 0;
409}
410
411const char *
412sc_time_tuple::unit_symbol() const
413{
414    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
415    return "";
416}
417
418double
419sc_time_tuple::to_double() const
420{
421    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
422    return 0.0;
423}
424
425std::string
426sc_time_tuple::to_string() const
427{
428    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
429    return "";
430}
431
432} // namespace sc_core
433