sc_time.cc revision 13124
1/* 2 * Copyright 2018 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution; 11 * neither the name of the copyright holders nor the names of its 12 * contributors may be used to endorse or promote products derived from 13 * this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Authors: Gabe Black 28 */ 29 30#include <vector> 31 32#include "base/logging.hh" 33#include "base/types.hh" 34#include "python/pybind11/pybind.hh" 35#include "systemc/core/python.hh" 36#include "systemc/ext/core/sc_time.hh" 37 38namespace sc_core 39{ 40 41namespace 42{ 43 44const char *TimeUnitNames[] = { 45 [SC_FS] = "fs", 46 [SC_PS] = "ps", 47 [SC_NS] = "ns", 48 [SC_US] = "us", 49 [SC_MS] = "ms", 50 [SC_SEC] = "s" 51}; 52 53double TimeUnitScale[] = { 54 [SC_FS] = 1.0e-15, 55 [SC_PS] = 1.0e-12, 56 [SC_NS] = 1.0e-9, 57 [SC_US] = 1.0e-6, 58 [SC_MS] = 1.0e-3, 59 [SC_SEC] = 1.0 60}; 61 62bool timeFixed = false; 63bool pythonReady = false; 64 65struct SetInfo 66{ 67 SetInfo(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu) : 68 time(time), d(d), tu(tu) 69 {} 70 71 ::sc_core::sc_time *time; 72 double d; 73 ::sc_core::sc_time_unit tu; 74}; 75std::vector<SetInfo> toSet; 76 77void 78setWork(sc_time *time, double d, ::sc_core::sc_time_unit tu) 79{ 80 //XXX Assuming the time resolution is 1ps. 81 double scale = TimeUnitScale[tu] / TimeUnitScale[SC_PS]; 82 // Accellera claims there is a linux bug, and that these next two 83 // lines work around them. 84 volatile double tmp = d * scale + 0.5; 85 *time = sc_time::from_value(static_cast<uint64_t>(tmp)); 86} 87 88void 89fixTime() 90{ 91 auto ticks = pybind11::module::import("m5.ticks"); 92 auto fix_global_frequency = ticks.attr("fixGlobalFrequency"); 93 fix_global_frequency(); 94 95 for (auto &t: toSet) 96 setWork(t.time, t.d, t.tu); 97 toSet.clear(); 98} 99 100void 101set(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu) 102{ 103 // Only fix time once. 104 if (!timeFixed) { 105 timeFixed = true; 106 107 // If we've run, python is working and we haven't fixed time yet. 108 if (pythonReady) 109 fixTime(); 110 } 111 if (pythonReady) { 112 // Time should be working. Set up this sc_time. 113 setWork(time, d, tu); 114 } else { 115 // Time isn't set up yet. Defer setting up this sc_time. 116 toSet.emplace_back(time, d, tu); 117 } 118} 119 120class TimeSetter : public ::sc_gem5::PythonReadyFunc 121{ 122 public: 123 TimeSetter() : ::sc_gem5::PythonReadyFunc() {} 124 125 void 126 run() override 127 { 128 // Record that we've run and python/pybind should be usable. 129 pythonReady = true; 130 131 // If time is already fixed, let python know. 132 if (timeFixed) 133 fixTime(); 134 } 135} timeSetter; 136 137double defaultUnit = 1.0e-9; 138 139} // anonymous namespace 140 141sc_time::sc_time() : val(0) {} 142 143sc_time::sc_time(double d, sc_time_unit tu) 144{ 145 val = 0; 146 if (d != 0) 147 set(this, d, tu); 148} 149 150sc_time::sc_time(const sc_time &t) 151{ 152 val = t.val; 153} 154 155sc_time::sc_time(double d, bool scale) 156{ 157 //XXX Assuming the time resolution is 1ps. 158 if (scale) 159 set(this, d * defaultUnit, SC_SEC); 160 else 161 set(this, d, SC_PS); 162} 163 164sc_time::sc_time(sc_dt::uint64 v, bool scale) 165{ 166 //XXX Assuming the time resolution is 1ps. 167 if (scale) 168 set(this, static_cast<double>(v) * defaultUnit, SC_SEC); 169 else 170 set(this, static_cast<double>(v), SC_PS); 171} 172 173sc_time & 174sc_time::operator = (const sc_time &t) 175{ 176 val = t.val; 177 return *this; 178} 179 180sc_dt::uint64 181sc_time::value() const 182{ 183 return val; 184} 185 186double 187sc_time::to_double() const 188{ 189 return static_cast<double>(val); 190} 191double 192sc_time::to_seconds() const 193{ 194 double d = to_double(); 195 //XXX Assuming the time resolution is 1ps. 196 double scale = TimeUnitScale[SC_PS] / TimeUnitScale[SC_SEC]; 197 return d * scale; 198} 199 200const std::string 201sc_time::to_string() const 202{ 203 warn("%s not implemented.\n", __PRETTY_FUNCTION__); 204 return ""; 205} 206 207bool 208sc_time::operator == (const sc_time &t) const 209{ 210 return val == t.val; 211} 212 213bool 214sc_time::operator != (const sc_time &t) const 215{ 216 return val != t.val; 217} 218 219bool 220sc_time::operator < (const sc_time &t) const 221{ 222 return val < t.val; 223} 224 225bool 226sc_time::operator <= (const sc_time &t) const 227{ 228 return val <= t.val; 229} 230 231bool 232sc_time::operator > (const sc_time &t) const 233{ 234 return val > t.val; 235} 236 237bool 238sc_time::operator >= (const sc_time &t) const 239{ 240 return val >= t.val; 241} 242 243sc_time & 244sc_time::operator += (const sc_time &t) 245{ 246 val += t.val; 247 return *this; 248} 249 250sc_time & 251sc_time::operator -= (const sc_time &t) 252{ 253 val -= t.val; 254 return *this; 255} 256 257sc_time & 258sc_time::operator *= (double d) 259{ 260 val = static_cast<int64_t>(static_cast<double>(val) * d + 0.5); 261 return *this; 262} 263 264sc_time & 265sc_time::operator /= (double d) 266{ 267 val = static_cast<int64_t>(static_cast<double>(val) / d + 0.5); 268 return *this; 269} 270 271void 272sc_time::print(std::ostream &os) const 273{ 274 if (val == 0) { 275 os << "0 s"; 276 } else { 277 //XXX Assuming the time resolution is 1ps. 278 sc_time_unit tu = SC_PS; 279 uint64_t scaled = val; 280 while (tu < SC_SEC && (scaled % 1000) == 0) { 281 tu = (sc_time_unit)((int)tu + 1); 282 scaled /= 1000; 283 } 284 285 os << scaled << ' ' << TimeUnitNames[tu]; 286 } 287} 288 289sc_time 290sc_time::from_value(sc_dt::uint64 u) 291{ 292 sc_time t; 293 t.val = u; 294 return t; 295} 296 297sc_time 298sc_time::from_seconds(double d) 299{ 300 sc_time t; 301 set(&t, d, SC_SEC); 302 return t; 303} 304 305sc_time 306sc_time::from_string(const char *str) 307{ 308 warn("%s not implemented.\n", __PRETTY_FUNCTION__); 309 return sc_time(); 310} 311 312const sc_time 313operator + (const sc_time &a, const sc_time &b) 314{ 315 return sc_time::from_value(a.value() + b.value()); 316} 317 318const sc_time 319operator - (const sc_time &a, const sc_time &b) 320{ 321 return sc_time::from_value(a.value() - b.value()); 322} 323 324const sc_time 325operator * (const sc_time &t, double d) 326{ 327 volatile double tmp = static_cast<double>(t.value()) * d + 0.5; 328 return sc_time::from_value(static_cast<int64_t>(tmp)); 329} 330 331const sc_time 332operator * (double d, const sc_time &t) 333{ 334 volatile double tmp = d * static_cast<double>(t.value()) + 0.5; 335 return sc_time::from_value(static_cast<int64_t>(tmp)); 336} 337 338const sc_time 339operator / (const sc_time &t, double d) 340{ 341 volatile double tmp = static_cast<double>(t.value()) / d + 0.5; 342 return sc_time::from_value(static_cast<int64_t>(tmp)); 343} 344 345double 346operator / (const sc_time &t1, const sc_time &t2) 347{ 348 return t1.to_double() / t2.to_double(); 349} 350 351std::ostream & 352operator << (std::ostream &os, const sc_time &t) 353{ 354 t.print(os); 355 return os; 356} 357 358const sc_time SC_ZERO_TIME; 359 360void 361sc_set_time_resolution(double, sc_time_unit) 362{ 363 warn("%s not implemented.\n", __PRETTY_FUNCTION__); 364} 365 366sc_time 367sc_get_time_resolution() 368{ 369 warn("%s not implemented.\n", __PRETTY_FUNCTION__); 370 return sc_time(); 371} 372 373const sc_time & 374sc_max_time() 375{ 376 static const sc_time MaxScTime = sc_time::from_value(MaxTick); 377 return MaxScTime; 378} 379 380void 381sc_set_default_time_unit(double d, sc_time_unit tu) 382{ 383 defaultUnit = d * TimeUnitScale[tu]; 384} 385 386sc_time 387sc_get_default_time_unit() 388{ 389 return sc_time(defaultUnit, SC_SEC); 390} 391 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