In the past it happened several times that some changes in gem5 broke the SystemC coupling. Recently Accelera has changed the licence for SystemC from their own licence to Apache2.0, which is compatible with gem5. However, SystemC usually relies on the Boost library, but I was able to exchange the boost calls by c++11 alternatives. The recent SystemC version is placed into /ext and is integrated into gem5's build system. The goal is to integrate some SystemC tests for the CI in some following patches. Change-Id: I4b66ec806b5e3cffc1d7c85d3735ff4fa5b31fd0 Reviewed-on: https://gem5-review.googlesource.com/2240 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
1912 lines
50 KiB
C++
1912 lines
50 KiB
C++
/*****************************************************************************
|
|
|
|
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
|