sc_vcd_trace.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2006 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_vcd_trace.cpp - Implementation of VCD tracing.
00021 
00022   Original Author - Abhijit Ghosh, Synopsys, Inc.
00023 
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027 
00028   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00029   changes you are making here.
00030 
00031       Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc.
00032   Description of Modification: - Replaced 'width' of sc_(u)int with their
00033                                  'bitwidth()'.
00034     
00035       Name, Affiliation, Date:
00036   Description of Modification:
00037 
00038  *****************************************************************************/
00039 
00040 /*****************************************************************************
00041 
00042    Acknowledgement: The tracing mechanism is based on the tracing
00043    mechanism developed at Infineon (formerly Siemens HL). Though this
00044    code is somewhat different, and significantly enhanced, the basics
00045    are identical to what was originally contributed by Infineon.  The
00046    contribution of Infineon in the development of this tracing
00047    technology is hereby acknowledged.
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 // Forward declarations for functions that come later in the file
00073 // Map sc_dt::sc_logic to printable VCD
00074 static char map_sc_logic_state_to_vcd_state(char in_char);
00075 
00076 // Remove name problems associated with [] in vcd names
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 //  CLASS : vcd_trace
00084 //
00085 //  Base class for VCD traces.
00086 // ----------------------------------------------------------------------------
00087 
00088 class vcd_trace
00089 {
00090 public:
00091 
00092     vcd_trace(const std::string& name_, const std::string& vcd_name_);
00093 
00094     // Needs to be pure virtual as has to be defined by the particular
00095     // type being traced
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     // Comparison function needs to be pure virtual too
00103     virtual bool changed() = 0;
00104 
00105     // Make this virtual as some derived classes may overwrite
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     /* Intentionally blank */
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 // same as above but not that ugly
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   /* Intentionally Blank, should be defined for each type separately */
00204 }
00205 
00206 const char*
00207 vcd_trace::strip_leading_bits(const char* originalbuf)
00208 {
00209     //*********************************************************************
00210     // - Remove multiple leading 0,z,x, and replace by only one
00211     // - For example,
00212     //    b000z100    -> b0z100
00213     //    b00000xxx   -> b0xxx
00214     //    b000        -> b0
00215     //    bzzzzz1     -> bz1
00216     //    bxxxz10     -> xz10
00217     // - For leading 0's followed by 1, remove all leading 0's
00218     //    b0000010101 -> b10101  
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     // else
00236     return position-1;
00237 }
00238 
00239 vcd_trace::~vcd_trace()
00240 {
00241   /* Intentionally Blank */
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 // Trace sc_dt::sc_bv_base (sc_dt::sc_bv)
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 // Trace sc_dt::sc_lv_base (sc_dt::sc_lv)
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 // The last may look strange, but is correct
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 // The last may look strange, but is correct
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     // Check for overflow
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     // Check for overflow
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     // Check for overflow
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     // Check for overflow
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     // Check for overflow
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     // Check for overflow
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     // Check for overflow
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     // Check for overflow
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     // Check for overflow
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     // Check for overflow
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     // find number of bits required to represent enumeration literal - counting loop
01655     for (nliterals = 0; enum_literals_[nliterals]; nliterals++);
01656 
01657     // Figure out number of bits required to represent the number of literals
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     // Set the mask
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     // Check for overflow
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            vcd_trace_file functions
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; // Make this the default
01722     initialized = false;
01723     vcd_name_index = 0;
01724 
01725     // default time step is the time resolution
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     //date:
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     //version:
01745     std::fprintf(fp, "$version\n %s\n$end\n\n", sc_version());
01746 
01747     //timescale:
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     // Don't print message if running regression
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     // Create a dummy scope
01792     std::fputs("$scope module SystemC $end\n", fp);
01793 
01794     //variable definitions:
01795     int i;
01796     for (i = 0; i < (int)traces.size(); i++) {
01797         vcd_trace* t = traces[i];
01798         t->set_width(); // needed for all vectors
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     // double inittime = sc_simulation_time();
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     //no newline in comments allowed, as some viewers may crash
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     // Just to make g++ shut up in the optimized mode
02001     this_time_units_high = this_time_units_low = 0;
02002 
02003     // Trace delta cycles only when enabled
02004     if (!trace_delta_cycles && this_is_a_delta_cycle) return;
02005 
02006     // Check for initialization
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     // Since VCD does not understand 0 time progression, we have to fake
02039     // delta cycles with progressing time by one unit
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     // Not a delta cycle and time has not progressed
02057     if( ! this_is_a_delta_cycle && now_equals_previous_time &&
02058     ( now_units_high != 0 || now_units_low != 0 ) ) {
02059     // Don't print the message at time zero
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     // Not a delta cycle and time has gone backward
02075     // This will happen with large number of delta cycles between two real
02076     // advances of time
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     // Note that we don't set this_time_units_high/low to any value only
02092         // in this case because we are not going to do any tracing. In the
02093         // optimized mode, the compiler complains because of this. Therefore,
02094         // we include the lines at the very beginning of this function to make
02095         // the compiler shut up.
02096         return; 
02097     }
02098 
02099     // Now do the actual printing 
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         // Write the variable
02119             t->write(fp);
02120             std::fputc('\n', fp);
02121         }
02122     }
02123     // Put another newline after all values are printed
02124     if(time_printed) std::fputc('\n', fp);
02125 
02126     if(time_printed){
02127         // We update previous_time_units only when we print time because
02128         // this field stores the previous time that was printed, not the
02129         // previous time this function was called
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 // same as above
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 // Functions specific to VCD tracing
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 } // namespace sc_core

Generated on Wed Jan 21 15:32:10 2009 for SystemC by  doxygen 1.5.5