Skip to content

Commit

Permalink
Merge pull request #697 from pah/apple-atomic-time
Browse files Browse the repository at this point in the history
sc_time: atomic time_resolution_fixed
  • Loading branch information
lmailletcontoz authored Nov 25, 2024
2 parents 7009ff8 + dfbd5fb commit f5d939a
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 41 deletions.
72 changes: 37 additions & 35 deletions src/sysc/kernel/sc_time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ const char* time_units[] = {
"ys"
};


static void inline time_params_freeze( sc_time_params* tp )
{
tp->time_resolution_fixed.store( true, std::memory_order_relaxed );
}

[[nodiscard]] static bool inline time_params_frozen( sc_time_params* tp )
{
return tp->time_resolution_fixed.load();
}

// ----------------------------------------------------------------------------
// CLASS : sc_time_tuple
//
Expand All @@ -78,17 +89,12 @@ const char* time_units[] = {
void
sc_time_tuple::init( value_type val )
{
sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
time_params->time_resolution_fixed = true;

auto tr_log10 = std::log10( time_params->time_resolution );
auto scale = static_cast<unsigned>( tr_log10 );

[[maybe_unused]] double ignored = 0.0;
sc_assert( std::modf( tr_log10, &ignored ) == 0.0 );
auto * time_params = sc_get_curr_simcontext()->m_time_params;
time_params_freeze( time_params );

constexpr unsigned tu_max = sizeof(time_units) / sizeof(time_units[0])-1;
unsigned tu = tu_max - (scale / 3);
auto scale = time_params->time_resolution_log10;
auto tu = tu_max - (scale / 3);
while( tu > 0 && ( val % 10 ) == 0 ) {
val /= 10;
scale++;
Expand Down Expand Up @@ -149,13 +155,12 @@ from_value_and_unit( double v, sc_time_unit tu, sc_time_params* tp )
{
sc_time::value_type t = 0;
if( v != 0 ) {
time_params_freeze( tp );
double scale_fac = time_values[5-tu] / tp->time_resolution; // sc_time_unit constants have offset of 5
// linux bug workaround; don't change next two lines
volatile double tmp = v * scale_fac + 0.5;
t = static_cast<sc_dt::int64>( tmp );
tp->time_resolution_fixed = true;
}

return t;
}

Expand Down Expand Up @@ -225,7 +230,8 @@ sc_time::sc_time( double v, bool scale )
}

if( v != 0 ) {
sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
auto * time_params = sc_get_curr_simcontext()->m_time_params;
time_params_freeze( time_params );
if( scale ) {
double scale_fac = sc_dt::uint64_to_double( time_params->default_time_unit );
// linux bug workaround; don't change next two lines
Expand All @@ -236,7 +242,6 @@ sc_time::sc_time( double v, bool scale )
volatile double tmp = v + 0.5;
m_value = static_cast<sc_dt::int64>( tmp );
}
time_params->time_resolution_fixed = true;
}
}

Expand All @@ -251,7 +256,8 @@ sc_time::sc_time( value_type v, bool scale )
}

if( v != 0 ) {
sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
auto * time_params = sc_get_curr_simcontext()->m_time_params;
time_params_freeze( time_params );
if( scale ) {
double scale_fac = sc_dt::uint64_to_double(
time_params->default_time_unit );
Expand All @@ -261,7 +267,6 @@ sc_time::sc_time( value_type v, bool scale )
} else {
m_value = v;
}
time_params->time_resolution_fixed = true;
}
}

Expand All @@ -280,8 +285,8 @@ sc_time::from_value( value_type v )
{
sc_time t;
if( v != 0 && v != ~sc_dt::UINT64_ZERO ) {
sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
time_params->time_resolution_fixed = true;
auto * time_params = sc_get_curr_simcontext()->m_time_params;
time_params_freeze( time_params );
}
t.m_value = v;
return t;
Expand All @@ -293,21 +298,25 @@ sc_time::from_value( value_type v )
double
sc_time::to_default_time_units() const
{
sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
if( m_value == 0 )
return 0.0;
time_params->time_resolution_fixed = true;

auto * time_params = sc_get_curr_simcontext()->m_time_params;
time_params_freeze( time_params );

return ( sc_dt::uint64_to_double( m_value ) /
sc_dt::uint64_to_double( time_params->default_time_unit ) );
}

double
sc_time::to_seconds() const
{
sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
if( m_value == 0 )
return 0.0;
time_params->time_resolution_fixed = true;

auto * time_params = sc_get_curr_simcontext()->m_time_params;
time_params_freeze( time_params );

return ( sc_dt::uint64_to_double( m_value ) *
( time_params->time_resolution / time_values[0] ) );
}
Expand All @@ -330,16 +339,13 @@ sc_time::print( ::std::ostream& os ) const

sc_time_params::sc_time_params()
: time_resolution( time_values[4] ), // default 1 ps
time_resolution_log10( static_cast<unsigned>(log10(time_resolution)) ),
time_resolution_specified( false ),
time_resolution_fixed( false ),
default_time_unit( 1000 ), // default 1 ns
default_time_unit_specified( false )
{}

sc_time_params::~sc_time_params()
{}


// ----------------------------------------------------------------------------

// functions for accessing the time resolution and default time unit
Expand All @@ -359,22 +365,20 @@ sc_set_time_resolution( double v, sc_time_unit tu )
SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "value not a power of ten" );
}

