From 44854a900f76d02d57dfeb4ec6564befd7c7041f Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Fri, 22 Nov 2024 08:35:58 +0100 Subject: [PATCH 1/3] sc_time: atomic time_resolution_fixed Use a std::atomic to handle the time_resolution_fixed flag in the kernel, tracking whether the time resolution has been set or non-zero sc_time objects have been constructed. Signed-off-by: Philipp A. Hartmann --- src/sysc/kernel/sc_time.cpp | 59 +++++++++++++++++++++---------------- src/sysc/kernel/sc_time.h | 8 ++--- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/sysc/kernel/sc_time.cpp b/src/sysc/kernel/sc_time.cpp index df6caf15a..289783e63 100644 --- a/src/sysc/kernel/sc_time.cpp +++ b/src/sysc/kernel/sc_time.cpp @@ -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 // @@ -78,8 +89,8 @@ 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 * time_params = sc_get_curr_simcontext()->m_time_params; + time_params_freeze( time_params ); auto tr_log10 = std::log10( time_params->time_resolution ); auto scale = static_cast( tr_log10 ); @@ -149,13 +160,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( tmp ); - tp->time_resolution_fixed = true; } - return t; } @@ -225,7 +235,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 @@ -236,7 +247,6 @@ sc_time::sc_time( double v, bool scale ) volatile double tmp = v + 0.5; m_value = static_cast( tmp ); } - time_params->time_resolution_fixed = true; } } @@ -251,7 +261,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 ); @@ -261,7 +272,6 @@ sc_time::sc_time( value_type v, bool scale ) } else { m_value = v; } - time_params->time_resolution_fixed = true; } } @@ -280,8 +290,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; @@ -293,10 +303,12 @@ 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 ) ); } @@ -304,10 +316,12 @@ sc_time::to_default_time_units() const 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] ) ); } @@ -336,10 +350,6 @@ sc_time_params::sc_time_params() default_time_unit_specified( false ) {} -sc_time_params::~sc_time_params() -{} - - // ---------------------------------------------------------------------------- // functions for accessing the time resolution and default time unit @@ -366,7 +376,7 @@ sc_set_time_resolution( double v, sc_time_unit tu ) SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "simulation running" ); } - sc_time_params* time_params = simc->m_time_params; + auto * time_params = simc->m_time_params; // can be specified only once if( time_params->time_resolution_specified ) { @@ -374,7 +384,7 @@ sc_set_time_resolution( double v, sc_time_unit tu ) } // 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" ); } @@ -430,19 +440,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 diff --git a/src/sysc/kernel/sc_time.h b/src/sysc/kernel/sc_time.h index 4b03b6479..8f03eed67 100644 --- a/src/sysc/kernel/sc_time.h +++ b/src/sysc/kernel/sc_time.h @@ -34,6 +34,7 @@ #include "sysc/datatypes/int/sc_nbdefs.h" #include "sysc/datatypes/fx/scfx_ieee.h" +#include #include #include @@ -472,15 +473,14 @@ 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 femto seconds + bool time_resolution_specified; + std::atomic time_resolution_fixed; sc_time::value_type default_time_unit; // in time resolution bool default_time_unit_specified; sc_time_params(); - ~sc_time_params(); }; From 63d1f3dccacae78d501aca866af331586fb6ef7f Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Fri, 22 Nov 2024 08:35:58 +0100 Subject: [PATCH 2/3] sc_time: improve sc_time_tuple::init Signed-off-by: Philipp A. Hartmann --- src/sysc/kernel/sc_time.cpp | 15 +++++---------- src/sysc/kernel/sc_time.h | 3 ++- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/sysc/kernel/sc_time.cpp b/src/sysc/kernel/sc_time.cpp index 289783e63..570b9d8a7 100644 --- a/src/sysc/kernel/sc_time.cpp +++ b/src/sysc/kernel/sc_time.cpp @@ -92,14 +92,9 @@ sc_time_tuple::init( value_type val ) auto * time_params = sc_get_curr_simcontext()->m_time_params; time_params_freeze( time_params ); - auto tr_log10 = std::log10( time_params->time_resolution ); - auto scale = static_cast( tr_log10 ); - - [[maybe_unused]] double ignored = 0.0; - sc_assert( std::modf( tr_log10, &ignored ) == 0.0 ); - 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++; @@ -344,6 +339,7 @@ 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(log10(time_resolution)) ), time_resolution_specified( false ), time_resolution_fixed( false ), default_time_unit( 1000 ), // default 1 ns @@ -369,14 +365,12 @@ 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" ); } - auto * 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 ) { @@ -405,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( log10( resolution ) ); time_params->time_resolution_specified = true; } diff --git a/src/sysc/kernel/sc_time.h b/src/sysc/kernel/sc_time.h index 8f03eed67..08fcb8f64 100644 --- a/src/sysc/kernel/sc_time.h +++ b/src/sysc/kernel/sc_time.h @@ -473,7 +473,8 @@ operator << ( ::std::ostream& os, const sc_time& t ) struct SC_API sc_time_params { - double time_resolution; // in femto seconds + double time_resolution; // in yocto seconds + unsigned time_resolution_log10; bool time_resolution_specified; std::atomic time_resolution_fixed; From dfbd5fb85db7f00aef6e6234ccf4cb13074ce05e Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Fri, 22 Nov 2024 14:23:44 +0100 Subject: [PATCH 3/3] tests: sc_time/test19: simple benchmark mode Signed-off-by: Philipp A. Hartmann --- .../systemc/kernel/sc_time/test19/test19.cpp | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/systemc/kernel/sc_time/test19/test19.cpp b/tests/systemc/kernel/sc_time/test19/test19.cpp index 7f4c1b066..e4930fec8 100644 --- a/tests/systemc/kernel/sc_time/test19/test19.cpp +++ b/tests/systemc/kernel/sc_time/test19/test19.cpp @@ -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 ); @@ -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 ); @@ -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" ); @@ -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; }