sc_time.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2006 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_time.cpp --
00021 
00022   Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
00023 
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027 
00028   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00029   changes you are making here.
00030 
00031       Name, Affiliation, Date:
00032   Description of Modification:
00033 
00034  *****************************************************************************/
00035 
00036 
00037 // $Log: sc_time.cpp,v $
00038 // Revision 1.1.1.1  2006/12/15 20:31:37  acg
00039 // SystemC 2.2
00040 //
00041 // Revision 1.6  2006/01/26 21:04:55  acg
00042 //  Andy Goodrich: deprecation message changes and additional messages.
00043 //
00044 // Revision 1.5  2006/01/25 00:31:19  acg
00045 //  Andy Goodrich: Changed over to use a standard message id of
00046 //  SC_ID_IEEE_1666_DEPRECATION for all deprecation messages.
00047 //
00048 // Revision 1.4  2006/01/24 20:49:05  acg
00049 // Andy Goodrich: changes to remove the use of deprecated features within the
00050 // simulator, and to issue warning messages when deprecated features are used.
00051 //
00052 // Revision 1.3  2006/01/13 18:44:30  acg
00053 // Added $Log to record CVS changes into the source.
00054 //
00055 
00056 #include <math.h>
00057 #include <stdio.h>
00058 
00059 #include "sysc/kernel/sc_kernel_ids.h"
00060 #include "sysc/kernel/sc_simcontext.h"
00061 #include "sysc/kernel/sc_time.h"
00062 #include "sysc/utils/sc_utils_ids.h"
00063 
00064 namespace sc_core {
00065 
00066 static
00067 double time_values[] = {
00068     1,       // fs
00069     1e3,     // ps
00070     1e6,     // ns
00071     1e9,     // us
00072     1e12,    // ms
00073     1e15     // s
00074 };
00075 
00076 static
00077 const char* time_units[] = {
00078     "fs",
00079     "ps",
00080     "ns",
00081     "us",
00082     "ms",
00083     "s"
00084 };
00085 
00086 
00087 // ----------------------------------------------------------------------------
00088 //  CLASS : sc_time
00089 //
00090 //  The time class.
00091 // ----------------------------------------------------------------------------
00092 
00093 // constructors
00094 
00095 sc_time::sc_time( double v, sc_time_unit tu )
00096 : m_value( 0 )
00097 {
00098     if( v != 0 ) {
00099     sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
00100     double scale_fac = time_values[tu] / time_params->time_resolution;
00101     // linux bug workaround; don't change next two lines
00102     volatile double tmp = v * scale_fac + 0.5;
00103     m_value = SCAST<sc_dt::int64>( tmp );
00104     time_params->time_resolution_fixed = true;
00105     }
00106 }
00107 
00108 sc_time::sc_time( double v, sc_time_unit tu, sc_simcontext* simc )
00109 : m_value( 0 )
00110 {
00111     if( v != 0 ) {
00112     sc_time_params* time_params = simc->m_time_params;
00113     double scale_fac = time_values[tu] / time_params->time_resolution;
00114     // linux bug workaround; don't change next two lines
00115     volatile double tmp = v * scale_fac + 0.5;
00116     m_value = SCAST<sc_dt::int64>( tmp );
00117     time_params->time_resolution_fixed = true;
00118     }
00119 }
00120 
00121 sc_time::sc_time( double v, bool scale )
00122 : m_value( 0 )
00123 {
00124     if( v != 0 ) {
00125     sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
00126     if( scale ) {
00127         double scale_fac = sc_dt::uint64_to_double(
00128         time_params->default_time_unit );
00129         // linux bug workaround; don't change next two lines
00130         volatile double tmp = v * scale_fac + 0.5;
00131         m_value = SCAST<sc_dt::int64>( tmp );
00132     } else {
00133         // linux bug workaround; don't change next two lines
00134         volatile double tmp = v + 0.5;
00135         m_value = SCAST<sc_dt::int64>( tmp );
00136     }
00137     time_params->time_resolution_fixed = true;
00138     }
00139 }
00140 
00141 sc_time::sc_time( sc_dt::uint64 v, bool scale )
00142 : m_value( 0 )
00143 {
00144     if( v != 0 ) {
00145     sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
00146     if( scale ) {
00147         double scale_fac = sc_dt::uint64_to_double(
00148         time_params->default_time_unit );
00149         // linux bug workaround; don't change next two lines
00150         volatile double tmp = sc_dt::uint64_to_double( v ) *
00151                           scale_fac + 0.5;
00152         m_value = SCAST<sc_dt::int64>( tmp );
00153     } else {
00154         m_value = v;
00155     }
00156     time_params->time_resolution_fixed = true;
00157     }
00158 }
00159 
00160 
00161 // conversion functions
00162 
00163 double
00164 sc_time::to_default_time_units() const
00165 {
00166     sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
00167     return ( sc_dt::uint64_to_double( m_value ) /
00168          sc_dt::uint64_to_double( time_params->default_time_unit ) );
00169 }
00170 
00171 double
00172 sc_time::to_seconds() const
00173 {
00174     sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
00175     return ( sc_dt::uint64_to_double( m_value ) *
00176          time_params->time_resolution * 1e-15 );
00177 }
00178 
00179 const std::string
00180 sc_time::to_string() const
00181 {
00182     sc_dt::uint64 val = m_value;
00183     if( val == 0 ) {
00184     return std::string( "0 s" );
00185     }
00186     sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
00187     sc_dt::uint64 tr = SCAST<sc_dt::int64>( time_params->time_resolution );
00188     int n = 0;
00189     while( ( tr % 10 ) == 0 ) {
00190     tr /= 10;
00191     n ++;
00192     }
00193     assert( tr == 1 );
00194     while( ( val % 10 ) == 0 ) {
00195     val /= 10;
00196     n ++;
00197     }
00198     char buf[BUFSIZ];
00199 #if !defined( _MSC_VER )
00200     std::sprintf( buf, "%llu", val );
00201 #else
00202     std::sprintf( buf, "%I64u", val );
00203 #endif
00204     std::string result( buf );
00205     if( n >= 15 ) {
00206     for( int i = n - 15; i > 0; -- i ) {
00207         result += "0";
00208     }
00209     result += " s";
00210     } else {
00211     for( int i = n % 3; i > 0; -- i ) {
00212         result += "0";
00213     }
00214     result += " ";
00215     result += time_units[n / 3];
00216     }
00217     return result;
00218 }
00219 
00220 
00221 // print function
00222 
00223 void
00224 sc_time::print( ::std::ostream& os ) const
00225 {
00226     os << to_string();
00227 }
00228 
00229 
00230 // ----------------------------------------------------------------------------
00231 //  STRUCT : sc_time_params
00232 //
00233 //  Struct that holds the time resolution and default time unit.
00234 // ----------------------------------------------------------------------------
00235 
00236 sc_time_params::sc_time_params()
00237 : time_resolution( 1000 ),      // default 1 ps
00238   time_resolution_specified( false ),
00239   time_resolution_fixed( false ),
00240   default_time_unit( 1000 ),        // default 1 ns
00241   default_time_unit_specified( false )
00242 {}
00243 
00244 sc_time_params::~sc_time_params()
00245 {}
00246 
00247 
00248 // ----------------------------------------------------------------------------
00249 
00250 // functions for accessing the time resolution and default time unit
00251 
00252 void
00253 sc_set_time_resolution( double v, sc_time_unit tu )
00254 {
00255     // first perform the necessary checks
00256 
00257     // must be positive
00258     if( v < 0.0 ) {
00259     SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "value not positive" );
00260     }
00261 
00262     // must be a power of ten
00263     double dummy;
00264 #if defined( __HP_aCC ) || defined(__ppc__)
00265     // aCC seems to have a bug in modf()
00266     if( modf( log10( v < 1.0 ? 1.0/v : v ), &dummy ) != 0.0 ) {
00267 #else
00268     if( modf( log10( v ), &dummy ) != 0.0 ) {
00269 #endif
00270     SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_,
00271              "value not a power of ten" );
00272     }
00273 
00274     sc_simcontext* simc = sc_get_curr_simcontext();
00275 
00276     // can only be specified during elaboration
00277     if( sc_is_running() ) {
00278     SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "simulation running" );
00279     }
00280 
00281     sc_time_params* time_params = simc->m_time_params;
00282 
00283     // can be specified only once
00284     if( time_params->time_resolution_specified ) {
00285     SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "already specified" );
00286     }
00287 
00288     // can only be specified before any sc_time is constructed
00289     if( time_params->time_resolution_fixed ) {
00290     SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_,
00291              "sc_time object(s) constructed" );
00292     }
00293 
00294     // must be larger than or equal to 1 fs
00295     volatile double resolution = v * time_values[tu];
00296     if( resolution < 1.0 ) {
00297     SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_,
00298              "value smaller than 1 fs" );
00299     }
00300 
00301     // recalculate the default time unit
00302     volatile double time_unit = sc_dt::uint64_to_double(
00303     time_params->default_time_unit ) *
00304     ( time_params->time_resolution / resolution );
00305     if( time_unit < 1.0 ) {
00306     SC_REPORT_WARNING( SC_ID_DEFAULT_TIME_UNIT_CHANGED_, 0 );
00307     time_params->default_time_unit = 1;
00308     } else {
00309     time_params->default_time_unit = SCAST<sc_dt::int64>( time_unit );
00310     }
00311 
00312     time_params->time_resolution = resolution;
00313     time_params->time_resolution_specified = true;
00314 }
00315 
00316 sc_time 
00317 sc_get_time_resolution()
00318 {
00319     return sc_time( sc_dt::UINT64_ONE, false );
00320 }
00321 
00322 
00323 void
00324 sc_set_default_time_unit( double v, sc_time_unit tu )
00325 {
00326     static bool warn_default_time_unit=true;
00327     if ( warn_default_time_unit )
00328     {
00329         warn_default_time_unit=false;
00330         SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
00331         "deprecated function: sc_set_default_time_unit");
00332     }
00333     
00334     // first perform the necessary checks
00335 
00336     // must be positive
00337     if( v < 0.0 ) {
00338     SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "value not positive" );
00339     }
00340 
00341     // must be a power of ten
00342     double dummy;
00343     if( modf( log10( v ), &dummy ) != 0.0 ) {
00344     SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_,
00345              "value not a power of ten" );
00346     }
00347 
00348     sc_simcontext* simc = sc_get_curr_simcontext();
00349 
00350     // can only be specified during elaboration
00351     if( sc_is_running() ) {
00352     SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "simulation running" );
00353     }
00354 
00355     sc_time_params* time_params = simc->m_time_params;
00356 
00357     // can only be specified before any sc_time is constructed
00358     if( time_params->time_resolution_fixed ) {
00359         SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_,
00360                          "sc_time object(s) constructed" );
00361     }
00362 
00363     // can be specified only once
00364     if( time_params->default_time_unit_specified ) {
00365     SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "already specified" );
00366     }
00367 
00368     // must be larger than or equal to the time resolution
00369     volatile double time_unit = ( v * time_values[tu] ) /
00370                             time_params->time_resolution;
00371     if( time_unit < 1.0 ) {
00372     SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_,
00373              "value smaller than time resolution" );
00374     }
00375 
00376     time_params->default_time_unit = SCAST<sc_dt::int64>( time_unit );
00377     time_params->default_time_unit_specified = true;
00378 }
00379 
00380 sc_time
00381 sc_get_default_time_unit()
00382 {
00383     bool warn_get_default_time_unit = true;
00384     if ( warn_get_default_time_unit )
00385     {
00386         warn_get_default_time_unit=false;
00387         SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
00388             "deprecated function: sc_get_default_time_unit");
00389     }
00390     return sc_time( sc_get_curr_simcontext()->m_time_params->default_time_unit,
00391             false );
00392 }
00393 
00394 
00395 // ----------------------------------------------------------------------------
00396 
00397 const sc_time SC_ZERO_TIME;
00398 
00399 
00400 } // namespace sc_core
00401 // Taf!

Generated on Wed Jan 21 15:32:09 2009 for SystemC by  doxygen 1.5.5