1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 sc_time.cpp -- 23 24 Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 25 26 CHANGE LOG AT THE END OF THE FILE 27 *****************************************************************************/ 28 29 30#include <math.h> 31#include <stdio.h> 32 33#include "sysc/kernel/sc_kernel_ids.h" 34#include "sysc/kernel/sc_simcontext.h" 35#include "sysc/kernel/sc_time.h" 36#include "sysc/utils/sc_utils_ids.h" 37 38#if !defined(PRIu64) 39# if defined(_MSC_VER) || defined(__MINGW32__) 40# define PRIu64 "I64u" 41# else 42# define PRIu64 "llu" 43# endif 44#endif // PRIu64 45 46#ifdef SC_ENABLE_EARLY_MAXTIME_CREATION 47# define SC_MAXTIME_ALLOWED_ 1 48#else 49# define SC_MAXTIME_ALLOWED_ 0 50#endif 51 52namespace sc_core { 53 54static 55double time_values[] = { 56 1, // fs 57 1e3, // ps 58 1e6, // ns 59 1e9, // us 60 1e12, // ms 61 1e15 // s 62}; 63 64static 65const char* time_units[] = { 66 "fs", 67 "ps", 68 "ns", 69 "us", 70 "ms", 71 "s" 72}; 73 74 75// ---------------------------------------------------------------------------- 76// CLASS : sc_time 77// 78// The time class. 79// ---------------------------------------------------------------------------- 80 81// constructors 82 83sc_time::sc_time( double v, sc_time_unit tu ) 84: m_value( 0 ) 85{ 86 if( v != 0 ) { 87 sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; 88 double scale_fac = time_values[tu] / time_params->time_resolution; 89 // linux bug workaround; don't change next two lines 90 volatile double tmp = v * scale_fac + 0.5; 91 m_value = SCAST<sc_dt::int64>( tmp ); 92 time_params->time_resolution_fixed = true; 93 } 94} 95 96sc_time::sc_time( double v, sc_time_unit tu, sc_simcontext* simc ) 97: m_value( 0 ) 98{ 99 if( v != 0 ) { 100 sc_time_params* time_params = simc->m_time_params; 101 double scale_fac = time_values[tu] / time_params->time_resolution; 102 // linux bug workaround; don't change next two lines 103 volatile double tmp = v * scale_fac + 0.5; 104 m_value = SCAST<sc_dt::int64>( tmp ); 105 time_params->time_resolution_fixed = true; 106 } 107} 108 109sc_time::sc_time( double v, bool scale ) 110: m_value( 0 ) 111{ 112 static bool warn_constructor=true; 113 if ( warn_constructor ) { 114 warn_constructor=false; 115 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 116 "deprecated constructor: sc_time(double,bool)"); 117 } 118 119 if( v != 0 ) { 120 sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; 121 if( scale ) { 122 double scale_fac = sc_dt::uint64_to_double( 123 time_params->default_time_unit ); 124 // linux bug workaround; don't change next two lines 125 volatile double tmp = v * scale_fac + 0.5; 126 m_value = SCAST<sc_dt::int64>( tmp ); 127 } else { 128 // linux bug workaround; don't change next two lines 129 volatile double tmp = v + 0.5; 130 m_value = SCAST<sc_dt::int64>( tmp ); 131 } 132 time_params->time_resolution_fixed = true; 133 } 134} 135 136sc_time::sc_time( value_type v, bool scale ) 137: m_value( 0 ) 138{ 139 static bool warn_constructor=true; 140 if ( warn_constructor ) { 141 warn_constructor=false; 142 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 143 "deprecated constructor: sc_time(uint64,bool)"); 144 } 145 146 if( v != 0 ) { 147 sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; 148 if( scale ) { 149 double scale_fac = sc_dt::uint64_to_double( 150 time_params->default_time_unit ); 151 // linux bug workaround; don't change next two lines 152 volatile double tmp = sc_dt::uint64_to_double( v ) * 153 scale_fac + 0.5; 154 m_value = SCAST<sc_dt::int64>( tmp ); 155 } else { 156 m_value = v; 157 } 158 time_params->time_resolution_fixed = true; 159 } 160} 161 162sc_time 163sc_time::from_value( value_type v ) 164{ 165 sc_time t; 166 if( v != 0 && !(SC_MAXTIME_ALLOWED_ && v == ~sc_dt::UINT64_ZERO) ) { 167 sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; 168 time_params->time_resolution_fixed = true; 169 } 170 t.m_value = v; 171 return t; 172} 173 174 175// conversion functions 176 177double 178sc_time::to_default_time_units() const 179{ 180 sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; 181# if SC_MAXTIME_ALLOWED_ 182 if( m_value == 0 ) 183 return 0.0; 184 time_params->time_resolution_fixed = true; 185# endif // SC_MAXTIME_ALLOWED_ 186 return ( sc_dt::uint64_to_double( m_value ) / 187 sc_dt::uint64_to_double( time_params->default_time_unit ) ); 188} 189 190double 191sc_time::to_seconds() const 192{ 193 sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; 194# if SC_MAXTIME_ALLOWED_ 195 if( m_value == 0 ) 196 return 0.0; 197 time_params->time_resolution_fixed = true; 198# endif // SC_MAXTIME_ALLOWED_ 199 return ( sc_dt::uint64_to_double( m_value ) * 200 time_params->time_resolution * 1e-15 ); 201} 202 203const std::string 204sc_time::to_string() const 205{ 206 value_type val = m_value; 207 if( val == 0 ) { 208 return std::string( "0 s" ); 209 } 210 sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; 211# if SC_MAXTIME_ALLOWED_ 212 time_params->time_resolution_fixed = true; 213# endif // SC_MAXTIME_ALLOWED_ 214 value_type tr = SCAST<sc_dt::int64>( time_params->time_resolution ); 215 int n = 0; 216 while( ( tr % 10 ) == 0 ) { 217 tr /= 10; 218 n ++; 219 } 220 assert( tr == 1 ); 221 while( ( val % 10 ) == 0 ) { 222 val /= 10; 223 n ++; 224 } 225 char buf[BUFSIZ]; 226 std::sprintf( buf, "%" PRIu64, val ); 227 std::string result( buf ); 228 if( n >= 15 ) { 229 for( int i = n - 15; i > 0; -- i ) { 230 result += "0"; 231 } 232 result += " s"; 233 } else { 234 for( int i = n % 3; i > 0; -- i ) { 235 result += "0"; 236 } 237 result += " "; 238 result += time_units[n / 3]; 239 } 240 return result; 241} 242 243 244// print function 245 246void 247sc_time::print( ::std::ostream& os ) const 248{ 249 os << to_string(); 250} 251 252 253// ---------------------------------------------------------------------------- 254// STRUCT : sc_time_params 255// 256// Struct that holds the time resolution and default time unit. 257// ---------------------------------------------------------------------------- 258 259sc_time_params::sc_time_params() 260: time_resolution( 1000 ), // default 1 ps 261 time_resolution_specified( false ), 262 time_resolution_fixed( false ), 263 default_time_unit( 1000 ), // default 1 ns 264 default_time_unit_specified( false ) 265{} 266 267sc_time_params::~sc_time_params() 268{} 269 270 271// ---------------------------------------------------------------------------- 272 273// functions for accessing the time resolution and default time unit 274 275void 276sc_set_time_resolution( double v, sc_time_unit tu ) 277{ 278 // first perform the necessary checks 279 280 // must be positive 281 if( v < 0.0 ) { 282 SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "value not positive" ); 283 } 284 285 // must be a power of ten 286 double dummy; 287#if defined( __HP_aCC ) || defined(__ppc__) 288 // aCC seems to have a bug in modf() 289 if( modf( log10( v < 1.0 ? 1.0/v : v ), &dummy ) != 0.0 ) { 290#else 291 if( modf( log10( v ), &dummy ) != 0.0 ) { 292#endif 293 SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, 294 "value not a power of ten" ); 295 } 296 297 sc_simcontext* simc = sc_get_curr_simcontext(); 298 299 // can only be specified during elaboration 300 if( sc_is_running() ) { 301 SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "simulation running" ); 302 } 303 304 sc_time_params* time_params = simc->m_time_params; 305 306 // can be specified only once 307 if( time_params->time_resolution_specified ) { 308 SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "already specified" ); 309 } 310 311 // can only be specified before any sc_time is constructed 312 if( time_params->time_resolution_fixed ) { 313 SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, 314 "sc_time object(s) constructed" ); 315 } 316 317 // must be larger than or equal to 1 fs 318 volatile double resolution = v * time_values[tu]; 319 if( resolution < 1.0 ) { 320 SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, 321 "value smaller than 1 fs" ); 322 } 323 324 // recalculate the default time unit 325 volatile double time_unit = sc_dt::uint64_to_double( 326 time_params->default_time_unit ) * 327 ( time_params->time_resolution / resolution ); 328 if( time_unit < 1.0 ) { 329 SC_REPORT_WARNING( SC_ID_DEFAULT_TIME_UNIT_CHANGED_, 0 ); 330 time_params->default_time_unit = 1; 331 } else { 332 time_params->default_time_unit = SCAST<sc_dt::int64>( time_unit ); 333 } 334 335 time_params->time_resolution = resolution; 336 time_params->time_resolution_specified = true; 337} 338 339sc_time 340sc_get_time_resolution() 341{ 342 return sc_time::from_value( sc_dt::UINT64_ONE ); 343} 344 345 346void 347sc_set_default_time_unit( double v, sc_time_unit tu ) 348{ 349 static bool warn_default_time_unit=true; 350 if ( warn_default_time_unit ) 351 { 352 warn_default_time_unit=false; 353 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 354 "deprecated function: sc_set_default_time_unit"); 355 } 356 357 // first perform the necessary checks 358 359 // must be positive 360 if( v < 0.0 ) { 361 SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "value not positive" ); 362 } 363 364 // must be a power of ten 365 double dummy; 366 if( modf( log10( v ), &dummy ) != 0.0 ) { 367 SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, 368 "value not a power of ten" ); 369 } 370 371 sc_simcontext* simc = sc_get_curr_simcontext(); 372 373 // can only be specified during elaboration 374 if( sc_is_running() ) { 375 SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "simulation running" ); 376 } 377 378 sc_time_params* time_params = simc->m_time_params; 379 380 // can only be specified before any sc_time is constructed 381 if( time_params->time_resolution_fixed ) { 382 SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, 383 "sc_time object(s) constructed" ); 384 } 385 386 // can be specified only once 387 if( time_params->default_time_unit_specified ) { 388 SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "already specified" ); 389 } 390 391 // must be larger than or equal to the time resolution 392 volatile double time_unit = ( v * time_values[tu] ) / 393 time_params->time_resolution; 394 if( time_unit < 1.0 ) { 395 SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, 396 "value smaller than time resolution" ); 397 } 398 399 time_params->default_time_unit = SCAST<sc_dt::int64>( time_unit ); 400 time_params->default_time_unit_specified = true; 401} 402 403sc_time 404sc_get_default_time_unit() 405{ 406 static bool warn_get_default_time_unit = true; 407 if ( warn_get_default_time_unit ) 408 { 409 warn_get_default_time_unit=false; 410 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 411 "deprecated function: sc_get_default_time_unit"); 412 } 413 return sc_time::from_value( 414 sc_get_curr_simcontext()->m_time_params->default_time_unit 415 ); 416} 417 418 419// ---------------------------------------------------------------------------- 420 421const sc_time SC_ZERO_TIME; 422 423#undef SC_MAXTIME_ALLOWED_ 424 425} // namespace sc_core 426 427// $Log: sc_time.cpp,v $ 428// Revision 1.7 2011/08/26 20:46:11 acg 429// Andy Goodrich: moved the modification log to the end of the file to 430// eliminate source line number skew when check-ins are done. 431// 432// Revision 1.6 2011/07/24 16:08:36 acg 433// Philipp A. Hartmann: fix C99 format specifiers for Solaris. 434// 435// Revision 1.5 2011/02/18 20:27:14 acg 436// Andy Goodrich: Updated Copyrights. 437// 438// Revision 1.4 2011/02/13 21:47:38 acg 439// Andy Goodrich: update copyright notice. 440// 441// Revision 1.3 2011/01/19 23:21:50 acg 442// Andy Goodrich: changes for IEEE 1666 2011 443// 444// Revision 1.2 2008/05/22 17:06:27 acg 445// Andy Goodrich: updated copyright notice to include 2008. 446// 447// Revision 1.1.1.1 2006/12/15 20:20:05 acg 448// SystemC 2.3 449// 450// Revision 1.6 2006/01/26 21:04:55 acg 451// Andy Goodrich: deprecation message changes and additional messages. 452// 453// Revision 1.5 2006/01/25 00:31:19 acg 454// Andy Goodrich: Changed over to use a standard message id of 455// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. 456// 457// Revision 1.4 2006/01/24 20:49:05 acg 458// Andy Goodrich: changes to remove the use of deprecated features within the 459// simulator, and to issue warning messages when deprecated features are used. 460// 461// Revision 1.3 2006/01/13 18:44:30 acg 462// Added $Log to record CVS changes into the source. 463// 464 465// Taf! 466