sc_simcontext* simc = sc_get_curr_simcontext();

// can only be specified during elaboration
if( sc_is_running() ) {
SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "simulation running" );
}

sc_time_params* time_params = simc->m_time_params;
auto * time_params = sc_get_curr_simcontext()->m_time_params;

// can be specified only once
if( time_params->time_resolution_specified ) {
SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "already specified" );
}

// can only be specified before any sc_time is constructed
if( time_params->time_resolution_fixed ) {
if( time_params_frozen( time_params ) ) {
SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "sc_time object(s) constructed" );
}

Expand All @@ -395,6 +399,7 @@ sc_set_time_resolution( double v, sc_time_unit tu )
}

time_params->time_resolution = resolution;
time_params->time_resolution_log10 = static_cast<unsigned>( log10( resolution ) );
time_params->time_resolution_specified = true;
}

Expand Down Expand Up @@ -430,19 +435,16 @@ sc_set_default_time_unit( double v, sc_time_unit tu )
"value not a power of ten" );
}

sc_simcontext* simc = sc_get_curr_simcontext();

// can only be specified during elaboration
if( sc_is_running() ) {
SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "simulation running" );
}

sc_time_params* time_params = simc->m_time_params;
auto * time_params = sc_get_curr_simcontext()->m_time_params;

// can only be specified before any sc_time is constructed
if( time_params->time_resolution_fixed ) {
SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_,
"sc_time object(s) constructed" );
if( time_params_frozen( time_params ) ) {
SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "sc_time object(s) constructed" );
}

// can be specified only once
Expand Down
9 changes: 5 additions & 4 deletions src/sysc/kernel/sc_time.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "sysc/datatypes/int/sc_nbdefs.h"
#include "sysc/datatypes/fx/scfx_ieee.h"

#include <atomic>
#include <iostream>

#include <string_view>
Expand Down Expand Up @@ -460,15 +461,15 @@ operator << ( ::std::ostream& os, const sc_time& t )

struct SC_API sc_time_params
{
double time_resolution; // in yocto seconds
bool time_resolution_specified;
bool time_resolution_fixed;
double time_resolution; // in yocto seconds
unsigned time_resolution_log10;
bool time_resolution_specified;
std::atomic<bool> time_resolution_fixed;

sc_time::value_type default_time_unit; // in time resolution
bool default_time_unit_specified;

sc_time_params();
~sc_time_params();
};


Expand Down
27 changes: 25 additions & 2 deletions tests/systemc/kernel/sc_time/test19/test19.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ void check_time( const sc_time& t, sc_time_unit tu, const std::string & str )
{
sc_time_tuple tp = t;

#ifndef BENCHMARK
std::cout << t.to_string() << ", value=" << t.value() << std::endl;
std::cout << " ";
if( tp.has_value() )
std::cout << "t.value=" << tp.value();
else
std::cout << "t.double=" << tp.to_double();
std::cout << ", t.unit=" << tp.unit_symbol()
<< std::endl;
std::cout << ", t.unit=" << tp.unit_symbol() << std::endl;
#endif // BENCHMARK

sc_assert( tp.has_value() );
sc_assert( t.to_string() == str );
Expand All @@ -50,10 +51,26 @@ void check_time( const sc_time& t, sc_time_unit tu, const std::string & str )
sc_assert( t == u );
sc_assert( u == tp );
sc_assert( tp.unit() == sc_time_tuple(u).unit() );
}

#ifdef BENCHMARK
int test_iteration();

int sc_main( int, char*[] )
{
sc_report_handler::set_actions( SC_WARNING, SC_DO_NOTHING );

static const int iterations = 20'000;
for(int i = 0; i < iterations; ++i ) {
test_iteration();
}
return 0;
}

int test_iteration()
#else
int sc_main( int, char*[] )
#endif
{
sc_report_handler::set_actions( SC_ID_SET_TIME_RESOLUTION_, SC_DO_NOTHING );
sc_report_handler::set_actions( SC_ID_TIME_CONVERSION_FAILED_, SC_DISPLAY );
Expand All @@ -77,7 +94,9 @@ int sc_main( int, char*[] )
for( auto res : resolutions )
{
sc_set_time_resolution( res, resunit );
#ifndef BENCHMARK
std::cout << "\nResolution = " << sc_get_time_resolution() << std::endl;
#endif // BENCHMARK

check_time( sc_time( 10, SC_NS), SC_NS, "10 ns" );
check_time( sc_time( 100, SC_NS), SC_NS, "100 ns" );
Expand All @@ -98,12 +117,16 @@ int sc_main( int, char*[] )

{
sc_set_time_resolution(1, SC_SEC);
#ifndef BENCHMARK
std::cout << "\nResolution = " << sc_get_time_resolution() << std::endl;
#endif // BENCHMARK

auto t = sc_core::sc_time(1, SC_SEC);
check_time( t, SC_SEC, "1 s");
}

#ifndef BENCHMARK
cout << "\nProgram completed" << endl;
#endif // BENCHMARK
return 0;
}

0 comments on commit f5d939a

Please sign in to comment.