00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include <assert.h>
00053 #include <time.h>
00054 #include <cstdlib>
00055
00056 #include "sysc/kernel/sc_simcontext.h"
00057 #include "sysc/kernel/sc_ver.h"
00058 #include "sysc/datatypes/bit/sc_bit.h"
00059 #include "sysc/datatypes/bit/sc_logic.h"
00060 #include "sysc/datatypes/bit/sc_lv_base.h"
00061 #include "sysc/datatypes/int/sc_signed.h"
00062 #include "sysc/datatypes/int/sc_unsigned.h"
00063 #include "sysc/datatypes/int/sc_int_base.h"
00064 #include "sysc/datatypes/int/sc_uint_base.h"
00065 #include "sysc/datatypes/fx/fx.h"
00066 #include "sysc/tracing/sc_vcd_trace.h"
00067
00068 namespace sc_core {
00069
00070 static bool running_regression = false;
00071
00072
00073
00074 static char map_sc_logic_state_to_vcd_state(char in_char);
00075
00076
00077 static void remove_vcd_name_problems(std::string& name);
00078
00079 const char* vcd_types[vcd_trace_file::VCD_LAST]={"wire","real"};
00080
00081
00082
00083
00084
00085
00086
00087
00088 class vcd_trace
00089 {
00090 public:
00091
00092 vcd_trace(const std::string& name_, const std::string& vcd_name_);
00093
00094
00095
00096 virtual void write(FILE* f) = 0;
00097
00098 virtual void set_width();
00099
00100 static const char* strip_leading_bits(const char* originalbuf);
00101
00102
00103 virtual bool changed() = 0;
00104
00105
00106 virtual void print_variable_declaration_line(FILE* f);
00107
00108 void compose_data_line(char* rawdata, char* compdata);
00109 std::string compose_line(const std::string data);
00110
00111 virtual ~vcd_trace();
00112
00113 const std::string name;
00114 const std::string vcd_name;
00115 const char* vcd_var_typ_name;
00116 int bit_width;
00117 };
00118
00119
00120 vcd_trace::vcd_trace(const std::string& name_,
00121 const std::string& vcd_name_)
00122 : name(name_),
00123 vcd_name(vcd_name_),
00124 bit_width(0)
00125 {
00126
00127 }
00128
00129 void
00130 vcd_trace::compose_data_line(char* rawdata, char* compdata)
00131 {
00132 assert(rawdata != compdata);
00133
00134 if(bit_width == 0)
00135 {
00136 compdata[0] = '\0';
00137 }
00138 else
00139 {
00140 if(bit_width == 1)
00141 {
00142 compdata[0] = rawdata[0];
00143 strcpy(&(compdata[1]), vcd_name.c_str());
00144 }
00145 else
00146 {
00147 const char* effective_begin = strip_leading_bits(rawdata);
00148 std::sprintf(compdata, "b%s %s", effective_begin, vcd_name.c_str());
00149 }
00150 }
00151 }
00152
00153
00154 std::string
00155 vcd_trace::compose_line(const std::string data)
00156 {
00157 if(bit_width == 0)
00158 return "";
00159 if(bit_width == 1)
00160 return data + vcd_name;
00161 return std::string("b")+strip_leading_bits(data.c_str())+" "+vcd_name;
00162 }
00163
00164 void
00165 vcd_trace::print_variable_declaration_line(FILE* f)
00166 {
00167 char buf[2000];
00168
00169 if ( bit_width <= 0 )
00170 {
00171 std::sprintf(buf, "Traced object \"%s\" has 0 Bits, cannot be traced.",
00172 name.c_str());
00173 put_error_message(buf, false);
00174 }
00175 else
00176 {
00177 std::string namecopy = name;
00178 remove_vcd_name_problems(namecopy);
00179 if ( bit_width == 1 )
00180 {
00181 std::sprintf(buf, "$var %s % 3d %s %s $end\n",
00182 vcd_var_typ_name,
00183 bit_width,
00184 vcd_name.c_str(),
00185 namecopy.c_str());
00186 }
00187 else
00188 {
00189 std::sprintf(buf, "$var %s % 3d %s %s [%d:0] $end\n",
00190 vcd_var_typ_name,
00191 bit_width,
00192 vcd_name.c_str(),
00193 namecopy.c_str(),
00194 bit_width-1);
00195 }
00196 std::fputs(buf, f);
00197 }
00198 }
00199
00200 void
00201 vcd_trace::set_width()
00202 {
00203
00204 }
00205
00206 const char*
00207 vcd_trace::strip_leading_bits(const char* originalbuf)
00208 {
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 const char* position = originalbuf;
00221
00222 if( strlen(originalbuf) < 2 ||
00223 (originalbuf[0] != 'z' && originalbuf[0] != 'x' &&
00224 originalbuf[0] != '0' ))
00225 return originalbuf;
00226
00227 char first_char = *position;
00228 while(*position == first_char)
00229 {
00230 position++;
00231 }
00232
00233 if(first_char == '0' && *position == '1')
00234 return position;
00235
00236 return position-1;
00237 }
00238
00239 vcd_trace::~vcd_trace()
00240 {
00241
00242 }
00243
00244
00245 template <class T>
00246 class vcd_T_trace : public vcd_trace
00247 {
00248 public:
00249
00250 vcd_T_trace( const T& object_,
00251 const std::string& name_,
00252 const std::string& vcd_name_,
00253 vcd_trace_file::vcd_enum type_ )
00254 : vcd_trace( name_, vcd_name_ ),
00255 object( object_ ),
00256 old_value( object_ )
00257 {
00258 vcd_var_typ_name = vcd_types[type_];
00259 }
00260
00261 void write( FILE* f )
00262 {
00263 std::fprintf( f, "%s", compose_line( object.to_string() ).c_str() );
00264 old_value = object;
00265 }
00266
00267 bool changed()
00268 { return !(object == old_value); }
00269
00270 void set_width()
00271 { bit_width = object.length(); }
00272
00273 protected:
00274
00275 const T& object;
00276 T old_value;
00277 };
00278
00279 typedef vcd_T_trace<sc_dt::sc_bv_base> vcd_sc_bv_trace;
00280 typedef vcd_T_trace<sc_dt::sc_lv_base> vcd_sc_lv_trace;
00281
00282
00283 void
00284 vcd_trace_file::trace(
00285 const sc_dt::sc_bv_base& object, const std::string& name)
00286 {
00287 traceT(object,name);
00288 }
00289
00290
00291 void
00292 vcd_trace_file::trace(
00293 const sc_dt::sc_lv_base& object, const std::string& name)
00294 {
00295 traceT(object,name);
00296 }
00297
00298
00299
00300 class vcd_bool_trace : public vcd_trace {
00301 public:
00302 vcd_bool_trace(const bool& object_,
00303 const std::string& name_,
00304 const std::string& vcd_name_);
00305 void write(FILE* f);
00306 bool changed();
00307
00308 protected:
00309 const bool& object;
00310 bool old_value;
00311 };
00312
00313 vcd_bool_trace::vcd_bool_trace(const bool& object_,
00314 const std::string& name_,
00315 const std::string& vcd_name_)
00316 : vcd_trace(name_, vcd_name_), object(object_)
00317 {
00318 vcd_var_typ_name = "wire";
00319 bit_width = 1;
00320 old_value = object;
00321 }
00322
00323 bool
00324 vcd_bool_trace::changed()
00325 {
00326 return object != old_value;
00327 }
00328
00329 void
00330 vcd_bool_trace::write(FILE* f)
00331 {
00332 if (object == true) std::fputc('1', f);
00333 else std::fputc('0', f);
00334
00335 std::fprintf(f,"%s", vcd_name.c_str());
00336
00337 old_value = object;
00338 }
00339
00340
00341
00342 class vcd_sc_bit_trace : public vcd_trace {
00343 public:
00344 vcd_sc_bit_trace(const sc_dt::sc_bit& , const std::string& ,
00345 const std::string& );
00346 void write(FILE* f);
00347 bool changed();
00348
00349 protected:
00350 const sc_dt::sc_bit& object;
00351 sc_dt::sc_bit old_value;
00352 };
00353
00354 vcd_sc_bit_trace::vcd_sc_bit_trace( const sc_dt::sc_bit& object_,
00355 const std::string& name,
00356 const std::string& vcd_name)
00357 : vcd_trace(name, vcd_name), object( object_ )
00358 {
00359 vcd_var_typ_name = "wire";
00360 bit_width = 1;
00361 old_value = object;
00362 }
00363
00364 bool
00365 vcd_sc_bit_trace::changed()
00366 {
00367 return object != old_value;
00368 }
00369
00370 void
00371 vcd_sc_bit_trace::write(FILE* f)
00372 {
00373 if (object == true) std::fputc('1', f);
00374 else std::fputc('0', f);
00375
00376 std::fprintf(f,"%s", vcd_name.c_str());
00377
00378 old_value = object;
00379 }
00380
00381
00382
00383 class vcd_sc_logic_trace : public vcd_trace {
00384 public:
00385 vcd_sc_logic_trace(const sc_dt::sc_logic& object_,
00386 const std::string& name_,
00387 const std::string& vcd_name_);
00388 void write(FILE* f);
00389 bool changed();
00390
00391 protected:
00392 const sc_dt::sc_logic& object;
00393 sc_dt::sc_logic old_value;
00394 };
00395
00396
00397 vcd_sc_logic_trace::vcd_sc_logic_trace(const sc_dt::sc_logic& object_,
00398 const std::string& name_,
00399 const std::string& vcd_name_)
00400 : vcd_trace(name_, vcd_name_), object(object_)
00401 {
00402 vcd_var_typ_name = "wire";
00403 bit_width = 1;
00404 old_value = object;
00405 }
00406
00407
00408 bool
00409 vcd_sc_logic_trace::changed()
00410 {
00411 return object != old_value;
00412 }
00413
00414
00415 void
00416 vcd_sc_logic_trace::write(FILE* f)
00417 {
00418 char out_char;
00419 out_char = map_sc_logic_state_to_vcd_state(object.to_char());
00420 std::fputc(out_char, f);
00421
00422 std::fprintf(f,"%s", vcd_name.c_str());
00423
00424 old_value = object;
00425 }
00426
00427
00428
00429
00430 class vcd_sc_unsigned_trace : public vcd_trace {
00431 public:
00432 vcd_sc_unsigned_trace(const sc_dt::sc_unsigned& object,
00433 const std::string& name_,
00434 const std::string& vcd_name_);
00435 void write(FILE* f);
00436 bool changed();
00437 void set_width();
00438
00439 protected:
00440 const sc_dt::sc_unsigned& object;
00441 sc_dt::sc_unsigned old_value;
00442 };
00443
00444
00445 vcd_sc_unsigned_trace::vcd_sc_unsigned_trace(const sc_dt::sc_unsigned& object_,
00446 const std::string& name_,
00447 const std::string& vcd_name_)
00448 : vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length())
00449
00450 {
00451 vcd_var_typ_name = "wire";
00452 old_value = object;
00453 }
00454
00455 bool
00456 vcd_sc_unsigned_trace::changed()
00457 {
00458 return object != old_value;
00459 }
00460
00461 void
00462 vcd_sc_unsigned_trace::write(FILE* f)
00463 {
00464 char rawdata[1000], *rawdata_ptr = rawdata;
00465 char compdata[1000];
00466
00467 int bitindex;
00468 for (bitindex = object.length() - 1; bitindex >= 0; --bitindex) {
00469 *rawdata_ptr++ = "01"[(object)[bitindex]];
00470 }
00471 *rawdata_ptr = '\0';
00472 compose_data_line(rawdata, compdata);
00473
00474 std::fputs(compdata, f);
00475 old_value = object;
00476 }
00477
00478 void
00479 vcd_sc_unsigned_trace::set_width()
00480 {
00481 bit_width = object.length();
00482 }
00483
00484
00485
00486
00487 class vcd_sc_signed_trace : public vcd_trace {
00488 public:
00489 vcd_sc_signed_trace(const sc_dt::sc_signed& object,
00490 const std::string& name_,
00491 const std::string& vcd_name_);
00492 void write(FILE* f);
00493 bool changed();
00494 void set_width();
00495
00496 protected:
00497 const sc_dt::sc_signed& object;
00498 sc_dt::sc_signed old_value;
00499 };
00500
00501
00502 vcd_sc_signed_trace::vcd_sc_signed_trace(const sc_dt::sc_signed& object_,
00503 const std::string& name_,
00504 const std::string& vcd_name_)
00505 : vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length())
00506 {
00507 vcd_var_typ_name = "wire";
00508 old_value = object;
00509 }
00510
00511 bool
00512 vcd_sc_signed_trace::changed()
00513 {
00514 return object != old_value;
00515 }
00516
00517 void
00518 vcd_sc_signed_trace::write(FILE* f)
00519 {
00520 char rawdata[1000], *rawdata_ptr = rawdata;
00521 char compdata[1000];
00522
00523 int bitindex;
00524 for (bitindex = object.length() - 1; bitindex >= 0; --bitindex) {
00525 *rawdata_ptr++ = "01"[(object)[bitindex]];
00526 }
00527 *rawdata_ptr = '\0';
00528 compose_data_line(rawdata, compdata);
00529
00530 std::fputs(compdata, f);
00531 old_value = object;
00532 }
00533
00534 void
00535 vcd_sc_signed_trace::set_width()
00536 {
00537 bit_width = object.length();
00538 }
00539
00540
00541
00542 class vcd_sc_uint_base_trace : public vcd_trace {
00543 public:
00544 vcd_sc_uint_base_trace(const sc_dt::sc_uint_base& object,
00545 const std::string& name_,
00546 const std::string& vcd_name_);
00547 void write(FILE* f);
00548 bool changed();
00549 void set_width();
00550
00551 protected:
00552 const sc_dt::sc_uint_base& object;
00553 sc_dt::sc_uint_base old_value;
00554 };
00555
00556
00557 vcd_sc_uint_base_trace::vcd_sc_uint_base_trace(
00558 const sc_dt::sc_uint_base& object_,
00559 const std::string& name_,
00560 const std::string& vcd_name_)
00561 : vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length())
00562
00563 {
00564 vcd_var_typ_name = "wire";
00565 old_value = object;
00566 }
00567
00568 bool
00569 vcd_sc_uint_base_trace::changed()
00570 {
00571 return object != old_value;
00572 }
00573
00574 void
00575 vcd_sc_uint_base_trace::write(FILE* f)
00576 {
00577 char rawdata[1000], *rawdata_ptr = rawdata;
00578 char compdata[1000];
00579
00580 int bitindex;
00581 for (bitindex = object.length()-1; bitindex >= 0; --bitindex) {
00582 *rawdata_ptr++ = "01"[int((object)[bitindex])];
00583 }
00584 *rawdata_ptr = '\0';
00585 compose_data_line(rawdata, compdata);
00586
00587 std::fputs(compdata, f);
00588 old_value = object;
00589 }
00590
00591 void
00592 vcd_sc_uint_base_trace::set_width()
00593 {
00594 bit_width = object.length();
00595 }
00596
00597
00598
00599
00600 class vcd_sc_int_base_trace : public vcd_trace {
00601 public:
00602 vcd_sc_int_base_trace(const sc_dt::sc_int_base& object,
00603 const std::string& name_,
00604 const std::string& vcd_name_);
00605 void write(FILE* f);
00606 bool changed();
00607 void set_width();
00608
00609 protected:
00610 const sc_dt::sc_int_base& object;
00611 sc_dt::sc_int_base old_value;
00612 };
00613
00614
00615 vcd_sc_int_base_trace::vcd_sc_int_base_trace(const sc_dt::sc_int_base& object_,
00616 const std::string& name_,
00617 const std::string& vcd_name_)
00618 : vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length())
00619 {
00620 vcd_var_typ_name = "wire";
00621 old_value = object;
00622 }
00623
00624 bool
00625 vcd_sc_int_base_trace::changed()
00626 {
00627 return object != old_value;
00628 }
00629
00630 void
00631 vcd_sc_int_base_trace::write(FILE* f)
00632 {
00633 char rawdata[1000], *rawdata_ptr = rawdata;
00634 char compdata[1000];
00635
00636 int bitindex;
00637 for (bitindex = object.length()-1; bitindex >= 0; --bitindex) {
00638 *rawdata_ptr++ = "01"[int((object)[bitindex])];
00639 }
00640 *rawdata_ptr = '\0';
00641 compose_data_line(rawdata, compdata);
00642
00643 std::fputs(compdata, f);
00644 old_value = object;
00645 }
00646
00647 void
00648 vcd_sc_int_base_trace::set_width()
00649 {
00650 bit_width = object.length();
00651 }
00652
00653
00654
00655
00656 class vcd_sc_fxval_trace : public vcd_trace
00657 {
00658 public:
00659
00660 vcd_sc_fxval_trace( const sc_dt::sc_fxval& object,
00661 const std::string& name_,
00662 const std::string& vcd_name_ );
00663 void write( FILE* f );
00664 bool changed();
00665
00666 protected:
00667
00668 const sc_dt::sc_fxval& object;
00669 sc_dt::sc_fxval old_value;
00670
00671 };
00672
00673 vcd_sc_fxval_trace::vcd_sc_fxval_trace( const sc_dt::sc_fxval& object_,
00674 const std::string& name_,
00675 const std::string& vcd_name_ )
00676 : vcd_trace( name_, vcd_name_ ),
00677 object( object_ )
00678 {
00679 vcd_var_typ_name = "real";
00680 bit_width = 1;
00681 old_value = object;
00682 }
00683
00684 bool
00685 vcd_sc_fxval_trace::changed()
00686 {
00687 return object != old_value;
00688 }
00689
00690 void
00691 vcd_sc_fxval_trace::write( FILE* f )
00692 {
00693 std::fprintf( f, "r%.16g %s", object.to_double(), vcd_name.c_str() );
00694 old_value = object;
00695 }
00696
00697
00698
00699 class vcd_sc_fxval_fast_trace : public vcd_trace
00700 {
00701 public:
00702
00703 vcd_sc_fxval_fast_trace( const sc_dt::sc_fxval_fast& object,
00704 const std::string& name_,
00705 const std::string& vcd_name_ );
00706 void write( FILE* f );
00707 bool changed();
00708
00709 protected:
00710
00711 const sc_dt::sc_fxval_fast& object;
00712 sc_dt::sc_fxval_fast old_value;
00713
00714 };
00715
00716 vcd_sc_fxval_fast_trace::vcd_sc_fxval_fast_trace(
00717 const sc_dt::sc_fxval_fast& object_,
00718 const std::string& name_,
00719 const std::string& vcd_name_ )
00720 : vcd_trace( name_, vcd_name_ ),
00721 object( object_ )
00722 {
00723 vcd_var_typ_name = "real";
00724 bit_width = 1;
00725 old_value = object;
00726 }
00727
00728 bool
00729 vcd_sc_fxval_fast_trace::changed()
00730 {
00731 return object != old_value;
00732 }
00733
00734 void
00735 vcd_sc_fxval_fast_trace::write( FILE* f )
00736 {
00737 std::fprintf( f, "r%.16g %s", object.to_double(), vcd_name.c_str() );
00738 old_value = object;
00739 }
00740
00741
00742
00743 class vcd_sc_fxnum_trace : public vcd_trace
00744 {
00745 public:
00746
00747 vcd_sc_fxnum_trace( const sc_dt::sc_fxnum& object,
00748 const std::string& name_,
00749 const std::string& vcd_name_ );
00750 void write( FILE* f );
00751 bool changed();
00752 void set_width();
00753
00754 protected:
00755
00756 const sc_dt::sc_fxnum& object;
00757 sc_dt::sc_fxnum old_value;
00758
00759 };
00760
00761 vcd_sc_fxnum_trace::vcd_sc_fxnum_trace( const sc_dt::sc_fxnum& object_,
00762 const std::string& name_,
00763 const std::string& vcd_name_ )
00764 : vcd_trace( name_, vcd_name_ ),
00765 object( object_ ),
00766 old_value( object_.m_params.type_params(),
00767 object_.m_params.enc(),
00768 object_.m_params.cast_switch(),
00769 0 )
00770 {
00771 vcd_var_typ_name = "wire";
00772 old_value = object;
00773 }
00774
00775 bool
00776 vcd_sc_fxnum_trace::changed()
00777 {
00778 return object != old_value;
00779 }
00780
00781 void
00782 vcd_sc_fxnum_trace::write( FILE* f )
00783 {
00784 char rawdata[1000], *rawdata_ptr = rawdata;
00785 char compdata[1000];
00786
00787 int bitindex;
00788 for( bitindex = object.wl() - 1; bitindex >= 0; -- bitindex )
00789 {
00790 *rawdata_ptr ++ = "01"[(object)[bitindex]];
00791 }
00792 *rawdata_ptr = '\0';
00793 compose_data_line( rawdata, compdata );
00794
00795 std::fputs( compdata, f );
00796 old_value = object;
00797 }
00798
00799 void
00800 vcd_sc_fxnum_trace::set_width()
00801 {
00802 bit_width = object.wl();
00803 }
00804
00805
00806
00807 class vcd_sc_fxnum_fast_trace : public vcd_trace
00808 {
00809 public:
00810
00811 vcd_sc_fxnum_fast_trace( const sc_dt::sc_fxnum_fast& object,
00812 const std::string& name_,
00813 const std::string& vcd_name_ );
00814 void write( FILE* f );
00815 bool changed();
00816 void set_width();
00817
00818 protected:
00819
00820 const sc_dt::sc_fxnum_fast& object;
00821 sc_dt::sc_fxnum_fast old_value;
00822
00823 };
00824
00825 vcd_sc_fxnum_fast_trace::vcd_sc_fxnum_fast_trace(
00826 const sc_dt::sc_fxnum_fast& object_,
00827 const std::string& name_,
00828 const std::string& vcd_name_ )
00829 : vcd_trace( name_, vcd_name_ ),
00830 object( object_ ),
00831 old_value( object_.m_params.type_params(),
00832 object_.m_params.enc(),
00833 object_.m_params.cast_switch(),
00834 0 )
00835 {
00836 vcd_var_typ_name = "wire";
00837 old_value = object;
00838 }
00839
00840 bool
00841 vcd_sc_fxnum_fast_trace::changed()
00842 {
00843 return object != old_value;
00844 }
00845
00846 void
00847 vcd_sc_fxnum_fast_trace::write( FILE* f )
00848 {
00849 char rawdata[1000], *rawdata_ptr = rawdata;
00850 char compdata[1000];
00851
00852 int bitindex;
00853 for( bitindex = object.wl() - 1; bitindex >= 0; -- bitindex )
00854 {
00855 *rawdata_ptr ++ = "01"[(object)[bitindex]];
00856 }
00857 *rawdata_ptr = '\0';
00858 compose_data_line( rawdata, compdata );
00859
00860 std::fputs( compdata, f );
00861 old_value = object;
00862 }
00863
00864 void
00865 vcd_sc_fxnum_fast_trace::set_width()
00866 {
00867 bit_width = object.wl();
00868 }
00869
00870
00871
00872
00873 class vcd_unsigned_int_trace : public vcd_trace {
00874 public:
00875 vcd_unsigned_int_trace(const unsigned& object,
00876 const std::string& name_,
00877 const std::string& vcd_name_,
00878 int width_);
00879 void write(FILE* f);
00880 bool changed();
00881
00882 protected:
00883 const unsigned& object;
00884 unsigned old_value;
00885 unsigned mask;
00886 };
00887
00888
00889 vcd_unsigned_int_trace::vcd_unsigned_int_trace(
00890 const unsigned& object_,
00891 const std::string& name_,
00892 const std::string& vcd_name_,
00893 int width_)
00894 : vcd_trace(name_, vcd_name_), object(object_)
00895 {
00896 bit_width = width_;
00897 if (bit_width < 32) {
00898 mask = ~(-1 << bit_width);
00899 } else {
00900 mask = 0xffffffff;
00901 }
00902
00903 vcd_var_typ_name = "wire";
00904 old_value = object;
00905 }
00906
00907
00908 bool
00909 vcd_unsigned_int_trace::changed()
00910 {
00911 return object != old_value;
00912 }
00913
00914
00915 void
00916 vcd_unsigned_int_trace::write(FILE* f)
00917 {
00918 char rawdata[1000];
00919 char compdata[1000];
00920 int bitindex;
00921
00922
00923 if ((object & mask) != object) {
00924 for (bitindex = 0; bitindex < bit_width; bitindex++){
00925 rawdata[bitindex] = 'x';
00926 }
00927 }
00928 else{
00929 unsigned bit_mask = 1 << (bit_width-1);
00930 for (bitindex = 0; bitindex < bit_width; bitindex++) {
00931 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
00932 bit_mask = bit_mask >> 1;
00933 }
00934 }
00935 rawdata[bitindex] = '\0';
00936 compose_data_line(rawdata, compdata);
00937 std::fputs(compdata, f);
00938 old_value = object;
00939 }
00940
00941
00942
00943 class vcd_unsigned_short_trace : public vcd_trace {
00944 public:
00945 vcd_unsigned_short_trace(const unsigned short& object,
00946 const std::string& name_,
00947 const std::string& vcd_name_,
00948 int width_);
00949 void write(FILE* f);
00950 bool changed();
00951
00952 protected:
00953 const unsigned short& object;
00954 unsigned short old_value;
00955 unsigned short mask;
00956 };
00957
00958
00959 vcd_unsigned_short_trace::vcd_unsigned_short_trace(
00960 const unsigned short& object_,
00961 const std::string& name_,
00962 const std::string& vcd_name_,
00963 int width_)
00964 : vcd_trace(name_, vcd_name_), object(object_)
00965 {
00966 bit_width = width_;
00967 if (bit_width < 16) {
00968 mask = ~(-1 << bit_width);
00969 } else {
00970 mask = 0xffff;
00971 }
00972
00973 vcd_var_typ_name = "wire";
00974 old_value = object;
00975 }
00976
00977
00978 bool
00979 vcd_unsigned_short_trace::changed()
00980 {
00981 return object != old_value;
00982 }
00983
00984
00985 void
00986 vcd_unsigned_short_trace::write(FILE* f)
00987 {
00988 char rawdata[1000];
00989 char compdata[1000];
00990 int bitindex;
00991
00992
00993 if ((object & mask) != object) {
00994 for (bitindex = 0; bitindex < bit_width; bitindex++){
00995 rawdata[bitindex] = 'x';
00996 }
00997 }
00998 else{
00999 unsigned bit_mask = 1 << (bit_width-1);
01000 for (bitindex = 0; bitindex < bit_width; bitindex++) {
01001 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
01002 bit_mask = bit_mask >> 1;
01003 }
01004 }
01005 rawdata[bitindex] = '\0';
01006 compose_data_line(rawdata, compdata);
01007 std::fputs(compdata, f);
01008 old_value = object;
01009 }
01010
01011
01012
01013 class vcd_unsigned_char_trace : public vcd_trace {
01014 public:
01015 vcd_unsigned_char_trace(const unsigned char& object,
01016 const std::string& name_,
01017 const std::string& vcd_name_,
01018 int width_);
01019 void write(FILE* f);
01020 bool changed();
01021
01022 protected:
01023 const unsigned char& object;
01024 unsigned char old_value;
01025 unsigned char mask;
01026 };
01027
01028
01029 vcd_unsigned_char_trace::vcd_unsigned_char_trace(
01030 const unsigned char& object_,
01031 const std::string& name_,
01032 const std::string& vcd_name_,
01033 int width_)
01034 : vcd_trace(name_, vcd_name_), object(object_)
01035 {
01036 bit_width = width_;
01037 if (bit_width < 8) {
01038 mask = ~(-1 << bit_width);
01039 } else {
01040 mask = 0xff;
01041 }
01042
01043 vcd_var_typ_name = "wire";
01044 old_value = object;
01045 }
01046
01047
01048 bool vcd_unsigned_char_trace::changed()
01049 {
01050 return object != old_value;
01051 }
01052
01053
01054 void vcd_unsigned_char_trace::write(FILE* f)
01055 {
01056 char rawdata[1000];
01057 char compdata[1000];
01058 int bitindex;
01059
01060
01061 if ((object & mask) != object) {
01062 for (bitindex = 0; bitindex < bit_width; bitindex++){
01063 rawdata[bitindex] = 'x';
01064 }
01065 }
01066 else{
01067 unsigned bit_mask = 1 << (bit_width-1);
01068 for (bitindex = 0; bitindex < bit_width; bitindex++) {
01069 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
01070 bit_mask = bit_mask >> 1;
01071 }
01072 }
01073 rawdata[bitindex] = '\0';
01074 compose_data_line(rawdata, compdata);
01075 std::fputs(compdata, f);
01076 old_value = object;
01077 }
01078
01079
01080
01081 class vcd_unsigned_long_trace : public vcd_trace {
01082 public:
01083 vcd_unsigned_long_trace(const unsigned long& object,
01084 const std::string& name_,
01085 const std::string& vcd_name_,
01086 int width_);
01087 void write(FILE* f);
01088 bool changed();
01089
01090 protected:
01091 const unsigned long& object;
01092 unsigned long old_value;
01093 unsigned long mask;
01094 };
01095
01096
01097 vcd_unsigned_long_trace::vcd_unsigned_long_trace(
01098 const unsigned long& object_,
01099 const std::string& name_,
01100 const std::string& vcd_name_,
01101 int width_)
01102 : vcd_trace(name_, vcd_name_), object(object_)
01103 {
01104 bit_width = width_;
01105 if (bit_width < 32) {
01106 mask = ~(-1 << bit_width);
01107 } else {
01108 mask = 0xffffffff;
01109 }
01110
01111 vcd_var_typ_name = "wire";
01112 old_value = object;
01113 }
01114
01115
01116 bool vcd_unsigned_long_trace::changed()
01117 {
01118 return object != old_value;
01119 }
01120
01121
01122 void vcd_unsigned_long_trace::write(FILE* f)
01123 {
01124 char rawdata[1000];
01125 char compdata[1000];
01126 int bitindex;
01127
01128
01129 if ((object & mask) != object) {
01130 for (bitindex = 0; bitindex < bit_width; bitindex++){
01131 rawdata[bitindex] = 'x';
01132 }
01133 }
01134 else{
01135 unsigned bit_mask = 1 << (bit_width-1);
01136 for (bitindex = 0; bitindex < bit_width; bitindex++) {
01137 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
01138 bit_mask = bit_mask >> 1;
01139 }
01140 }
01141 rawdata[bitindex] = '\0';
01142 compose_data_line(rawdata, compdata);
01143 std::fputs(compdata, f);
01144 old_value = object;
01145 }
01146
01147
01148
01149 class vcd_signed_int_trace : public vcd_trace {
01150 public:
01151 vcd_signed_int_trace(const int& object,
01152 const std::string& name_,
01153 const std::string& vcd_name_,
01154 int width_);
01155 void write(FILE* f);
01156 bool changed();
01157
01158 protected:
01159 const int& object;
01160 int old_value;
01161 unsigned mask;
01162 };
01163
01164
01165 vcd_signed_int_trace::vcd_signed_int_trace(const signed& object_,
01166 const std::string& name_,
01167 const std::string& vcd_name_,
01168 int width_)
01169 : vcd_trace(name_, vcd_name_), object(object_)
01170 {
01171 bit_width = width_;
01172 if (bit_width < 32) {
01173 mask = ~(-1 << bit_width);
01174 } else {
01175 mask = 0xffffffff;
01176 }
01177
01178 vcd_var_typ_name = "wire";
01179 old_value = object;
01180 }
01181
01182
01183 bool vcd_signed_int_trace::changed()
01184 {
01185 return object != old_value;
01186 }
01187
01188
01189 void vcd_signed_int_trace::write(FILE* f)
01190 {
01191 char rawdata[1000];
01192 char compdata[1000];
01193 int bitindex;
01194
01195
01196 if (((unsigned) object & mask) != (unsigned) object) {
01197 for (bitindex = 0; bitindex < bit_width; bitindex++){
01198 rawdata[bitindex] = 'x';
01199 }
01200 }
01201 else{
01202 unsigned bit_mask = 1 << (bit_width-1);
01203 for (bitindex = 0; bitindex < bit_width; bitindex++) {
01204 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
01205 bit_mask = bit_mask >> 1;
01206 }
01207 }
01208 rawdata[bitindex] = '\0';
01209 compose_data_line(rawdata, compdata);
01210 std::fputs(compdata, f);
01211 old_value = object;
01212 }
01213
01214
01215
01216 class vcd_signed_short_trace : public vcd_trace {
01217 public:
01218 vcd_signed_short_trace(const short& object,
01219 const std::string& name_,
01220 const std::string& vcd_name_,
01221 int width_);
01222 void write(FILE* f);
01223 bool changed();
01224
01225 protected:
01226 const short& object;
01227 short old_value;
01228 unsigned short mask;
01229 };
01230
01231
01232 vcd_signed_short_trace::vcd_signed_short_trace(
01233 const short& object_,
01234 const std::string& name_,
01235 const std::string& vcd_name_,
01236 int width_)
01237 : vcd_trace(name_, vcd_name_), object(object_)
01238 {
01239 bit_width = width_;
01240 if (bit_width < 16) {
01241 mask = ~(-1 << bit_width);
01242 } else {
01243 mask = 0xffff;
01244 }
01245
01246 vcd_var_typ_name = "wire";
01247 old_value = object;
01248 }
01249
01250
01251 bool vcd_signed_short_trace::changed()
01252 {
01253 return object != old_value;
01254 }
01255
01256
01257 void vcd_signed_short_trace::write(FILE* f)
01258 {
01259 char rawdata[1000];
01260 char compdata[1000];
01261 int bitindex;
01262
01263
01264 if (((unsigned short) object & mask) != (unsigned short) object) {
01265 for (bitindex = 0; bitindex < bit_width; bitindex++){
01266 rawdata[bitindex] = 'x';
01267 }
01268 }
01269 else{
01270 unsigned bit_mask = 1 << (bit_width-1);
01271 for (bitindex = 0; bitindex < bit_width; bitindex++) {
01272 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
01273 bit_mask = bit_mask >> 1;
01274 }
01275 }
01276 rawdata[bitindex] = '\0';
01277 compose_data_line(rawdata, compdata);
01278 std::fputs(compdata, f);
01279 old_value = object;
01280 }
01281
01282
01283
01284 class vcd_signed_char_trace : public vcd_trace {
01285 public:
01286 vcd_signed_char_trace(const char& object,
01287 const std::string& name_,
01288 const std::string& vcd_name_,
01289 int width_);
01290 void write(FILE* f);
01291 bool changed();
01292
01293 protected:
01294 const char& object;
01295 char old_value;
01296 unsigned char mask;
01297 };
01298
01299
01300 vcd_signed_char_trace::vcd_signed_char_trace(const char& object_,
01301 const std::string& name_,
01302 const std::string& vcd_name_,
01303 int width_)
01304 : vcd_trace(name_, vcd_name_), object(object_)
01305 {
01306 bit_width = width_;
01307 if (bit_width < 8) {
01308 mask = ~(-1 << bit_width);
01309 } else {
01310 mask = 0xff;
01311 }
01312
01313 vcd_var_typ_name = "wire";
01314 old_value = object;
01315 }
01316
01317
01318 bool vcd_signed_char_trace::changed()
01319 {
01320 return object != old_value;
01321 }
01322
01323
01324 void vcd_signed_char_trace::write(FILE* f)
01325 {
01326 char rawdata[1000];
01327 char compdata[1000];
01328 int bitindex;
01329
01330
01331 if (((unsigned char) object & mask) != (unsigned char) object) {
01332 for (bitindex = 0; bitindex < bit_width; bitindex++){
01333 rawdata[bitindex] = 'x';
01334 }
01335 }
01336 else{
01337 unsigned bit_mask = 1 << (bit_width-1);
01338 for (bitindex = 0; bitindex < bit_width; bitindex++) {
01339 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
01340 bit_mask = bit_mask >> 1;
01341 }
01342 }
01343 rawdata[bitindex] = '\0';
01344 compose_data_line(rawdata, compdata);
01345 std::fputs(compdata, f);
01346 old_value = object;
01347 }
01348
01349
01350
01351 class vcd_int64_trace : public vcd_trace {
01352 public:
01353 vcd_int64_trace(const sc_dt::int64& object,
01354 const std::string& name_,
01355 const std::string& vcd_name_,
01356 int width_);
01357 void write(FILE* f);
01358 bool changed();
01359
01360 protected:
01361 const sc_dt::int64& object;
01362 sc_dt::int64 old_value;
01363 sc_dt::uint64 mask;
01364 };
01365
01366
01367 vcd_int64_trace::vcd_int64_trace(const sc_dt::int64& object_,
01368 const std::string& name_,
01369 const std::string& vcd_name_,
01370 int width_)
01371 : vcd_trace(name_, vcd_name_), object(object_)
01372 {
01373 bit_width = width_;
01374 mask = (sc_dt::uint64)-1;
01375 if (bit_width < 64) mask = ~(mask << bit_width);
01376
01377 vcd_var_typ_name = "wire";
01378 old_value = object;
01379 }
01380
01381
01382 bool vcd_int64_trace::changed()
01383 {
01384 return object != old_value;
01385 }
01386
01387
01388 void vcd_int64_trace::write(FILE* f)
01389 {
01390 char rawdata[1000];
01391 char compdata[1000];
01392 int bitindex;
01393
01394
01395 if (((sc_dt::uint64) object & mask) != (sc_dt::uint64) object)
01396 {
01397 for (bitindex = 0; bitindex < bit_width; bitindex++)
01398 {
01399 rawdata[bitindex] = 'x';
01400 }
01401 }
01402 else
01403 {
01404 sc_dt::uint64 bit_mask = 1;
01405 bit_mask = bit_mask << (bit_width-1);
01406 for (bitindex = 0; bitindex < bit_width; bitindex++) {
01407 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
01408 bit_mask = bit_mask >> 1;
01409 }
01410 }
01411 rawdata[bitindex] = '\0';
01412 compose_data_line(rawdata, compdata);
01413 std::fputs(compdata, f);
01414 old_value = object;
01415 }
01416
01417
01418
01419
01420 class vcd_uint64_trace : public vcd_trace {
01421 public:
01422 vcd_uint64_trace(const sc_dt::uint64& object,
01423 const std::string& name_,
01424 const std::string& vcd_name_,
01425 int width_);
01426 void write(FILE* f);
01427 bool changed();
01428
01429 protected:
01430 const sc_dt::uint64& object;
01431 sc_dt::uint64 old_value;
01432 sc_dt::uint64 mask;
01433 };
01434
01435
01436 vcd_uint64_trace::vcd_uint64_trace( const sc_dt::uint64& object_,
01437 const std::string& name_,
01438 const std::string& vcd_name_,
01439 int width_)
01440 : vcd_trace(name_, vcd_name_), object(object_)
01441 {
01442 bit_width = width_;
01443 mask = (sc_dt::uint64)-1;
01444 if ( bit_width < 64 ) mask = ~(mask << bit_width);
01445
01446 vcd_var_typ_name = "wire";
01447 old_value = object;
01448 }
01449
01450
01451 bool vcd_uint64_trace::changed()
01452 {
01453 return object != old_value;
01454 }
01455
01456
01457 void vcd_uint64_trace::write(FILE* f)
01458 {
01459 char rawdata[1000];
01460 char compdata[1000];
01461 int bitindex;
01462
01463
01464 if ((object & mask) != object)
01465 {
01466 for (bitindex = 0; bitindex < bit_width; bitindex++){
01467 rawdata[bitindex] = 'x';
01468 }
01469 }
01470 else
01471 {
01472 sc_dt::uint64 bit_mask = 1;
01473 bit_mask = bit_mask << (bit_width-1);
01474 for (bitindex = 0; bitindex < bit_width; bitindex++)
01475 {
01476 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
01477 bit_mask = bit_mask >> 1;
01478 }
01479 }
01480 rawdata[bitindex] = '\0';
01481 compose_data_line(rawdata, compdata);
01482 std::fputs(compdata, f);
01483 old_value = object;
01484 }
01485
01486
01487
01488
01489 class vcd_signed_long_trace : public vcd_trace {
01490 public:
01491 vcd_signed_long_trace(const long& object,
01492 const std::string& name_,
01493 const std::string& vcd_name_,
01494 int width_);
01495 void write(FILE* f);
01496 bool changed();
01497
01498 protected:
01499 const long& object;
01500 long old_value;
01501 unsigned long mask;
01502 };
01503
01504
01505 vcd_signed_long_trace::vcd_signed_long_trace(const long& object_,
01506 const std::string& name_,
01507 const std::string& vcd_name_,
01508 int width_)
01509 : vcd_trace(name_, vcd_name_), object(object_)
01510 {
01511 bit_width = width_;
01512 if (bit_width < 32) {
01513 mask = ~(-1 << bit_width);
01514 } else {
01515 mask = 0xffffffff;
01516 }
01517
01518 vcd_var_typ_name = "wire";
01519 old_value = object;
01520 }
01521
01522
01523 bool vcd_signed_long_trace::changed()
01524 {
01525 return object != old_value;
01526 }
01527
01528
01529 void vcd_signed_long_trace::write(FILE* f)
01530 {
01531 char rawdata[1000];
01532 char compdata[1000];
01533 int bitindex;
01534
01535
01536 if (((unsigned long) object & mask) != (unsigned long) object) {
01537 for (bitindex = 0; bitindex < bit_width; bitindex++){
01538 rawdata[bitindex] = 'x';
01539 }
01540 }
01541 else{
01542 unsigned bit_mask = 1 << (bit_width-1);
01543 for (bitindex = 0; bitindex < bit_width; bitindex++) {
01544 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
01545 bit_mask = bit_mask >> 1;
01546 }
01547 }
01548 rawdata[bitindex] = '\0';
01549 compose_data_line(rawdata, compdata);
01550 std::fputs(compdata, f);
01551 old_value = object;
01552 }
01553
01554
01555
01556
01557 class vcd_float_trace : public vcd_trace {
01558 public:
01559 vcd_float_trace(const float& object,
01560 const std::string& name_,
01561 const std::string& vcd_name_);
01562 void write(FILE* f);
01563 bool changed();
01564
01565 protected:
01566 const float& object;
01567 float old_value;
01568 };
01569
01570 vcd_float_trace::vcd_float_trace(const float& object_,
01571 const std::string& name_,
01572 const std::string& vcd_name_)
01573 : vcd_trace(name_, vcd_name_), object(object_)
01574 {
01575 vcd_var_typ_name = "real";
01576 bit_width = 1;
01577 old_value = object;
01578 }
01579
01580 bool vcd_float_trace::changed()
01581 {
01582 return object != old_value;
01583 }
01584
01585 void vcd_float_trace::write(FILE* f)
01586 {
01587 std::fprintf(f, "r%.16g %s", object, vcd_name.c_str());
01588 old_value = object;
01589 }
01590
01591
01592
01593 class vcd_double_trace : public vcd_trace {
01594 public:
01595 vcd_double_trace(const double& object,
01596 const std::string& name_,
01597 const std::string& vcd_name_);
01598 void write(FILE* f);
01599 bool changed();
01600
01601 protected:
01602 const double& object;
01603 double old_value;
01604 };
01605
01606 vcd_double_trace::vcd_double_trace(const double& object_,
01607 const std::string& name_,
01608 const std::string& vcd_name_)
01609 : vcd_trace(name_, vcd_name_), object(object_)
01610 {
01611 vcd_var_typ_name = "real";
01612 bit_width = 1;
01613 old_value = object;
01614 }
01615
01616 bool vcd_double_trace::changed()
01617 {
01618 return object != old_value;
01619 }
01620
01621 void vcd_double_trace::write(FILE* f)
01622 {
01623 std::fprintf(f, "r%.16g %s", object, vcd_name.c_str());
01624 old_value = object;
01625 }
01626
01627
01628
01629
01630 class vcd_enum_trace : public vcd_trace {
01631 public:
01632 vcd_enum_trace(const unsigned& object_,
01633 const std::string& name_,
01634 const std::string& vcd_name_,
01635 const char** enum_literals);
01636 void write(FILE* f);
01637 bool changed();
01638
01639 protected:
01640 const unsigned& object;
01641 unsigned old_value;
01642 unsigned mask;
01643 const char** literals;
01644 unsigned nliterals;
01645 };
01646
01647
01648 vcd_enum_trace::vcd_enum_trace(const unsigned& object_,
01649 const std::string& name_,
01650 const std::string& vcd_name_,
01651 const char** enum_literals_)
01652 : vcd_trace(name_, vcd_name_), object(object_), literals(enum_literals_)
01653 {
01654
01655 for (nliterals = 0; enum_literals_[nliterals]; nliterals++);
01656
01657
01658 bit_width = 0;
01659 unsigned shifted_maxindex = nliterals-1;
01660 while(shifted_maxindex != 0){
01661 shifted_maxindex >>= 1;
01662 bit_width++;
01663 }
01664
01665
01666 if (bit_width < 32) {
01667 mask = ~(-1 << bit_width);
01668 } else {
01669 mask = 0xffffffff;
01670 }
01671
01672 vcd_var_typ_name = "wire";
01673 old_value = object;
01674 }
01675
01676 bool vcd_enum_trace::changed()
01677 {
01678 return object != old_value;
01679 }
01680
01681 void vcd_enum_trace::write(FILE* f)
01682 {
01683 char rawdata[1000];
01684 char compdata[1000];
01685 int bitindex;
01686
01687
01688 if ((object & mask) != object) {
01689 for (bitindex = 0; bitindex < bit_width; bitindex++){
01690 rawdata[bitindex] = 'x';
01691 }
01692 } else {
01693 unsigned bit_mask = 1 << (bit_width-1);
01694 for (bitindex = 0; bitindex < bit_width; bitindex++) {
01695 rawdata[bitindex] = (object & bit_mask)? '1' : '0';
01696 bit_mask = bit_mask >> 1;
01697 }
01698 }
01699 rawdata[bitindex] = '\0';
01700 compose_data_line(rawdata, compdata);
01701 std::fputs(compdata, f);
01702 old_value = object;
01703 }
01704
01705
01706
01707
01708
01709
01710 vcd_trace_file::vcd_trace_file(const char *name)
01711 {
01712 std::string file_name = name ;
01713 file_name += ".vcd";
01714 fp = fopen(file_name.c_str(), "w");
01715 if (!fp) {
01716 std::string msg = std::string("Cannot write trace file '") +
01717 file_name + "'";
01718 ::std::cerr << "FATAL: " << msg << "\n";
01719 exit(1);
01720 }
01721 trace_delta_cycles = false;
01722 initialized = false;
01723 vcd_name_index = 0;
01724
01725
01726 timescale_unit = sc_get_time_resolution().to_seconds();
01727
01728 timescale_set_by_user = false;
01729 }
01730
01731
01732 void vcd_trace_file::initialize()
01733 {
01734 char buf[2000];
01735
01736
01737 time_t long_time;
01738 time(&long_time);
01739 struct tm* p_tm;
01740 p_tm = localtime(&long_time);
01741 strftime(buf, 199, "%b %d, %Y %H:%M:%S", p_tm);
01742 std::fprintf(fp, "$date\n %s\n$end\n\n", buf);
01743
01744
01745 std::fprintf(fp, "$version\n %s\n$end\n\n", sc_version());
01746
01747
01748 static struct SC_TIMESCALE_TO_TEXT {
01749 double unit;
01750 const char* text;
01751 } timescale_to_text [] = {
01752 { sc_time(1, SC_FS).to_seconds(), "1 fs" },
01753 { sc_time(10, SC_FS).to_seconds(), "10 fs" },
01754 { sc_time(100, SC_FS).to_seconds(),"100 fs" },
01755 { sc_time(1, SC_PS).to_seconds(), "1 ps" },
01756 { sc_time(10, SC_PS).to_seconds(), "10 ps" },
01757 { sc_time(100, SC_PS).to_seconds(),"100 ps" },
01758 { sc_time(1, SC_NS).to_seconds(), "1 ns" },
01759 { sc_time(10, SC_NS).to_seconds(), "10 ns" },
01760 { sc_time(100, SC_NS).to_seconds(),"100 ns" },
01761 { sc_time(1, SC_US).to_seconds(), "1 us" },
01762 { sc_time(10, SC_US).to_seconds(), "10 us" },
01763 { sc_time(100, SC_US).to_seconds(),"100 us" },
01764 { sc_time(1, SC_MS).to_seconds(), "1 ms" },
01765 { sc_time(10, SC_MS).to_seconds(), "10 ms" },
01766 { sc_time(100, SC_MS).to_seconds(),"100 ms" },
01767 { sc_time(1, SC_SEC).to_seconds(), "1 sec" },
01768 { sc_time(10, SC_SEC).to_seconds(), "10 sec" },
01769 { sc_time(100, SC_SEC).to_seconds(),"100 sec" }
01770 };
01771 static int timescale_to_text_n =
01772 sizeof(timescale_to_text)/sizeof(SC_TIMESCALE_TO_TEXT);
01773
01774 for ( int time_i = 0; time_i < timescale_to_text_n; time_i++ )
01775 {
01776 if (timescale_unit == timescale_to_text[time_i].unit)
01777 {
01778 std::fprintf(fp,"$timescale\n %s\n$end\n\n",
01779 timescale_to_text[time_i].text);
01780 break;
01781 }
01782 }
01783
01784
01785 running_regression = ( getenv( "SYSTEMC_REGRESSION" ) != NULL );
01786
01787 if( ! timescale_set_by_user && ! running_regression ) {
01788 ::std::cout << "WARNING: Default time step is used for VCD tracing." << ::std::endl;
01789 }
01790
01791
01792 std::fputs("$scope module SystemC $end\n", fp);
01793
01794
01795 int i;
01796 for (i = 0; i < (int)traces.size(); i++) {
01797 vcd_trace* t = traces[i];
01798 t->set_width();
01799 t->print_variable_declaration_line(fp);
01800 }
01801
01802 std::fputs("$upscope $end\n", fp);
01803
01804 std::fputs("$enddefinitions $end\n\n", fp);
01805
01806
01807 double inittime = sc_time_stamp().to_seconds();
01808
01809 std::sprintf(buf,
01810 "All initial values are dumped below at time "
01811 "%g sec = %g timescale units.",
01812 inittime, inittime/timescale_unit
01813 );
01814 write_comment(buf);
01815
01816 double_to_special_int64(inittime/timescale_unit,
01817 &previous_time_units_high,
01818 &previous_time_units_low );
01819
01820
01821 std::fputs("$dumpvars\n",fp);
01822 for (i = 0; i < (int)traces.size(); i++) {
01823 vcd_trace* t = traces[i];
01824 t->write(fp);
01825 std::fputc('\n', fp);
01826 }
01827 std::fputs("$end\n\n", fp);
01828 }
01829
01830
01831
01832
01833 #define DEFN_TRACE_METHOD(tp) \
01834 void \
01835 vcd_trace_file::trace(const tp& object_, const std::string& name_) \
01836 { \
01837 if( initialized ) { \
01838 put_error_message( \
01839 "No traces can be added once simulation has started.\n" \
01840 "To add traces, create a new vcd trace file.", false ); \
01841 } \
01842 std::string temp_vcd_name; \
01843 create_vcd_name( &temp_vcd_name ); \
01844 traces.push_back( new vcd_ ## tp ## _trace( object_, \
01845 name_, \
01846 temp_vcd_name ) ); \
01847 }
01848
01849 DEFN_TRACE_METHOD(bool)
01850 DEFN_TRACE_METHOD(float)
01851 DEFN_TRACE_METHOD(double)
01852
01853 #undef DEFN_TRACE_METHOD
01854 #define DEFN_TRACE_METHOD(tp) \
01855 void \
01856 vcd_trace_file::trace(const sc_dt::tp& object_, const std::string& name_)\
01857 { \
01858 if( initialized ) { \
01859 put_error_message( \
01860 "No traces can be added once simulation has started.\n" \
01861 "To add traces, create a new vcd trace file.", false ); \
01862 } \
01863 std::string temp_vcd_name; \
01864 create_vcd_name( &temp_vcd_name ); \
01865 traces.push_back( new vcd_ ## tp ## _trace( object_, \
01866 name_, \
01867 temp_vcd_name ) ); \
01868 }
01869
01870 DEFN_TRACE_METHOD(sc_bit)
01871 DEFN_TRACE_METHOD(sc_logic)
01872
01873 DEFN_TRACE_METHOD(sc_signed)
01874 DEFN_TRACE_METHOD(sc_unsigned)
01875 DEFN_TRACE_METHOD(sc_int_base)
01876 DEFN_TRACE_METHOD(sc_uint_base)
01877
01878 DEFN_TRACE_METHOD(sc_fxval)
01879 DEFN_TRACE_METHOD(sc_fxval_fast)
01880 DEFN_TRACE_METHOD(sc_fxnum)
01881 DEFN_TRACE_METHOD(sc_fxnum_fast)
01882
01883 #undef DEFN_TRACE_METHOD
01884
01885
01886 #define DEFN_TRACE_METHOD_SIGNED(tp) \
01887 void \
01888 vcd_trace_file::trace( const tp& object_, \
01889 const std::string& name_, \
01890 int width_ ) \
01891 { \
01892 if( initialized ) { \
01893 put_error_message( \
01894 "No traces can be added once simulation has started.\n" \
01895 "To add traces, create a new vcd trace file.", false ); \
01896 } \
01897 std::string temp_vcd_name; \
01898 create_vcd_name( &temp_vcd_name ); \
01899 traces.push_back( new vcd_signed_ ## tp ## _trace( object_, \
01900 name_, \
01901 temp_vcd_name, \
01902 width_ ) ); \
01903 }
01904
01905 #define DEFN_TRACE_METHOD_UNSIGNED(tp) \
01906 void \
01907 vcd_trace_file::trace( const unsigned tp& object_, \
01908 const std::string& name_, \
01909 int width_ ) \
01910 { \
01911 if( initialized ) { \
01912 put_error_message( \
01913 "No traces can be added once simulation has started.\n" \
01914 "To add traces, create a new vcd trace file.", false ); \
01915 } \
01916 std::string temp_vcd_name; \
01917 create_vcd_name( &temp_vcd_name ); \
01918 traces.push_back( new vcd_unsigned_ ## tp ## _trace( object_, \
01919 name_, \
01920 temp_vcd_name, \
01921 width_ ) ); \
01922 }
01923
01924 DEFN_TRACE_METHOD_SIGNED(char)
01925 DEFN_TRACE_METHOD_SIGNED(short)
01926 DEFN_TRACE_METHOD_SIGNED(int)
01927 DEFN_TRACE_METHOD_SIGNED(long)
01928
01929 DEFN_TRACE_METHOD_UNSIGNED(char)
01930 DEFN_TRACE_METHOD_UNSIGNED(short)
01931 DEFN_TRACE_METHOD_UNSIGNED(int)
01932 DEFN_TRACE_METHOD_UNSIGNED(long)
01933
01934 #undef DEFN_TRACE_METHOD_SIGNED
01935 #undef DEFN_TRACE_METHOD_UNSIGNED
01936
01937 #define DEFN_TRACE_METHOD_LONG_LONG(tp) \
01938 void \
01939 vcd_trace_file::trace( const sc_dt::tp& object_, \
01940 const std::string& name_, \
01941 int width_ ) \
01942 { \
01943 if( initialized ) { \
01944 put_error_message( \
01945 "No traces can be added once simulation has started.\n" \
01946 "To add traces, create a new vcd trace file.", false ); \
01947 } \
01948 std::string temp_vcd_name; \
01949 create_vcd_name( &temp_vcd_name ); \
01950 traces.push_back( new vcd_ ## tp ## _trace( object_, \
01951 name_, \
01952 temp_vcd_name, \
01953 width_ ) ); \
01954 }
01955 DEFN_TRACE_METHOD_LONG_LONG(int64)
01956 DEFN_TRACE_METHOD_LONG_LONG(uint64)
01957
01958 #undef DEFN_TRACE_METHOD_LONG_LONG
01959
01960 void
01961 vcd_trace_file::trace( const unsigned& object_,
01962 const std::string& name_,
01963 const char** enum_literals_ )
01964 {
01965 if( initialized ) {
01966 put_error_message(
01967 "No traces can be added once simulation has started.\n"
01968 "To add traces, create a new vcd trace file.", false );
01969 }
01970 std::string temp_vcd_name;
01971 create_vcd_name( &temp_vcd_name );
01972 traces.push_back( new vcd_enum_trace( object_,
01973 name_,
01974 temp_vcd_name,
01975 enum_literals_ ) );
01976 }
01977
01978
01979 void
01980 vcd_trace_file::write_comment(const std::string& comment)
01981 {
01982
01983 std::fputs("$comment\n", fp);
01984 std::fputs(comment.c_str(), fp);
01985 std::fputs("\n$end\n\n", fp);
01986 }
01987
01988 void
01989 vcd_trace_file::delta_cycles(bool flag)
01990 {
01991 trace_delta_cycles = flag;
01992 }
01993
01994 void
01995 vcd_trace_file::cycle(bool this_is_a_delta_cycle)
01996 {
01997 char message[4000];
01998 unsigned this_time_units_high, this_time_units_low;
01999
02000
02001 this_time_units_high = this_time_units_low = 0;
02002
02003
02004 if (!trace_delta_cycles && this_is_a_delta_cycle) return;
02005
02006
02007 if (!initialized) {
02008 initialize();
02009 initialized = true;
02010 return;
02011 };
02012
02013
02014 double now_units = sc_time_stamp().to_seconds() / timescale_unit;
02015 unsigned now_units_high, now_units_low;
02016 double_to_special_int64(now_units, &now_units_high, &now_units_low );
02017
02018 bool now_later_than_previous_time = false;
02019 if( now_units_low > previous_time_units_low
02020 && now_units_high == previous_time_units_high
02021 || now_units_high > previous_time_units_high){
02022 now_later_than_previous_time = true;
02023 }
02024
02025 bool now_equals_previous_time = false;
02026 if(now_later_than_previous_time){
02027 this_time_units_high = now_units_high;
02028 this_time_units_low = now_units_low;
02029 } else {
02030 if( now_units_low == previous_time_units_low
02031 && now_units_high == previous_time_units_high){
02032 now_equals_previous_time = true;
02033 this_time_units_high = now_units_high;
02034 this_time_units_low = now_units_low;
02035 }
02036 }
02037
02038
02039
02040 if(this_is_a_delta_cycle){
02041 this_time_units_high = previous_time_units_high;
02042 this_time_units_low = previous_time_units_low + 1;
02043 if(this_time_units_low == 1000000000){
02044 this_time_units_high++;
02045 this_time_units_low=0;
02046 }
02047 static bool warned = false;
02048 if(!warned){
02049 ::std::cout << "Note: VCD delta cycling with pseudo timesteps (1 unit) "
02050 "is performed.\n" << ::std::endl;
02051 warned = true;
02052 }
02053 }
02054
02055
02056
02057 if( ! this_is_a_delta_cycle && now_equals_previous_time &&
02058 ( now_units_high != 0 || now_units_low != 0 ) ) {
02059
02060 static bool warned = false;
02061 if( ! warned && ! running_regression ) {
02062 std::sprintf(message,
02063 "Multiple cycles found with same (%u) time units count.\n"
02064 "Waveform viewers will only show the states of the last one.\n"
02065 "Use ((vcd_trace_file*)vcdfile)->sc_set_vcd_time_unit(int exponent10_seconds)\n"
02066 "to increase time resolution.",
02067 now_units_low
02068 );
02069 put_error_message(message, true);
02070 warned = true;
02071 }
02072 }
02073
02074
02075
02076
02077 if(!this_is_a_delta_cycle && !now_equals_previous_time &&
02078 !now_later_than_previous_time){
02079 static bool warned = false;
02080 if(!warned){
02081 std::sprintf(message,
02082 "Cycle found with falling (%u -> %u) time units count.\n"
02083 "This can occur when delta cycling is activated.\n"
02084 "Cycles with falling time are not shown.\n"
02085 "Use ((vcd_trace_file*)vcdfile)->sc_set_vcd_time_unit(int exponent10_seconds)\n"
02086 "to increase time resolution.",
02087 previous_time_units_low, now_units_low);
02088 put_error_message(message, true);
02089 warned = true;
02090 }
02091
02092
02093
02094
02095
02096 return;
02097 }
02098
02099
02100 bool time_printed = false;
02101 vcd_trace* const* const l_traces = &traces[0];
02102 for (int i = 0; i < (int)traces.size(); i++) {
02103 vcd_trace* t = l_traces[i];
02104 if(t->changed()){
02105 if(time_printed == false){
02106 char buf[200];
02107 if(this_time_units_high){
02108 std::sprintf(buf, "#%u%09u", this_time_units_high, this_time_units_low);
02109 }
02110 else{
02111 std::sprintf(buf, "#%u", this_time_units_low);
02112 }
02113 std::fputs(buf, fp);
02114 std::fputc('\n', fp);
02115 time_printed = true;
02116 }
02117
02118
02119 t->write(fp);
02120 std::fputc('\n', fp);
02121 }
02122 }
02123
02124 if(time_printed) std::fputc('\n', fp);
02125
02126 if(time_printed){
02127
02128
02129
02130 previous_time_units_high = this_time_units_high;
02131 previous_time_units_low = this_time_units_low;
02132 }
02133 }
02134
02135 void
02136 vcd_trace_file::create_vcd_name(std::string* p_destination)
02137 {
02138 const char first_type_used = 'a';
02139 const int used_types_count = 'z' - 'a' + 1;
02140 int result;
02141
02142 char char4 = (char)(vcd_name_index % used_types_count);
02143
02144 result = vcd_name_index / used_types_count;
02145 char char3 = (char)(result % used_types_count);
02146
02147 result = result / used_types_count;
02148 char char2 = (char)(result % used_types_count);
02149
02150 char buf[20];
02151 std::sprintf(buf, "%c%c%c",
02152 char2 + first_type_used,
02153 char3 + first_type_used,
02154 char4 + first_type_used);
02155 *p_destination = buf;
02156 vcd_name_index++;
02157 }
02158
02159
02160 std::string
02161 vcd_trace_file::obtain_name()
02162 {
02163 const char first_type_used = 'a';
02164 const int used_types_count = 'z' - 'a' + 1;
02165 int result;
02166
02167 char char4 = (char)(vcd_name_index % used_types_count);
02168
02169 result = vcd_name_index / used_types_count;
02170 char char3 = (char)(result % used_types_count);
02171
02172 result = result / used_types_count;
02173 char char2 = (char)(result % used_types_count);
02174
02175 char buf[20];
02176 std::sprintf(buf, "%c%c%c",
02177 char2 + first_type_used,
02178 char3 + first_type_used,
02179 char4 + first_type_used);
02180 vcd_name_index++;
02181 return std::string(buf);
02182 }
02183
02184 vcd_trace_file::~vcd_trace_file()
02185 {
02186 int i;
02187 for (i = 0; i < (int)traces.size(); i++) {
02188 vcd_trace* t = traces[i];
02189 delete t;
02190 }
02191 fclose(fp);
02192 }
02193
02194
02195
02196
02197 static char
02198 map_sc_logic_state_to_vcd_state(char in_char)
02199 {
02200 char out_char;
02201
02202 switch(in_char){
02203 case 'U':
02204 case 'X':
02205 case 'W':
02206 case 'D':
02207 out_char = 'x';
02208 break;
02209 case '0':
02210 case 'L':
02211 out_char = '0';
02212 break;
02213 case '1':
02214 case 'H':
02215 out_char = '1';
02216 break;
02217 case 'Z':
02218 out_char = 'z';
02219 break;
02220 default:
02221 out_char = '?';
02222 }
02223
02224 return out_char;
02225 }
02226
02227
02228
02229
02230 static
02231 void
02232 remove_vcd_name_problems(std::string& name)
02233 {
02234 char message[4000];
02235 static bool warned = false;
02236
02237 bool braces_removed = false;
02238 for (unsigned int i = 0; i< name.length(); i++) {
02239 if (name[i] == '[') {
02240 name[i] = '(';
02241 braces_removed = true;
02242 }
02243 else if (name[i] == ']') {
02244 name[i] = ')';
02245 braces_removed = true;
02246 }
02247 }
02248
02249 if(braces_removed && !warned){
02250 std::sprintf(message,
02251 "Traced objects found with name containing [], which may be\n"
02252 "interpreted by the waveform viewer in unexpected ways.\n"
02253 "So the [] is automatically replaced by ().");
02254 put_error_message(message, true);
02255 warned = true;
02256 }
02257 }
02258
02259
02260 sc_trace_file*
02261 sc_create_vcd_trace_file(const char * name)
02262 {
02263 sc_trace_file *tf;
02264
02265 tf = new vcd_trace_file(name);
02266 sc_get_curr_simcontext()->add_trace_file(tf);
02267 return tf;
02268 }
02269
02270 void
02271 sc_close_vcd_trace_file( sc_trace_file* tf )
02272 {
02273 vcd_trace_file* vcd_tf = (vcd_trace_file*)tf;
02274 delete vcd_tf;
02275 }
02276
02277 }