sc_time.cc revision 13265
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" 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 4913039Sgabeblack@google.combool timeFixed = false; 5013039Sgabeblack@google.combool pythonReady = false; 5113039Sgabeblack@google.com 5213039Sgabeblack@google.comstruct SetInfo 5313039Sgabeblack@google.com{ 5413039Sgabeblack@google.com SetInfo(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu) : 5513039Sgabeblack@google.com time(time), d(d), tu(tu) 5613039Sgabeblack@google.com {} 5713039Sgabeblack@google.com 5813039Sgabeblack@google.com ::sc_core::sc_time *time; 5913039Sgabeblack@google.com double d; 6013039Sgabeblack@google.com ::sc_core::sc_time_unit tu; 6113039Sgabeblack@google.com}; 6213039Sgabeblack@google.comstd::vector<SetInfo> toSet; 6313039Sgabeblack@google.com 6412986Sgabeblack@google.comvoid 6513039Sgabeblack@google.comsetWork(sc_time *time, double d, ::sc_core::sc_time_unit tu) 6612986Sgabeblack@google.com{ 6713252Sgabeblack@google.com double scale = sc_gem5::TimeUnitScale[tu] * SimClock::Float::s; 6813039Sgabeblack@google.com // Accellera claims there is a linux bug, and that these next two 6913039Sgabeblack@google.com // lines work around them. 7013039Sgabeblack@google.com volatile double tmp = d * scale + 0.5; 7113039Sgabeblack@google.com *time = sc_time::from_value(static_cast<uint64_t>(tmp)); 7213039Sgabeblack@google.com} 7312986Sgabeblack@google.com 7413039Sgabeblack@google.comvoid 7513039Sgabeblack@google.comfixTime() 7613039Sgabeblack@google.com{ 7712986Sgabeblack@google.com auto ticks = pybind11::module::import("m5.ticks"); 7812986Sgabeblack@google.com auto fix_global_frequency = ticks.attr("fixGlobalFrequency"); 7912986Sgabeblack@google.com fix_global_frequency(); 8013039Sgabeblack@google.com 8113039Sgabeblack@google.com for (auto &t: toSet) 8213039Sgabeblack@google.com setWork(t.time, t.d, t.tu); 8313039Sgabeblack@google.com toSet.clear(); 8412986Sgabeblack@google.com} 8512986Sgabeblack@google.com 8613039Sgabeblack@google.comvoid 8713195Sgabeblack@google.comattemptToFixTime() 8813195Sgabeblack@google.com{ 8913195Sgabeblack@google.com // Only fix time once. 9013195Sgabeblack@google.com if (!timeFixed) { 9113195Sgabeblack@google.com timeFixed = true; 9213195Sgabeblack@google.com 9313195Sgabeblack@google.com // If we've run, python is working and we haven't fixed time yet. 9413195Sgabeblack@google.com if (pythonReady) 9513195Sgabeblack@google.com fixTime(); 9613195Sgabeblack@google.com } 9713195Sgabeblack@google.com} 9813195Sgabeblack@google.com 9913195Sgabeblack@google.comvoid 10013149Sgabeblack@google.comsetGlobalFrequency(Tick ticks_per_second) 10113149Sgabeblack@google.com{ 10213149Sgabeblack@google.com auto ticks = pybind11::module::import("m5.ticks"); 10313149Sgabeblack@google.com auto set_global_frequency = ticks.attr("setGlobalFrequency"); 10413149Sgabeblack@google.com set_global_frequency(ticks_per_second); 10513149Sgabeblack@google.com fixTime(); 10613149Sgabeblack@google.com} 10713149Sgabeblack@google.com 10813149Sgabeblack@google.comvoid 10913039Sgabeblack@google.comset(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu) 11013039Sgabeblack@google.com{ 11113195Sgabeblack@google.com if (d != 0) 11213195Sgabeblack@google.com attemptToFixTime(); 11313039Sgabeblack@google.com if (pythonReady) { 11413039Sgabeblack@google.com // Time should be working. Set up this sc_time. 11513039Sgabeblack@google.com setWork(time, d, tu); 11613039Sgabeblack@google.com } else { 11713039Sgabeblack@google.com // Time isn't set up yet. Defer setting up this sc_time. 11813039Sgabeblack@google.com toSet.emplace_back(time, d, tu); 11913039Sgabeblack@google.com } 12013039Sgabeblack@google.com} 12113039Sgabeblack@google.com 12213039Sgabeblack@google.comclass TimeSetter : public ::sc_gem5::PythonReadyFunc 12313039Sgabeblack@google.com{ 12413039Sgabeblack@google.com public: 12513039Sgabeblack@google.com TimeSetter() : ::sc_gem5::PythonReadyFunc() {} 12613039Sgabeblack@google.com 12713039Sgabeblack@google.com void 12813039Sgabeblack@google.com run() override 12913039Sgabeblack@google.com { 13013039Sgabeblack@google.com // Record that we've run and python/pybind should be usable. 13113039Sgabeblack@google.com pythonReady = true; 13213039Sgabeblack@google.com 13313039Sgabeblack@google.com // If time is already fixed, let python know. 13413039Sgabeblack@google.com if (timeFixed) 13513039Sgabeblack@google.com fixTime(); 13613039Sgabeblack@google.com } 13713039Sgabeblack@google.com} timeSetter; 13813039Sgabeblack@google.com 13913124Sgabeblack@google.comdouble defaultUnit = 1.0e-9; 14013124Sgabeblack@google.com 14112983Sgabeblack@google.com} // anonymous namespace 14212983Sgabeblack@google.com 14312983Sgabeblack@google.comsc_time::sc_time() : val(0) {} 14412983Sgabeblack@google.com 14512983Sgabeblack@google.comsc_time::sc_time(double d, sc_time_unit tu) 14612983Sgabeblack@google.com{ 14712983Sgabeblack@google.com val = 0; 14813195Sgabeblack@google.com set(this, d, tu); 14912837Sgabeblack@google.com} 15012837Sgabeblack@google.com 15112983Sgabeblack@google.comsc_time::sc_time(const sc_time &t) 15212837Sgabeblack@google.com{ 15312983Sgabeblack@google.com val = t.val; 15412837Sgabeblack@google.com} 15512837Sgabeblack@google.com 15613265Sgabeblack@google.comsc_time::sc_time(double d, const char *unit) 15713265Sgabeblack@google.com{ 15813265Sgabeblack@google.com sc_time_unit tu; 15913265Sgabeblack@google.com for (tu = SC_FS; tu <= SC_SEC; tu = (sc_time_unit)(tu + 1)) { 16013265Sgabeblack@google.com if (strcmp(unit, sc_gem5::TimeUnitNames[tu]) == 0 || 16113265Sgabeblack@google.com strcmp(unit, sc_gem5::TimeUnitConstantNames[tu]) == 0) { 16213265Sgabeblack@google.com break; 16313265Sgabeblack@google.com } 16413265Sgabeblack@google.com } 16513265Sgabeblack@google.com 16613265Sgabeblack@google.com if (tu > SC_SEC) { 16713265Sgabeblack@google.com SC_REPORT_ERROR("(E567) sc_time conversion failed", 16813265Sgabeblack@google.com "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) { 31413265Sgabeblack@google.com SC_REPORT_ERROR("(E567) sc_time conversion failed", 31513265Sgabeblack@google.com "invalid value given"); 31613265Sgabeblack@google.com return SC_ZERO_TIME; 31713265Sgabeblack@google.com } 31813265Sgabeblack@google.com 31913265Sgabeblack@google.com while (*end && std::isspace(*end)) 32013265Sgabeblack@google.com end++; 32113265Sgabeblack@google.com 32213265Sgabeblack@google.com return sc_time(d, end); 32312923Sgabeblack@google.com} 32412923Sgabeblack@google.com 32512837Sgabeblack@google.comconst sc_time 32612989Sgabeblack@google.comoperator + (const sc_time &a, const sc_time &b) 32712837Sgabeblack@google.com{ 32812989Sgabeblack@google.com return sc_time::from_value(a.value() + b.value()); 32912837Sgabeblack@google.com} 33012837Sgabeblack@google.com 33112837Sgabeblack@google.comconst sc_time 33212989Sgabeblack@google.comoperator - (const sc_time &a, const sc_time &b) 33312837Sgabeblack@google.com{ 33412989Sgabeblack@google.com return sc_time::from_value(a.value() - b.value()); 33512837Sgabeblack@google.com} 33612837Sgabeblack@google.com 33712837Sgabeblack@google.comconst sc_time 33813040Sgabeblack@google.comoperator * (const sc_time &t, double d) 33912837Sgabeblack@google.com{ 34013040Sgabeblack@google.com volatile double tmp = static_cast<double>(t.value()) * d + 0.5; 34113040Sgabeblack@google.com return sc_time::from_value(static_cast<int64_t>(tmp)); 34212837Sgabeblack@google.com} 34312837Sgabeblack@google.com 34412837Sgabeblack@google.comconst sc_time 34513040Sgabeblack@google.comoperator * (double d, const sc_time &t) 34612837Sgabeblack@google.com{ 34713040Sgabeblack@google.com volatile double tmp = d * static_cast<double>(t.value()) + 0.5; 34813040Sgabeblack@google.com return sc_time::from_value(static_cast<int64_t>(tmp)); 34912837Sgabeblack@google.com} 35012837Sgabeblack@google.com 35112837Sgabeblack@google.comconst sc_time 35213040Sgabeblack@google.comoperator / (const sc_time &t, double d) 35312837Sgabeblack@google.com{ 35413040Sgabeblack@google.com volatile double tmp = static_cast<double>(t.value()) / d + 0.5; 35513040Sgabeblack@google.com return sc_time::from_value(static_cast<int64_t>(tmp)); 35612837Sgabeblack@google.com} 35712837Sgabeblack@google.com 35812837Sgabeblack@google.comdouble 35913040Sgabeblack@google.comoperator / (const sc_time &t1, const sc_time &t2) 36012837Sgabeblack@google.com{ 36113040Sgabeblack@google.com return t1.to_double() / t2.to_double(); 36212837Sgabeblack@google.com} 36312837Sgabeblack@google.com 36412837Sgabeblack@google.comstd::ostream & 36512983Sgabeblack@google.comoperator << (std::ostream &os, const sc_time &t) 36612837Sgabeblack@google.com{ 36712983Sgabeblack@google.com t.print(os); 36812837Sgabeblack@google.com return os; 36912837Sgabeblack@google.com} 37012837Sgabeblack@google.com 37112837Sgabeblack@google.comconst sc_time SC_ZERO_TIME; 37212837Sgabeblack@google.com 37312837Sgabeblack@google.comvoid 37413149Sgabeblack@google.comsc_set_time_resolution(double d, sc_time_unit tu) 37512837Sgabeblack@google.com{ 37613151Sgabeblack@google.com if (d <= 0.0) { 37713149Sgabeblack@google.com SC_REPORT_ERROR("(E514) set time resolution failed", 37813149Sgabeblack@google.com "value not positive"); 37913149Sgabeblack@google.com } 38013149Sgabeblack@google.com double dummy; 38113149Sgabeblack@google.com if (modf(log10(d), &dummy) != 0.0) { 38213149Sgabeblack@google.com SC_REPORT_ERROR("(E514) set time resolution failed", 38313149Sgabeblack@google.com "value not a power of ten"); 38413149Sgabeblack@google.com } 38513149Sgabeblack@google.com if (sc_is_running()) { 38613149Sgabeblack@google.com SC_REPORT_ERROR("(E514) set time resolution failed", 38713149Sgabeblack@google.com "simulation running"); 38813149Sgabeblack@google.com } 38913149Sgabeblack@google.com static bool specified = false; 39013149Sgabeblack@google.com if (specified) { 39113149Sgabeblack@google.com SC_REPORT_ERROR("(E514) set time resolution failed", 39213149Sgabeblack@google.com "already specified"); 39313149Sgabeblack@google.com } 39413149Sgabeblack@google.com // This won't detect the timescale being fixed outside of systemc, but 39513149Sgabeblack@google.com // it's at least some protection. 39613149Sgabeblack@google.com if (timeFixed) { 39713149Sgabeblack@google.com SC_REPORT_ERROR("(E514) set time resolution failed", 39813149Sgabeblack@google.com "sc_time object(s) constructed"); 39913149Sgabeblack@google.com } 40013149Sgabeblack@google.com 40113252Sgabeblack@google.com double seconds = d * sc_gem5::TimeUnitScale[tu]; 40213252Sgabeblack@google.com if (seconds < sc_gem5::TimeUnitScale[SC_FS]) { 40313149Sgabeblack@google.com SC_REPORT_ERROR("(E514) set time resolution failed", 40413149Sgabeblack@google.com "value smaller than 1 fs"); 40513149Sgabeblack@google.com } 40613195Sgabeblack@google.com 40713195Sgabeblack@google.com if (seconds > defaultUnit) { 40813195Sgabeblack@google.com SC_REPORT_WARNING( 40913195Sgabeblack@google.com "(W516) default time unit changed to time resolution", ""); 41013195Sgabeblack@google.com defaultUnit = seconds; 41113195Sgabeblack@google.com } 41213195Sgabeblack@google.com 41313195Sgabeblack@google.com // Get rid of fractional parts of d. 41413195Sgabeblack@google.com while (d < 1.0 && tu > SC_FS) { 41513195Sgabeblack@google.com d *= 1000; 41613195Sgabeblack@google.com tu = (sc_time_unit)(tu - 1); 41713195Sgabeblack@google.com } 41813195Sgabeblack@google.com 41913252Sgabeblack@google.com Tick ticks_per_second = 42013252Sgabeblack@google.com sc_gem5::TimeUnitFrequency[tu] / static_cast<Tick>(d); 42113149Sgabeblack@google.com setGlobalFrequency(ticks_per_second); 42213149Sgabeblack@google.com specified = true; 42312837Sgabeblack@google.com} 42412837Sgabeblack@google.com 42512837Sgabeblack@google.comsc_time 42612837Sgabeblack@google.comsc_get_time_resolution() 42712837Sgabeblack@google.com{ 42813149Sgabeblack@google.com return sc_time::from_value(1); 42912837Sgabeblack@google.com} 43012837Sgabeblack@google.com 43112837Sgabeblack@google.comconst sc_time & 43212837Sgabeblack@google.comsc_max_time() 43312837Sgabeblack@google.com{ 43412989Sgabeblack@google.com static const sc_time MaxScTime = sc_time::from_value(MaxTick); 43512989Sgabeblack@google.com return MaxScTime; 43612837Sgabeblack@google.com} 43712837Sgabeblack@google.com 43812916Sgabeblack@google.comvoid 43913124Sgabeblack@google.comsc_set_default_time_unit(double d, sc_time_unit tu) 44012916Sgabeblack@google.com{ 44113151Sgabeblack@google.com if (d < 0.0) { 44213151Sgabeblack@google.com SC_REPORT_ERROR("(E515) set default time unit failed", 44313151Sgabeblack@google.com "value not positive"); 44413151Sgabeblack@google.com } 44513151Sgabeblack@google.com double dummy; 44613151Sgabeblack@google.com if (modf(log10(d), &dummy) != 0.0) { 44713151Sgabeblack@google.com SC_REPORT_ERROR("(E515) set default time unit failed", 44813151Sgabeblack@google.com "value not a power of ten"); 44913151Sgabeblack@google.com } 45013151Sgabeblack@google.com if (sc_is_running()) { 45113151Sgabeblack@google.com SC_REPORT_ERROR("(E515) set default time unit failed", 45213151Sgabeblack@google.com "simulation running"); 45313151Sgabeblack@google.com } 45413151Sgabeblack@google.com static bool specified = false; 45513151Sgabeblack@google.com if (specified) { 45613151Sgabeblack@google.com SC_REPORT_ERROR("(E515) set default time unit failed", 45713151Sgabeblack@google.com "already specified"); 45813151Sgabeblack@google.com } 45913151Sgabeblack@google.com // This won't detect the timescale being fixed outside of systemc, but 46013151Sgabeblack@google.com // it's at least some protection. 46113151Sgabeblack@google.com if (timeFixed) { 46213151Sgabeblack@google.com SC_REPORT_ERROR("(E515) set default time unit failed", 46313151Sgabeblack@google.com "sc_time object(s) constructed"); 46413151Sgabeblack@google.com } 46513151Sgabeblack@google.com 46613151Sgabeblack@google.com // Normalize d to seconds. 46713252Sgabeblack@google.com defaultUnit = d * sc_gem5::TimeUnitScale[tu]; 46813151Sgabeblack@google.com specified = true; 46913247Sgabeblack@google.com 47013247Sgabeblack@google.com double resolution = SimClock::Float::Hz; 47113247Sgabeblack@google.com if (resolution == 0.0) 47213252Sgabeblack@google.com resolution = sc_gem5::TimeUnitScale[SC_PS]; 47313247Sgabeblack@google.com if (defaultUnit < resolution) { 47413247Sgabeblack@google.com SC_REPORT_ERROR("(E515) set default time unit failed", 47513247Sgabeblack@google.com "value smaller than time resolution"); 47613247Sgabeblack@google.com } 47712916Sgabeblack@google.com} 47812916Sgabeblack@google.com 47912916Sgabeblack@google.comsc_time 48012916Sgabeblack@google.comsc_get_default_time_unit() 48112916Sgabeblack@google.com{ 48213124Sgabeblack@google.com return sc_time(defaultUnit, SC_SEC); 48312916Sgabeblack@google.com} 48412916Sgabeblack@google.com 48513263Sgabeblack@google.comsc_time_tuple::sc_time_tuple(const sc_time &t) : 48613263Sgabeblack@google.com _value(), _unit(SC_SEC), _set(true) 48712927Sgabeblack@google.com{ 48813263Sgabeblack@google.com if (!t.value()) 48913263Sgabeblack@google.com return; 49013263Sgabeblack@google.com 49113263Sgabeblack@google.com Tick frequency = SimClock::Frequency; 49213263Sgabeblack@google.com 49313263Sgabeblack@google.com // Shrink the frequency by scaling down the time period, ie converting 49413263Sgabeblack@google.com // it from cycles per second to cycles per millisecond, etc. 49513263Sgabeblack@google.com while (_unit > 1 && (frequency % 1000 == 0)) { 49613263Sgabeblack@google.com _unit = (sc_time_unit)((int)_unit - 1); 49713263Sgabeblack@google.com frequency /= 1000; 49813263Sgabeblack@google.com } 49913263Sgabeblack@google.com 50013263Sgabeblack@google.com // Convert the frequency into a period. 50113263Sgabeblack@google.com Tick period; 50213263Sgabeblack@google.com if (frequency > 1) { 50313263Sgabeblack@google.com _unit = (sc_time_unit)((int)_unit - 1); 50413263Sgabeblack@google.com period = 1000 / frequency; 50513263Sgabeblack@google.com } else { 50613263Sgabeblack@google.com period = frequency; 50713263Sgabeblack@google.com } 50813263Sgabeblack@google.com 50913263Sgabeblack@google.com // Scale our integer value by the period. 51013263Sgabeblack@google.com _value = t.value() * period; 51113263Sgabeblack@google.com 51213263Sgabeblack@google.com // Shrink the scaled time value by increasing the size of the units 51313263Sgabeblack@google.com // it's measured by, avoiding fractional parts. 51413263Sgabeblack@google.com while (_unit < SC_SEC && (_value % 1000) == 0) { 51513263Sgabeblack@google.com _unit = (sc_time_unit)((int)_unit + 1); 51613263Sgabeblack@google.com _value /= 1000; 51713263Sgabeblack@google.com } 51812927Sgabeblack@google.com} 51912927Sgabeblack@google.com 52012927Sgabeblack@google.combool 52112927Sgabeblack@google.comsc_time_tuple::has_value() const 52212927Sgabeblack@google.com{ 52313263Sgabeblack@google.com return _set; 52412927Sgabeblack@google.com} 52512927Sgabeblack@google.com 52613263Sgabeblack@google.comsc_dt::uint64 sc_time_tuple::value() const { return _value; } 52712927Sgabeblack@google.com 52812927Sgabeblack@google.comconst char * 52912927Sgabeblack@google.comsc_time_tuple::unit_symbol() const 53012927Sgabeblack@google.com{ 53113263Sgabeblack@google.com return sc_gem5::TimeUnitNames[_unit]; 53212927Sgabeblack@google.com} 53312927Sgabeblack@google.com 53413263Sgabeblack@google.comdouble sc_time_tuple::to_double() const { return static_cast<double>(_value); } 53512927Sgabeblack@google.com 53612927Sgabeblack@google.comstd::string 53712927Sgabeblack@google.comsc_time_tuple::to_string() const 53812927Sgabeblack@google.com{ 53913263Sgabeblack@google.com std::ostringstream ss; 54013263Sgabeblack@google.com ss << _value << ' ' << unit_symbol(); 54113263Sgabeblack@google.com return ss.str(); 54212927Sgabeblack@google.com} 54312927Sgabeblack@google.com 54412837Sgabeblack@google.com} // namespace sc_core 545