sc_vcd_trace.cpp revision 12027
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 sc_vcd_trace.cpp - Implementation of VCD tracing. 23 24 Original Author - Abhijit Ghosh, Synopsys, Inc. 25 26 *****************************************************************************/ 27 28/***************************************************************************** 29 30 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 31 changes you are making here. 32 33 Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. 34 Description of Modification: - Replaced 'width' of sc_(u)int with their 35 'bitwidth()'. 36 37 Name, Affiliation, Date: 38 Description of Modification: 39 40 *****************************************************************************/ 41 42/***************************************************************************** 43 44 Acknowledgement: The tracing mechanism is based on the tracing 45 mechanism developed at Infineon (formerly Siemens HL). Though this 46 code is somewhat different, and significantly enhanced, the basics 47 are identical to what was originally contributed by Infineon. The 48 contribution of Infineon in the development of this tracing 49 technology is hereby acknowledged. 50 51 *****************************************************************************/ 52 53 54#include <cstdlib> 55#include <string.h> 56#include <vector> 57 58#define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion 59 60#include "sysc/kernel/sc_simcontext.h" 61#include "sysc/kernel/sc_ver.h" 62#include "sysc/datatypes/bit/sc_bit.h" 63#include "sysc/datatypes/bit/sc_logic.h" 64#include "sysc/datatypes/bit/sc_lv_base.h" 65#include "sysc/datatypes/int/sc_signed.h" 66#include "sysc/datatypes/int/sc_unsigned.h" 67#include "sysc/datatypes/int/sc_int_base.h" 68#include "sysc/datatypes/int/sc_uint_base.h" 69#include "sysc/datatypes/fx/fx.h" 70#include "sysc/tracing/sc_vcd_trace.h" 71 72namespace sc_core { 73 74// Forward declarations for functions that come later in the file 75// Map sc_dt::sc_logic to printable VCD 76static char map_sc_logic_state_to_vcd_state(char in_char); 77 78// Remove name problems associated with [] in vcd names 79static void remove_vcd_name_problems(vcd_trace const* vcd, std::string& name); 80 81const char* vcd_types[vcd_trace_file::VCD_LAST]={"wire","real"}; 82 83 84// ---------------------------------------------------------------------------- 85// CLASS : vcd_trace 86// 87// Base class for VCD traces. 88// ---------------------------------------------------------------------------- 89 90class vcd_trace 91{ 92public: 93 94 vcd_trace(const std::string& name_, const std::string& vcd_name_); 95 96 // Needs to be pure virtual as has to be defined by the particular 97 // type being traced 98 virtual void write(FILE* f) = 0; 99 100 virtual void set_width(); 101 102 static const char* strip_leading_bits(const char* originalbuf); 103 104 // Comparison function needs to be pure virtual too 105 virtual bool changed() = 0; 106 107 // Make this virtual as some derived classes may overwrite 108 virtual void print_variable_declaration_line(FILE* f); 109 110 void compose_data_line(char* rawdata, char* compdata); 111 std::string compose_line(const std::string& data); 112 113 virtual ~vcd_trace(); 114 115 const std::string name; 116 const std::string vcd_name; 117 const char* vcd_var_typ_name; 118 int bit_width; 119}; 120 121 122vcd_trace::vcd_trace(const std::string& name_, const std::string& vcd_name_) 123: name(name_), vcd_name(vcd_name_), vcd_var_typ_name(0), bit_width(0) 124{ 125 /* Intentionally blank */ 126} 127 128void 129vcd_trace::compose_data_line(char* rawdata, char* compdata) 130{ 131 sc_assert(rawdata != compdata); 132 133 if(bit_width == 0) 134 { 135 compdata[0] = '\0'; 136 } 137 else 138 { 139 if(bit_width == 1) 140 { 141 compdata[0] = rawdata[0]; 142 strcpy(&(compdata[1]), vcd_name.c_str()); 143 } 144 else 145 { 146 const char* effective_begin = strip_leading_bits(rawdata); 147 std::sprintf(compdata, "b%s %s", effective_begin, vcd_name.c_str()); 148 } 149 } 150} 151 152// same as above but not that ugly 153std::string 154vcd_trace::compose_line(const std::string& data) 155{ 156 if(bit_width == 0) 157 return ""; 158 if(bit_width == 1) 159 return data + vcd_name; 160 return std::string("b")+strip_leading_bits(data.c_str())+" "+vcd_name; 161} 162 163void 164vcd_trace::print_variable_declaration_line(FILE* f) 165{ 166 char buf[2000]; 167 168 if ( bit_width <= 0 ) 169 { 170 std::stringstream ss; 171 ss << "'" << name << "' has 0 bits"; 172 SC_REPORT_ERROR( SC_ID_TRACING_OBJECT_IGNORED_ 173 , ss.str().c_str() ); 174 return; 175 } 176 177 std::string namecopy = name; 178 remove_vcd_name_problems(this, namecopy); 179 if ( bit_width == 1 ) 180 { 181 std::sprintf(buf, "$var %s % 3d %s %s $end\n", 182 vcd_var_typ_name, 183 bit_width, 184 vcd_name.c_str(), 185 namecopy.c_str()); 186 } 187 else 188 { 189 std::sprintf(buf, "$var %s % 3d %s %s [%d:0] $end\n", 190 vcd_var_typ_name, 191 bit_width, 192 vcd_name.c_str(), 193 namecopy.c_str(), 194 bit_width-1); 195 } 196 std::fputs(buf, f); 197} 198 199void 200vcd_trace::set_width() 201{ 202 /* Intentionally Blank, should be defined for each type separately */ 203} 204 205const char* 206vcd_trace::strip_leading_bits(const char* originalbuf) 207{ 208 //********************************************************************* 209 // - Remove multiple leading 0,z,x, and replace by only one 210 // - For example, 211 // b000z100 -> b0z100 212 // b00000xxx -> b0xxx 213 // b000 -> b0 214 // bzzzzz1 -> bz1 215 // bxxxz10 -> xz10 216 // - For leading 0's followed by 1, remove all leading 0's 217 // b0000010101 -> b10101 218 219 const char* position = originalbuf; 220 221 if( strlen(originalbuf) < 2 || 222 (originalbuf[0] != 'z' && originalbuf[0] != 'x' && 223 originalbuf[0] != '0' )) 224 return originalbuf; 225 226 char first_char = *position; 227 while(*position == first_char) 228 { 229 position++; 230 } 231 232 if(first_char == '0' && *position == '1') 233 return position; 234 // else 235 return position-1; 236} 237 238vcd_trace::~vcd_trace() 239{ 240 /* Intentionally Blank */ 241} 242 243 244template <class T> 245class vcd_T_trace : public vcd_trace 246{ 247 public: 248 249 vcd_T_trace( const T& object_, 250 const std::string& name_, 251 const std::string& vcd_name_, 252 vcd_trace_file::vcd_enum type_ ) 253 : vcd_trace( name_, vcd_name_ ), 254 object( object_ ), 255 old_value( object_ ) 256 { 257 vcd_var_typ_name = vcd_types[type_]; 258 } 259 260 void write( FILE* f ) 261 { 262 std::fprintf( f, "%s", compose_line( object.to_string() ).c_str() ); 263 old_value = object; 264 } 265 266 bool changed() 267 { return !(object == old_value); } 268 269 void set_width() 270 { bit_width = object.length(); } 271 272protected: 273 274 const T& object; 275 T old_value; 276}; 277 278typedef vcd_T_trace<sc_dt::sc_bv_base> vcd_sc_bv_trace; 279typedef vcd_T_trace<sc_dt::sc_lv_base> vcd_sc_lv_trace; 280 281// Trace sc_dt::sc_bv_base (sc_dt::sc_bv) 282void 283vcd_trace_file::trace( 284 const sc_dt::sc_bv_base& object, const std::string& name) 285{ 286 traceT(object,name); 287} 288 289// Trace sc_dt::sc_lv_base (sc_dt::sc_lv) 290void 291vcd_trace_file::trace( 292 const sc_dt::sc_lv_base& object, const std::string& name) 293{ 294 traceT(object,name); 295} 296 297/*****************************************************************************/ 298 299class vcd_bool_trace : public vcd_trace { 300public: 301 vcd_bool_trace(const bool& object_, 302 const std::string& name_, 303 const std::string& vcd_name_); 304 void write(FILE* f); 305 bool changed(); 306 307protected: 308 const bool& object; 309 bool old_value; 310}; 311 312vcd_bool_trace::vcd_bool_trace(const bool& object_, 313 const std::string& name_, 314 const std::string& vcd_name_) 315: vcd_trace(name_, vcd_name_), object(object_), old_value(object_) 316{ 317 vcd_var_typ_name = "wire"; 318 bit_width = 1; 319} 320 321bool 322vcd_bool_trace::changed() 323{ 324 return object != old_value; 325} 326 327void 328vcd_bool_trace::write(FILE* f) 329{ 330 if (object == true) std::fputc('1', f); 331 else std::fputc('0', f); 332 333 std::fprintf(f,"%s", vcd_name.c_str()); 334 335 old_value = object; 336} 337 338//***************************************************************************** 339 340class vcd_sc_bit_trace : public vcd_trace { 341public: 342 vcd_sc_bit_trace(const sc_dt::sc_bit& , const std::string& , 343 const std::string& ); 344 void write(FILE* f); 345 bool changed(); 346 347protected: 348 const sc_dt::sc_bit& object; 349 sc_dt::sc_bit old_value; 350}; 351 352vcd_sc_bit_trace::vcd_sc_bit_trace( const sc_dt::sc_bit& object_, 353 const std::string& name, 354 const std::string& vcd_name) 355: vcd_trace(name, vcd_name), object( object_ ), old_value( object_ ) 356{ 357 vcd_var_typ_name = "wire"; 358 bit_width = 1; 359} 360 361bool 362vcd_sc_bit_trace::changed() 363{ 364 return object != old_value; 365} 366 367void 368vcd_sc_bit_trace::write(FILE* f) 369{ 370 if (object == true) std::fputc('1', f); 371 else std::fputc('0', f); 372 373 std::fprintf(f,"%s", vcd_name.c_str()); 374 375 old_value = object; 376} 377 378/*****************************************************************************/ 379 380class vcd_sc_logic_trace : public vcd_trace { 381public: 382 vcd_sc_logic_trace(const sc_dt::sc_logic& object_, 383 const std::string& name_, 384 const std::string& vcd_name_); 385 void write(FILE* f); 386 bool changed(); 387 388protected: 389 const sc_dt::sc_logic& object; 390 sc_dt::sc_logic old_value; 391}; 392 393 394vcd_sc_logic_trace::vcd_sc_logic_trace(const sc_dt::sc_logic& object_, 395 const std::string& name_, 396 const std::string& vcd_name_) 397: vcd_trace(name_, vcd_name_), object(object_), old_value(object_) 398{ 399 vcd_var_typ_name = "wire"; 400 bit_width = 1; 401} 402 403 404bool 405vcd_sc_logic_trace::changed() 406{ 407 return object != old_value; 408} 409 410 411void 412vcd_sc_logic_trace::write(FILE* f) 413{ 414 char out_char; 415 out_char = map_sc_logic_state_to_vcd_state(object.to_char()); 416 std::fputc(out_char, f); 417 418 std::fprintf(f,"%s", vcd_name.c_str()); 419 420 old_value = object; 421} 422 423 424/*****************************************************************************/ 425 426class vcd_sc_unsigned_trace : public vcd_trace { 427public: 428 vcd_sc_unsigned_trace(const sc_dt::sc_unsigned& object, 429 const std::string& name_, 430 const std::string& vcd_name_); 431 void write(FILE* f); 432 bool changed(); 433 void set_width(); 434 435protected: 436 const sc_dt::sc_unsigned& object; 437 sc_dt::sc_unsigned old_value; 438}; 439 440 441vcd_sc_unsigned_trace::vcd_sc_unsigned_trace(const sc_dt::sc_unsigned& object_, 442 const std::string& name_, 443 const std::string& vcd_name_) 444: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) 445// The last may look strange, but is correct 446{ 447 vcd_var_typ_name = "wire"; 448 old_value = object; 449} 450 451bool 452vcd_sc_unsigned_trace::changed() 453{ 454 return object != old_value; 455} 456 457void 458vcd_sc_unsigned_trace::write(FILE* f) 459{ 460 static std::vector<char> compdata(1024), rawdata(1024); 461 typedef std::vector<char>::size_type size_t; 462 463 if ( compdata.size() < (size_t)object.length() ) { 464 size_t sz = ( (size_t)object.length() + 4096 ) & (~(size_t)(4096-1)); 465 std::vector<char>( sz ).swap( compdata ); // resize without copying values 466 std::vector<char>( sz ).swap( rawdata ); 467 } 468 char *rawdata_ptr = &rawdata[0]; 469 470 for (int bitindex = object.length() - 1; bitindex >= 0; --bitindex) { 471 *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; 472 } 473 *rawdata_ptr = '\0'; 474 compose_data_line(&rawdata[0], &compdata[0]); 475 476 std::fputs(&compdata[0], f); 477 old_value = object; 478} 479 480void 481vcd_sc_unsigned_trace::set_width() 482{ 483 bit_width = object.length(); 484} 485 486 487/*****************************************************************************/ 488 489class vcd_sc_signed_trace : public vcd_trace { 490public: 491 vcd_sc_signed_trace(const sc_dt::sc_signed& object, 492 const std::string& name_, 493 const std::string& vcd_name_); 494 void write(FILE* f); 495 bool changed(); 496 void set_width(); 497 498protected: 499 const sc_dt::sc_signed& object; 500 sc_dt::sc_signed old_value; 501}; 502 503 504vcd_sc_signed_trace::vcd_sc_signed_trace(const sc_dt::sc_signed& object_, 505 const std::string& name_, 506 const std::string& vcd_name_) 507: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) 508{ 509 vcd_var_typ_name = "wire"; 510 old_value = object; 511} 512 513bool 514vcd_sc_signed_trace::changed() 515{ 516 return object != old_value; 517} 518 519void 520vcd_sc_signed_trace::write(FILE* f) 521{ 522 static std::vector<char> compdata(1024), rawdata(1024); 523 typedef std::vector<char>::size_type size_t; 524 525 if ( compdata.size() < (size_t)object.length() ) { 526 size_t sz = ( (size_t)object.length() + 4096 ) & (~(size_t)(4096-1)); 527 std::vector<char>( sz ).swap( compdata ); // resize without copying values 528 std::vector<char>( sz ).swap( rawdata ); 529 } 530 char *rawdata_ptr = &rawdata[0]; 531 532 for (int bitindex = object.length() - 1; bitindex >= 0; --bitindex) { 533 *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; 534 } 535 *rawdata_ptr = '\0'; 536 compose_data_line(&rawdata[0], &compdata[0]); 537 538 std::fputs(&compdata[0], f); 539 old_value = object; 540} 541 542void 543vcd_sc_signed_trace::set_width() 544{ 545 bit_width = object.length(); 546} 547 548/*****************************************************************************/ 549 550class vcd_sc_uint_base_trace : public vcd_trace { 551public: 552 vcd_sc_uint_base_trace(const sc_dt::sc_uint_base& object, 553 const std::string& name_, 554 const std::string& vcd_name_); 555 void write(FILE* f); 556 bool changed(); 557 void set_width(); 558 559protected: 560 const sc_dt::sc_uint_base& object; 561 sc_dt::sc_uint_base old_value; 562}; 563 564 565vcd_sc_uint_base_trace::vcd_sc_uint_base_trace( 566 const sc_dt::sc_uint_base& object_, 567 const std::string& name_, 568 const std::string& vcd_name_) 569: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) 570// The last may look strange, but is correct 571{ 572 vcd_var_typ_name = "wire"; 573 old_value = object; 574} 575 576bool 577vcd_sc_uint_base_trace::changed() 578{ 579 return object != old_value; 580} 581 582void 583vcd_sc_uint_base_trace::write(FILE* f) 584{ 585 char rawdata[1000], *rawdata_ptr = rawdata; 586 char compdata[1000]; 587 588 int bitindex; 589 for (bitindex = object.length()-1; bitindex >= 0; --bitindex) { 590 *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; 591 } 592 *rawdata_ptr = '\0'; 593 compose_data_line(rawdata, compdata); 594 595 std::fputs(compdata, f); 596 old_value = object; 597} 598 599void 600vcd_sc_uint_base_trace::set_width() 601{ 602 bit_width = object.length(); 603} 604 605 606/*****************************************************************************/ 607 608class vcd_sc_int_base_trace : public vcd_trace { 609public: 610 vcd_sc_int_base_trace(const sc_dt::sc_int_base& object, 611 const std::string& name_, 612 const std::string& vcd_name_); 613 void write(FILE* f); 614 bool changed(); 615 void set_width(); 616 617protected: 618 const sc_dt::sc_int_base& object; 619 sc_dt::sc_int_base old_value; 620}; 621 622 623vcd_sc_int_base_trace::vcd_sc_int_base_trace(const sc_dt::sc_int_base& object_, 624 const std::string& name_, 625 const std::string& vcd_name_) 626: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) 627{ 628 vcd_var_typ_name = "wire"; 629 old_value = object; 630} 631 632bool 633vcd_sc_int_base_trace::changed() 634{ 635 return object != old_value; 636} 637 638void 639vcd_sc_int_base_trace::write(FILE* f) 640{ 641 char rawdata[1000], *rawdata_ptr = rawdata; 642 char compdata[1000]; 643 644 int bitindex; 645 for (bitindex = object.length()-1; bitindex >= 0; --bitindex) { 646 *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; 647 } 648 *rawdata_ptr = '\0'; 649 compose_data_line(rawdata, compdata); 650 651 std::fputs(compdata, f); 652 old_value = object; 653} 654 655void 656vcd_sc_int_base_trace::set_width() 657{ 658 bit_width = object.length(); 659} 660 661 662/*****************************************************************************/ 663 664class vcd_sc_fxval_trace : public vcd_trace 665{ 666public: 667 668 vcd_sc_fxval_trace( const sc_dt::sc_fxval& object, 669 const std::string& name_, 670 const std::string& vcd_name_ ); 671 void write( FILE* f ); 672 bool changed(); 673 674protected: 675 676 const sc_dt::sc_fxval& object; 677 sc_dt::sc_fxval old_value; 678 679}; 680 681vcd_sc_fxval_trace::vcd_sc_fxval_trace( const sc_dt::sc_fxval& object_, 682 const std::string& name_, 683 const std::string& vcd_name_ ) 684: vcd_trace( name_, vcd_name_ ), 685 object( object_ ), old_value( object_ ) 686{ 687 vcd_var_typ_name = "real"; 688 bit_width = 1; 689} 690 691bool 692vcd_sc_fxval_trace::changed() 693{ 694 return object != old_value; 695} 696 697void 698vcd_sc_fxval_trace::write( FILE* f ) 699{ 700 std::fprintf( f, "r%.16g %s", object.to_double(), vcd_name.c_str() ); 701 old_value = object; 702} 703 704/*****************************************************************************/ 705 706class vcd_sc_fxval_fast_trace : public vcd_trace 707{ 708public: 709 710 vcd_sc_fxval_fast_trace( const sc_dt::sc_fxval_fast& object, 711 const std::string& name_, 712 const std::string& vcd_name_ ); 713 void write( FILE* f ); 714 bool changed(); 715 716protected: 717 718 const sc_dt::sc_fxval_fast& object; 719 sc_dt::sc_fxval_fast old_value; 720 721}; 722 723vcd_sc_fxval_fast_trace::vcd_sc_fxval_fast_trace( 724 const sc_dt::sc_fxval_fast& object_, 725 const std::string& name_, 726 const std::string& vcd_name_ ) 727: vcd_trace( name_, vcd_name_ ), 728 object( object_ ), old_value( object_ ) 729{ 730 vcd_var_typ_name = "real"; 731 bit_width = 1; 732} 733 734bool 735vcd_sc_fxval_fast_trace::changed() 736{ 737 return object != old_value; 738} 739 740void 741vcd_sc_fxval_fast_trace::write( FILE* f ) 742{ 743 std::fprintf( f, "r%.16g %s", object.to_double(), vcd_name.c_str() ); 744 old_value = object; 745} 746 747/*****************************************************************************/ 748 749class vcd_sc_fxnum_trace : public vcd_trace 750{ 751public: 752 753 vcd_sc_fxnum_trace( const sc_dt::sc_fxnum& object, 754 const std::string& name_, 755 const std::string& vcd_name_ ); 756 void write( FILE* f ); 757 bool changed(); 758 void set_width(); 759 760protected: 761 762 const sc_dt::sc_fxnum& object; 763 sc_dt::sc_fxnum old_value; 764 765}; 766 767vcd_sc_fxnum_trace::vcd_sc_fxnum_trace( const sc_dt::sc_fxnum& object_, 768 const std::string& name_, 769 const std::string& vcd_name_ ) 770: vcd_trace( name_, vcd_name_ ), 771 object( object_ ), 772 old_value( object_.m_params.type_params(), 773 object_.m_params.enc(), 774 object_.m_params.cast_switch(), 775 0 ) 776{ 777 vcd_var_typ_name = "wire"; 778 old_value = object; 779} 780 781bool 782vcd_sc_fxnum_trace::changed() 783{ 784 return object != old_value; 785} 786 787void 788vcd_sc_fxnum_trace::write( FILE* f ) 789{ 790 static std::vector<char> compdata(1024), rawdata(1024); 791 typedef std::vector<char>::size_type size_t; 792 793 if ( compdata.size() < (size_t)object.wl() ) { 794 size_t sz = ( (size_t)object.wl() + 4096 ) & (~(size_t)(4096-1)); 795 std::vector<char>( sz ).swap( compdata ); // resize without copying values 796 std::vector<char>( sz ).swap( rawdata ); 797 } 798 char *rawdata_ptr = &rawdata[0]; 799 800 for(int bitindex = object.wl() - 1; bitindex >= 0; -- bitindex ) 801 { 802 *rawdata_ptr ++ = "01"[object[bitindex]]; 803 } 804 *rawdata_ptr = '\0'; 805 compose_data_line( &rawdata[0], &compdata[0] ); 806 807 std::fputs( &compdata[0], f ); 808 old_value = object; 809} 810 811void 812vcd_sc_fxnum_trace::set_width() 813{ 814 bit_width = object.wl(); 815} 816 817/*****************************************************************************/ 818 819class vcd_sc_fxnum_fast_trace : public vcd_trace 820{ 821public: 822 823 vcd_sc_fxnum_fast_trace( const sc_dt::sc_fxnum_fast& object, 824 const std::string& name_, 825 const std::string& vcd_name_ ); 826 void write( FILE* f ); 827 bool changed(); 828 void set_width(); 829 830protected: 831 832 const sc_dt::sc_fxnum_fast& object; 833 sc_dt::sc_fxnum_fast old_value; 834 835}; 836 837vcd_sc_fxnum_fast_trace::vcd_sc_fxnum_fast_trace( 838 const sc_dt::sc_fxnum_fast& object_, 839 const std::string& name_, 840 const std::string& vcd_name_ ) 841: vcd_trace( name_, vcd_name_ ), 842 object( object_ ), 843 old_value( object_.m_params.type_params(), 844 object_.m_params.enc(), 845 object_.m_params.cast_switch(), 846 0 ) 847{ 848 vcd_var_typ_name = "wire"; 849 old_value = object; 850} 851 852bool 853vcd_sc_fxnum_fast_trace::changed() 854{ 855 return object != old_value; 856} 857 858void 859vcd_sc_fxnum_fast_trace::write( FILE* f ) 860{ 861 static std::vector<char> compdata(1024), rawdata(1024); 862 typedef std::vector<char>::size_type size_t; 863 864 if ( compdata.size() < (size_t)object.wl() ) { 865 size_t sz = ( (size_t)object.wl() + 4096 ) & (~(size_t)(4096-1)); 866 std::vector<char>( sz ).swap( compdata ); // resize without copying values 867 std::vector<char>( sz ).swap( rawdata ); 868 } 869 char *rawdata_ptr = &rawdata[0]; 870 871 for(int bitindex = object.wl() - 1; bitindex >= 0; -- bitindex ) 872 { 873 *rawdata_ptr ++ = "01"[object[bitindex]]; 874 } 875 *rawdata_ptr = '\0'; 876 compose_data_line( &rawdata[0], &compdata[0] ); 877 878 std::fputs( &compdata[0], f ); 879 old_value = object; 880} 881 882void 883vcd_sc_fxnum_fast_trace::set_width() 884{ 885 bit_width = object.wl(); 886} 887 888 889/*****************************************************************************/ 890 891class vcd_unsigned_int_trace : public vcd_trace { 892public: 893 vcd_unsigned_int_trace(const unsigned& object, 894 const std::string& name_, 895 const std::string& vcd_name_, 896 int width_); 897 void write(FILE* f); 898 bool changed(); 899 900protected: 901 const unsigned& object; 902 unsigned old_value; 903 unsigned mask; 904}; 905 906 907vcd_unsigned_int_trace::vcd_unsigned_int_trace( 908 const unsigned& object_, 909 const std::string& name_, 910 const std::string& vcd_name_, 911 int width_) 912: vcd_trace(name_, vcd_name_), object(object_), old_value( object_ ), 913 mask((unsigned)-1) 914{ 915 bit_width = width_; 916 if (bit_width < 32) mask = ~(-1 << bit_width); 917 918 vcd_var_typ_name = "wire"; 919} 920 921 922bool 923vcd_unsigned_int_trace::changed() 924{ 925 return object != old_value; 926} 927 928 929void 930vcd_unsigned_int_trace::write(FILE* f) 931{ 932 char rawdata[1000]; 933 char compdata[1000]; 934 int bitindex; 935 936 // Check for overflow 937 if ((object & mask) != object) { 938 for (bitindex = 0; bitindex < bit_width; bitindex++){ 939 rawdata[bitindex] = 'x'; 940 } 941 } 942 else{ 943 unsigned bit_mask = 1 << (bit_width-1); 944 for (bitindex = 0; bitindex < bit_width; bitindex++) { 945 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 946 bit_mask = bit_mask >> 1; 947 } 948 } 949 rawdata[bitindex] = '\0'; 950 compose_data_line(rawdata, compdata); 951 std::fputs(compdata, f); 952 old_value = object; 953} 954 955/*****************************************************************************/ 956 957class vcd_unsigned_short_trace : public vcd_trace { 958public: 959 vcd_unsigned_short_trace(const unsigned short& object, 960 const std::string& name_, 961 const std::string& vcd_name_, 962 int width_); 963 void write(FILE* f); 964 bool changed(); 965 966protected: 967 const unsigned short& object; 968 unsigned short old_value; 969 unsigned short mask; 970}; 971 972 973vcd_unsigned_short_trace::vcd_unsigned_short_trace( 974 const unsigned short& object_, 975 const std::string& name_, 976 const std::string& vcd_name_, 977 int width_) 978: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xffff) 979{ 980 bit_width = width_; 981 if (bit_width < 16) mask = (unsigned short)~(-1 << bit_width); 982 983 vcd_var_typ_name = "wire"; 984} 985 986 987bool 988vcd_unsigned_short_trace::changed() 989{ 990 return object != old_value; 991} 992 993 994void 995vcd_unsigned_short_trace::write(FILE* f) 996{ 997 char rawdata[1000]; 998 char compdata[1000]; 999 int bitindex; 1000 1001 // Check for overflow 1002 if ((object & mask) != object) { 1003 for (bitindex = 0; bitindex < bit_width; bitindex++){ 1004 rawdata[bitindex] = 'x'; 1005 } 1006 } 1007 else{ 1008 unsigned bit_mask = 1 << (bit_width-1); 1009 for (bitindex = 0; bitindex < bit_width; bitindex++) { 1010 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 1011 bit_mask = bit_mask >> 1; 1012 } 1013 } 1014 rawdata[bitindex] = '\0'; 1015 compose_data_line(rawdata, compdata); 1016 std::fputs(compdata, f); 1017 old_value = object; 1018} 1019 1020/*****************************************************************************/ 1021 1022class vcd_unsigned_char_trace : public vcd_trace { 1023public: 1024 vcd_unsigned_char_trace(const unsigned char& object, 1025 const std::string& name_, 1026 const std::string& vcd_name_, 1027 int width_); 1028 void write(FILE* f); 1029 bool changed(); 1030 1031protected: 1032 const unsigned char& object; 1033 unsigned char old_value; 1034 unsigned char mask; 1035}; 1036 1037 1038vcd_unsigned_char_trace::vcd_unsigned_char_trace( 1039 const unsigned char& object_, 1040 const std::string& name_, 1041 const std::string& vcd_name_, 1042 int width_) 1043: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xff) 1044{ 1045 bit_width = width_; 1046 if (bit_width < 8) mask = (unsigned char)~(-1 << bit_width); 1047 vcd_var_typ_name = "wire"; 1048} 1049 1050 1051bool vcd_unsigned_char_trace::changed() 1052{ 1053 return object != old_value; 1054} 1055 1056 1057void vcd_unsigned_char_trace::write(FILE* f) 1058{ 1059 char rawdata[1000]; 1060 char compdata[1000]; 1061 int bitindex; 1062 1063 // Check for overflow 1064 if ((object & mask) != object) { 1065 for (bitindex = 0; bitindex < bit_width; bitindex++){ 1066 rawdata[bitindex] = 'x'; 1067 } 1068 } 1069 else{ 1070 unsigned bit_mask = 1 << (bit_width-1); 1071 for (bitindex = 0; bitindex < bit_width; bitindex++) { 1072 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 1073 bit_mask = bit_mask >> 1; 1074 } 1075 } 1076 rawdata[bitindex] = '\0'; 1077 compose_data_line(rawdata, compdata); 1078 std::fputs(compdata, f); 1079 old_value = object; 1080} 1081 1082/*****************************************************************************/ 1083 1084class vcd_unsigned_long_trace : public vcd_trace { 1085public: 1086 vcd_unsigned_long_trace(const unsigned long& object, 1087 const std::string& name_, 1088 const std::string& vcd_name_, 1089 int width_); 1090 void write(FILE* f); 1091 bool changed(); 1092 1093protected: 1094 const unsigned long& object; 1095 unsigned long old_value; 1096 unsigned long mask; 1097}; 1098 1099 1100vcd_unsigned_long_trace::vcd_unsigned_long_trace( 1101 const unsigned long& object_, 1102 const std::string& name_, 1103 const std::string& vcd_name_, 1104 int width_) 1105: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), 1106 mask((unsigned long)-1) 1107{ 1108 bit_width = width_; 1109 if ( bit_width < (int)(sizeof(unsigned long)*8) ) 1110 mask = ~(-1L << bit_width); 1111 1112 vcd_var_typ_name = "wire"; 1113} 1114 1115 1116bool vcd_unsigned_long_trace::changed() 1117{ 1118 return object != old_value; 1119} 1120 1121 1122void vcd_unsigned_long_trace::write(FILE* f) 1123{ 1124 char rawdata[1000]; 1125 char compdata[1000]; 1126 int bitindex; 1127 1128 // Check for overflow 1129 if ((object & mask) != object) { 1130 for (bitindex = 0; bitindex < bit_width; bitindex++){ 1131 rawdata[bitindex] = 'x'; 1132 } 1133 } 1134 else{ 1135 unsigned long bit_mask = 1ul << (bit_width-1); 1136 for (bitindex = 0; bitindex < bit_width; bitindex++) { 1137 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 1138 bit_mask = bit_mask >> 1; 1139 } 1140 } 1141 rawdata[bitindex] = '\0'; 1142 compose_data_line(rawdata, compdata); 1143 std::fputs(compdata, f); 1144 old_value = object; 1145} 1146 1147/*****************************************************************************/ 1148 1149class vcd_signed_int_trace : public vcd_trace { 1150public: 1151 vcd_signed_int_trace(const int& object, 1152 const std::string& name_, 1153 const std::string& vcd_name_, 1154 int width_); 1155 void write(FILE* f); 1156 bool changed(); 1157 1158protected: 1159 const int& object; 1160 int old_value; 1161 unsigned mask; 1162}; 1163 1164 1165vcd_signed_int_trace::vcd_signed_int_trace(const signed& object_, 1166 const std::string& name_, 1167 const std::string& vcd_name_, 1168 int width_) 1169: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), 1170 mask((unsigned)-1) 1171{ 1172 bit_width = width_; 1173 if (bit_width < 32) mask = ~(-1 << bit_width); 1174 1175 vcd_var_typ_name = "wire"; 1176} 1177 1178 1179bool vcd_signed_int_trace::changed() 1180{ 1181 return object != old_value; 1182} 1183 1184 1185void vcd_signed_int_trace::write(FILE* f) 1186{ 1187 char rawdata[1000]; 1188 char compdata[1000]; 1189 int bitindex; 1190 1191 // Check for overflow 1192 if (((unsigned) object & mask) != (unsigned) object) { 1193 for (bitindex = 0; bitindex < bit_width; bitindex++){ 1194 rawdata[bitindex] = 'x'; 1195 } 1196 } 1197 else{ 1198 unsigned bit_mask = 1 << (bit_width-1); 1199 for (bitindex = 0; bitindex < bit_width; bitindex++) { 1200 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 1201 bit_mask = bit_mask >> 1; 1202 } 1203 } 1204 rawdata[bitindex] = '\0'; 1205 compose_data_line(rawdata, compdata); 1206 std::fputs(compdata, f); 1207 old_value = object; 1208} 1209 1210/*****************************************************************************/ 1211 1212class vcd_signed_short_trace : public vcd_trace { 1213public: 1214 vcd_signed_short_trace(const short& object, 1215 const std::string& name_, 1216 const std::string& vcd_name_, 1217 int width_); 1218 void write(FILE* f); 1219 bool changed(); 1220 1221protected: 1222 const short& object; 1223 short old_value; 1224 unsigned short mask; 1225}; 1226 1227 1228vcd_signed_short_trace::vcd_signed_short_trace( 1229 const short& object_, 1230 const std::string& name_, 1231 const std::string& vcd_name_, 1232 int width_) 1233: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xffff) 1234{ 1235 bit_width = width_; 1236 if (bit_width < 16) mask = (unsigned short)~(-1 << bit_width); 1237 1238 vcd_var_typ_name = "wire"; 1239} 1240 1241 1242bool vcd_signed_short_trace::changed() 1243{ 1244 return object != old_value; 1245} 1246 1247 1248void vcd_signed_short_trace::write(FILE* f) 1249{ 1250 char rawdata[1000]; 1251 char compdata[1000]; 1252 int bitindex; 1253 1254 // Check for overflow 1255 if (((unsigned short) object & mask) != (unsigned short) object) { 1256 for (bitindex = 0; bitindex < bit_width; bitindex++){ 1257 rawdata[bitindex] = 'x'; 1258 } 1259 } 1260 else{ 1261 unsigned bit_mask = 1 << (bit_width-1); 1262 for (bitindex = 0; bitindex < bit_width; bitindex++) { 1263 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 1264 bit_mask = bit_mask >> 1; 1265 } 1266 } 1267 rawdata[bitindex] = '\0'; 1268 compose_data_line(rawdata, compdata); 1269 std::fputs(compdata, f); 1270 old_value = object; 1271} 1272 1273/*****************************************************************************/ 1274 1275class vcd_signed_char_trace : public vcd_trace { 1276public: 1277 vcd_signed_char_trace(const char& object, 1278 const std::string& name_, 1279 const std::string& vcd_name_, 1280 int width_); 1281 void write(FILE* f); 1282 bool changed(); 1283 1284protected: 1285 const char& object; 1286 char old_value; 1287 unsigned char mask; 1288}; 1289 1290 1291vcd_signed_char_trace::vcd_signed_char_trace(const char& object_, 1292 const std::string& name_, 1293 const std::string& vcd_name_, 1294 int width_) 1295: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xff) 1296{ 1297 bit_width = width_; 1298 if (bit_width < 8) mask = (unsigned char)~(-1 << bit_width); 1299 1300 vcd_var_typ_name = "wire"; 1301} 1302 1303 1304bool vcd_signed_char_trace::changed() 1305{ 1306 return object != old_value; 1307} 1308 1309 1310void vcd_signed_char_trace::write(FILE* f) 1311{ 1312 char rawdata[1000]; 1313 char compdata[1000]; 1314 int bitindex; 1315 1316 // Check for overflow 1317 if (((unsigned char) object & mask) != (unsigned char) object) { 1318 for (bitindex = 0; bitindex < bit_width; bitindex++){ 1319 rawdata[bitindex] = 'x'; 1320 } 1321 } 1322 else{ 1323 unsigned bit_mask = 1 << (bit_width-1); 1324 for (bitindex = 0; bitindex < bit_width; bitindex++) { 1325 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 1326 bit_mask = bit_mask >> 1; 1327 } 1328 } 1329 rawdata[bitindex] = '\0'; 1330 compose_data_line(rawdata, compdata); 1331 std::fputs(compdata, f); 1332 old_value = object; 1333} 1334 1335/*****************************************************************************/ 1336 1337class vcd_int64_trace : public vcd_trace { 1338public: 1339 vcd_int64_trace(const sc_dt::int64& object, 1340 const std::string& name_, 1341 const std::string& vcd_name_, 1342 int width_); 1343 void write(FILE* f); 1344 bool changed(); 1345 1346protected: 1347 const sc_dt::int64& object; 1348 sc_dt::int64 old_value; 1349 sc_dt::uint64 mask; 1350}; 1351 1352 1353vcd_int64_trace::vcd_int64_trace(const sc_dt::int64& object_, 1354 const std::string& name_, 1355 const std::string& vcd_name_, 1356 int width_) 1357: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), 1358 mask((sc_dt::uint64)-1) 1359{ 1360 bit_width = width_; 1361 if (bit_width < 64) mask = ~(mask << bit_width); 1362 vcd_var_typ_name = "wire"; 1363} 1364 1365 1366bool vcd_int64_trace::changed() 1367{ 1368 return object != old_value; 1369} 1370 1371 1372void vcd_int64_trace::write(FILE* f) 1373{ 1374 char rawdata[1000]; 1375 char compdata[1000]; 1376 int bitindex; 1377 1378 // Check for overflow 1379 if (((sc_dt::uint64) object & mask) != (sc_dt::uint64) object) 1380 { 1381 for (bitindex = 0; bitindex < bit_width; bitindex++) 1382 { 1383 rawdata[bitindex] = 'x'; 1384 } 1385 } 1386 else 1387 { 1388 sc_dt::uint64 bit_mask = 1; 1389 bit_mask = bit_mask << (bit_width-1); 1390 for (bitindex = 0; bitindex < bit_width; bitindex++) { 1391 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 1392 bit_mask = bit_mask >> 1; 1393 } 1394 } 1395 rawdata[bitindex] = '\0'; 1396 compose_data_line(rawdata, compdata); 1397 std::fputs(compdata, f); 1398 old_value = object; 1399} 1400 1401 1402/*****************************************************************************/ 1403 1404class vcd_uint64_trace : public vcd_trace { 1405public: 1406 vcd_uint64_trace(const sc_dt::uint64& object, 1407 const std::string& name_, 1408 const std::string& vcd_name_, 1409 int width_); 1410 void write(FILE* f); 1411 bool changed(); 1412 1413protected: 1414 const sc_dt::uint64& object; 1415 sc_dt::uint64 old_value; 1416 sc_dt::uint64 mask; 1417}; 1418 1419 1420vcd_uint64_trace::vcd_uint64_trace( const sc_dt::uint64& object_, 1421 const std::string& name_, 1422 const std::string& vcd_name_, 1423 int width_) 1424: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), 1425 mask((sc_dt::uint64)-1) 1426{ 1427 bit_width = width_; 1428 if ( bit_width < 64 ) mask = ~(mask << bit_width); 1429 vcd_var_typ_name = "wire"; 1430} 1431 1432 1433bool vcd_uint64_trace::changed() 1434{ 1435 return object != old_value; 1436} 1437 1438 1439void vcd_uint64_trace::write(FILE* f) 1440{ 1441 char rawdata[1000]; 1442 char compdata[1000]; 1443 int bitindex; 1444 1445 // Check for overflow 1446 if ((object & mask) != object) 1447 { 1448 for (bitindex = 0; bitindex < bit_width; bitindex++){ 1449 rawdata[bitindex] = 'x'; 1450 } 1451 } 1452 else 1453 { 1454 sc_dt::uint64 bit_mask = 1; 1455 bit_mask = bit_mask << (bit_width-1); 1456 for (bitindex = 0; bitindex < bit_width; bitindex++) 1457 { 1458 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 1459 bit_mask = bit_mask >> 1; 1460 } 1461 } 1462 rawdata[bitindex] = '\0'; 1463 compose_data_line(rawdata, compdata); 1464 std::fputs(compdata, f); 1465 old_value = object; 1466} 1467 1468 1469/*****************************************************************************/ 1470 1471class vcd_signed_long_trace : public vcd_trace { 1472public: 1473 vcd_signed_long_trace(const long& object, 1474 const std::string& name_, 1475 const std::string& vcd_name_, 1476 int width_); 1477 void write(FILE* f); 1478 bool changed(); 1479 1480protected: 1481 const long& object; 1482 long old_value; 1483 unsigned long mask; 1484}; 1485 1486 1487vcd_signed_long_trace::vcd_signed_long_trace(const long& object_, 1488 const std::string& name_, 1489 const std::string& vcd_name_, 1490 int width_) 1491: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), 1492 mask((unsigned long)-1) 1493{ 1494 bit_width = width_; 1495 if ( bit_width < (int)(sizeof(long)*8) ) 1496 mask = ~(-1L << bit_width); 1497 vcd_var_typ_name = "wire"; 1498} 1499 1500 1501bool vcd_signed_long_trace::changed() 1502{ 1503 return object != old_value; 1504} 1505 1506 1507void vcd_signed_long_trace::write(FILE* f) 1508{ 1509 char rawdata[1000]; 1510 char compdata[1000]; 1511 int bitindex; 1512 1513 // Check for overflow 1514 if (((unsigned long) object & mask) != (unsigned long) object) { 1515 for (bitindex = 0; bitindex < bit_width; bitindex++){ 1516 rawdata[bitindex] = 'x'; 1517 } 1518 } 1519 else{ 1520 unsigned long bit_mask = 1ul << (bit_width-1); 1521 for (bitindex = 0; bitindex < bit_width; bitindex++) { 1522 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 1523 bit_mask = bit_mask >> 1; 1524 } 1525 } 1526 rawdata[bitindex] = '\0'; 1527 compose_data_line(rawdata, compdata); 1528 std::fputs(compdata, f); 1529 old_value = object; 1530} 1531 1532 1533/*****************************************************************************/ 1534 1535class vcd_float_trace : public vcd_trace { 1536public: 1537 vcd_float_trace(const float& object, 1538 const std::string& name_, 1539 const std::string& vcd_name_); 1540 void write(FILE* f); 1541 bool changed(); 1542 1543protected: 1544 const float& object; 1545 float old_value; 1546}; 1547 1548vcd_float_trace::vcd_float_trace(const float& object_, 1549 const std::string& name_, 1550 const std::string& vcd_name_) 1551: vcd_trace(name_, vcd_name_), object(object_) 1552{ 1553 vcd_var_typ_name = "real"; 1554 bit_width = 1; 1555 old_value = object; 1556} 1557 1558bool vcd_float_trace::changed() 1559{ 1560 return object != old_value; 1561} 1562 1563void vcd_float_trace::write(FILE* f) 1564{ 1565 std::fprintf(f, "r%.16g %s", object, vcd_name.c_str()); 1566 old_value = object; 1567} 1568 1569/*****************************************************************************/ 1570 1571class vcd_double_trace : public vcd_trace { 1572public: 1573 vcd_double_trace(const double& object, 1574 const std::string& name_, 1575 const std::string& vcd_name_); 1576 void write(FILE* f); 1577 bool changed(); 1578 1579protected: 1580 const double& object; 1581 double old_value; 1582}; 1583 1584vcd_double_trace::vcd_double_trace(const double& object_, 1585 const std::string& name_, 1586 const std::string& vcd_name_) 1587: vcd_trace(name_, vcd_name_), object(object_), old_value(object_) 1588{ 1589 vcd_var_typ_name = "real"; 1590 bit_width = 1; 1591} 1592 1593bool vcd_double_trace::changed() 1594{ 1595 return object != old_value; 1596} 1597 1598void vcd_double_trace::write(FILE* f) 1599{ 1600 std::fprintf(f, "r%.16g %s", object, vcd_name.c_str()); 1601 old_value = object; 1602} 1603 1604 1605/*****************************************************************************/ 1606 1607class vcd_enum_trace : public vcd_trace { 1608public: 1609 vcd_enum_trace(const unsigned& object_, 1610 const std::string& name_, 1611 const std::string& vcd_name_, 1612 const char** enum_literals); 1613 void write(FILE* f); 1614 bool changed(); 1615 1616protected: 1617 const unsigned& object; 1618 unsigned old_value; 1619 unsigned mask; 1620 const char** literals; 1621 unsigned nliterals; 1622}; 1623 1624 1625vcd_enum_trace::vcd_enum_trace(const unsigned& object_, 1626 const std::string& name_, 1627 const std::string& vcd_name_, 1628 const char** enum_literals_) 1629: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), 1630 mask(0xffffffff), literals(enum_literals_), nliterals(0) 1631{ 1632 // find number of bits required to represent enumeration literal - counting loop 1633 for (nliterals = 0; enum_literals_[nliterals]; nliterals++) continue; 1634 1635 // Figure out number of bits required to represent the number of literals 1636 bit_width = 0; 1637 unsigned shifted_maxindex = nliterals-1; 1638 while(shifted_maxindex != 0){ 1639 shifted_maxindex >>= 1; 1640 bit_width++; 1641 } 1642 1643 // Set the mask 1644 if (bit_width < 32) { 1645 mask = ~(-1 << bit_width); 1646 } else { 1647 mask = 0xffffffff; 1648 } 1649 1650 vcd_var_typ_name = "wire"; 1651} 1652 1653bool vcd_enum_trace::changed() 1654{ 1655 return object != old_value; 1656} 1657 1658void vcd_enum_trace::write(FILE* f) 1659{ 1660 char rawdata[1000]; 1661 char compdata[1000]; 1662 int bitindex; 1663 1664 // Check for overflow 1665 if ((object & mask) != object) { 1666 for (bitindex = 0; bitindex < bit_width; bitindex++){ 1667 rawdata[bitindex] = 'x'; 1668 } 1669 } else { 1670 unsigned long bit_mask = 1ul << (bit_width-1); 1671 for (bitindex = 0; bitindex < bit_width; bitindex++) { 1672 rawdata[bitindex] = (object & bit_mask)? '1' : '0'; 1673 bit_mask = bit_mask >> 1; 1674 } 1675 } 1676 rawdata[bitindex] = '\0'; 1677 compose_data_line(rawdata, compdata); 1678 std::fputs(compdata, f); 1679 old_value = object; 1680} 1681 1682 1683/***************************************************************************** 1684 vcd_trace_file functions 1685 *****************************************************************************/ 1686 1687vcd_trace_file::vcd_trace_file(const char *name) 1688 : sc_trace_file_base( name, "vcd" ) 1689 , vcd_name_index(0) 1690 , previous_time_units_low(0) 1691 , previous_time_units_high(0) 1692 , traces() 1693{} 1694 1695 1696void 1697vcd_trace_file::do_initialize() 1698{ 1699 char buf[2000]; 1700 1701 //date: 1702 std::fprintf(fp, "$date\n %s\n$end\n\n", localtime_string().c_str() ); 1703 1704 //version: 1705 std::fprintf(fp, "$version\n %s\n$end\n\n", sc_version()); 1706 1707 //timescale: 1708 static struct SC_TIMESCALE_TO_TEXT { 1709 double unit; 1710 const char* text; 1711 } timescale_to_text [] = { 1712 { sc_time(1, SC_FS).to_seconds(), "1 fs" }, 1713 { sc_time(10, SC_FS).to_seconds(), "10 fs" }, 1714 { sc_time(100, SC_FS).to_seconds(),"100 fs" }, 1715 { sc_time(1, SC_PS).to_seconds(), "1 ps" }, 1716 { sc_time(10, SC_PS).to_seconds(), "10 ps" }, 1717 { sc_time(100, SC_PS).to_seconds(),"100 ps" }, 1718 { sc_time(1, SC_NS).to_seconds(), "1 ns" }, 1719 { sc_time(10, SC_NS).to_seconds(), "10 ns" }, 1720 { sc_time(100, SC_NS).to_seconds(),"100 ns" }, 1721 { sc_time(1, SC_US).to_seconds(), "1 us" }, 1722 { sc_time(10, SC_US).to_seconds(), "10 us" }, 1723 { sc_time(100, SC_US).to_seconds(),"100 us" }, 1724 { sc_time(1, SC_MS).to_seconds(), "1 ms" }, 1725 { sc_time(10, SC_MS).to_seconds(), "10 ms" }, 1726 { sc_time(100, SC_MS).to_seconds(),"100 ms" }, 1727 { sc_time(1, SC_SEC).to_seconds(), "1 sec" }, 1728 { sc_time(10, SC_SEC).to_seconds(), "10 sec" }, 1729 { sc_time(100, SC_SEC).to_seconds(),"100 sec" } 1730 }; 1731 static int timescale_to_text_n = 1732 sizeof(timescale_to_text)/sizeof(SC_TIMESCALE_TO_TEXT); 1733 1734 for ( int time_i = 0; time_i < timescale_to_text_n; time_i++ ) 1735 { 1736 if (timescale_unit == timescale_to_text[time_i].unit) 1737 { 1738 std::fprintf(fp,"$timescale\n %s\n$end\n\n", 1739 timescale_to_text[time_i].text); 1740 break; 1741 } 1742 } 1743 1744 // Create a dummy scope 1745 std::fputs("$scope module SystemC $end\n", fp); 1746 1747 //variable definitions: 1748 for (int i = 0; i < (int)traces.size(); i++) { 1749 vcd_trace* t = traces[i]; 1750 t->set_width(); // needed for all vectors 1751 t->print_variable_declaration_line(fp); 1752 } 1753 1754 std::fputs("$upscope $end\n", fp); 1755 1756 std::fputs("$enddefinitions $end\n\n", fp); 1757 1758 // double inittime = sc_simulation_time(); 1759 double inittime = sc_time_stamp().to_seconds(); 1760 1761 std::sprintf(buf, 1762 "All initial values are dumped below at time " 1763 "%g sec = %g timescale units.", 1764 inittime, inittime/timescale_unit 1765 ); 1766 write_comment(buf); 1767 1768 double_to_special_int64(inittime/timescale_unit, 1769 &previous_time_units_high, 1770 &previous_time_units_low ); 1771 1772 1773 std::fputs("$dumpvars\n",fp); 1774 for (int i = 0; i < (int)traces.size(); i++) { 1775 traces[i]->write(fp); 1776 std::fputc('\n', fp); 1777 } 1778 std::fputs("$end\n\n", fp); 1779} 1780 1781 1782// ---------------------------------------------------------------------------- 1783 1784#define DEFN_TRACE_METHOD(tp) \ 1785void \ 1786vcd_trace_file::trace(const tp& object_, const std::string& name_) \ 1787{ \ 1788 if( add_trace_check(name_) ) \ 1789 traces.push_back( new vcd_ ## tp ## _trace( object_, \ 1790 name_, \ 1791 obtain_name() ) ); \ 1792} 1793 1794DEFN_TRACE_METHOD(bool) 1795DEFN_TRACE_METHOD(float) 1796DEFN_TRACE_METHOD(double) 1797 1798#undef DEFN_TRACE_METHOD 1799#define DEFN_TRACE_METHOD(tp) \ 1800void \ 1801vcd_trace_file::trace(const sc_dt::tp& object_, const std::string& name_) \ 1802{ \ 1803 if( add_trace_check(name_) ) \ 1804 traces.push_back( new vcd_ ## tp ## _trace( object_, \ 1805 name_, \ 1806 obtain_name() ) ); \ 1807} 1808 1809DEFN_TRACE_METHOD(sc_bit) 1810DEFN_TRACE_METHOD(sc_logic) 1811 1812DEFN_TRACE_METHOD(sc_signed) 1813DEFN_TRACE_METHOD(sc_unsigned) 1814DEFN_TRACE_METHOD(sc_int_base) 1815DEFN_TRACE_METHOD(sc_uint_base) 1816 1817DEFN_TRACE_METHOD(sc_fxval) 1818DEFN_TRACE_METHOD(sc_fxval_fast) 1819DEFN_TRACE_METHOD(sc_fxnum) 1820DEFN_TRACE_METHOD(sc_fxnum_fast) 1821 1822#undef DEFN_TRACE_METHOD 1823 1824 1825#define DEFN_TRACE_METHOD_SIGNED(tp) \ 1826void \ 1827vcd_trace_file::trace( const tp& object_, \ 1828 const std::string& name_, \ 1829 int width_ ) \ 1830{ \ 1831 if( add_trace_check(name_) ) \ 1832 traces.push_back( new vcd_signed_ ## tp ## _trace( object_, \ 1833 name_, \ 1834 obtain_name(), \ 1835 width_ ) ); \ 1836} 1837 1838#define DEFN_TRACE_METHOD_UNSIGNED(tp) \ 1839void \ 1840vcd_trace_file::trace( const unsigned tp& object_, \ 1841 const std::string& name_, \ 1842 int width_ ) \ 1843{ \ 1844 if( add_trace_check(name_) ) \ 1845 traces.push_back( new vcd_unsigned_ ## tp ## _trace( object_, \ 1846 name_, \ 1847 obtain_name(), \ 1848 width_ ) ); \ 1849} 1850 1851DEFN_TRACE_METHOD_SIGNED(char) 1852DEFN_TRACE_METHOD_SIGNED(short) 1853DEFN_TRACE_METHOD_SIGNED(int) 1854DEFN_TRACE_METHOD_SIGNED(long) 1855 1856DEFN_TRACE_METHOD_UNSIGNED(char) 1857DEFN_TRACE_METHOD_UNSIGNED(short) 1858DEFN_TRACE_METHOD_UNSIGNED(int) 1859DEFN_TRACE_METHOD_UNSIGNED(long) 1860 1861#undef DEFN_TRACE_METHOD_SIGNED 1862#undef DEFN_TRACE_METHOD_UNSIGNED 1863 1864#define DEFN_TRACE_METHOD_LONG_LONG(tp) \ 1865void \ 1866vcd_trace_file::trace( const sc_dt::tp& object_, \ 1867 const std::string& name_, \ 1868 int width_ ) \ 1869{ \ 1870 if( add_trace_check(name_) ) \ 1871 traces.push_back( new vcd_ ## tp ## _trace( object_, \ 1872 name_, \ 1873 obtain_name(), \ 1874 width_ ) ); \ 1875} 1876 1877DEFN_TRACE_METHOD_LONG_LONG(int64) 1878DEFN_TRACE_METHOD_LONG_LONG(uint64) 1879 1880#undef DEFN_TRACE_METHOD_LONG_LONG 1881 1882void 1883vcd_trace_file::trace( const unsigned& object_, 1884 const std::string& name_, 1885 const char** enum_literals_ ) 1886{ 1887 if( add_trace_check(name_) ) 1888 traces.push_back( new vcd_enum_trace( object_, 1889 name_, 1890 obtain_name(), 1891 enum_literals_ ) ); 1892} 1893 1894 1895void 1896vcd_trace_file::write_comment(const std::string& comment) 1897{ 1898 if(!fp) open_fp(); 1899 //no newline in comments allowed, as some viewers may crash 1900 std::fputs("$comment\n", fp); 1901 std::fputs(comment.c_str(), fp); 1902 std::fputs("\n$end\n\n", fp); 1903} 1904 1905void 1906vcd_trace_file::cycle(bool this_is_a_delta_cycle) 1907{ 1908 unsigned this_time_units_high, this_time_units_low; 1909 1910 // Just to make g++ shut up in the optimized mode 1911 this_time_units_high = this_time_units_low = 0; 1912 1913 // Trace delta cycles only when enabled 1914 if (!delta_cycles() && this_is_a_delta_cycle) return; 1915 1916 // Check for initialization 1917 if( initialize() ) { 1918 return; 1919 }; 1920 1921 1922 double now_units = sc_time_stamp().to_seconds() / timescale_unit; 1923 unsigned now_units_high, now_units_low; 1924 double_to_special_int64(now_units, &now_units_high, &now_units_low ); 1925 1926 bool now_later_than_previous_time = false; 1927 if( (now_units_low > previous_time_units_low 1928 && now_units_high == previous_time_units_high) 1929 || now_units_high > previous_time_units_high){ 1930 now_later_than_previous_time = true; 1931 } 1932 1933 bool now_equals_previous_time = false; 1934 if(now_later_than_previous_time){ 1935 this_time_units_high = now_units_high; 1936 this_time_units_low = now_units_low; 1937 } else { 1938 if( now_units_low == previous_time_units_low 1939 && now_units_high == previous_time_units_high){ 1940 now_equals_previous_time = true; 1941 this_time_units_high = now_units_high; 1942 this_time_units_low = now_units_low; 1943 } 1944 } 1945 1946 // Since VCD does not understand 0 time progression, we have to fake 1947 // delta cycles with progressing time by one unit 1948 if(this_is_a_delta_cycle){ 1949 this_time_units_high = previous_time_units_high; 1950 this_time_units_low = previous_time_units_low + 1; 1951 if(this_time_units_low == 1000000000){ 1952 this_time_units_high++; 1953 this_time_units_low=0; 1954 } 1955 static bool warned = false; 1956 if(!warned){ 1957 SC_REPORT_INFO( SC_ID_TRACING_VCD_DELTA_CYCLE_ 1958 , sc_time( timescale_unit, SC_SEC ) 1959 .to_string().c_str() ); 1960 warned = true; 1961 } 1962 } 1963 1964 1965 // Not a delta cycle and time has not progressed 1966 if( ! this_is_a_delta_cycle && now_equals_previous_time && 1967 ( now_units_high != 0 || now_units_low != 0 ) ) { 1968 // Don't print the message at time zero 1969 static bool warned = false; 1970 if( ! warned ) { 1971 std::stringstream ss; 1972 ss << "units count: " << now_units_low << "\n" 1973 "\tWaveform viewers will only show the states of the last one.\n" 1974 "\tUse `tracefile->set_time_unit(double, sc_time_unit);'" 1975 " to increase the time resolution."; 1976 SC_REPORT_WARNING( SC_ID_TRACING_VCD_DUPLICATE_TIME_ 1977 , ss.str().c_str() ); 1978 // warned = true; 1979 } 1980 } 1981 1982 // Not a delta cycle and time has gone backward 1983 // This will happen with large number of delta cycles between two real 1984 // advances of time 1985 if(!this_is_a_delta_cycle && !now_equals_previous_time && 1986 !now_later_than_previous_time){ 1987 static bool warned = false; 1988 if(!warned) { 1989 std::stringstream ss; 1990 ss << "units count (" 1991 << previous_time_units_low << "->" << now_units_low << ")\n" 1992 "\tThis can occur when delta cycling is activated." 1993 " Cycles with falling time are not shown.\n" 1994 "\tUse `tracefile->set_time_unit(double, sc_time_unit);'" 1995 " to increase the time resolution."; 1996 SC_REPORT_WARNING( SC_ID_TRACING_VCD_DUPLICATE_TIME_ 1997 , ss.str().c_str() ); 1998 // warned = true; 1999 } 2000 // Note that we don't set this_time_units_high/low to any value only 2001 // in this case because we are not going to do any tracing. In the 2002 // optimized mode, the compiler complains because of this. Therefore, 2003 // we include the lines at the very beginning of this function to make 2004 // the compiler shut up. 2005 return; 2006 } 2007 2008 // Now do the actual printing 2009 bool time_printed = false; 2010 vcd_trace* const* const l_traces = &traces[0]; 2011 for (int i = 0; i < (int)traces.size(); i++) { 2012 vcd_trace* t = l_traces[i]; 2013 if(t->changed()){ 2014 if(time_printed == false){ 2015 char buf[200]; 2016 if(this_time_units_high){ 2017 std::sprintf(buf, "#%u%09u", this_time_units_high, this_time_units_low); 2018 } 2019 else{ 2020 std::sprintf(buf, "#%u", this_time_units_low); 2021 } 2022 std::fputs(buf, fp); 2023 std::fputc('\n', fp); 2024 time_printed = true; 2025 } 2026 2027 // Write the variable 2028 t->write(fp); 2029 std::fputc('\n', fp); 2030 } 2031 } 2032 // Put another newline after all values are printed 2033 if(time_printed) std::fputc('\n', fp); 2034 2035 if(time_printed){ 2036 // We update previous_time_units only when we print time because 2037 // this field stores the previous time that was printed, not the 2038 // previous time this function was called 2039 previous_time_units_high = this_time_units_high; 2040 previous_time_units_low = this_time_units_low; 2041 } 2042} 2043 2044#if 0 2045void 2046vcd_trace_file::create_vcd_name(std::string* p_destination) 2047{ 2048 obtain_name.swap( *p_destination ); 2049} 2050#endif 2051 2052// Create a VCD name for a variable 2053std::string 2054vcd_trace_file::obtain_name() 2055{ 2056 const char first_type_used = 'a'; 2057 const int used_types_count = 'z' - 'a' + 1; 2058 int result; 2059 2060 result = vcd_name_index; 2061 char char6 = (char)(vcd_name_index % used_types_count); 2062 2063 result = result / used_types_count; 2064 char char5 = (char)(result % used_types_count); 2065 2066 result = result / used_types_count; 2067 char char4 = (char)(result % used_types_count); 2068 2069 result = result / used_types_count; 2070 char char3 = (char)(result % used_types_count); 2071 2072 result = result / used_types_count; 2073 char char2 = (char)(result % used_types_count); 2074 2075 char buf[20]; 2076 std::sprintf(buf, "%c%c%c%c%c", 2077 char2 + first_type_used, 2078 char3 + first_type_used, 2079 char4 + first_type_used, 2080 char5 + first_type_used, 2081 char6 + first_type_used); 2082 vcd_name_index++; 2083 return std::string(buf); 2084} 2085 2086vcd_trace_file::~vcd_trace_file() 2087{ 2088 for( int i = 0; i < (int)traces.size(); i++ ) { 2089 vcd_trace* t = traces[i]; 2090 delete t; 2091 } 2092} 2093 2094 2095// Functions specific to VCD tracing 2096 2097static char 2098map_sc_logic_state_to_vcd_state(char in_char) 2099{ 2100 char out_char; 2101 2102 switch(in_char){ 2103 case 'U': 2104 case 'X': 2105 case 'W': 2106 case 'D': 2107 out_char = 'x'; 2108 break; 2109 case '0': 2110 case 'L': 2111 out_char = '0'; 2112 break; 2113 case '1': 2114 case 'H': 2115 out_char = '1'; 2116 break; 2117 case 'Z': 2118 out_char = 'z'; 2119 break; 2120 default: 2121 out_char = '?'; 2122 } 2123 2124 return out_char; 2125} 2126 2127 2128 2129 2130static 2131void 2132remove_vcd_name_problems(vcd_trace const* vcd, std::string& name) 2133{ 2134 static bool warned = false; 2135 bool braces_removed = false; 2136 for (unsigned int i = 0; i< name.length(); i++) { 2137 if (name[i] == '[') { 2138 name[i] = '('; 2139 braces_removed = true; 2140 } 2141 else if (name[i] == ']') { 2142 name[i] = ')'; 2143 braces_removed = true; 2144 } 2145 } 2146 2147 if(braces_removed && !warned){ 2148 std::stringstream ss; 2149 ss << vcd->name << ":\n" 2150 "\tTraced objects found with name containing [], which may be\n" 2151 "\tinterpreted by the waveform viewer in unexpected ways.\n" 2152 "\tSo the [] is automatically replaced by ()."; 2153 2154 SC_REPORT_WARNING( SC_ID_TRACING_OBJECT_NAME_FILTERED_ 2155 , ss.str().c_str() ); 2156 } 2157} 2158 2159// ---------------------------------------------------------------------------- 2160 2161sc_trace_file* 2162sc_create_vcd_trace_file(const char * name) 2163{ 2164 sc_trace_file * tf = new vcd_trace_file(name); 2165 return tf; 2166} 2167 2168void 2169sc_close_vcd_trace_file( sc_trace_file* tf ) 2170{ 2171 vcd_trace_file* vcd_tf = static_cast<vcd_trace_file*>(tf); 2172 delete vcd_tf; 2173} 2174 2175} // namespace sc_core 2176