sc_time.cc (13263:bcd6d8140486) sc_time.cc (13265:6cde60ee99fb)
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 <sstream>
31#include <vector>
32
33#include "base/logging.hh"
34#include "base/types.hh"
35#include "python/pybind11/pybind.hh"
36#include "sim/core.hh"
37#include "systemc/core/python.hh"
38#include "systemc/core/time.hh"
39#include "systemc/ext/core/sc_main.hh"
40#include "systemc/ext/core/sc_time.hh"
41#include "systemc/ext/utils/sc_report_handler.hh"
42
43namespace sc_core
44{
45
46namespace
47{
48
49bool timeFixed = false;
50bool pythonReady = false;
51
52struct SetInfo
53{
54 SetInfo(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu) :
55 time(time), d(d), tu(tu)
56 {}
57
58 ::sc_core::sc_time *time;
59 double d;
60 ::sc_core::sc_time_unit tu;
61};
62std::vector<SetInfo> toSet;
63
64void
65setWork(sc_time *time, double d, ::sc_core::sc_time_unit tu)
66{
67 double scale = sc_gem5::TimeUnitScale[tu] * SimClock::Float::s;
68 // Accellera claims there is a linux bug, and that these next two
69 // lines work around them.
70 volatile double tmp = d * scale + 0.5;
71 *time = sc_time::from_value(static_cast<uint64_t>(tmp));
72}
73
74void
75fixTime()
76{
77 auto ticks = pybind11::module::import("m5.ticks");
78 auto fix_global_frequency = ticks.attr("fixGlobalFrequency");
79 fix_global_frequency();
80
81 for (auto &t: toSet)
82 setWork(t.time, t.d, t.tu);
83 toSet.clear();
84}
85
86void
87attemptToFixTime()
88{
89 // Only fix time once.
90 if (!timeFixed) {
91 timeFixed = true;
92
93 // If we've run, python is working and we haven't fixed time yet.
94 if (pythonReady)
95 fixTime();
96 }
97}
98
99void
100setGlobalFrequency(Tick ticks_per_second)
101{
102 auto ticks = pybind11::module::import("m5.ticks");
103 auto set_global_frequency = ticks.attr("setGlobalFrequency");
104 set_global_frequency(ticks_per_second);
105 fixTime();
106}
107
108void
109set(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu)
110{
111 if (d != 0)
112 attemptToFixTime();
113 if (pythonReady) {
114 // Time should be working. Set up this sc_time.
115 setWork(time, d, tu);
116 } else {
117 // Time isn't set up yet. Defer setting up this sc_time.
118 toSet.emplace_back(time, d, tu);
119 }
120}
121
122class TimeSetter : public ::sc_gem5::PythonReadyFunc
123{
124 public:
125 TimeSetter() : ::sc_gem5::PythonReadyFunc() {}
126
127 void
128 run() override
129 {
130 // Record that we've run and python/pybind should be usable.
131 pythonReady = true;
132
133 // If time is already fixed, let python know.
134 if (timeFixed)
135 fixTime();
136 }
137} timeSetter;
138
139double defaultUnit = 1.0e-9;
140
141} // anonymous namespace
142
143sc_time::sc_time() : val(0) {}
144
145sc_time::sc_time(double d, sc_time_unit tu)
146{
147 val = 0;
148 set(this, d, tu);
149}
150
151sc_time::sc_time(const sc_time &t)
152{
153 val = t.val;
154}
155
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 <sstream>
31#include <vector>
32
33#include "base/logging.hh"
34#include "base/types.hh"
35#include "python/pybind11/pybind.hh"
36#include "sim/core.hh"
37#include "systemc/core/python.hh"
38#include "systemc/core/time.hh"
39#include "systemc/ext/core/sc_main.hh"
40#include "systemc/ext/core/sc_time.hh"
41#include "systemc/ext/utils/sc_report_handler.hh"
42
43namespace sc_core
44{
45
46namespace
47{
48
49bool timeFixed = false;
50bool pythonReady = false;
51
52struct SetInfo
53{
54 SetInfo(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu) :
55 time(time), d(d), tu(tu)
56 {}
57
58 ::sc_core::sc_time *time;
59 double d;
60 ::sc_core::sc_time_unit tu;
61};
62std::vector<SetInfo> toSet;
63
64void
65setWork(sc_time *time, double d, ::sc_core::sc_time_unit tu)
66{
67 double scale = sc_gem5::TimeUnitScale[tu] * SimClock::Float::s;
68 // Accellera claims there is a linux bug, and that these next two
69 // lines work around them.
70 volatile double tmp = d * scale + 0.5;
71 *time = sc_time::from_value(static_cast<uint64_t>(tmp));
72}
73
74void
75fixTime()
76{
77 auto ticks = pybind11::module::import("m5.ticks");
78 auto fix_global_frequency = ticks.attr("fixGlobalFrequency");
79 fix_global_frequency();
80
81 for (auto &t: toSet)
82 setWork(t.time, t.d, t.tu);
83 toSet.clear();
84}
85
86void
87attemptToFixTime()
88{
89 // Only fix time once.
90 if (!timeFixed) {
91 timeFixed = true;
92
93 // If we've run, python is working and we haven't fixed time yet.
94 if (pythonReady)
95 fixTime();
96 }
97}
98
99void
100setGlobalFrequency(Tick ticks_per_second)
101{
102 auto ticks = pybind11::module::import("m5.ticks");
103 auto set_global_frequency = ticks.attr("setGlobalFrequency");
104 set_global_frequency(ticks_per_second);
105 fixTime();
106}
107
108void
109set(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu)
110{
111 if (d != 0)
112 attemptToFixTime();
113 if (pythonReady) {
114 // Time should be working. Set up this sc_time.
115 setWork(time, d, tu);
116 } else {
117 // Time isn't set up yet. Defer setting up this sc_time.
118 toSet.emplace_back(time, d, tu);
119 }
120}
121
122class TimeSetter : public ::sc_gem5::PythonReadyFunc
123{
124 public:
125 TimeSetter() : ::sc_gem5::PythonReadyFunc() {}
126
127 void
128 run() override
129 {
130 // Record that we've run and python/pybind should be usable.
131 pythonReady = true;
132
133 // If time is already fixed, let python know.
134 if (timeFixed)
135 fixTime();
136 }
137} timeSetter;
138
139double defaultUnit = 1.0e-9;
140
141} // anonymous namespace
142
143sc_time::sc_time() : val(0) {}
144
145sc_time::sc_time(double d, sc_time_unit tu)
146{
147 val = 0;
148 set(this, d, tu);
149}
150
151sc_time::sc_time(const sc_time &t)
152{
153 val = t.val;
154}
155
156sc_time::sc_time(double d, const char *unit)
157{
158 sc_time_unit tu;
159 for (tu = SC_FS; tu <= SC_SEC; tu = (sc_time_unit)(tu + 1)) {
160 if (strcmp(unit, sc_gem5::TimeUnitNames[tu]) == 0 ||
161 strcmp(unit, sc_gem5::TimeUnitConstantNames[tu]) == 0) {
162 break;
163 }
164 }
165
166 if (tu > SC_SEC) {
167 SC_REPORT_ERROR("(E567) sc_time conversion failed",
168 "invalid unit given");
169 val = 0;
170 return;
171 }
172 set(this, d, tu);
173}
174
156sc_time::sc_time(double d, bool scale)
157{
158 double scaler = scale ? defaultUnit : SimClock::Float::Hz;
159 set(this, d * scaler, SC_SEC);
160}
161
162sc_time::sc_time(sc_dt::uint64 v, bool scale)
163{
164 double scaler = scale ? defaultUnit : SimClock::Float::Hz;
165 set(this, static_cast<double>(v) * scaler, SC_SEC);
166}
167
168sc_time &
169sc_time::operator = (const sc_time &t)
170{
171 val = t.val;
172 return *this;
173}
174
175sc_dt::uint64
176sc_time::value() const
177{
178 return val;
179}
180
181double
182sc_time::to_double() const
183{
184 return static_cast<double>(val);
185}
186double
187sc_time::to_seconds() const
188{
189 return to_double() * SimClock::Float::Hz;
190}
191
192const std::string
193sc_time::to_string() const
194{
195 std::ostringstream ss;
196 print(ss);
197 return ss.str();
198}
199
200bool
201sc_time::operator == (const sc_time &t) const
202{
203 return val == t.val;
204}
205
206bool
207sc_time::operator != (const sc_time &t) const
208{
209 return val != t.val;
210}
211
212bool
213sc_time::operator < (const sc_time &t) const
214{
215 return val < t.val;
216}
217
218bool
219sc_time::operator <= (const sc_time &t) const
220{
221 return val <= t.val;
222}
223
224bool
225sc_time::operator > (const sc_time &t) const
226{
227 return val > t.val;
228}
229
230bool
231sc_time::operator >= (const sc_time &t) const
232{
233 return val >= t.val;
234}
235
236sc_time &
237sc_time::operator += (const sc_time &t)
238{
239 val += t.val;
240 return *this;
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 *= (double d)
252{
253 val = static_cast<int64_t>(static_cast<double>(val) * d + 0.5);
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
264void
265sc_time::print(std::ostream &os) const
266{
267 os << sc_time_tuple(*this).to_string();
268}
269
270sc_time
271sc_time::from_value(sc_dt::uint64 u)
272{
273 if (u)
274 attemptToFixTime();
275 sc_time t;
276 t.val = u;
277 return t;
278}
279
280sc_time
281sc_time::from_seconds(double d)
282{
283 sc_time t;
284 set(&t, d, SC_SEC);
285 return t;
286}
287
288sc_time
289sc_time::from_string(const char *str)
290{
175sc_time::sc_time(double d, bool scale)
176{
177 double scaler = scale ? defaultUnit : SimClock::Float::Hz;
178 set(this, d * scaler, SC_SEC);
179}
180
181sc_time::sc_time(sc_dt::uint64 v, bool scale)
182{
183 double scaler = scale ? defaultUnit : SimClock::Float::Hz;
184 set(this, static_cast<double>(v) * scaler, SC_SEC);
185}
186
187sc_time &
188sc_time::operator = (const sc_time &t)
189{
190 val = t.val;
191 return *this;
192}
193
194sc_dt::uint64
195sc_time::value() const
196{
197 return val;
198}
199
200double
201sc_time::to_double() const
202{
203 return static_cast<double>(val);
204}
205double
206sc_time::to_seconds() const
207{
208 return to_double() * SimClock::Float::Hz;
209}
210
211const std::string
212sc_time::to_string() const
213{
214 std::ostringstream ss;
215 print(ss);
216 return ss.str();
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
243bool
244sc_time::operator > (const sc_time &t) const
245{
246 return val > t.val;
247}
248
249bool
250sc_time::operator >= (const sc_time &t) const
251{
252 return val >= t.val;
253}
254
255sc_time &
256sc_time::operator += (const sc_time &t)
257{
258 val += t.val;
259 return *this;
260}
261
262sc_time &
263sc_time::operator -= (const sc_time &t)
264{
265 val -= t.val;
266 return *this;
267}
268
269sc_time &
270sc_time::operator *= (double d)
271{
272 val = static_cast<int64_t>(static_cast<double>(val) * d + 0.5);
273 return *this;
274}
275
276sc_time &
277sc_time::operator /= (double d)
278{
279 val = static_cast<int64_t>(static_cast<double>(val) / d + 0.5);
280 return *this;
281}
282
283void
284sc_time::print(std::ostream &os) const
285{
286 os << sc_time_tuple(*this).to_string();
287}
288
289sc_time
290sc_time::from_value(sc_dt::uint64 u)
291{
292 if (u)
293 attemptToFixTime();
294 sc_time t;
295 t.val = u;
296 return t;
297}
298
299sc_time
300sc_time::from_seconds(double d)
301{
302 sc_time t;
303 set(&t, d, SC_SEC);
304 return t;
305}
306
307sc_time
308sc_time::from_string(const char *str)
309{
291 warn("%s not implemented.\n", __PRETTY_FUNCTION__);
292 return sc_time();
310 char *end = nullptr;
311
312 double d = str ? std::strtod(str, &end) : 0.0;
313 if (str == end || d < 0.0) {
314 SC_REPORT_ERROR("(E567) sc_time conversion failed",
315 "invalid value given");
316 return SC_ZERO_TIME;
317 }
318
319 while (*end && std::isspace(*end))
320 end++;
321
322 return sc_time(d, end);
293}
294
295const sc_time
296operator + (const sc_time &a, const sc_time &b)
297{
298 return sc_time::from_value(a.value() + b.value());
299}
300
301const sc_time
302operator - (const sc_time &a, const sc_time &b)
303{
304 return sc_time::from_value(a.value() - b.value());
305}
306
307const sc_time
308operator * (const sc_time &t, double d)
309{
310 volatile double tmp = static_cast<double>(t.value()) * d + 0.5;
311 return sc_time::from_value(static_cast<int64_t>(tmp));
312}
313
314const sc_time
315operator * (double d, const sc_time &t)
316{
317 volatile double tmp = d * static_cast<double>(t.value()) + 0.5;
318 return sc_time::from_value(static_cast<int64_t>(tmp));
319}
320
321const sc_time
322operator / (const sc_time &t, double d)
323{
324 volatile double tmp = static_cast<double>(t.value()) / d + 0.5;
325 return sc_time::from_value(static_cast<int64_t>(tmp));
326}
327
328double
329operator / (const sc_time &t1, const sc_time &t2)
330{
331 return t1.to_double() / t2.to_double();
332}
333
334std::ostream &
335operator << (std::ostream &os, const sc_time &t)
336{
337 t.print(os);
338 return os;
339}
340
341const sc_time SC_ZERO_TIME;
342
343void
344sc_set_time_resolution(double d, sc_time_unit tu)
345{
346 if (d <= 0.0) {
347 SC_REPORT_ERROR("(E514) set time resolution failed",
348 "value not positive");
349 }
350 double dummy;
351 if (modf(log10(d), &dummy) != 0.0) {
352 SC_REPORT_ERROR("(E514) set time resolution failed",
353 "value not a power of ten");
354 }
355 if (sc_is_running()) {
356 SC_REPORT_ERROR("(E514) set time resolution failed",
357 "simulation running");
358 }
359 static bool specified = false;
360 if (specified) {
361 SC_REPORT_ERROR("(E514) set time resolution failed",
362 "already specified");
363 }
364 // This won't detect the timescale being fixed outside of systemc, but
365 // it's at least some protection.
366 if (timeFixed) {
367 SC_REPORT_ERROR("(E514) set time resolution failed",
368 "sc_time object(s) constructed");
369 }
370
371 double seconds = d * sc_gem5::TimeUnitScale[tu];
372 if (seconds < sc_gem5::TimeUnitScale[SC_FS]) {
373 SC_REPORT_ERROR("(E514) set time resolution failed",
374 "value smaller than 1 fs");
375 }
376
377 if (seconds > defaultUnit) {
378 SC_REPORT_WARNING(
379 "(W516) default time unit changed to time resolution", "");
380 defaultUnit = seconds;
381 }
382
383 // Get rid of fractional parts of d.
384 while (d < 1.0 && tu > SC_FS) {
385 d *= 1000;
386 tu = (sc_time_unit)(tu - 1);
387 }
388
389 Tick ticks_per_second =
390 sc_gem5::TimeUnitFrequency[tu] / static_cast<Tick>(d);
391 setGlobalFrequency(ticks_per_second);
392 specified = true;
393}
394
395sc_time
396sc_get_time_resolution()
397{
398 return sc_time::from_value(1);
399}
400
401const sc_time &
402sc_max_time()
403{
404 static const sc_time MaxScTime = sc_time::from_value(MaxTick);
405 return MaxScTime;
406}
407
408void
409sc_set_default_time_unit(double d, sc_time_unit tu)
410{
411 if (d < 0.0) {
412 SC_REPORT_ERROR("(E515) set default time unit failed",
413 "value not positive");
414 }
415 double dummy;
416 if (modf(log10(d), &dummy) != 0.0) {
417 SC_REPORT_ERROR("(E515) set default time unit failed",
418 "value not a power of ten");
419 }
420 if (sc_is_running()) {
421 SC_REPORT_ERROR("(E515) set default time unit failed",
422 "simulation running");
423 }
424 static bool specified = false;
425 if (specified) {
426 SC_REPORT_ERROR("(E515) set default time unit failed",
427 "already specified");
428 }
429 // This won't detect the timescale being fixed outside of systemc, but
430 // it's at least some protection.
431 if (timeFixed) {
432 SC_REPORT_ERROR("(E515) set default time unit failed",
433 "sc_time object(s) constructed");
434 }
435
436 // Normalize d to seconds.
437 defaultUnit = d * sc_gem5::TimeUnitScale[tu];
438 specified = true;
439
440 double resolution = SimClock::Float::Hz;
441 if (resolution == 0.0)
442 resolution = sc_gem5::TimeUnitScale[SC_PS];
443 if (defaultUnit < resolution) {
444 SC_REPORT_ERROR("(E515) set default time unit failed",
445 "value smaller than time resolution");
446 }
447}
448
449sc_time
450sc_get_default_time_unit()
451{
452 return sc_time(defaultUnit, SC_SEC);
453}
454
455sc_time_tuple::sc_time_tuple(const sc_time &t) :
456 _value(), _unit(SC_SEC), _set(true)
457{
458 if (!t.value())
459 return;
460
461 Tick frequency = SimClock::Frequency;
462
463 // Shrink the frequency by scaling down the time period, ie converting
464 // it from cycles per second to cycles per millisecond, etc.
465 while (_unit > 1 && (frequency % 1000 == 0)) {
466 _unit = (sc_time_unit)((int)_unit - 1);
467 frequency /= 1000;
468 }
469
470 // Convert the frequency into a period.
471 Tick period;
472 if (frequency > 1) {
473 _unit = (sc_time_unit)((int)_unit - 1);
474 period = 1000 / frequency;
475 } else {
476 period = frequency;
477 }
478
479 // Scale our integer value by the period.
480 _value = t.value() * period;
481
482 // Shrink the scaled time value by increasing the size of the units
483 // it's measured by, avoiding fractional parts.
484 while (_unit < SC_SEC && (_value % 1000) == 0) {
485 _unit = (sc_time_unit)((int)_unit + 1);
486 _value /= 1000;
487 }
488}
489
490bool
491sc_time_tuple::has_value() const
492{
493 return _set;
494}
495
496sc_dt::uint64 sc_time_tuple::value() const { return _value; }
497
498const char *
499sc_time_tuple::unit_symbol() const
500{
501 return sc_gem5::TimeUnitNames[_unit];
502}
503
504double sc_time_tuple::to_double() const { return static_cast<double>(_value); }
505
506std::string
507sc_time_tuple::to_string() const
508{
509 std::ostringstream ss;
510 ss << _value << ' ' << unit_symbol();
511 return ss.str();
512}
513
514} // namespace sc_core
323}
324
325const sc_time
326operator + (const sc_time &a, const sc_time &b)
327{
328 return sc_time::from_value(a.value() + b.value());
329}
330
331const sc_time
332operator - (const sc_time &a, const sc_time &b)
333{
334 return sc_time::from_value(a.value() - b.value());
335}
336
337const sc_time
338operator * (const sc_time &t, double d)
339{
340 volatile double tmp = static_cast<double>(t.value()) * d + 0.5;
341 return sc_time::from_value(static_cast<int64_t>(tmp));
342}
343
344const sc_time
345operator * (double d, const sc_time &t)
346{
347 volatile double tmp = d * static_cast<double>(t.value()) + 0.5;
348 return sc_time::from_value(static_cast<int64_t>(tmp));
349}
350
351const sc_time
352operator / (const sc_time &t, double d)
353{
354 volatile double tmp = static_cast<double>(t.value()) / d + 0.5;
355 return sc_time::from_value(static_cast<int64_t>(tmp));
356}
357
358double
359operator / (const sc_time &t1, const sc_time &t2)
360{
361 return t1.to_double() / t2.to_double();
362}
363
364std::ostream &
365operator << (std::ostream &os, const sc_time &t)
366{
367 t.print(os);
368 return os;
369}
370
371const sc_time SC_ZERO_TIME;
372
373void
374sc_set_time_resolution(double d, sc_time_unit tu)
375{
376 if (d <= 0.0) {
377 SC_REPORT_ERROR("(E514) set time resolution failed",
378 "value not positive");
379 }
380 double dummy;
381 if (modf(log10(d), &dummy) != 0.0) {
382 SC_REPORT_ERROR("(E514) set time resolution failed",
383 "value not a power of ten");
384 }
385 if (sc_is_running()) {
386 SC_REPORT_ERROR("(E514) set time resolution failed",
387 "simulation running");
388 }
389 static bool specified = false;
390 if (specified) {
391 SC_REPORT_ERROR("(E514) set time resolution failed",
392 "already specified");
393 }
394 // This won't detect the timescale being fixed outside of systemc, but
395 // it's at least some protection.
396 if (timeFixed) {
397 SC_REPORT_ERROR("(E514) set time resolution failed",
398 "sc_time object(s) constructed");
399 }
400
401 double seconds = d * sc_gem5::TimeUnitScale[tu];
402 if (seconds < sc_gem5::TimeUnitScale[SC_FS]) {
403 SC_REPORT_ERROR("(E514) set time resolution failed",
404 "value smaller than 1 fs");
405 }
406
407 if (seconds > defaultUnit) {
408 SC_REPORT_WARNING(
409 "(W516) default time unit changed to time resolution", "");
410 defaultUnit = seconds;
411 }
412
413 // Get rid of fractional parts of d.
414 while (d < 1.0 && tu > SC_FS) {
415 d *= 1000;
416 tu = (sc_time_unit)(tu - 1);
417 }
418
419 Tick ticks_per_second =
420 sc_gem5::TimeUnitFrequency[tu] / static_cast<Tick>(d);
421 setGlobalFrequency(ticks_per_second);
422 specified = true;
423}
424
425sc_time
426sc_get_time_resolution()
427{
428 return sc_time::from_value(1);
429}
430
431const sc_time &
432sc_max_time()
433{
434 static const sc_time MaxScTime = sc_time::from_value(MaxTick);
435 return MaxScTime;
436}
437
438void
439sc_set_default_time_unit(double d, sc_time_unit tu)
440{
441 if (d < 0.0) {
442 SC_REPORT_ERROR("(E515) set default time unit failed",
443 "value not positive");
444 }
445 double dummy;
446 if (modf(log10(d), &dummy) != 0.0) {
447 SC_REPORT_ERROR("(E515) set default time unit failed",
448 "value not a power of ten");
449 }
450 if (sc_is_running()) {
451 SC_REPORT_ERROR("(E515) set default time unit failed",
452 "simulation running");
453 }
454 static bool specified = false;
455 if (specified) {
456 SC_REPORT_ERROR("(E515) set default time unit failed",
457 "already specified");
458 }
459 // This won't detect the timescale being fixed outside of systemc, but
460 // it's at least some protection.
461 if (timeFixed) {
462 SC_REPORT_ERROR("(E515) set default time unit failed",
463 "sc_time object(s) constructed");
464 }
465
466 // Normalize d to seconds.
467 defaultUnit = d * sc_gem5::TimeUnitScale[tu];
468 specified = true;
469
470 double resolution = SimClock::Float::Hz;
471 if (resolution == 0.0)
472 resolution = sc_gem5::TimeUnitScale[SC_PS];
473 if (defaultUnit < resolution) {
474 SC_REPORT_ERROR("(E515) set default time unit failed",
475 "value smaller than time resolution");
476 }
477}
478
479sc_time
480sc_get_default_time_unit()
481{
482 return sc_time(defaultUnit, SC_SEC);
483}
484
485sc_time_tuple::sc_time_tuple(const sc_time &t) :
486 _value(), _unit(SC_SEC), _set(true)
487{
488 if (!t.value())
489 return;
490
491 Tick frequency = SimClock::Frequency;
492
493 // Shrink the frequency by scaling down the time period, ie converting
494 // it from cycles per second to cycles per millisecond, etc.
495 while (_unit > 1 && (frequency % 1000 == 0)) {
496 _unit = (sc_time_unit)((int)_unit - 1);
497 frequency /= 1000;
498 }
499
500 // Convert the frequency into a period.
501 Tick period;
502 if (frequency > 1) {
503 _unit = (sc_time_unit)((int)_unit - 1);
504 period = 1000 / frequency;
505 } else {
506 period = frequency;
507 }
508
509 // Scale our integer value by the period.
510 _value = t.value() * period;
511
512 // Shrink the scaled time value by increasing the size of the units
513 // it's measured by, avoiding fractional parts.
514 while (_unit < SC_SEC && (_value % 1000) == 0) {
515 _unit = (sc_time_unit)((int)_unit + 1);
516 _value /= 1000;
517 }
518}
519
520bool
521sc_time_tuple::has_value() const
522{
523 return _set;
524}
525
526sc_dt::uint64 sc_time_tuple::value() const { return _value; }
527
528const char *
529sc_time_tuple::unit_symbol() const
530{
531 return sc_gem5::TimeUnitNames[_unit];
532}
533
534double sc_time_tuple::to_double() const { return static_cast<double>(_value); }
535
536std::string
537sc_time_tuple::to_string() const
538{
539 std::ostringstream ss;
540 ss << _value << ' ' << unit_symbol();
541 return ss.str();
542}
543
544} // namespace sc_core