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