diff options
Diffstat (limited to 'ext/systemc/src/sysc/tracing')
-rw-r--r-- | ext/systemc/src/sysc/tracing/sc_trace.cpp | 217 | ||||
-rw-r--r-- | ext/systemc/src/sysc/tracing/sc_trace.h | 397 | ||||
-rw-r--r-- | ext/systemc/src/sysc/tracing/sc_trace_file_base.cpp | 273 | ||||
-rw-r--r-- | ext/systemc/src/sysc/tracing/sc_trace_file_base.h | 140 | ||||
-rw-r--r-- | ext/systemc/src/sysc/tracing/sc_tracing_ids.h | 79 | ||||
-rw-r--r-- | ext/systemc/src/sysc/tracing/sc_vcd_trace.cpp | 2175 | ||||
-rw-r--r-- | ext/systemc/src/sysc/tracing/sc_vcd_trace.h | 228 | ||||
-rw-r--r-- | ext/systemc/src/sysc/tracing/sc_wif_trace.cpp | 1911 | ||||
-rw-r--r-- | ext/systemc/src/sysc/tracing/sc_wif_trace.h | 222 |
9 files changed, 5642 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/tracing/sc_trace.cpp b/ext/systemc/src/sysc/tracing/sc_trace.cpp new file mode 100644 index 000000000..09a2fa3b2 --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_trace.cpp @@ -0,0 +1,217 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_trace.cpp - Functions for tracing signals and variables. + + Original Author: Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, the basics are identical to what was + originally contributed by Infineon. The contribution of Infineon + in the development of this tracing technology is hereby + acknowledged. + + *****************************************************************************/ + +#include <stdarg.h> +#include <stdio.h> + +#include "sysc/tracing/sc_trace.h" +#include "sysc/tracing/sc_tracing_ids.h" +#include "sysc/communication/sc_signal_ifs.h" +#include "sysc/utils/sc_report.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// Trace file common functions. + +sc_trace_file::sc_trace_file() +{ + /* Intentionally blank */ +} + +void tprintf(sc_trace_file* tf, const char* format, ...) +{ + static char buffer[4096]; + va_list ap; + va_start(ap, format); + (void) vsprintf(buffer, format, ap); + va_end(ap); + if (tf) tf->write_comment(buffer); +} + +void sc_trace_file::space(int) +{ + /* Intentionally blank */ +} + +void sc_trace_file::delta_cycles(bool) +{ + /* Intentionally blank */ +} + + +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<char>& object, + const std::string& name, + int width ) +{ + if( tf ) { + tf->trace( object.read(), name, width ); + } +} + +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<short>& object, + const std::string& name, + int width ) +{ + if( tf ) { + tf->trace( object.read(), name, width ); + } +} + +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<int>& object, + const std::string& name, + int width ) +{ + if( tf ) { + tf->trace( object.read(), name, width ); + } +} + +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<long>& object, + const std::string& name, + int width ) +{ + if( tf ) { + tf->trace( object.read(), name, width ); + } +} + + +void +sc_trace(sc_trace_file* /* not used */, + const void* /* not used */, + const std::string& name) +{ + SC_REPORT_WARNING( SC_ID_TRACING_OBJECT_IGNORED_, name.c_str() ); +} + + + +void double_to_special_int64(double in, unsigned* high, unsigned* low) +{ + double invar = in; + if(invar > 5e17) invar = 5e17; // Saturation limit + if(invar < 0.0) invar = 0.0; + invar += .5; + *high = (unsigned)(invar / 1e9); + double rest = invar - 1e9 * (*high); + if(rest < 0) *low = 0; + else *low = (unsigned)rest; +} + + +// ---------------------------------------------------------------------------- + +#define DEFN_TRACE_FUNC_REF_A(tp) \ +void \ +sc_trace( sc_trace_file* tf, const tp& object, const std::string& name ) \ +{ \ + if( tf ) { \ + tf->trace( object, name ); \ + } \ +} + +#define DEFN_TRACE_FUNC_PTR_A(tp) \ +void \ +sc_trace( sc_trace_file* tf, const tp* object, const std::string& name ) \ +{ \ + if( tf ) { \ + tf->trace( *object, name ); \ + } \ +} + +#define DEFN_TRACE_FUNC_A(tp) \ +DEFN_TRACE_FUNC_REF_A(tp) \ +DEFN_TRACE_FUNC_PTR_A(tp) + + +DEFN_TRACE_FUNC_A( sc_dt::sc_bit ) +DEFN_TRACE_FUNC_A( sc_dt::sc_logic ) + +DEFN_TRACE_FUNC_A( sc_dt::sc_int_base ) +DEFN_TRACE_FUNC_A( sc_dt::sc_uint_base ) +DEFN_TRACE_FUNC_A( sc_dt::sc_signed ) +DEFN_TRACE_FUNC_A( sc_dt::sc_unsigned ) + +DEFN_TRACE_FUNC_REF_A( sc_dt::sc_bv_base ) +DEFN_TRACE_FUNC_REF_A( sc_dt::sc_lv_base ) + + +#undef DEFN_TRACE_FUNC_REF_A +#undef DEFN_TRACE_FUNC_PTR_A +#undef DEFN_TRACE_FUNC_A + + +void +sc_trace( sc_trace_file* tf, + const unsigned int& object, + const std::string& name, + const char** enum_literals ) +{ + static bool warn_sc_trace_literals=true; + if ( warn_sc_trace_literals ) + { + warn_sc_trace_literals=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "tracing of enumerated literals is deprecated" ); + } + + if( tf ) tf->trace( object, name, enum_literals ); +} + +} // namespace sc_core + +// Taf! diff --git a/ext/systemc/src/sysc/tracing/sc_trace.h b/ext/systemc/src/sysc/tracing/sc_trace.h new file mode 100644 index 000000000..256e430a7 --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_trace.h @@ -0,0 +1,397 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_trace.h - Functions for tracing signals and variables. + + Author: Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, the basics are identical to what was + originally contributed by Infineon. The contribution of Infineon + in the development of this tracing technology is hereby + acknowledged. + + *****************************************************************************/ + +#ifndef SC_TRACE_H +#define SC_TRACE_H + +#include <cstdio> + +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/kernel/sc_time.h" + +// Some forward declarations +namespace sc_dt +{ + class sc_bit; + class sc_logic; + class sc_bv_base; + class sc_lv_base; + class sc_signed; + class sc_unsigned; + class sc_int_base; + class sc_uint_base; + class sc_fxval; + class sc_fxval_fast; + class sc_fxnum; + class sc_fxnum_fast; +} + +namespace sc_core { + +class sc_time; + +template <class T> class sc_signal_in_if; + + +// Base class for all kinds of trace files. + +class sc_trace_file +{ + friend class sc_simcontext; + +public: + + // Constructor + sc_trace_file(); + + // All functions are pure virtual because they need to be defined by the + // particular tracing mechanism + + +#define DECL_TRACE_METHOD_A(tp) \ + virtual void trace( const tp& object, \ + const std::string& name ) = 0; + +#define DECL_TRACE_METHOD_B(tp) \ + virtual void trace( const tp& object, \ + const std::string& name, \ + int width ) = 0; + + + DECL_TRACE_METHOD_A( bool ) + DECL_TRACE_METHOD_A( sc_dt::sc_bit ) + DECL_TRACE_METHOD_A( sc_dt::sc_logic ) + + DECL_TRACE_METHOD_B( unsigned char ) + DECL_TRACE_METHOD_B( unsigned short ) + DECL_TRACE_METHOD_B( unsigned int ) + DECL_TRACE_METHOD_B( unsigned long ) + DECL_TRACE_METHOD_B( char ) + DECL_TRACE_METHOD_B( short ) + DECL_TRACE_METHOD_B( int ) + DECL_TRACE_METHOD_B( long ) + DECL_TRACE_METHOD_B( sc_dt::int64 ) + DECL_TRACE_METHOD_B( sc_dt::uint64 ) + + DECL_TRACE_METHOD_A( float ) + DECL_TRACE_METHOD_A( double ) + DECL_TRACE_METHOD_A( sc_dt::sc_int_base ) + DECL_TRACE_METHOD_A( sc_dt::sc_uint_base ) + DECL_TRACE_METHOD_A( sc_dt::sc_signed ) + DECL_TRACE_METHOD_A( sc_dt::sc_unsigned ) + + DECL_TRACE_METHOD_A( sc_dt::sc_fxval ) + DECL_TRACE_METHOD_A( sc_dt::sc_fxval_fast ) + DECL_TRACE_METHOD_A( sc_dt::sc_fxnum ) + DECL_TRACE_METHOD_A( sc_dt::sc_fxnum_fast ) + + DECL_TRACE_METHOD_A( sc_dt::sc_bv_base ) + DECL_TRACE_METHOD_A( sc_dt::sc_lv_base ) + + +#undef DECL_TRACE_METHOD_A +#undef DECL_TRACE_METHOD_B + + // Trace an enumerated object - where possible output the enumeration + // literals in the trace file. Enum literals is a null terminated array + // of null terminated char* literal strings. + virtual void trace( const unsigned int& object, + const std::string& name, + const char** enum_literals ) = 0; + + // Output a comment to the trace file + virtual void write_comment( const std::string& comment ) = 0; + + // Set the amount of space before next column + // (For most formats this does nothing) + virtual void space( int n ); + + // Also trace transitions between delta cycles if flag is true. + virtual void delta_cycles( bool flag ); + + // Set time unit. + virtual void set_time_unit( double v, sc_time_unit tu )=0; + +protected: + + // Write trace info for cycle + virtual void cycle( bool delta_cycle ) = 0; + + // Flush results and close file + virtual ~sc_trace_file() + { /* Intentionally blank */ } +}; + +/*****************************************************************************/ + +// Now comes all the SystemC defined tracing functions. +// We define two sc_trace() versions for scalar types; one where the object to +// be traced is passed as a reference and the other where a pointer to the +// tracing object is passed. + +#define DECL_TRACE_FUNC_REF_A(tp) \ +void \ +sc_trace( sc_trace_file* tf, \ + const tp& object, \ + const std::string& name ); + +#define DECL_TRACE_FUNC_PTR_A(tp) \ +void \ +sc_trace( sc_trace_file* tf, \ + const tp* object, \ + const std::string& name ); \ + +#define DECL_TRACE_FUNC_A(tp) \ +DECL_TRACE_FUNC_REF_A(tp) \ +DECL_TRACE_FUNC_PTR_A(tp) + + +DECL_TRACE_FUNC_A( sc_dt::sc_bit ) +DECL_TRACE_FUNC_A( sc_dt::sc_logic ) + +DECL_TRACE_FUNC_A( sc_dt::sc_int_base ) +DECL_TRACE_FUNC_A( sc_dt::sc_uint_base ) +DECL_TRACE_FUNC_A( sc_dt::sc_signed ) +DECL_TRACE_FUNC_A( sc_dt::sc_unsigned ) + +DECL_TRACE_FUNC_REF_A( sc_dt::sc_bv_base ) +DECL_TRACE_FUNC_REF_A( sc_dt::sc_lv_base ) + + +#undef DECL_TRACE_FUNC_REF_A +#undef DECL_TRACE_FUNC_PTR_A +#undef DECL_TRACE_FUNC_A + + +// ---------------------------------------------------------------------------- + +#define DEFN_TRACE_FUNC_REF_A(tp) \ +inline \ +void \ +sc_trace( sc_trace_file* tf, const tp& object, const std::string& name ) \ +{ \ + if( tf ) { \ + tf->trace( object, name ); \ + } \ +} + +#define DEFN_TRACE_FUNC_PTR_A(tp) \ +inline \ +void \ +sc_trace( sc_trace_file* tf, const tp* object, const std::string& name ) \ +{ \ + if( tf ) { \ + tf->trace( *object, name ); \ + } \ +} + +#define DEFN_TRACE_FUNC_A(tp) \ +DEFN_TRACE_FUNC_REF_A(tp) \ +DEFN_TRACE_FUNC_PTR_A(tp) + + +#define DEFN_TRACE_FUNC_REF_B(tp) \ +inline \ +void \ +sc_trace( sc_trace_file* tf, const tp& object, const std::string& name, \ + int width = 8 * sizeof( tp ) ) \ +{ \ + if( tf ) { \ + tf->trace( object, name, width ); \ + } \ +} + +#define DEFN_TRACE_FUNC_PTR_B(tp) \ +inline \ +void \ +sc_trace( sc_trace_file* tf, const tp* object, const std::string& name, \ + int width = 8 * sizeof( tp ) ) \ +{ \ + if( tf ) { \ + tf->trace( *object, name, width ); \ + } \ +} + + +#define DEFN_TRACE_FUNC_B(tp) \ +DEFN_TRACE_FUNC_REF_B(tp) \ +DEFN_TRACE_FUNC_PTR_B(tp) + + +DEFN_TRACE_FUNC_A( bool ) +DEFN_TRACE_FUNC_A( float ) +DEFN_TRACE_FUNC_A( double ) + +DEFN_TRACE_FUNC_B( unsigned char ) +DEFN_TRACE_FUNC_B( unsigned short ) +DEFN_TRACE_FUNC_B( unsigned int ) +DEFN_TRACE_FUNC_B( unsigned long ) +DEFN_TRACE_FUNC_B( char ) +DEFN_TRACE_FUNC_B( short ) +DEFN_TRACE_FUNC_B( int ) +DEFN_TRACE_FUNC_B( long ) +DEFN_TRACE_FUNC_B( sc_dt::int64 ) +DEFN_TRACE_FUNC_B( sc_dt::uint64 ) + + +#undef DEFN_TRACE_FUNC_REF_A +#undef DEFN_TRACE_FUNC_PTR_A +#undef DEFN_TRACE_FUNC_A + +#undef DEFN_TRACE_FUNC_REF_B +#undef DEFN_TRACE_FUNC_PTR_B +#undef DEFN_TRACE_FUNC_B + + +template <class T> +inline +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<T>& object, + const std::string& name ) +{ + sc_trace( tf, object.read(), name ); +} + +template< class T > +inline +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<T>& object, + const char* name ) +{ + sc_trace( tf, object.read(), name ); +} + + +// specializations for signals of type char, short, int, long + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if<char>& object, + const std::string& name, + int width ); + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if<short>& object, + const std::string& name, + int width ); + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if<int>& object, + const std::string& name, + int width ); + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if<long>& object, + const std::string& name, + int width ); + + +// 1. non-template function is better than template +// 2. more-specialized template is better than less-specialized +// 3. no partial specialization for template functions + + +// Trace an enumerated object - where possible output the enumeration literals +// in the trace file. Enum literals is a null terminated array of null +// terminated char* literal strings. + +void +sc_trace( sc_trace_file* tf, + const unsigned int& object, + const std::string& name, + const char** enum_literals ); + + +// Dummy function for arbitrary types of value, does nothing + +extern void sc_trace( sc_trace_file* tf, + const void* object, + const std::string& name ); + + +// Turn on/off delta cycle tracing on trace file `tf'. +// Default is to turn on delta cycle tracing. + +inline +void +sc_trace_delta_cycles( sc_trace_file* tf, bool on = true ) +{ + if( tf ) tf->delta_cycles( on ); +} + + +// Output a comment to the trace file + +inline +void +sc_write_comment( sc_trace_file* tf, const std::string& comment ) +{ + if( tf ) tf->write_comment( comment ); +} + + +// Equivalent of std::fprintf for trace files! + +void tprintf( sc_trace_file* tf, const char* format, ... ); + +// ---------------------------------------------------------------------------- +// Create VCD file +extern sc_trace_file *sc_create_vcd_trace_file(const char* name); +extern void sc_close_vcd_trace_file( sc_trace_file* tf ); + + +// ---------------------------------------------------------------------------- +// Create WIF file +extern sc_trace_file *sc_create_wif_trace_file(const char *name); +extern void sc_close_wif_trace_file( sc_trace_file* tf ); + +} // namespace sc_core + +#endif // SC_TRACE_H +// Taf diff --git a/ext/systemc/src/sysc/tracing/sc_trace_file_base.cpp b/ext/systemc/src/sysc/tracing/sc_trace_file_base.cpp new file mode 100644 index 000000000..4f4345468 --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_trace_file_base.cpp @@ -0,0 +1,273 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_trace_file_base.cpp - Shared internal tracing implementation + + Original Author: Philipp A. Hartmann, OFFIS, 2013-11-15 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. The + contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + +#include <ctime> + +#include "sysc/tracing/sc_trace_file_base.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_simcontext_int.h" + +#if SC_TRACING_PHASE_CALLBACKS_ +# include "sysc/kernel/sc_object_int.h" +#endif + +namespace sc_core { + +bool sc_trace_file_base::tracing_initialized_ = false; + + +sc_trace_file_base::sc_trace_file_base( const char* name, const char* extension ) + : sc_trace_file() +#if SC_TRACING_PHASE_CALLBACKS_ + , sc_object( sc_gen_unique_name("$$$$kernel_tracefile$$$$") ) +#endif + , fp(0) + , timescale_unit() + , timescale_set_by_user(false) + , filename_() + , initialized_(false) + , trace_delta_cycles_(false) +{ + if( !name || !*name ) { + SC_REPORT_ERROR( SC_ID_TRACING_FOPEN_FAILED_, "no name given" ); + return; + } else { + std::stringstream ss; + ss << name << "." << extension; + ss.str().swap( filename_ ); + } + +#if SC_TRACING_PHASE_CALLBACKS_ == 1 + // remove from hierarchy + sc_object::detach(); + // register regular (non-delta) callbacks + sc_object::register_simulation_phase_callback( + // Note: Usually, one would expect to dump the initial values + // of the traced variables at the end of the initialization + // phase. The "non-callback" implementation dumps those + // values only after the first delta cycle, though. + // SC_END_OF_INITIALIZATION | + SC_BEFORE_TIMESTEP | + SC_PAUSED | SC_STOPPED + ); +#else // explicitly register with simcontext + sc_get_curr_simcontext()->add_trace_file( this ); +#endif +} + +sc_trace_file_base::~sc_trace_file_base() +{ + if( fp ) + fclose(fp); + +#if SC_TRACING_PHASE_CALLBACKS_ == 0 + // unregister from simcontext + sc_get_curr_simcontext()->remove_trace_file( this ); +#endif +} + +/*****************************************************************************/ +// simulation phase callback based trigger +// +// The tracing updates are triggered +// (- at the end of the initialization phase [disabled for now]) +// - before an update of the simulation time +// - before returning to sc_start (via sc_pause() or sc_stop()) +// - after an update phase (if delta cycles need to be traced) +// +#if SC_TRACING_PHASE_CALLBACKS_ +void +sc_trace_file_base::simulation_phase_callback() +{ + // delta cycle is traced at the end of an update phase + cycle( simcontext()->get_status() == SC_END_OF_UPDATE ); +} +#endif // SC_TRACING_PHASE_CALLBACKS_ + +/*****************************************************************************/ + +bool +sc_trace_file_base::initialize() +{ + if( initialized_ ) + return false; + + initialized_ = true; + + if( !tracing_initialized_ ) { + tracing_initialized_ = true; + bool running_regression = ( getenv( "SYSTEMC_REGRESSION" ) != NULL ); + + // hide some messages during regression + if( running_regression ) { + sc_report_handler::set_actions( SC_ID_TRACING_TIMESCALE_DEFAULT_ + , SC_INFO, SC_DO_NOTHING ); + sc_report_handler::set_actions( SC_ID_TRACING_VCD_DUPLICATE_TIME_ + , SC_WARNING, SC_DO_NOTHING ); + } + } + + // open trace file + if(!fp) open_fp(); + + // setup timescale + if( !timescale_set_by_user ) + { + timescale_unit = sc_get_time_resolution().to_seconds(); + + std::stringstream ss; + ss << sc_get_time_resolution() << " (" << filename_ << ")"; + SC_REPORT_INFO( SC_ID_TRACING_TIMESCALE_DEFAULT_ + , ss.str().c_str() ); + } + + // initialize derived tracing implementation class (VCD/WIF) + do_initialize(); + + return initialized_; +} + +void +sc_trace_file_base::open_fp() +{ + sc_assert( !fp ); + fp = fopen( filename(), "w" ); + if( !fp ) { + SC_REPORT_ERROR( SC_ID_TRACING_FOPEN_FAILED_, filename() ); + std::terminate(); // can't recover from here + } +} + +void +sc_trace_file_base::delta_cycles( bool flag ) +{ + trace_delta_cycles_ = flag; +#if SC_TRACING_PHASE_CALLBACKS_ + if( trace_delta_cycles_ ) { + sc_object::register_simulation_phase_callback( SC_END_OF_UPDATE ); + } else { + sc_object::unregister_simulation_phase_callback( SC_END_OF_UPDATE ); + } +#endif +} + +void +sc_trace_file_base::set_time_unit( double v, sc_time_unit tu ) +{ + if( initialized_ ) + { + std::stringstream ss; + ss << filename_ << "\n" + "\tTimescale unit cannot be changed once tracing has begun.\n" + "\tTo change the scale, create a new trace file."; + SC_REPORT_ERROR( SC_ID_TRACING_ALREADY_INITIALIZED_ + , ss.str().c_str() ); + return; + } + + switch ( tu ) + { + case SC_FS: v = v * 1e-15; break; + case SC_PS: v = v * 1e-12; break; + case SC_NS: v = v * 1e-9; break; + case SC_US: v = v * 1e-6; break; + case SC_MS: v = v * 1e-3; break; + case SC_SEC: break; + default: { + std::stringstream ss; + ss << "unknown time unit:" << tu + << " (" << filename_ << ")"; + SC_REPORT_WARNING( SC_ID_TRACING_TIMESCALE_UNIT_ + , ss.str().c_str() ); + } + } + + timescale_set_by_user = true; + timescale_unit = v; + + // EMIT ADVISORY MESSAGE ABOUT CHANGE IN TIME SCALE: + { + std::stringstream ss; + ss << sc_time( timescale_unit, SC_SEC ) + << " (" << filename_ << ")"; + SC_REPORT_INFO( SC_ID_TRACING_TIMESCALE_UNIT_, ss.str().c_str() ); + } +} + +bool +sc_trace_file_base::add_trace_check( const std::string & name ) const +{ + if( !initialized_ ) return true; + + std::stringstream ss; + ss << "sc_trace() failed:\n" + "\tNo traces can be added to " + "'" << filename_ << "'" + " once trace recording has started.\n" + "\tTo add tracing of '" << name << "', create a new trace file."; + + SC_REPORT_ERROR( SC_ID_TRACING_ALREADY_INITIALIZED_ + , ss.str().c_str() ); + return false; +} + +// obtain formatted time string +std::string localtime_string() +{ + char buf[200]; + time_t long_time; + time(&long_time); + struct tm* p_tm = localtime(&long_time); + strftime(buf, 199, "%b %d, %Y %H:%M:%S", p_tm); + return buf; +} + + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +// Taf! diff --git a/ext/systemc/src/sysc/tracing/sc_trace_file_base.h b/ext/systemc/src/sysc/tracing/sc_trace_file_base.h new file mode 100644 index 000000000..c0217266f --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_trace_file_base.h @@ -0,0 +1,140 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_trace_file_base.h - Shared internal tracing implementation + + Original Author: Philipp A. Hartmann, OFFIS, 2013-11-15 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. The + contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + +#ifndef SC_TRACE_FILE_BASE_H_INCLUDED_ +#define SC_TRACE_FILE_BASE_H_INCLUDED_ + +#include <cstdio> + +// use callback-based tracing implementation +#if defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING ) +# define SC_TRACING_PHASE_CALLBACKS_ 1 +# include "sysc/kernel/sc_object.h" +#else +# define SC_TRACING_PHASE_CALLBACKS_ 0 +#endif + +#include "sysc/tracing/sc_trace.h" +#include "sysc/tracing/sc_tracing_ids.h" + +namespace sc_core { + +// shared implementation of trace files +class sc_trace_file_base + : public sc_trace_file +#if SC_TRACING_PHASE_CALLBACKS_ + , private sc_object // to be used as callback target +#endif +{ +public: + const char* filename() const + { return filename_.c_str(); } + + bool delta_cycles() const + { return trace_delta_cycles_; } + + // Also trace transitions between delta cycles if flag is true. + virtual void delta_cycles(bool flag); + + // set a user-define timescale unit for the trace file + virtual void set_time_unit( double v, sc_time_unit tu); + +protected: + sc_trace_file_base( const char* name, const char* extension ); + + // returns true, iff initialization has been performed + bool initialize(); + // ensure that file has been opened (needed for early write_comment()) + void open_fp(); + // perform format specific initialization + virtual void do_initialize() = 0; + + // returns true, if new trace objects can still be added + // (i.e. trace file is not yet initialized) + bool add_trace_check( const std::string& name ) const; + + // Flush results and close file. + virtual ~sc_trace_file_base(); + +#if SC_TRACING_PHASE_CALLBACKS_ +private: + virtual void simulation_phase_callback(); +#endif // SC_TRACING_PHASE_CALLBACKS_ + +protected: + FILE* fp; // pointer to the trace file + double timescale_unit; // in seconds + bool timescale_set_by_user; // = true means set by user + +private: + std::string filename_; // name of the file (for reporting) + bool initialized_; // tracing started? + bool trace_delta_cycles_; // also trace delta transitions? + + static bool tracing_initialized_; // shared setup of tracing implementation + +private: // disabled + sc_trace_file_base( const sc_trace_file_base& ) /* = delete */; + sc_trace_file_base& operator=( const sc_trace_file_base& ) /* = delete */; + +}; // class sc_trace_file_base + +// ----------------------------------------------------------------------- + +// Convert double time to 64-bit integer + +void double_to_special_int64( double in, unsigned* high, unsigned* low ); + +// obtain formatted time string +std::string localtime_string(); + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +#endif // SC_TRACE_FILE_BASE_H_INCLUDED_ +// Taf! diff --git a/ext/systemc/src/sysc/tracing/sc_tracing_ids.h b/ext/systemc/src/sysc/tracing/sc_tracing_ids.h new file mode 100644 index 000000000..dacdb9451 --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_tracing_ids.h @@ -0,0 +1,79 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_tracing_ids.h -- Report ids for the tracing code. + + Original Author: Philipp A. Hartmann, OFFIS, 2013-11-17 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_TRACING_IDS_H +#define SC_TRACING_IDS_H + +// ---------------------------------------------------------------------------- +// Report ids (tracing) +// +// Report ids in the range of 700-799. +// ---------------------------------------------------------------------------- + +#ifndef SC_DEFINE_MESSAGE +#define SC_DEFINE_MESSAGE(id,unused1,unused2) \ + namespace sc_core { extern const char id[]; } +#endif + +SC_DEFINE_MESSAGE( SC_ID_TRACING_FOPEN_FAILED_, 701, + "cannot open tracefile for writing" ) + +SC_DEFINE_MESSAGE( SC_ID_TRACING_TIMESCALE_DEFAULT_, 702, + "default timescale unit used for tracing" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_TIMESCALE_UNIT_, 703, + "tracing timescale unit set" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_VCD_DELTA_CYCLE_, 704, + "VCD delta cycle tracing with pseudo timesteps (1 unit)" ) +/* unused IDs 705-709 */ +SC_DEFINE_MESSAGE( SC_ID_TRACING_OBJECT_IGNORED_, 710, + "object cannot not be traced" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_OBJECT_NAME_FILTERED_, 711, + "traced object name filtered" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_INVALID_ENUM_VALUE_, 712, + "traced value of enumerated type undefined" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_VCD_DUPLICATE_TIME_, 713, + "multiple VCD tracing cycles with the same time detected" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_VCD_REVERSED_TIME_, 714, + "VCD tracing cycle with falling time detected" ) +/* unused IDs 715-719 */ +SC_DEFINE_MESSAGE( SC_ID_TRACING_ALREADY_INITIALIZED_, 720, + "sc_trace_file already initialized" ) + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +#endif // SC_TRACING_IDS_H +// Taf! diff --git a/ext/systemc/src/sysc/tracing/sc_vcd_trace.cpp b/ext/systemc/src/sysc/tracing/sc_vcd_trace.cpp new file mode 100644 index 000000000..616d6274d --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_vcd_trace.cpp @@ -0,0 +1,2175 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_vcd_trace.cpp - Implementation of VCD tracing. + + Original Author - Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Replaced 'width' of sc_(u)int with their + 'bitwidth()'. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. The + contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + + +#include <cstdlib> +#include <string.h> +#include <vector> + +#define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_ver.h" +#include "sysc/datatypes/bit/sc_bit.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/fx/fx.h" +#include "sysc/tracing/sc_vcd_trace.h" + +namespace sc_core { + +// Forward declarations for functions that come later in the file +// Map sc_dt::sc_logic to printable VCD +static char map_sc_logic_state_to_vcd_state(char in_char); + +// Remove name problems associated with [] in vcd names +static void remove_vcd_name_problems(vcd_trace const* vcd, std::string& name); + +const char* vcd_types[vcd_trace_file::VCD_LAST]={"wire","real"}; + + +// ---------------------------------------------------------------------------- +// CLASS : vcd_trace +// +// Base class for VCD traces. +// ---------------------------------------------------------------------------- + +class vcd_trace +{ +public: + + vcd_trace(const std::string& name_, const std::string& vcd_name_); + + // Needs to be pure virtual as has to be defined by the particular + // type being traced + virtual void write(FILE* f) = 0; + + virtual void set_width(); + + static const char* strip_leading_bits(const char* originalbuf); + + // Comparison function needs to be pure virtual too + virtual bool changed() = 0; + + // Make this virtual as some derived classes may overwrite + virtual void print_variable_declaration_line(FILE* f); + + void compose_data_line(char* rawdata, char* compdata); + std::string compose_line(const std::string& data); + + virtual ~vcd_trace(); + + const std::string name; + const std::string vcd_name; + const char* vcd_var_typ_name; + int bit_width; +}; + + +vcd_trace::vcd_trace(const std::string& name_, const std::string& vcd_name_) +: name(name_), vcd_name(vcd_name_), vcd_var_typ_name(0), bit_width(0) +{ + /* Intentionally blank */ +} + +void +vcd_trace::compose_data_line(char* rawdata, char* compdata) +{ + sc_assert(rawdata != compdata); + + if(bit_width == 0) + { + compdata[0] = '\0'; + } + else + { + if(bit_width == 1) + { + compdata[0] = rawdata[0]; + strcpy(&(compdata[1]), vcd_name.c_str()); + } + else + { + const char* effective_begin = strip_leading_bits(rawdata); + std::sprintf(compdata, "b%s %s", effective_begin, vcd_name.c_str()); + } + } +} + +// same as above but not that ugly +std::string +vcd_trace::compose_line(const std::string& data) +{ + if(bit_width == 0) + return ""; + if(bit_width == 1) + return data + vcd_name; + return std::string("b")+strip_leading_bits(data.c_str())+" "+vcd_name; +} + +void +vcd_trace::print_variable_declaration_line(FILE* f) +{ + char buf[2000]; + + if ( bit_width <= 0 ) + { + std::stringstream ss; + ss << "'" << name << "' has 0 bits"; + SC_REPORT_ERROR( SC_ID_TRACING_OBJECT_IGNORED_ + , ss.str().c_str() ); + return; + } + + std::string namecopy = name; + remove_vcd_name_problems(this, namecopy); + if ( bit_width == 1 ) + { + std::sprintf(buf, "$var %s % 3d %s %s $end\n", + vcd_var_typ_name, + bit_width, + vcd_name.c_str(), + namecopy.c_str()); + } + else + { + std::sprintf(buf, "$var %s % 3d %s %s [%d:0] $end\n", + vcd_var_typ_name, + bit_width, + vcd_name.c_str(), + namecopy.c_str(), + bit_width-1); + } + std::fputs(buf, f); +} + +void +vcd_trace::set_width() +{ + /* Intentionally Blank, should be defined for each type separately */ +} + +const char* +vcd_trace::strip_leading_bits(const char* originalbuf) +{ + //********************************************************************* + // - Remove multiple leading 0,z,x, and replace by only one + // - For example, + // b000z100 -> b0z100 + // b00000xxx -> b0xxx + // b000 -> b0 + // bzzzzz1 -> bz1 + // bxxxz10 -> xz10 + // - For leading 0's followed by 1, remove all leading 0's + // b0000010101 -> b10101 + + const char* position = originalbuf; + + if( strlen(originalbuf) < 2 || + (originalbuf[0] != 'z' && originalbuf[0] != 'x' && + originalbuf[0] != '0' )) + return originalbuf; + + char first_char = *position; + while(*position == first_char) + { + position++; + } + + if(first_char == '0' && *position == '1') + return position; + // else + return position-1; +} + +vcd_trace::~vcd_trace() +{ + /* Intentionally Blank */ +} + + +template <class T> +class vcd_T_trace : public vcd_trace +{ + public: + + vcd_T_trace( const T& object_, + const std::string& name_, + const std::string& vcd_name_, + vcd_trace_file::vcd_enum type_ ) + : vcd_trace( name_, vcd_name_ ), + object( object_ ), + old_value( object_ ) + { + vcd_var_typ_name = vcd_types[type_]; + } + + void write( FILE* f ) + { + std::fprintf( f, "%s", compose_line( object.to_string() ).c_str() ); + old_value = object; + } + + bool changed() + { return !(object == old_value); } + + void set_width() + { bit_width = object.length(); } + +protected: + + const T& object; + T old_value; +}; + +typedef vcd_T_trace<sc_dt::sc_bv_base> vcd_sc_bv_trace; +typedef vcd_T_trace<sc_dt::sc_lv_base> vcd_sc_lv_trace; + +// Trace sc_dt::sc_bv_base (sc_dt::sc_bv) +void +vcd_trace_file::trace( + const sc_dt::sc_bv_base& object, const std::string& name) +{ + traceT(object,name); +} + +// Trace sc_dt::sc_lv_base (sc_dt::sc_lv) +void +vcd_trace_file::trace( + const sc_dt::sc_lv_base& object, const std::string& name) +{ + traceT(object,name); +} + +/*****************************************************************************/ + +class vcd_bool_trace : public vcd_trace { +public: + vcd_bool_trace(const bool& object_, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + +protected: + const bool& object; + bool old_value; +}; + +vcd_bool_trace::vcd_bool_trace(const bool& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_) +{ + vcd_var_typ_name = "wire"; + bit_width = 1; +} + +bool +vcd_bool_trace::changed() +{ + return object != old_value; +} + +void +vcd_bool_trace::write(FILE* f) +{ + if (object == true) std::fputc('1', f); + else std::fputc('0', f); + + std::fprintf(f,"%s", vcd_name.c_str()); + + old_value = object; +} + +//***************************************************************************** + +class vcd_sc_bit_trace : public vcd_trace { +public: + vcd_sc_bit_trace(const sc_dt::sc_bit& , const std::string& , + const std::string& ); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::sc_bit& object; + sc_dt::sc_bit old_value; +}; + +vcd_sc_bit_trace::vcd_sc_bit_trace( const sc_dt::sc_bit& object_, + const std::string& name, + const std::string& vcd_name) +: vcd_trace(name, vcd_name), object( object_ ), old_value( object_ ) +{ + vcd_var_typ_name = "wire"; + bit_width = 1; +} + +bool +vcd_sc_bit_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_bit_trace::write(FILE* f) +{ + if (object == true) std::fputc('1', f); + else std::fputc('0', f); + + std::fprintf(f,"%s", vcd_name.c_str()); + + old_value = object; +} + +/*****************************************************************************/ + +class vcd_sc_logic_trace : public vcd_trace { +public: + vcd_sc_logic_trace(const sc_dt::sc_logic& object_, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::sc_logic& object; + sc_dt::sc_logic old_value; +}; + + +vcd_sc_logic_trace::vcd_sc_logic_trace(const sc_dt::sc_logic& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_) +{ + vcd_var_typ_name = "wire"; + bit_width = 1; +} + + +bool +vcd_sc_logic_trace::changed() +{ + return object != old_value; +} + + +void +vcd_sc_logic_trace::write(FILE* f) +{ + char out_char; + out_char = map_sc_logic_state_to_vcd_state(object.to_char()); + std::fputc(out_char, f); + + std::fprintf(f,"%s", vcd_name.c_str()); + + old_value = object; +} + + +/*****************************************************************************/ + +class vcd_sc_unsigned_trace : public vcd_trace { +public: + vcd_sc_unsigned_trace(const sc_dt::sc_unsigned& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_unsigned& object; + sc_dt::sc_unsigned old_value; +}; + + +vcd_sc_unsigned_trace::vcd_sc_unsigned_trace(const sc_dt::sc_unsigned& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) +// The last may look strange, but is correct +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_unsigned_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_unsigned_trace::write(FILE* f) +{ + static std::vector<char> compdata(1024), rawdata(1024); + typedef std::vector<char>::size_type size_t; + + if ( compdata.size() < (size_t)object.length() ) { + size_t sz = ( (size_t)object.length() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( compdata ); // resize without copying values + std::vector<char>( sz ).swap( rawdata ); + } + char *rawdata_ptr = &rawdata[0]; + + for (int bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; + } + *rawdata_ptr = '\0'; + compose_data_line(&rawdata[0], &compdata[0]); + + std::fputs(&compdata[0], f); + old_value = object; +} + +void +vcd_sc_unsigned_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class vcd_sc_signed_trace : public vcd_trace { +public: + vcd_sc_signed_trace(const sc_dt::sc_signed& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_signed& object; + sc_dt::sc_signed old_value; +}; + + +vcd_sc_signed_trace::vcd_sc_signed_trace(const sc_dt::sc_signed& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_signed_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_signed_trace::write(FILE* f) +{ + static std::vector<char> compdata(1024), rawdata(1024); + typedef std::vector<char>::size_type size_t; + + if ( compdata.size() < (size_t)object.length() ) { + size_t sz = ( (size_t)object.length() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( compdata ); // resize without copying values + std::vector<char>( sz ).swap( rawdata ); + } + char *rawdata_ptr = &rawdata[0]; + + for (int bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; + } + *rawdata_ptr = '\0'; + compose_data_line(&rawdata[0], &compdata[0]); + + std::fputs(&compdata[0], f); + old_value = object; +} + +void +vcd_sc_signed_trace::set_width() +{ + bit_width = object.length(); +} + +/*****************************************************************************/ + +class vcd_sc_uint_base_trace : public vcd_trace { +public: + vcd_sc_uint_base_trace(const sc_dt::sc_uint_base& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_uint_base& object; + sc_dt::sc_uint_base old_value; +}; + + +vcd_sc_uint_base_trace::vcd_sc_uint_base_trace( + const sc_dt::sc_uint_base& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) +// The last may look strange, but is correct +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_uint_base_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_uint_base_trace::write(FILE* f) +{ + char rawdata[1000], *rawdata_ptr = rawdata; + char compdata[1000]; + + int bitindex; + for (bitindex = object.length()-1; bitindex >= 0; --bitindex) { + *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; + } + *rawdata_ptr = '\0'; + compose_data_line(rawdata, compdata); + + std::fputs(compdata, f); + old_value = object; +} + +void +vcd_sc_uint_base_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class vcd_sc_int_base_trace : public vcd_trace { +public: + vcd_sc_int_base_trace(const sc_dt::sc_int_base& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_int_base& object; + sc_dt::sc_int_base old_value; +}; + + +vcd_sc_int_base_trace::vcd_sc_int_base_trace(const sc_dt::sc_int_base& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_int_base_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_int_base_trace::write(FILE* f) +{ + char rawdata[1000], *rawdata_ptr = rawdata; + char compdata[1000]; + + int bitindex; + for (bitindex = object.length()-1; bitindex >= 0; --bitindex) { + *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; + } + *rawdata_ptr = '\0'; + compose_data_line(rawdata, compdata); + + std::fputs(compdata, f); + old_value = object; +} + +void +vcd_sc_int_base_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class vcd_sc_fxval_trace : public vcd_trace +{ +public: + + vcd_sc_fxval_trace( const sc_dt::sc_fxval& object, + const std::string& name_, + const std::string& vcd_name_ ); + void write( FILE* f ); + bool changed(); + +protected: + + const sc_dt::sc_fxval& object; + sc_dt::sc_fxval old_value; + +}; + +vcd_sc_fxval_trace::vcd_sc_fxval_trace( const sc_dt::sc_fxval& object_, + const std::string& name_, + const std::string& vcd_name_ ) +: vcd_trace( name_, vcd_name_ ), + object( object_ ), old_value( object_ ) +{ + vcd_var_typ_name = "real"; + bit_width = 1; +} + +bool +vcd_sc_fxval_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_fxval_trace::write( FILE* f ) +{ + std::fprintf( f, "r%.16g %s", object.to_double(), vcd_name.c_str() ); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_sc_fxval_fast_trace : public vcd_trace +{ +public: + + vcd_sc_fxval_fast_trace( const sc_dt::sc_fxval_fast& object, + const std::string& name_, + const std::string& vcd_name_ ); + void write( FILE* f ); + bool changed(); + +protected: + + const sc_dt::sc_fxval_fast& object; + sc_dt::sc_fxval_fast old_value; + +}; + +vcd_sc_fxval_fast_trace::vcd_sc_fxval_fast_trace( + const sc_dt::sc_fxval_fast& object_, + const std::string& name_, + const std::string& vcd_name_ ) +: vcd_trace( name_, vcd_name_ ), + object( object_ ), old_value( object_ ) +{ + vcd_var_typ_name = "real"; + bit_width = 1; +} + +bool +vcd_sc_fxval_fast_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_fxval_fast_trace::write( FILE* f ) +{ + std::fprintf( f, "r%.16g %s", object.to_double(), vcd_name.c_str() ); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_sc_fxnum_trace : public vcd_trace +{ +public: + + vcd_sc_fxnum_trace( const sc_dt::sc_fxnum& object, + const std::string& name_, + const std::string& vcd_name_ ); + void write( FILE* f ); + bool changed(); + void set_width(); + +protected: + + const sc_dt::sc_fxnum& object; + sc_dt::sc_fxnum old_value; + +}; + +vcd_sc_fxnum_trace::vcd_sc_fxnum_trace( const sc_dt::sc_fxnum& object_, + const std::string& name_, + const std::string& vcd_name_ ) +: vcd_trace( name_, vcd_name_ ), + object( object_ ), + old_value( object_.m_params.type_params(), + object_.m_params.enc(), + object_.m_params.cast_switch(), + 0 ) +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_fxnum_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_fxnum_trace::write( FILE* f ) +{ + static std::vector<char> compdata(1024), rawdata(1024); + typedef std::vector<char>::size_type size_t; + + if ( compdata.size() < (size_t)object.wl() ) { + size_t sz = ( (size_t)object.wl() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( compdata ); // resize without copying values + std::vector<char>( sz ).swap( rawdata ); + } + char *rawdata_ptr = &rawdata[0]; + + for(int bitindex = object.wl() - 1; bitindex >= 0; -- bitindex ) + { + *rawdata_ptr ++ = "01"[object[bitindex]]; + } + *rawdata_ptr = '\0'; + compose_data_line( &rawdata[0], &compdata[0] ); + + std::fputs( &compdata[0], f ); + old_value = object; +} + +void +vcd_sc_fxnum_trace::set_width() +{ + bit_width = object.wl(); +} + +/*****************************************************************************/ + +class vcd_sc_fxnum_fast_trace : public vcd_trace +{ +public: + + vcd_sc_fxnum_fast_trace( const sc_dt::sc_fxnum_fast& object, + const std::string& name_, + const std::string& vcd_name_ ); + void write( FILE* f ); + bool changed(); + void set_width(); + +protected: + + const sc_dt::sc_fxnum_fast& object; + sc_dt::sc_fxnum_fast old_value; + +}; + +vcd_sc_fxnum_fast_trace::vcd_sc_fxnum_fast_trace( + const sc_dt::sc_fxnum_fast& object_, + const std::string& name_, + const std::string& vcd_name_ ) +: vcd_trace( name_, vcd_name_ ), + object( object_ ), + old_value( object_.m_params.type_params(), + object_.m_params.enc(), + object_.m_params.cast_switch(), + 0 ) +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_fxnum_fast_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_fxnum_fast_trace::write( FILE* f ) +{ + static std::vector<char> compdata(1024), rawdata(1024); + typedef std::vector<char>::size_type size_t; + + if ( compdata.size() < (size_t)object.wl() ) { + size_t sz = ( (size_t)object.wl() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( compdata ); // resize without copying values + std::vector<char>( sz ).swap( rawdata ); + } + char *rawdata_ptr = &rawdata[0]; + + for(int bitindex = object.wl() - 1; bitindex >= 0; -- bitindex ) + { + *rawdata_ptr ++ = "01"[object[bitindex]]; + } + *rawdata_ptr = '\0'; + compose_data_line( &rawdata[0], &compdata[0] ); + + std::fputs( &compdata[0], f ); + old_value = object; +} + +void +vcd_sc_fxnum_fast_trace::set_width() +{ + bit_width = object.wl(); +} + + +/*****************************************************************************/ + +class vcd_unsigned_int_trace : public vcd_trace { +public: + vcd_unsigned_int_trace(const unsigned& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned& object; + unsigned old_value; + unsigned mask; +}; + + +vcd_unsigned_int_trace::vcd_unsigned_int_trace( + const unsigned& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value( object_ ), + mask((unsigned)-1) +{ + bit_width = width_; + if (bit_width < 32) mask = ~(-1 << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool +vcd_unsigned_int_trace::changed() +{ + return object != old_value; +} + + +void +vcd_unsigned_int_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_unsigned_short_trace : public vcd_trace { +public: + vcd_unsigned_short_trace(const unsigned short& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned short& object; + unsigned short old_value; + unsigned short mask; +}; + + +vcd_unsigned_short_trace::vcd_unsigned_short_trace( + const unsigned short& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xffff) +{ + bit_width = width_; + if (bit_width < 16) mask = (unsigned short)~(-1 << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool +vcd_unsigned_short_trace::changed() +{ + return object != old_value; +} + + +void +vcd_unsigned_short_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_unsigned_char_trace : public vcd_trace { +public: + vcd_unsigned_char_trace(const unsigned char& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned char& object; + unsigned char old_value; + unsigned char mask; +}; + + +vcd_unsigned_char_trace::vcd_unsigned_char_trace( + const unsigned char& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xff) +{ + bit_width = width_; + if (bit_width < 8) mask = (unsigned char)~(-1 << bit_width); + vcd_var_typ_name = "wire"; +} + + +bool vcd_unsigned_char_trace::changed() +{ + return object != old_value; +} + + +void vcd_unsigned_char_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_unsigned_long_trace : public vcd_trace { +public: + vcd_unsigned_long_trace(const unsigned long& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned long& object; + unsigned long old_value; + unsigned long mask; +}; + + +vcd_unsigned_long_trace::vcd_unsigned_long_trace( + const unsigned long& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask((unsigned long)-1) +{ + bit_width = width_; + if ( bit_width < (int)(sizeof(unsigned long)*8) ) + mask = ~(-1L << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool vcd_unsigned_long_trace::changed() +{ + return object != old_value; +} + + +void vcd_unsigned_long_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned long bit_mask = 1ul << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_signed_int_trace : public vcd_trace { +public: + vcd_signed_int_trace(const int& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const int& object; + int old_value; + unsigned mask; +}; + + +vcd_signed_int_trace::vcd_signed_int_trace(const signed& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask((unsigned)-1) +{ + bit_width = width_; + if (bit_width < 32) mask = ~(-1 << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool vcd_signed_int_trace::changed() +{ + return object != old_value; +} + + +void vcd_signed_int_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if (((unsigned) object & mask) != (unsigned) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_signed_short_trace : public vcd_trace { +public: + vcd_signed_short_trace(const short& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const short& object; + short old_value; + unsigned short mask; +}; + + +vcd_signed_short_trace::vcd_signed_short_trace( + const short& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xffff) +{ + bit_width = width_; + if (bit_width < 16) mask = (unsigned short)~(-1 << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool vcd_signed_short_trace::changed() +{ + return object != old_value; +} + + +void vcd_signed_short_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if (((unsigned short) object & mask) != (unsigned short) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_signed_char_trace : public vcd_trace { +public: + vcd_signed_char_trace(const char& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const char& object; + char old_value; + unsigned char mask; +}; + + +vcd_signed_char_trace::vcd_signed_char_trace(const char& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xff) +{ + bit_width = width_; + if (bit_width < 8) mask = (unsigned char)~(-1 << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool vcd_signed_char_trace::changed() +{ + return object != old_value; +} + + +void vcd_signed_char_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if (((unsigned char) object & mask) != (unsigned char) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_int64_trace : public vcd_trace { +public: + vcd_int64_trace(const sc_dt::int64& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::int64& object; + sc_dt::int64 old_value; + sc_dt::uint64 mask; +}; + + +vcd_int64_trace::vcd_int64_trace(const sc_dt::int64& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask((sc_dt::uint64)-1) +{ + bit_width = width_; + if (bit_width < 64) mask = ~(mask << bit_width); + vcd_var_typ_name = "wire"; +} + + +bool vcd_int64_trace::changed() +{ + return object != old_value; +} + + +void vcd_int64_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if (((sc_dt::uint64) object & mask) != (sc_dt::uint64) object) + { + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + rawdata[bitindex] = 'x'; + } + } + else + { + sc_dt::uint64 bit_mask = 1; + bit_mask = bit_mask << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + + +/*****************************************************************************/ + +class vcd_uint64_trace : public vcd_trace { +public: + vcd_uint64_trace(const sc_dt::uint64& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::uint64& object; + sc_dt::uint64 old_value; + sc_dt::uint64 mask; +}; + + +vcd_uint64_trace::vcd_uint64_trace( const sc_dt::uint64& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask((sc_dt::uint64)-1) +{ + bit_width = width_; + if ( bit_width < 64 ) mask = ~(mask << bit_width); + vcd_var_typ_name = "wire"; +} + + +bool vcd_uint64_trace::changed() +{ + return object != old_value; +} + + +void vcd_uint64_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) + { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else + { + sc_dt::uint64 bit_mask = 1; + bit_mask = bit_mask << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + + +/*****************************************************************************/ + +class vcd_signed_long_trace : public vcd_trace { +public: + vcd_signed_long_trace(const long& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const long& object; + long old_value; + unsigned long mask; +}; + + +vcd_signed_long_trace::vcd_signed_long_trace(const long& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask((unsigned long)-1) +{ + bit_width = width_; + if ( bit_width < (int)(sizeof(long)*8) ) + mask = ~(-1L << bit_width); + vcd_var_typ_name = "wire"; +} + + +bool vcd_signed_long_trace::changed() +{ + return object != old_value; +} + + +void vcd_signed_long_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if (((unsigned long) object & mask) != (unsigned long) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned long bit_mask = 1ul << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + + +/*****************************************************************************/ + +class vcd_float_trace : public vcd_trace { +public: + vcd_float_trace(const float& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + +protected: + const float& object; + float old_value; +}; + +vcd_float_trace::vcd_float_trace(const float& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_) +{ + vcd_var_typ_name = "real"; + bit_width = 1; + old_value = object; +} + +bool vcd_float_trace::changed() +{ + return object != old_value; +} + +void vcd_float_trace::write(FILE* f) +{ + std::fprintf(f, "r%.16g %s", object, vcd_name.c_str()); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_double_trace : public vcd_trace { +public: + vcd_double_trace(const double& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + +protected: + const double& object; + double old_value; +}; + +vcd_double_trace::vcd_double_trace(const double& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_) +{ + vcd_var_typ_name = "real"; + bit_width = 1; +} + +bool vcd_double_trace::changed() +{ + return object != old_value; +} + +void vcd_double_trace::write(FILE* f) +{ + std::fprintf(f, "r%.16g %s", object, vcd_name.c_str()); + old_value = object; +} + + +/*****************************************************************************/ + +class vcd_enum_trace : public vcd_trace { +public: + vcd_enum_trace(const unsigned& object_, + const std::string& name_, + const std::string& vcd_name_, + const char** enum_literals); + void write(FILE* f); + bool changed(); + +protected: + const unsigned& object; + unsigned old_value; + unsigned mask; + const char** literals; + unsigned nliterals; +}; + + +vcd_enum_trace::vcd_enum_trace(const unsigned& object_, + const std::string& name_, + const std::string& vcd_name_, + const char** enum_literals_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask(0xffffffff), literals(enum_literals_), nliterals(0) +{ + // find number of bits required to represent enumeration literal - counting loop + for (nliterals = 0; enum_literals_[nliterals]; nliterals++) continue; + + // Figure out number of bits required to represent the number of literals + bit_width = 0; + unsigned shifted_maxindex = nliterals-1; + while(shifted_maxindex != 0){ + shifted_maxindex >>= 1; + bit_width++; + } + + // Set the mask + if (bit_width < 32) { + mask = ~(-1 << bit_width); + } else { + mask = 0xffffffff; + } + + vcd_var_typ_name = "wire"; +} + +bool vcd_enum_trace::changed() +{ + return object != old_value; +} + +void vcd_enum_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } else { + unsigned long bit_mask = 1ul << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + + +/***************************************************************************** + vcd_trace_file functions + *****************************************************************************/ + +vcd_trace_file::vcd_trace_file(const char *name) + : sc_trace_file_base( name, "vcd" ) + , vcd_name_index(0) + , previous_time_units_low(0) + , previous_time_units_high(0) + , traces() +{} + + +void +vcd_trace_file::do_initialize() +{ + char buf[2000]; + + //date: + std::fprintf(fp, "$date\n %s\n$end\n\n", localtime_string().c_str() ); + + //version: + std::fprintf(fp, "$version\n %s\n$end\n\n", sc_version()); + + //timescale: + static struct SC_TIMESCALE_TO_TEXT { + double unit; + const char* text; + } timescale_to_text [] = { + { sc_time(1, SC_FS).to_seconds(), "1 fs" }, + { sc_time(10, SC_FS).to_seconds(), "10 fs" }, + { sc_time(100, SC_FS).to_seconds(),"100 fs" }, + { sc_time(1, SC_PS).to_seconds(), "1 ps" }, + { sc_time(10, SC_PS).to_seconds(), "10 ps" }, + { sc_time(100, SC_PS).to_seconds(),"100 ps" }, + { sc_time(1, SC_NS).to_seconds(), "1 ns" }, + { sc_time(10, SC_NS).to_seconds(), "10 ns" }, + { sc_time(100, SC_NS).to_seconds(),"100 ns" }, + { sc_time(1, SC_US).to_seconds(), "1 us" }, + { sc_time(10, SC_US).to_seconds(), "10 us" }, + { sc_time(100, SC_US).to_seconds(),"100 us" }, + { sc_time(1, SC_MS).to_seconds(), "1 ms" }, + { sc_time(10, SC_MS).to_seconds(), "10 ms" }, + { sc_time(100, SC_MS).to_seconds(),"100 ms" }, + { sc_time(1, SC_SEC).to_seconds(), "1 sec" }, + { sc_time(10, SC_SEC).to_seconds(), "10 sec" }, + { sc_time(100, SC_SEC).to_seconds(),"100 sec" } + }; + static int timescale_to_text_n = + sizeof(timescale_to_text)/sizeof(SC_TIMESCALE_TO_TEXT); + + for ( int time_i = 0; time_i < timescale_to_text_n; time_i++ ) + { + if (timescale_unit == timescale_to_text[time_i].unit) + { + std::fprintf(fp,"$timescale\n %s\n$end\n\n", + timescale_to_text[time_i].text); + break; + } + } + + // Create a dummy scope + std::fputs("$scope module SystemC $end\n", fp); + + //variable definitions: + for (int i = 0; i < (int)traces.size(); i++) { + vcd_trace* t = traces[i]; + t->set_width(); // needed for all vectors + t->print_variable_declaration_line(fp); + } + + std::fputs("$upscope $end\n", fp); + + std::fputs("$enddefinitions $end\n\n", fp); + + // double inittime = sc_simulation_time(); + double inittime = sc_time_stamp().to_seconds(); + + std::sprintf(buf, + "All initial values are dumped below at time " + "%g sec = %g timescale units.", + inittime, inittime/timescale_unit + ); + write_comment(buf); + + double_to_special_int64(inittime/timescale_unit, + &previous_time_units_high, + &previous_time_units_low ); + + + std::fputs("$dumpvars\n",fp); + for (int i = 0; i < (int)traces.size(); i++) { + traces[i]->write(fp); + std::fputc('\n', fp); + } + std::fputs("$end\n\n", fp); +} + + +// ---------------------------------------------------------------------------- + +#define DEFN_TRACE_METHOD(tp) \ +void \ +vcd_trace_file::trace(const tp& object_, const std::string& name_) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new vcd_ ## tp ## _trace( object_, \ + name_, \ + obtain_name() ) ); \ +} + +DEFN_TRACE_METHOD(bool) +DEFN_TRACE_METHOD(float) +DEFN_TRACE_METHOD(double) + +#undef DEFN_TRACE_METHOD +#define DEFN_TRACE_METHOD(tp) \ +void \ +vcd_trace_file::trace(const sc_dt::tp& object_, const std::string& name_) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new vcd_ ## tp ## _trace( object_, \ + name_, \ + obtain_name() ) ); \ +} + +DEFN_TRACE_METHOD(sc_bit) +DEFN_TRACE_METHOD(sc_logic) + +DEFN_TRACE_METHOD(sc_signed) +DEFN_TRACE_METHOD(sc_unsigned) +DEFN_TRACE_METHOD(sc_int_base) +DEFN_TRACE_METHOD(sc_uint_base) + +DEFN_TRACE_METHOD(sc_fxval) +DEFN_TRACE_METHOD(sc_fxval_fast) +DEFN_TRACE_METHOD(sc_fxnum) +DEFN_TRACE_METHOD(sc_fxnum_fast) + +#undef DEFN_TRACE_METHOD + + +#define DEFN_TRACE_METHOD_SIGNED(tp) \ +void \ +vcd_trace_file::trace( const tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new vcd_signed_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +#define DEFN_TRACE_METHOD_UNSIGNED(tp) \ +void \ +vcd_trace_file::trace( const unsigned tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new vcd_unsigned_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +DEFN_TRACE_METHOD_SIGNED(char) +DEFN_TRACE_METHOD_SIGNED(short) +DEFN_TRACE_METHOD_SIGNED(int) +DEFN_TRACE_METHOD_SIGNED(long) + +DEFN_TRACE_METHOD_UNSIGNED(char) +DEFN_TRACE_METHOD_UNSIGNED(short) +DEFN_TRACE_METHOD_UNSIGNED(int) +DEFN_TRACE_METHOD_UNSIGNED(long) + +#undef DEFN_TRACE_METHOD_SIGNED +#undef DEFN_TRACE_METHOD_UNSIGNED + +#define DEFN_TRACE_METHOD_LONG_LONG(tp) \ +void \ +vcd_trace_file::trace( const sc_dt::tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new vcd_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +DEFN_TRACE_METHOD_LONG_LONG(int64) +DEFN_TRACE_METHOD_LONG_LONG(uint64) + +#undef DEFN_TRACE_METHOD_LONG_LONG + +void +vcd_trace_file::trace( const unsigned& object_, + const std::string& name_, + const char** enum_literals_ ) +{ + if( add_trace_check(name_) ) + traces.push_back( new vcd_enum_trace( object_, + name_, + obtain_name(), + enum_literals_ ) ); +} + + +void +vcd_trace_file::write_comment(const std::string& comment) +{ + if(!fp) open_fp(); + //no newline in comments allowed, as some viewers may crash + std::fputs("$comment\n", fp); + std::fputs(comment.c_str(), fp); + std::fputs("\n$end\n\n", fp); +} + +void +vcd_trace_file::cycle(bool this_is_a_delta_cycle) +{ + unsigned this_time_units_high, this_time_units_low; + + // Just to make g++ shut up in the optimized mode + this_time_units_high = this_time_units_low = 0; + + // Trace delta cycles only when enabled + if (!delta_cycles() && this_is_a_delta_cycle) return; + + // Check for initialization + if( initialize() ) { + return; + }; + + + double now_units = sc_time_stamp().to_seconds() / timescale_unit; + unsigned now_units_high, now_units_low; + double_to_special_int64(now_units, &now_units_high, &now_units_low ); + + bool now_later_than_previous_time = false; + if( (now_units_low > previous_time_units_low + && now_units_high == previous_time_units_high) + || now_units_high > previous_time_units_high){ + now_later_than_previous_time = true; + } + + bool now_equals_previous_time = false; + if(now_later_than_previous_time){ + this_time_units_high = now_units_high; + this_time_units_low = now_units_low; + } else { + if( now_units_low == previous_time_units_low + && now_units_high == previous_time_units_high){ + now_equals_previous_time = true; + this_time_units_high = now_units_high; + this_time_units_low = now_units_low; + } + } + + // Since VCD does not understand 0 time progression, we have to fake + // delta cycles with progressing time by one unit + if(this_is_a_delta_cycle){ + this_time_units_high = previous_time_units_high; + this_time_units_low = previous_time_units_low + 1; + if(this_time_units_low == 1000000000){ + this_time_units_high++; + this_time_units_low=0; + } + static bool warned = false; + if(!warned){ + SC_REPORT_INFO( SC_ID_TRACING_VCD_DELTA_CYCLE_ + , sc_time( timescale_unit, SC_SEC ) + .to_string().c_str() ); + warned = true; + } + } + + + // Not a delta cycle and time has not progressed + if( ! this_is_a_delta_cycle && now_equals_previous_time && + ( now_units_high != 0 || now_units_low != 0 ) ) { + // Don't print the message at time zero + static bool warned = false; + if( ! warned ) { + std::stringstream ss; + ss << "units count: " << now_units_low << "\n" + "\tWaveform viewers will only show the states of the last one.\n" + "\tUse `tracefile->set_time_unit(double, sc_time_unit);'" + " to increase the time resolution."; + SC_REPORT_WARNING( SC_ID_TRACING_VCD_DUPLICATE_TIME_ + , ss.str().c_str() ); + // warned = true; + } + } + + // Not a delta cycle and time has gone backward + // This will happen with large number of delta cycles between two real + // advances of time + if(!this_is_a_delta_cycle && !now_equals_previous_time && + !now_later_than_previous_time){ + static bool warned = false; + if(!warned) { + std::stringstream ss; + ss << "units count (" + << previous_time_units_low << "->" << now_units_low << ")\n" + "\tThis can occur when delta cycling is activated." + " Cycles with falling time are not shown.\n" + "\tUse `tracefile->set_time_unit(double, sc_time_unit);'" + " to increase the time resolution."; + SC_REPORT_WARNING( SC_ID_TRACING_VCD_DUPLICATE_TIME_ + , ss.str().c_str() ); + // warned = true; + } + // Note that we don't set this_time_units_high/low to any value only + // in this case because we are not going to do any tracing. In the + // optimized mode, the compiler complains because of this. Therefore, + // we include the lines at the very beginning of this function to make + // the compiler shut up. + return; + } + + // Now do the actual printing + bool time_printed = false; + vcd_trace* const* const l_traces = &traces[0]; + for (int i = 0; i < (int)traces.size(); i++) { + vcd_trace* t = l_traces[i]; + if(t->changed()){ + if(time_printed == false){ + char buf[200]; + if(this_time_units_high){ + std::sprintf(buf, "#%u%09u", this_time_units_high, this_time_units_low); + } + else{ + std::sprintf(buf, "#%u", this_time_units_low); + } + std::fputs(buf, fp); + std::fputc('\n', fp); + time_printed = true; + } + + // Write the variable + t->write(fp); + std::fputc('\n', fp); + } + } + // Put another newline after all values are printed + if(time_printed) std::fputc('\n', fp); + + if(time_printed){ + // We update previous_time_units only when we print time because + // this field stores the previous time that was printed, not the + // previous time this function was called + previous_time_units_high = this_time_units_high; + previous_time_units_low = this_time_units_low; + } +} + +#if 0 +void +vcd_trace_file::create_vcd_name(std::string* p_destination) +{ + obtain_name.swap( *p_destination ); +} +#endif + +// Create a VCD name for a variable +std::string +vcd_trace_file::obtain_name() +{ + const char first_type_used = 'a'; + const int used_types_count = 'z' - 'a' + 1; + int result; + + result = vcd_name_index; + char char6 = (char)(vcd_name_index % used_types_count); + + result = result / used_types_count; + char char5 = (char)(result % used_types_count); + + result = result / used_types_count; + char char4 = (char)(result % used_types_count); + + result = result / used_types_count; + char char3 = (char)(result % used_types_count); + + result = result / used_types_count; + char char2 = (char)(result % used_types_count); + + char buf[20]; + std::sprintf(buf, "%c%c%c%c%c", + char2 + first_type_used, + char3 + first_type_used, + char4 + first_type_used, + char5 + first_type_used, + char6 + first_type_used); + vcd_name_index++; + return std::string(buf); +} + +vcd_trace_file::~vcd_trace_file() +{ + for( int i = 0; i < (int)traces.size(); i++ ) { + vcd_trace* t = traces[i]; + delete t; + } +} + + +// Functions specific to VCD tracing + +static char +map_sc_logic_state_to_vcd_state(char in_char) +{ + char out_char; + + switch(in_char){ + case 'U': + case 'X': + case 'W': + case 'D': + out_char = 'x'; + break; + case '0': + case 'L': + out_char = '0'; + break; + case '1': + case 'H': + out_char = '1'; + break; + case 'Z': + out_char = 'z'; + break; + default: + out_char = '?'; + } + + return out_char; +} + + + + +static +void +remove_vcd_name_problems(vcd_trace const* vcd, std::string& name) +{ + static bool warned = false; + bool braces_removed = false; + for (unsigned int i = 0; i< name.length(); i++) { + if (name[i] == '[') { + name[i] = '('; + braces_removed = true; + } + else if (name[i] == ']') { + name[i] = ')'; + braces_removed = true; + } + } + + if(braces_removed && !warned){ + std::stringstream ss; + ss << vcd->name << ":\n" + "\tTraced objects found with name containing [], which may be\n" + "\tinterpreted by the waveform viewer in unexpected ways.\n" + "\tSo the [] is automatically replaced by ()."; + + SC_REPORT_WARNING( SC_ID_TRACING_OBJECT_NAME_FILTERED_ + , ss.str().c_str() ); + } +} + +// ---------------------------------------------------------------------------- + +sc_trace_file* +sc_create_vcd_trace_file(const char * name) +{ + sc_trace_file * tf = new vcd_trace_file(name); + return tf; +} + +void +sc_close_vcd_trace_file( sc_trace_file* tf ) +{ + vcd_trace_file* vcd_tf = static_cast<vcd_trace_file*>(tf); + delete vcd_tf; +} + +} // namespace sc_core diff --git a/ext/systemc/src/sysc/tracing/sc_vcd_trace.h b/ext/systemc/src/sysc/tracing/sc_vcd_trace.h new file mode 100644 index 000000000..760949ffb --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_vcd_trace.h @@ -0,0 +1,228 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_vcd_trace.h - Implementation of VCD tracing. + + Original Author - Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. The + contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + +#ifndef SC_VCD_TRACE_H +#define SC_VCD_TRACE_H + +#include "sysc/tracing/sc_trace_file_base.h" + +namespace sc_core { + +class vcd_trace; // defined in vcd_trace.cpp +template<class T> class vcd_T_trace; + + +// ---------------------------------------------------------------------------- +// CLASS : vcd_trace_file +// +// ... +// ---------------------------------------------------------------------------- + +class vcd_trace_file + : public sc_trace_file_base +{ +public: + + enum vcd_enum {VCD_WIRE=0, VCD_REAL=1, VCD_LAST}; + + // sc_set_vcd_time_unit is deprecated. +#if 0 // deprecated + inline void sc_set_vcd_time_unit(int exponent10_seconds) + { set_time_unit(exponent10_seconds); } +#endif + + // Create a Vcd trace file. + // `Name' forms the base of the name to which `.vcd' is added. + vcd_trace_file(const char *name); + + // Flush results and close file. + ~vcd_trace_file(); + +protected: + + // These are all virtual functions in sc_trace_file and + // they need to be defined here. + + // Trace a boolean object (single bit) + void trace(const bool& object, const std::string& name); + + // Trace a sc_bit object (single bit) + virtual void trace( const sc_dt::sc_bit& object, + const std::string& name); + + // Trace a sc_logic object (single bit) + void trace(const sc_dt::sc_logic& object, const std::string& name); + + // Trace an unsigned char with the given width + void trace(const unsigned char& object, const std::string& name, + int width); + + // Trace an unsigned short with the given width + void trace(const unsigned short& object, const std::string& name, + int width); + + // Trace an unsigned int with the given width + void trace(const unsigned int& object, const std::string& name, + int width); + + // Trace an unsigned long with the given width + void trace(const unsigned long& object, const std::string& name, + int width); + + // Trace a signed char with the given width + void trace(const char& object, const std::string& name, int width); + + // Trace a signed short with the given width + void trace(const short& object, const std::string& name, int width); + + // Trace a signed int with the given width + void trace(const int& object, const std::string& name, int width); + + // Trace a signed long with the given width + void trace(const long& object, const std::string& name, int width); + + // Trace an int64 with a given width + void trace(const sc_dt::int64& object, const std::string& name, + int width); + + // Trace a uint64 with a given width + void trace(const sc_dt::uint64& object, const std::string& name, + int width); + + // Trace a float + void trace(const float& object, const std::string& name); + + // Trace a double + void trace(const double& object, const std::string& name); + + // Trace sc_dt::sc_uint_base + void trace (const sc_dt::sc_uint_base& object, + const std::string& name); + + // Trace sc_dt::sc_int_base + void trace (const sc_dt::sc_int_base& object, + const std::string& name); + + // Trace sc_dt::sc_unsigned + void trace (const sc_dt::sc_unsigned& object, + const std::string& name); + + // Trace sc_dt::sc_signed + void trace (const sc_dt::sc_signed& object, const std::string& name); + + // Trace sc_dt::sc_fxval + void trace( const sc_dt::sc_fxval& object, const std::string& name ); + + // Trace sc_dt::sc_fxval_fast + void trace( const sc_dt::sc_fxval_fast& object, + const std::string& name ); + + // Trace sc_dt::sc_fxnum + void trace( const sc_dt::sc_fxnum& object, const std::string& name ); + + // Trace sc_dt::sc_fxnum_fast + void trace( const sc_dt::sc_fxnum_fast& object, + const std::string& name ); + + template<class T> + void traceT(const T& object, const std::string& name, + vcd_enum type=VCD_WIRE) + { + if( add_trace_check(name) ) + traces.push_back(new vcd_T_trace<T>( object, name + , obtain_name(),type) ); + } + + // Trace sc_dt::sc_bv_base (sc_dt::sc_bv) + virtual void trace(const sc_dt::sc_bv_base& object, + const std::string& name); + + // Trace sc_dt::sc_lv_base (sc_dt::sc_lv) + virtual void trace(const sc_dt::sc_lv_base& object, + const std::string& name); + // Trace an enumerated object - where possible output the enumeration literals + // in the trace file. Enum literals is a null terminated array of null + // terminated char* literal strings. + void trace(const unsigned& object, const std::string& name, + const char** enum_literals); + + // Output a comment to the trace file + void write_comment(const std::string& comment); + + // Write trace info for cycle. + void cycle(bool delta_cycle); + +private: + +#if SC_TRACING_PHASE_CALLBACKS_ + // avoid hidden overload warnings + virtual void trace( sc_trace_file* ) const { sc_assert(false); } +#endif // SC_TRACING_PHASE_CALLBACKS_ + + // Initialize the VCD tracing + virtual void do_initialize(); + + unsigned vcd_name_index; // Number of variables traced + + unsigned previous_time_units_low; // Previous time unit as 64-bit integer + unsigned previous_time_units_high; + +public: + + // Array to store the variables traced + std::vector<vcd_trace*> traces; + + // Create VCD names for each variable + std::string obtain_name(); + +}; + +} // namespace sc_core + +#endif // SC_VCD_TRACE_H +// Taf! diff --git a/ext/systemc/src/sysc/tracing/sc_wif_trace.cpp b/ext/systemc/src/sysc/tracing/sc_wif_trace.cpp new file mode 100644 index 000000000..b2bacee7d --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_wif_trace.cpp @@ -0,0 +1,1911 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_wif_trace.cpp - Implementation of WIF tracing. + + Original Author - Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Replaced 'width' of sc_(u)int with their + 'bitwidth()'. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. The + contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + +/***************************************************************************** + + Instead of creating the binary WIF format, we create the ASCII + WIF format which can be converted to the binary format using + a2wif (utility that comes with VSS from Synopsys). This way, + a user who does not have Synopsys VSS can still create WIF + files, but they can only be viewed by users who have VSS. + + *****************************************************************************/ + + +#include <cstdlib> +#include <vector> + +#define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_ver.h" +#include "sysc/datatypes/bit/sc_bit.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/fx/fx.h" +#include "sysc/tracing/sc_wif_trace.h" + +namespace sc_core { + +// Forward declarations for functions that come later in the file +static char map_sc_logic_state_to_wif_state(char in_char); + +const char* wif_names[wif_trace_file::WIF_LAST] = {"BIT","MVL","real"}; + + +// ---------------------------------------------------------------------------- +// CLASS : wif_trace +// +// Base class for WIF traces. +// ---------------------------------------------------------------------------- + +class wif_trace +{ +public: + + wif_trace(const std::string& name_, const std::string& wif_name_); + + // Needs to be pure virtual as has to be defined by the particular + // type being traced + virtual void write(FILE* f) = 0; + + virtual void set_width(); + + // Comparison function needs to be pure virtual too + virtual bool changed() = 0; + + // Got to declare this virtual as this will be overwritten + // by one base class + virtual void print_variable_declaration_line(FILE* f); + + virtual ~wif_trace(); + + const std::string name; // Name of the variable + const std::string wif_name; // Name of the variable in WIF file + const char* wif_type; // WIF data type + int bit_width; +}; + + +wif_trace::wif_trace(const std::string& name_, + const std::string& wif_name_) + : name(name_), wif_name(wif_name_), wif_type(0), bit_width(-1) +{ + /* Intentionally blank */ +} + +void +wif_trace::print_variable_declaration_line( FILE* f ) +{ + if( bit_width < 0 ) + { + std::stringstream ss; + ss << "'" << name << "' has < 0 bits"; + SC_REPORT_ERROR( SC_ID_TRACING_OBJECT_IGNORED_ + , ss.str().c_str() ); + return; + } + + std::fprintf( f, "declare %s \"%s\" %s ", + wif_name.c_str(), name.c_str(), wif_type ); + + if( bit_width > 0 ) { + std::fprintf( f, "0 %d ", bit_width - 1 ); + } + std::fprintf( f, "variable ;\n" ); + std::fprintf( f, "start_trace %s ;\n", wif_name.c_str() ); +} + +void +wif_trace::set_width() +{ + /* Intentionally Blank, should be defined for each type separately */ +} + +wif_trace::~wif_trace() +{ + /* Intentionally Blank */ +} + +// Classes for tracing individual data types + +/*****************************************************************************/ + +class wif_uint64_trace: public wif_trace { +public: + wif_uint64_trace(const sc_dt::uint64& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::uint64& object; + sc_dt::uint64 old_value; + sc_dt::uint64 mask; +}; + + +wif_uint64_trace::wif_uint64_trace(const sc_dt::uint64& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask(static_cast<sc_dt::uint64>(-1)) +{ + bit_width = width_; + if (bit_width < (int)(sizeof(sc_dt::uint64)*BITS_PER_BYTE)) + mask = ~(mask << bit_width); + wif_type = "BIT"; +} + + +bool wif_uint64_trace::changed() +{ + return object != old_value; +} + + +void wif_uint64_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) + { + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + buf[bitindex]='0'; + } + } + else + { + sc_dt::uint64 bit_mask = 1; + bit_mask = bit_mask << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_int64_trace: public wif_trace { +public: + wif_int64_trace(const sc_dt::int64& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::int64& object; + sc_dt::int64 old_value; + sc_dt::uint64 mask; +}; + + +wif_int64_trace::wif_int64_trace(const sc_dt::int64& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask(static_cast<sc_dt::uint64>(-1)) +{ + bit_width = width_; + if (bit_width < (int)(sizeof(sc_dt::int64)*BITS_PER_BYTE)) + mask = ~(mask << bit_width); + wif_type = "BIT"; +} + + +bool wif_int64_trace::changed() +{ + return object != old_value; +} + + +void wif_int64_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != (sc_dt::uint64)object) + { + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + buf[bitindex]='0'; + } + } + else + { + sc_dt::uint64 bit_mask = 1; + bit_mask = bit_mask << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_bool_trace +: public wif_trace +{ +public: + + wif_bool_trace( const bool& object_, + const std::string& name_, + const std::string& wif_name_ ); + void write( FILE* f ); + bool changed(); + +protected: + + const bool& object; + bool old_value; +}; + +wif_bool_trace::wif_bool_trace( const bool& object_, + const std::string& name_, + const std::string& wif_name_ ) +: wif_trace( name_, wif_name_ ), object( object_ ), old_value( object_ ) +{ + bit_width = 0; + wif_type = "BIT"; +} + +bool +wif_bool_trace::changed() +{ + return object != old_value; +} + +void +wif_bool_trace::write( FILE* f ) +{ + if( object == true ) { + std::fprintf( f, "assign %s \'1\' ;\n", wif_name.c_str() ); + } else { + std::fprintf( f, "assign %s \'0\' ;\n", wif_name.c_str() ); + } + old_value = object; +} + +//***************************************************************************** + +class wif_sc_bit_trace : public wif_trace { +public: + wif_sc_bit_trace(const sc_dt::sc_bit& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::sc_bit& object; + sc_dt::sc_bit old_value; +}; + +wif_sc_bit_trace::wif_sc_bit_trace(const sc_dt::sc_bit& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_) +{ + bit_width = 0; + wif_type = "BIT"; +} + +bool wif_sc_bit_trace::changed() +{ + return object != old_value; +} + +void wif_sc_bit_trace::write(FILE* f) +{ + if (object == true) { + std::fprintf(f, "assign %s \'1\' ;\n", wif_name.c_str()); + } else { + std::fprintf(f, "assign %s \'0\' ;\n", wif_name.c_str()); + } + old_value = object; +} + +/*****************************************************************************/ + +class wif_sc_logic_trace: public wif_trace { +public: + wif_sc_logic_trace(const sc_dt::sc_logic& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::sc_logic& object; + sc_dt::sc_logic old_value; +}; + + +wif_sc_logic_trace::wif_sc_logic_trace(const sc_dt::sc_logic& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_) +{ + bit_width = 0; + wif_type = "MVL"; +} + + +bool wif_sc_logic_trace::changed() +{ + return object != old_value; +} + + +void wif_sc_logic_trace::write(FILE* f) +{ + char wif_char; + std::fprintf(f, "assign %s \'", wif_name.c_str()); + wif_char = map_sc_logic_state_to_wif_state(object.to_char()); + std::fputc(wif_char, f); + std::fprintf(f,"\' ;\n"); + old_value = object; +} + + +/*****************************************************************************/ + +class wif_sc_unsigned_trace: public wif_trace { +public: + wif_sc_unsigned_trace(const sc_dt::sc_unsigned& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_unsigned& object; + sc_dt::sc_unsigned old_value; +}; + + +wif_sc_unsigned_trace::wif_sc_unsigned_trace(const sc_dt::sc_unsigned& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_.length()) +{ + old_value = object; + wif_type = "BIT"; +} + +bool wif_sc_unsigned_trace::changed() +{ + return object != old_value; +} + +void wif_sc_unsigned_trace::write(FILE* f) +{ + static std::vector<char> buf(1024); + typedef std::vector<char>::size_type size_t; + + if ( buf.size() < (size_t)object.length() ) { + size_t sz = ( (size_t)object.length() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( buf ); // resize without copying values + } + char *buf_ptr = &buf[0]; + + for(int bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *buf_ptr++ = "01"[object[bitindex].to_bool()]; + } + *buf_ptr = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), &buf[0]); + old_value = object; +} + +void wif_sc_unsigned_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class wif_sc_signed_trace: public wif_trace { +public: + wif_sc_signed_trace(const sc_dt::sc_signed& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_signed& object; + sc_dt::sc_signed old_value; +}; + + +wif_sc_signed_trace::wif_sc_signed_trace(const sc_dt::sc_signed& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_.length()) +{ + old_value = object; + wif_type = "BIT"; +} + +bool wif_sc_signed_trace::changed() +{ + return object != old_value; +} + +void wif_sc_signed_trace::write(FILE* f) +{ + static std::vector<char> buf(1024); + typedef std::vector<char>::size_type size_t; + + if ( buf.size() < (size_t)object.length() ) { + size_t sz = ( (size_t)object.length() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( buf ); // resize without copying values + } + char *buf_ptr = &buf[0]; + + for(int bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *buf_ptr++ = "01"[object[bitindex].to_bool()]; + } + *buf_ptr = '\0'; + + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), &buf[0]); + old_value = object; +} + +void wif_sc_signed_trace::set_width() +{ + bit_width = object.length(); +} + +/*****************************************************************************/ + +class wif_sc_uint_base_trace: public wif_trace { +public: + wif_sc_uint_base_trace(const sc_dt::sc_uint_base& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_uint_base& object; + sc_dt::sc_uint_base old_value; +}; + + +wif_sc_uint_base_trace::wif_sc_uint_base_trace( + const sc_dt::sc_uint_base& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_.length()) +{ + old_value = object; + wif_type = "BIT"; +} + +bool wif_sc_uint_base_trace::changed() +{ + return object != old_value; +} + +void wif_sc_uint_base_trace::write(FILE* f) +{ + char buf[1000], *buf_ptr = buf; + + int bitindex; + for(bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *buf_ptr++ = "01"[object[bitindex].to_bool()]; + } + *buf_ptr = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +void wif_sc_uint_base_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class wif_sc_int_base_trace: public wif_trace { +public: + wif_sc_int_base_trace(const sc_dt::sc_int_base& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_int_base& object; + sc_dt::sc_int_base old_value; +}; + + +wif_sc_int_base_trace::wif_sc_int_base_trace(const sc_dt::sc_int_base& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_.length()) +{ + old_value = object; + wif_type = "BIT"; +} + +bool wif_sc_int_base_trace::changed() +{ + return object != old_value; +} + +void wif_sc_int_base_trace::write(FILE* f) +{ + char buf[1000], *buf_ptr = buf; + + int bitindex; + for(bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *buf_ptr++ = "01"[object[bitindex].to_bool()]; + } + *buf_ptr = '\0'; + + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +void wif_sc_int_base_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class wif_sc_fxval_trace: public wif_trace +{ +public: + + wif_sc_fxval_trace( const sc_dt::sc_fxval& object_, + const std::string& name_, + const std::string& wif_name_ ); + void write( FILE* f ); + bool changed(); + +protected: + + const sc_dt::sc_fxval& object; + sc_dt::sc_fxval old_value; + +}; + +wif_sc_fxval_trace::wif_sc_fxval_trace( const sc_dt::sc_fxval& object_, + const std::string& name_, + const std::string& wif_name_ ) +: wif_trace( name_, wif_name_ ), object( object_ ), old_value( object_ ) +{ + bit_width = 0; + wif_type = "real"; +} + +bool +wif_sc_fxval_trace::changed() +{ + return object != old_value; +} + +void +wif_sc_fxval_trace::write( FILE* f ) +{ + std::fprintf( f, "assign %s %f ; \n", wif_name.c_str(), object.to_double() ); + old_value = object; +} + +/*****************************************************************************/ + +class wif_sc_fxval_fast_trace: public wif_trace +{ +public: + + wif_sc_fxval_fast_trace( const sc_dt::sc_fxval_fast& object_, + const std::string& name_, + const std::string& wif_name_ ); + void write( FILE* f ); + bool changed(); + +protected: + + const sc_dt::sc_fxval_fast& object; + sc_dt::sc_fxval_fast old_value; + +}; + +wif_sc_fxval_fast_trace::wif_sc_fxval_fast_trace( + const sc_dt::sc_fxval_fast& object_, + const std::string& name_, + const std::string& wif_name_ ) +: wif_trace(name_, wif_name_), object( object_ ), old_value( object_ ) +{ + bit_width = 0; + wif_type = "real"; +} + +bool +wif_sc_fxval_fast_trace::changed() +{ + return object != old_value; +} + +void +wif_sc_fxval_fast_trace::write( FILE* f ) +{ + std::fprintf( f, "assign %s %f ; \n", wif_name.c_str(), object.to_double() ); + old_value = object; +} + +/*****************************************************************************/ + +class wif_sc_fxnum_trace: public wif_trace +{ +public: + + wif_sc_fxnum_trace( const sc_dt::sc_fxnum& object_, + const std::string& name_, + const std::string& wif_name_ ); + void write( FILE* f ); + bool changed(); + void set_width(); + +protected: + + const sc_dt::sc_fxnum& object; + sc_dt::sc_fxnum old_value; + +}; + +wif_sc_fxnum_trace::wif_sc_fxnum_trace( const sc_dt::sc_fxnum& object_, + const std::string& name_, + const std::string& wif_name_ ) +: wif_trace( name_, wif_name_ ), + object( object_ ), + old_value( object_.m_params.type_params(), + object_.m_params.enc(), + object_.m_params.cast_switch(), + 0 ) +{ + old_value = object; + wif_type = "BIT"; +} + +bool +wif_sc_fxnum_trace::changed() +{ + return object != old_value; +} + +void +wif_sc_fxnum_trace::write( FILE* f ) +{ + static std::vector<char> buf(1024); + typedef std::vector<char>::size_type size_t; + + if ( buf.size() < (size_t)object.wl() ) { + size_t sz = ( (size_t)object.wl() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( buf ); // resize without copying values + } + char *buf_ptr = &buf[0]; + + for(int bitindex = object.wl() - 1; bitindex >= 0; --bitindex) + { + *buf_ptr ++ = "01"[object[bitindex]]; + } + *buf_ptr = '\0'; + + std::fprintf( f, "assign %s \"%s\" ;\n", wif_name.c_str(), &buf[0]); + old_value = object; +} + +void +wif_sc_fxnum_trace::set_width() +{ + bit_width = object.wl(); +} + +/*****************************************************************************/ + +class wif_sc_fxnum_fast_trace: public wif_trace +{ +public: + + wif_sc_fxnum_fast_trace( const sc_dt::sc_fxnum_fast& object_, + const std::string& name_, + const std::string& wif_name_ ); + void write( FILE* f ); + bool changed(); + void set_width(); + +protected: + + const sc_dt::sc_fxnum_fast& object; + sc_dt::sc_fxnum_fast old_value; + +}; + +wif_sc_fxnum_fast_trace::wif_sc_fxnum_fast_trace( + const sc_dt::sc_fxnum_fast& object_, + const std::string& name_, + const std::string& wif_name_ ) +: wif_trace( name_, wif_name_ ), + object( object_ ), + old_value( object_.m_params.type_params(), + object_.m_params.enc(), + object_.m_params.cast_switch(), + 0 ) +{ + old_value = object; + wif_type = "BIT"; +} + +bool +wif_sc_fxnum_fast_trace::changed() +{ + return object != old_value; +} + +void +wif_sc_fxnum_fast_trace::write( FILE* f ) +{ + static std::vector<char> buf(1024); + typedef std::vector<char>::size_type size_t; + + if ( buf.size() < (size_t)object.wl() ) { + size_t sz = ( (size_t)object.wl() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( buf ); // resize without copying values + } + char *buf_ptr = &buf[0]; + + for(int bitindex = object.wl() - 1; bitindex >= 0; --bitindex) + { + *buf_ptr ++ = "01"[object[bitindex]]; + } + *buf_ptr = '\0'; + + std::fprintf( f, "assign %s \"%s\" ;\n", wif_name.c_str(), &buf[0]); + old_value = object; +} + +void +wif_sc_fxnum_fast_trace::set_width() +{ + bit_width = object.wl(); +} + + +/*****************************************************************************/ + +class wif_unsigned_int_trace: public wif_trace { +public: + wif_unsigned_int_trace(const unsigned& object_, + const std::string& name_, + const std::string& wif_name_, int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned& object; + unsigned old_value; + unsigned mask; +}; + + +wif_unsigned_int_trace::wif_unsigned_int_trace(const unsigned& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask(0xffffffff) +{ + bit_width = width_; + if (bit_width < 32) { + mask = ~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_unsigned_int_trace::changed() +{ + return object != old_value; +} + + +void wif_unsigned_int_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex] = '0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + + +/*****************************************************************************/ + +class wif_unsigned_short_trace: public wif_trace { +public: + wif_unsigned_short_trace(const unsigned short& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned short& object; + unsigned short old_value; + unsigned short mask; +}; + + +wif_unsigned_short_trace::wif_unsigned_short_trace( + const unsigned short& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), mask(0xffff) +{ + bit_width = width_; + if (bit_width < 16) { + mask = (unsigned short)~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_unsigned_short_trace::changed() +{ + return object != old_value; +} + + +void wif_unsigned_short_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_unsigned_char_trace: public wif_trace { +public: + wif_unsigned_char_trace(const unsigned char& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned char& object; + unsigned char old_value; + unsigned char mask; +}; + + +wif_unsigned_char_trace::wif_unsigned_char_trace(const unsigned char& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), mask(0xff) +{ + bit_width = width_; + if (bit_width < 8) { + mask = (unsigned char)~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_unsigned_char_trace::changed() +{ + return object != old_value; +} + + +void wif_unsigned_char_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_unsigned_long_trace: public wif_trace { +public: + wif_unsigned_long_trace(const unsigned long& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned long& object; + unsigned long old_value; + unsigned long mask; +}; + + +wif_unsigned_long_trace::wif_unsigned_long_trace(const unsigned long& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask((unsigned long)-1L) +{ + bit_width = width_; + if (bit_width < (int)(sizeof(unsigned long)*BITS_PER_BYTE)) { + mask = ~(-1L << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_unsigned_long_trace::changed() +{ + return object != old_value; +} + + +void wif_unsigned_long_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned long bit_mask = 1ul << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_signed_int_trace: public wif_trace { +public: + wif_signed_int_trace(const int& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const int& object; + int old_value; + unsigned mask; +}; + + +wif_signed_int_trace::wif_signed_int_trace(const signed& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask(0xffffffff) +{ + bit_width = width_; + if (bit_width < 32) { + mask = ~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_signed_int_trace::changed() +{ + return object != old_value; +} + + +void wif_signed_int_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if (((unsigned) object & mask) != (unsigned) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_signed_short_trace: public wif_trace { +public: + wif_signed_short_trace(const short& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const short& object; + short old_value; + unsigned short mask; +}; + + +wif_signed_short_trace::wif_signed_short_trace(const short& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), mask(0xffff) +{ + bit_width = width_; + if (bit_width < 16) { + mask = (unsigned short)~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_signed_short_trace::changed() +{ + return object != old_value; +} + + +void wif_signed_short_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if (((unsigned short) object & mask) != (unsigned short) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_signed_char_trace: public wif_trace { +public: + wif_signed_char_trace(const char& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const char& object; + char old_value; + unsigned char mask; +}; + + +wif_signed_char_trace::wif_signed_char_trace(const char& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), mask(0xff) +{ + bit_width = width_; + if (bit_width < 8) { + mask = (unsigned char)~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_signed_char_trace::changed() +{ + return object != old_value; +} + + +void wif_signed_char_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if (((unsigned char) object & mask) != (unsigned char) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_signed_long_trace: public wif_trace { +public: + wif_signed_long_trace(const long& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const long& object; + long old_value; + unsigned long mask; +}; + + +wif_signed_long_trace::wif_signed_long_trace(const long& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask((unsigned long)-1L) +{ + bit_width = width_; + if (bit_width < (int)(sizeof(long)*BITS_PER_BYTE)) { + mask = ~(-1L << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_signed_long_trace::changed() +{ + return object != old_value; +} + + +void wif_signed_long_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if (((unsigned long) object & mask) != (unsigned long) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } else { + unsigned long bit_mask = 1ul << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + + +/*****************************************************************************/ + +class wif_float_trace: public wif_trace { +public: + wif_float_trace(const float& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + +protected: + const float& object; + float old_value; +}; + +wif_float_trace::wif_float_trace(const float& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_) +{ + bit_width = 0; + wif_type = "real"; +} + +bool wif_float_trace::changed() +{ + return object != old_value; +} + +void wif_float_trace::write(FILE* f) +{ + std::fprintf(f,"assign %s %f ; \n", wif_name.c_str(), object); + old_value = object; +} + +/*****************************************************************************/ + +class wif_double_trace: public wif_trace { +public: + wif_double_trace(const double& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + +protected: + const double& object; + double old_value; +}; + +wif_double_trace::wif_double_trace(const double& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_) +{ + bit_width = 0; + wif_type = "real"; +} + +bool wif_double_trace::changed() +{ + return object != old_value; +} + +void wif_double_trace::write(FILE* f) +{ + std::fprintf(f,"assign %s %f ; \n", wif_name.c_str(), object); + old_value = object; +} + + +/*****************************************************************************/ + +class wif_enum_trace : public wif_trace { +public: + wif_enum_trace(const unsigned& object_, + const std::string& name_, + const std::string& wif_name_, + const char** enum_literals); + void write(FILE* f); + bool changed(); + // Hides the definition of the same (virtual) function in wif_trace + void print_variable_declaration_line(FILE* f); + +protected: + const unsigned& object; + unsigned old_value; + + const char** literals; + unsigned nliterals; + std::string type_name; + + ~wif_enum_trace(); +}; + + +wif_enum_trace::wif_enum_trace(const unsigned& object_, + const std::string& name_, + const std::string& wif_name_, + const char** enum_literals_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + literals(enum_literals_), nliterals(0), type_name(name_ + "__type__") +{ + // find number of enumeration literals - counting loop + for (nliterals = 0; enum_literals_[nliterals]; nliterals++) continue; + + bit_width = 0; + wif_type = type_name.c_str(); +} + +void wif_enum_trace::print_variable_declaration_line(FILE* f) +{ + std::fprintf(f, "type scalar \"%s\" enum ", wif_type); + + for (unsigned i = 0; i < nliterals; i++) + std::fprintf(f, "\"%s\", ", literals[i]); + std::fprintf(f, "\"SC_WIF_UNDEF\" ;\n"); + + std::fprintf(f, "declare %s \"%s\" \"%s\" ", + wif_name.c_str(), name.c_str(), wif_type); + std::fprintf(f, "variable ;\n"); + std::fprintf(f, "start_trace %s ;\n", wif_name.c_str()); +} + +bool wif_enum_trace::changed() +{ + return object != old_value; +} + +void wif_enum_trace::write(FILE* f) +{ + static bool warning_issued = false; + const char* lit; + + if (object >= nliterals) { // Note unsigned value is always greater than 0 + if (!warning_issued) { + SC_REPORT_WARNING( SC_ID_TRACING_INVALID_ENUM_VALUE_ + , name.c_str() ); + warning_issued = true; + } + lit = "SC_WIF_UNDEF"; + } + else + { + lit = literals[object]; + } + std::fprintf( f, "assign %s \"%s\" ;\n", wif_name.c_str(), lit ); + old_value = object; +} + +wif_enum_trace::~wif_enum_trace() +{ + /* Intentionally blank */ +} + + +template <class T> +class wif_T_trace +: public wif_trace +{ +public: + + wif_T_trace( const T& object_, + const std::string& name_, + const std::string& wif_name_, + wif_trace_file::wif_enum type_ ) + : wif_trace( name_, wif_name_), + object( object_ ), + old_value( object_ ) + { wif_type = wif_names[type_]; } + + void write( FILE* f ) + { + std::fprintf( f, + "assign %s \"%s\" ;\n", + wif_name.c_str(), + object.to_string().c_str() ); + old_value = object; + } + + bool changed() + { return !(object == old_value); } + + void set_width() + { bit_width = object.length(); } + +protected: + + const T& object; + T old_value; +}; + +typedef wif_T_trace<sc_dt::sc_bv_base> wif_sc_bv_trace; +typedef wif_T_trace<sc_dt::sc_lv_base> wif_sc_lv_trace; + + +//*********************************************************************** +// wif_trace_file functions +//*********************************************************************** + + +wif_trace_file::wif_trace_file(const char * name) + : sc_trace_file_base( name, "awif" ) + , wif_name_index(0) + , previous_time_units_low(0) + , previous_time_units_high(0) + , previous_time(0.0) + , traces() +{} + + +void wif_trace_file::do_initialize() +{ + char buf[2000]; + + // init + std::fprintf(fp, "init ;\n\n"); + + //timescale: + if (timescale_unit == 1e-15) std::sprintf(buf,"0"); + else if(timescale_unit == 1e-14) std::sprintf(buf,"1"); + else if(timescale_unit == 1e-13) std::sprintf(buf,"2"); + else if(timescale_unit == 1e-12) std::sprintf(buf,"3"); + else if(timescale_unit == 1e-11) std::sprintf(buf,"4"); + else if(timescale_unit == 1e-10) std::sprintf(buf,"5"); + else if(timescale_unit == 1e-9) std::sprintf(buf,"6"); + else if(timescale_unit == 1e-8) std::sprintf(buf,"7"); + else if(timescale_unit == 1e-7) std::sprintf(buf,"8"); + else if(timescale_unit == 1e-6) std::sprintf(buf,"9"); + else if(timescale_unit == 1e-5) std::sprintf(buf,"10"); + else if(timescale_unit == 1e-4) std::sprintf(buf,"11"); + else if(timescale_unit == 1e-3) std::sprintf(buf,"12"); + else if(timescale_unit == 1e-2) std::sprintf(buf,"13"); + else if(timescale_unit == 1e-1) std::sprintf(buf,"14"); + else if(timescale_unit == 1e0) std::sprintf(buf,"15"); + else if(timescale_unit == 1e1) std::sprintf(buf,"16"); + else if(timescale_unit == 1e2) std::sprintf(buf,"17"); + std::fprintf(fp,"header %s \"%s\" ;\n\n", buf, sc_version()); + + std::fprintf(fp, "comment \"ASCII WIF file produced on date: %s\" ;\n" + , localtime_string().c_str()); + + //version: + std::fprintf(fp, "comment \"Created by %s\" ;\n", sc_version()); + //conversion info + std::fprintf(fp, "comment \"Convert this file to binary WIF format using a2wif\" ;\n\n"); + + // Define the two types we need to represent bool and sc_logic + std::fprintf(fp, "type scalar \"BIT\" enum '0', '1' ;\n"); + std::fprintf(fp, "type scalar \"MVL\" enum '0', '1', 'X', 'Z', '?' ;\n"); + std::fprintf(fp, "\n"); + + //variable definitions: + int i; + for (i = 0; i < (int)traces.size(); i++) { + wif_trace* t = traces[i]; + t->set_width(); //needed for all vectors + t->print_variable_declaration_line(fp); + } + + double inittime = sc_time_stamp().to_seconds(); + previous_time = inittime/timescale_unit; + + // Dump all values at initial time + std::sprintf(buf, + "All initial values are dumped below at time " + "%g sec = %g timescale units.", + inittime, + inittime/timescale_unit + ); + write_comment(buf); + + double_to_special_int64(inittime/timescale_unit, + &previous_time_units_high, + &previous_time_units_low ); + + for (i = 0; i < (int)traces.size(); i++) { + wif_trace* t = traces[i]; + t->write(fp); + } +} + +// ---------------------------------------------------------------------------- + +#define DEFN_TRACE_METHOD(tp) \ +void \ +wif_trace_file::trace( const tp& object_, const std::string& name_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new wif_ ## tp ## _trace( object_, \ + name_, \ + obtain_name() ) ); \ +} + +DEFN_TRACE_METHOD(bool) +DEFN_TRACE_METHOD(float) +DEFN_TRACE_METHOD(double) + +#undef DEFN_TRACE_METHOD +#define DEFN_TRACE_METHOD(tp) \ +void \ +wif_trace_file::trace(const sc_dt::tp& object_, const std::string& name_) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new wif_ ## tp ## _trace( object_, \ + name_, \ + obtain_name() ) ); \ +} + +DEFN_TRACE_METHOD(sc_bit) +DEFN_TRACE_METHOD(sc_logic) + +DEFN_TRACE_METHOD(sc_signed) +DEFN_TRACE_METHOD(sc_unsigned) +DEFN_TRACE_METHOD(sc_int_base) +DEFN_TRACE_METHOD(sc_uint_base) + +DEFN_TRACE_METHOD(sc_fxval) +DEFN_TRACE_METHOD(sc_fxval_fast) +DEFN_TRACE_METHOD(sc_fxnum) +DEFN_TRACE_METHOD(sc_fxnum_fast) + +#undef DEFN_TRACE_METHOD + + +#define DEFN_TRACE_METHOD_SIGNED(tp) \ +void \ +wif_trace_file::trace( const tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new wif_signed_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +#define DEFN_TRACE_METHOD_UNSIGNED(tp) \ +void \ +wif_trace_file::trace( const unsigned tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new wif_unsigned_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +DEFN_TRACE_METHOD_SIGNED(char) +DEFN_TRACE_METHOD_SIGNED(short) +DEFN_TRACE_METHOD_SIGNED(int) +DEFN_TRACE_METHOD_SIGNED(long) + +DEFN_TRACE_METHOD_UNSIGNED(char) +DEFN_TRACE_METHOD_UNSIGNED(short) +DEFN_TRACE_METHOD_UNSIGNED(int) +DEFN_TRACE_METHOD_UNSIGNED(long) + +#undef DEFN_TRACE_METHOD_SIGNED +#undef DEFN_TRACE_METHOD_UNSIGNED + + +#define DEFN_TRACE_METHOD_LONG_LONG(tp) \ +void \ +wif_trace_file::trace( const sc_dt::tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new wif_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +DEFN_TRACE_METHOD_LONG_LONG(int64) +DEFN_TRACE_METHOD_LONG_LONG(uint64) +#undef DEFN_TRACE_METHOD_LONG_LONG + +void +wif_trace_file::trace( const unsigned& object_, + const std::string& name_, + const char** enum_literals_ ) +{ + if( add_trace_check(name_) ) + traces.push_back( new wif_enum_trace( object_, + name_, + obtain_name(), + enum_literals_ ) ); +} + +void +wif_trace_file::trace( const sc_dt::sc_bv_base& object_, + const std::string& name_ ) +{ + traceT( object_, name_, WIF_BIT ); +} + +void +wif_trace_file::trace( const sc_dt::sc_lv_base& object_, + const std::string& name_ ) +{ + traceT( object_, name_, WIF_MVL ); +} + + +void +wif_trace_file::write_comment(const std::string& comment) +{ + if(!fp) open_fp(); + //no newline in comments allowed + std::fprintf(fp, "comment \"%s\" ;\n", comment.c_str()); +} + + +void +wif_trace_file::cycle(bool this_is_a_delta_cycle) +{ + unsigned now_units_high, now_units_low; + + // Trace delta cycles only when enabled + if (!delta_cycles() && this_is_a_delta_cycle) return; + + // Check for initialization + if( initialize() ) { + return; + }; + + // double now_units = sc_simulation_time() / timescale_unit; + double now_units = sc_time_stamp().to_seconds() / timescale_unit; + + double_to_special_int64(now_units, &now_units_high, &now_units_low ); + + // Now do the real stuff + unsigned delta_units_high, delta_units_low; + double diff_time; + diff_time = now_units - previous_time; + double_to_special_int64(diff_time, &delta_units_high, &delta_units_low); + if (this_is_a_delta_cycle && (diff_time == 0.0)) + delta_units_low++; // Increment time for delta cycle simulation + // Note that in the last statement above, we are assuming no more + // than 2^32 delta cycles - seems realistic + + bool time_printed = false; + wif_trace* const* const l_traces = &traces[0]; + for (int i = 0; i < (int)traces.size(); i++) { + wif_trace* t = l_traces[i]; + if(t->changed()){ + if(time_printed == false){ + if(delta_units_high){ + std::fprintf(fp, "delta_time %u%09u ;\n", delta_units_high, + delta_units_low); + } + else{ + std::fprintf(fp, "delta_time %u ;\n", delta_units_low); + } + time_printed = true; + } + + // Write the variable + t->write(fp); + } + } + + if(time_printed) { + std::fprintf(fp, "\n"); // Put another newline + // We update previous_time_units only when we print time because + // this field stores the previous time that was printed, not the + // previous time this function was called + previous_time_units_high = now_units_high; + previous_time_units_low = now_units_low; + previous_time = now_units; + } +} + +#if 0 +void +wif_trace_file::create_wif_name(std::string* ptr_to_str) +{ + obtain_name().swap(*ptr_to_str); +} +#endif + +// Create a WIF name for a variable +std::string +wif_trace_file::obtain_name() +{ + char buf[32]; + std::sprintf( buf, "O%d", wif_name_index ++ ); + return buf; +} + +wif_trace_file::~wif_trace_file() +{ + for( int i = 0; i < (int)traces.size(); i++ ) { + wif_trace* t = traces[i]; + delete t; + } +} + +// Map sc_logic values to values understandable by WIF +static char +map_sc_logic_state_to_wif_state(char in_char) +{ + char out_char; + + switch(in_char){ + case 'U': + case 'X': + case 'W': + case 'D': + out_char = 'X'; + break; + case '0': + case 'L': + out_char = '0'; + break; + case '1': + case 'H': + out_char = '1'; + break; + case 'Z': + out_char = 'Z'; + break; + default: + out_char = '?'; + } + return out_char; +} + +// ---------------------------------------------------------------------------- + +// Create the trace file +sc_trace_file* +sc_create_wif_trace_file(const char * name) +{ + sc_trace_file *tf = new wif_trace_file(name); + return tf; +} + + +void +sc_close_wif_trace_file( sc_trace_file* tf ) +{ + wif_trace_file* wif_tf = static_cast<wif_trace_file*>(tf); + delete wif_tf; +} + +} // namespace sc_core diff --git a/ext/systemc/src/sysc/tracing/sc_wif_trace.h b/ext/systemc/src/sysc/tracing/sc_wif_trace.h new file mode 100644 index 000000000..b4de46e1b --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_wif_trace.h @@ -0,0 +1,222 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_wif_trace.h - Implementation of WIF tracing. + + Original Author - Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. + The contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + +/***************************************************************************** + + Instead of creating the binary WIF format, we create the ASCII + WIF format which can be converted to the binary format using + a2wif (utility that comes with VSS from Synopsys). This way, + a user who does not have Synopsys VSS can still create WIF + files, but the files can only be viewed by users who have VSS. + + *****************************************************************************/ + +#ifndef SC_WIF_TRACE_H +#define SC_WIF_TRACE_H + +#include <cstdio> +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/tracing/sc_trace_file_base.h" + +namespace sc_core { + +class wif_trace; // defined in wif_trace.cc +template<class T> class wif_T_trace; + +class wif_trace_file + : public sc_trace_file_base +{ +public: + enum wif_enum {WIF_BIT=0, WIF_MVL=1, WIF_REAL=2, WIF_LAST}; + + // Create a wif trace file. + // `Name' forms the base of the name to which `.awif' is added. + explicit wif_trace_file(const char *name); + + ~wif_trace_file(); + +protected: + // These are all virtual functions in sc_trace_file and + // they need to be defined here. + + // Trace a boolean object (single bit) + void trace(const bool& object, const std::string& name); + + // Trace a sc_bit object (single bit) + void trace(const sc_dt::sc_bit& object, const std::string& name); + + // Trace a sc_logic object (single bit) + void trace(const sc_dt::sc_logic& object, const std::string& name); + + // Trace an unsigned char with the given width + void trace(const unsigned char& object, const std::string& name, + int width); + + // Trace an unsigned short with the given width + void trace(const unsigned short& object, const std::string& name, + int width); + + // Trace an unsigned int with the given width + void trace(const unsigned int& object, const std::string& name, + int width); + + // Trace an unsigned long with the given width + void trace(const unsigned long& object, const std::string& name, + int width); + + // Trace a signed char with the given width + void trace(const char& object, const std::string& name, int width); + + // Trace a signed short with the given width + void trace(const short& object, const std::string& name, int width); + + // Trace a signed int with the given width + void trace(const int& object, const std::string& name, int width); + + // Trace a signed long with the given width + void trace(const long& object, const std::string& name, int width); + + // Trace a signed long long with the given width + void trace(const sc_dt::int64& object, const std::string& name, + int width); + + // Trace an usigned long long with the given width + void trace(const sc_dt::uint64& object, const std::string& name, + int width); + + // Trace a float + void trace(const float& object, const std::string& name); + + // Trace a double + void trace(const double& object, const std::string& name); + + // Trace sc_unsigned + void trace (const sc_dt::sc_unsigned& object, + const std::string& name); + + // Trace sc_signed + void trace (const sc_dt::sc_signed& object, + const std::string& name); + + // Trace sc_uint_base + void trace (const sc_dt::sc_uint_base& object, + const std::string& name); + + // Trace sc_int_base + void trace (const sc_dt::sc_int_base& object, const std::string& name); + + // Trace sc_fxval + void trace( const sc_dt::sc_fxval& object, const std::string& name ); + + // Trace sc_fxval_fast + void trace( const sc_dt::sc_fxval_fast& object, + const std::string& name ); + + // Trace sc_fxnum + void trace( const sc_dt::sc_fxnum& object, const std::string& name ); + + // Trace sc_fxnum_fast + void trace( const sc_dt::sc_fxnum_fast& object, + const std::string& name ); + + template<class T> + void traceT(const T& object, const std::string& name, wif_enum type) + { + if( add_trace_check(name) ) + traces.push_back( new wif_T_trace<T>( object, name + , obtain_name(),type ) ); + } + + // Trace sc_bv_base (sc_bv) + virtual void trace( const sc_dt::sc_bv_base& object, + const std::string& name ); + + // Trace sc_lv_base (sc_lv) + virtual void trace( const sc_dt::sc_lv_base& object, + const std::string& name ); + + // Trace an enumerated object - where possible output the enumeration literals + // in the trace file. Enum literals is a null terminated array of null + // terminated char* literal strings. + void trace(const unsigned& object, const std::string& name, + const char** enum_literals); + + // Output a comment to the trace file + void write_comment(const std::string& comment); + + // Write trace info for cycle. + void cycle(bool delta_cycle); + +private: + +#if SC_TRACING_PHASE_CALLBACKS_ + // avoid hidden overload warnings + virtual void trace( sc_trace_file* ) const { sc_assert(false); } +#endif // SC_TRACING_PHASE_CALLBACKS_ + + // Initialize the tracing mechanism + virtual void do_initialize(); + + unsigned wif_name_index; // Number of variables traced + + unsigned previous_time_units_low; // Previous time as 64 bit integer + unsigned previous_time_units_high; + double previous_time; // Previous time as a double + +public: + // Create wif names for each variable + std::string obtain_name(); + + // Array to store the variables traced + std::vector<wif_trace*> traces; +}; + +} // namespace sc_core + +#endif // SC_WIF_TRACE_H +// Taf! |