source: sources/src/sc_trace.cc @ 26

Last change on this file since 26 was 17, checked in by buchmann, 16 years ago

Fix :

  • add missing system header includes
File size: 16.9 KB
Line 
1/*------------------------------------------------------------\
2|                                                             |
3| Tool    :                  systemcass                       |
4|                                                             |
5| File    :                   sc_trace.cc                     |
6|                                                             |
7| Author  :                 Kingbo Paul-Jerome                |
8|                           Buchmann Richard                  |
9|                                                             |
10| Date    :                   09_07_2004                      |
11|                                                             |
12\------------------------------------------------------------*/
13
14/*
15 * This file is part of the Disydent Project
16 * Copyright (C) Laboratoire LIP6 - Département ASIM
17 * Universite Pierre et Marie Curie
18 *
19 * Home page          : http://www-asim.lip6.fr/disydent
20 * E-mail             : mailto:richard.buchmann@lip6.fr
21 *
22 * This library is free software; you  can redistribute it and/or modify it
23 * under the terms  of the GNU Library General Public  License as published
24 * by the Free Software Foundation; either version 2 of the License, or (at
25 * your option) any later version.
26 *
27 * Disydent is distributed  in the hope  that it  will be
28 * useful, but WITHOUT  ANY WARRANTY; without even the  implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
30 * Public License for more details.
31 *
32 * You should have received a copy  of the GNU General Public License along
33 * with the GNU C Library; see the  file COPYING. If not, write to the Free
34 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 */
36
37#include "sc_port.h"
38#include "sc_clock.h"
39#include "sc_trace.h"
40#include "sc_interface.h"
41#include "bit2string.h"
42#include "hex2string.h"
43#include "assert.h"
44
45#include <list>
46#include <cstdio>
47#include <iostream>
48#include <cstring> //strlen
49
50//-----------------------------------------
51
52using namespace std;
53
54//-----------------------------------------
55#ifdef PAT_TRACE_FORMAT
56
57extern "C" {
58#include "genpat.h"
59}
60
61//#include "malloc.h" // NO LONGER SUPPORTED
62#include <cstdlib>
63#include <cstdio>
64
65#endif // PAT_TRACE_FORMAT
66//-----------------------------------------
67
68namespace sc_core {
69
70vector<sc_trace_file *>  trace_file_list;
71uint64                   cpt         = 0;
72uint64                   trace_start = 0;
73       
74//-----------------------------------------
75#if 0
76static ostream& operator << (ostream &, const signal2trace &);
77#endif
78
79//-----------------------------------------
80
81/*
82typedef list<signal2trace> signal2trace_list;
83
84template <typename T>
85static
86void make_list_from_vector (const vector<T>& v, list<T>& l)
87{
88        l.clear ();
89        typename vector<T>::const_iterator i;
90        for (i = v.begin (); i != v.end (); ++i)
91                l.push_back (*i);
92}
93
94template <typename T>
95static
96void make_vector_from_list (const list<T>& l, vector<T>& v)
97{
98        v.clear ();     
99        typename list<T>::const_iterator i;
100        for (i = l.begin (); i != l.end (); ++i)
101                v.push_back (*i);
102}
103
104static
105int operator<(const signal2trace &e1, const signal2trace &e2)
106{
107        return (e1.bit_size < e2.bit_size);
108}
109
110static void
111init (sc_trace_file *tf)
112{
113        signal2trace_list lsig;
114        make_list_from_vector (tf->sig_list, lsig);
115        lsig.reverse(); //sort ();
116        make_vector_from_list (lsig, tf->sig_list);
117}
118*/
119
120static 
121void 
122init (sc_trace_file &tf)
123{
124  if (dump_stage)
125    cerr << "Initializing trace functions : Looking for clocks...";
126
127        vector<signal2trace>::iterator i;
128        i = (tf.sig_list).begin();
129        while (i!=(tf.sig_list).end()) {
130                if (is_clock( *(i->inter) ) ) {
131                        tf.clk_list.push_back(*i);
132                        i = tf.sig_list.erase(i);
133                } 
134                else ++i;
135        }
136  if (dump_stage)
137    cerr << "Done\n";
138}
139
140static 
141void
142vcd_print_cycle_number (FILE *f,long long unsigned int num)
143{
144        string cycle;
145
146        //------------------------------------------------------------------------------------
147        // affichage des cycles (#500 ou #2500 etc...)
148        fprintf(f,"\n#%llu00\n", num * 5);//cycle de simulation
149}
150
151//--------------------------------------------------------------------------------------
152// trace function
153// Called each end of cycle to dump in trace files
154
155void
156trace_all (bool part)
157{
158        if (trace_file_list.empty ())
159                return;
160       
161  if (cpt >= trace_start)
162  {
163          vector<sc_trace_file*>::const_iterator ptf;
164        for (ptf = trace_file_list.begin (); ptf != trace_file_list.end(); ++ptf)
165    {
166      sc_trace_file *tf = *ptf;
167      ASSERT(tf != NULL);
168                trace (*tf, part);
169    }
170  }
171       
172        cpt++;
173}
174
175#if PAT_TRACE_FORMAT
176static void
177pat_set_value (char *buf, const signal2trace &s)
178{
179        if ( ( s.bit_size % 4 ) == 0 )
180        {
181                buf[1] = 'x';
182                hex2string( buf+2, s.inter->get_pointer() , s.bit_size );
183        }
184        else
185        {
186                buf[1] = 'b';
187                bit2string( buf+2, s.inter->get_pointer() , s.bit_size );
188        }
189}
190
191inline
192static 
193void
194affect    (const char          *cur,
195           const char          *nomSig,
196           const char          *buf)
197{
198#if 0
199  printf ("AFFECT (\"%s\", \"%s\", \"%s\");\n",
200    cur,
201    nomSig,
202    buf);
203#endif
204        AFFECT ((char*)cur, (char*)nomSig, (char*)buf );
205}
206
207inline
208static 
209void
210pat_trace (sc_trace_file       &tf, 
211           const signal2trace  &s2t, 
212           const ostringstream &cur1,
213           const ostringstream &cur2)
214{
215        static char buf[50] = "0\0";
216        //cout << "Nom du signal: " << s->nomSig;
217        pat_set_value (buf, s2t);
218        affect (cur1.str().c_str(), s2t.nomSig.c_str(), buf);
219        affect (cur2.str().c_str(), s2t.nomSig.c_str(), buf);
220}
221
222inline
223static 
224void
225pat_trace_clocks (sc_trace_file &tf,
226                  const ostringstream &cur1,
227                  const ostringstream &cur2)
228{
229        vector<signal2trace>::const_iterator s;
230        for(s=(tf.clk_list).begin();s!=(tf.clk_list).end();s++)
231        {
232    const signal2trace &s2t = *s;
233    char *name = (char*)((s2t.nomSig).c_str());
234    const sc_interface *inter = s2t.inter;
235    const sc_clock     *clk   = (const sc_clock *) inter;
236    bool  posedge_first       = clk->posedge_first;
237    char *a, *b;
238    if (posedge_first)
239    {
240      a = "0B1"; b = "0B0";
241    } else {
242      a = "0B0"; b = "0B1"; 
243    }
244    affect (cur1.str().c_str(), name, a);
245    affect (cur2.str().c_str(), name, b);
246        }
247}
248
249static
250void
251pat_trace_init (sc_trace_file &tf)
252{
253  init (tf);
254}
255
256static 
257void
258pat_trace (sc_trace_file &tf,
259           bool           part)
260{ 
261  if (part)
262    return;
263        if (cpt==trace_start) {
264                pat_trace_init (tf);
265        }
266        // time counters
267        ostringstream cur1,cur2; 
268  long long unsigned int buf = cpt * 5;
269        cur1 << buf << "00";
270        cur2 << buf + 5 << "00";
271        // affect each signal
272        vector<signal2trace>::iterator s;
273        for(s=(tf.sig_list).begin();s!=(tf.sig_list).end();s++)
274        {
275    pat_trace (tf, *s, cur1, cur2);
276        }
277  pat_trace_clocks (tf, cur1, cur2);
278}
279#else
280void
281pat_trace (sc_trace_file &tf,
282           bool           part)
283{
284}
285#endif // PAT_TRACE_FORMAT
286
287static
288bool
289is_modified (const signal2trace &s2t)
290{
291  unsigned int bit_size = s2t.bit_size;
292  if (bit_size > 32)
293  {
294    const uint64 *const pointer_saved   = (const uint64 *)s2t.pointer;
295    const uint64 *const pointer_current = (const uint64 *)s2t.inter->get_pointer ();
296    return (*pointer_saved != *pointer_current);
297  } else if (bit_size > 16) {
298    const uint32 *const pointer_saved   = s2t.pointer;
299    const uint32 *const pointer_current = s2t.inter->get_pointer ();
300    return (*pointer_saved != *pointer_current);
301  } else {
302    const uint16 *const pointer_saved   = (const uint16 *)s2t.pointer;
303    const uint16 *const pointer_current = (const uint16 *)s2t.inter->get_pointer ();
304    return (*pointer_saved != *pointer_current);
305  }
306}
307
308static
309bool
310save_modification (signal2trace &s2t)
311{
312  *(s2t.pointer) = *(s2t.inter->get_pointer ());
313}
314
315static
316inline
317void
318print (sc_trace_file &tf, signal2trace &s2t)
319{
320        char buf[100];
321        bit2string( buf+1, s2t.inter->get_pointer() , s2t.bit_size );
322       
323        char *buf2 = strip(buf+1);
324  int   len  = strlen (buf2);
325  if (s2t.bit_size != 1)
326  {
327    --buf2;
328    buf2[0] = 'b';
329    sprintf (buf2 + len + 1, " %s\n", s2t.alias);
330  } else {
331    sprintf (buf2 + len, "%s\n", s2t.alias);
332  }
333/*     
334        char *buf2 = strip(buf);
335  char buf3[128];
336
337  if (s2t.bit_size != 1)
338    sprintf (buf3, "b%s %s\n", buf2, s2t.alias);
339  else
340    sprintf (buf3, "%s%s\n", buf2, s2t.alias);
341  */ 
342        // ecriture liste[i] dans le fichier VCD:
343        if ((fprintf(tf.pfic,buf2))==0)
344        {
345          cerr << "erreur ecriture du couple Valeur/Nom du signal dans le VCD\n";
346                exit(16);
347        }
348}
349
350static
351inline 
352void
353vcd_trace (sc_trace_file &tf, 
354           signal2trace  &s2t, 
355           bool           skip = true)
356{
357  if ((skip) && (!is_modified (s2t)))
358    return;
359  save_modification (s2t);
360  print (tf, s2t);
361}
362
363static
364void
365vcd_trace_clocks (const sc_trace_file &tf, 
366                  bool v)
367{
368        vector<signal2trace>::const_iterator i;
369        for(i=(tf.clk_list).begin();i!=(tf.clk_list).end();i++) 
370        {
371    const signal2trace &s2t   = *i;
372    const sc_interface *inter = s2t.inter;
373    const sc_clock     *clk   = (const sc_clock *) inter;
374    bool  posedge_first       = clk->posedge_first;
375                fprintf(tf.pfic, "%c%s\n",(v^posedge_first)?'0':'1', i->alias);
376        }
377}
378
379static tab_t *vcd_signal_table = NULL;
380
381
382static
383int
384vcd_get_size (const signal2trace &s2t)
385{
386#if 0
387  cerr << "alias     : " << s2t.alias    << "\n";
388  cerr << "bit_size  : " << s2t.bit_size << "\n";
389  cerr << "=> #tab_t : " << ((s2t.bit_size - 1) / (sizeof (tab_t)*8)) + 1 << "\n";
390#endif
391  return ((s2t.bit_size - 1) / (sizeof (tab_t)*8)) + 1;
392}
393
394static
395int
396vcd_get_signal_table_size (const sc_trace_file &tf)
397{
398  int total_size = 0;
399        vector<signal2trace>::const_iterator i;
400        for(i=(tf.sig_list).begin();i!=(tf.sig_list).end();i++)
401        {
402    const signal2trace &s2t = *i;
403    total_size += vcd_get_size (s2t);
404  }
405  return total_size;
406}
407
408static
409void
410vcd_alloc_signal_table (int size)
411{
412  if (size == 0)
413    vcd_signal_table = NULL;
414  else
415    vcd_signal_table = (tab_t*) malloc (sizeof (tab_t) * size);
416#if DEBUG
417  if (vcd_signal_table == NULL)
418  {
419    cerr << "Internal error : Unable to allocate memory for signal table to trace.\n";
420    exit (24032005);
421  }
422#endif
423}
424
425static
426void
427vcd_bind_to_signal_table (sc_trace_file &tf)
428{
429  tab_t *cur = vcd_signal_table;
430        vector<signal2trace>::iterator i;
431        for(i=(tf.sig_list).begin();i!=(tf.sig_list).end();i++)
432        {
433    signal2trace &s2t = *i;
434    s2t.pointer = cur;
435    cur += vcd_get_size (s2t);
436#if 0
437    std::cout << s2t
438      << "\nget_pointer () => " << hex << s2t.inter->get_pointer ()
439      << "\nvcd pointer () => " << hex << s2t.pointer
440      << "\nvcd_get_size () => " << vcd_get_size (s2t)
441      << "\n";
442#endif
443  }
444}
445
446static
447void
448vcd_build_signal_table (sc_trace_file &tf)
449{
450  int s = vcd_get_signal_table_size (tf);
451
452  vcd_alloc_signal_table (s);
453
454  vcd_bind_to_signal_table (tf);
455}
456
457static
458void
459vcd_trace_init (sc_trace_file &tf)
460{
461        init (tf);
462        fprintf (tf.pfic,"$upscope $end\n$enddefinitions  $end\n\n$comment\nAll initial values are dumped below at time 0 sec = 0 timescale units.\n$end\n\n$dumpvars\n");
463  vcd_build_signal_table (tf);
464
465  // dump all var
466        vector<signal2trace>::iterator i;
467        for(i=(tf.sig_list).begin();i!=(tf.sig_list).end();i++)
468        {
469    vcd_trace (tf, *i, false);
470        }//fin de la liste des signal2trace
471
472  // clocks to trace
473  vcd_trace_clocks (tf, true);
474
475        if (cpt==trace_start)
476                fprintf(tf.pfic,"$end\n"); //fin du $dumpvars
477}
478
479static
480void
481vcd_trace (sc_trace_file &tf,
482           bool           part)
483{
484        if (sc_core::cpt==sc_core::trace_start) {
485    if (part == false)
486      vcd_trace_init (tf);
487  } else {
488#if defined(DEBUG)
489      if (vcd_signal_table == NULL)
490      {
491        cerr << "Internal Error : VCD signal table is not yet allocated.\n";
492        exit (1042005);
493      }
494#endif
495      vcd_print_cycle_number (tf.pfic,sc_core::cpt);
496      // signals to trace
497      if (part == false)
498      {
499//        vector<signal2trace> &sig_list = (part == false)?to_update_on_pos:to_update_on_neg;
500        vector<signal2trace>::iterator i;
501        for(i=tf.sig_list.begin();i!=tf.sig_list.end();i++)
502        {
503          vcd_trace (tf, *i);
504        }//fin de la liste des signal2trace
505      }
506      // clocks to trace
507      vcd_trace_clocks (tf, !part);
508  }
509}
510
511void
512trace (sc_trace_file &tf, bool part)
513{
514/*------------------------------------------------------------------------------------*/
515       
516        switch (tf.flag){
517
518        // fonction trace() pour VCD:
519        case VCD_FORMAT:
520                vcd_trace (tf, part);
521    break;//fin de la fonction trace() pour VCD
522
523/*------------------------------------------------------------------------------------*/
524       
525        // fonction trace() pour PAT:
526        case PAT_FORMAT : 
527    pat_trace (tf, part);
528                break;//fin de la fonction trace() pour PAT
529        }// fin du switch format pour trace()
530               
531}
532
533/*------------------------------------------------------------------------------------*/
534
535static
536void
537vcd_sc_trace (sc_trace_file *tf, const signal2trace &t, const std::string
538&name)
539{
540        //déclaration du signal dans l'en-tête du fichier VCD:
541        // exemple de déclarations :
542        // $var wire    1  aaa  clk       $end
543        // $var wire    1  aab  resetn       $end
544        // $var wire    1  aac  _mips0_IT_5       $end
545
546        std::string declaration;
547        std::ostringstream buf;
548  // begin
549        declaration = "$var wire ";
550        buf.width (4);
551  buf << t.bit_size;
552  declaration += buf.str();
553  declaration += "  ";
554  declaration += t.alias;
555  declaration += "  ";
556  declaration += name;
557  // bit range
558  if (t.bit_size != 1)
559  {
560    declaration += " [";
561          std::ostringstream bit_size;
562    bit_size << t.bit_size - 1;
563    declaration += bit_size.str();
564    declaration += ":0]";
565  }
566  // end
567        declaration += "       $end\n";
568        //declaration += "  $end\n";
569
570        if ((fprintf(tf->pfic,declaration.c_str()))==0)
571                {
572                        cerr << "erreur ecriture de declaration du signal sc_signal\n";
573                        exit(3);
574                }
575}
576
577static
578void
579pat_sc_trace (sc_trace_file *tf, const signal2trace &t, const std::string
580&name)
581{
582#ifdef PAT_TRACE_FORMAT
583        //exemple:
584        //DECLAR ("a", ":2", "X", IN, "3  downto 0", "" );
585        //DECLAR ("b", ":2", "X", IN, "3  downto 0", "" );
586        //DECLAR ("vdd", ":2", "B", IN, "", "" );
587
588        std::string downto;     
589        const sc_object *obj = (const sc_object *) t.inter;
590        const char *obj_kind = obj->kind ();
591        char *format;
592        char *dir;
593
594        if (strstr (obj_kind,"inout"))
595                dir = OUT; // Direction is OUT instead of INOUT
596               // because port behavior is only seen as an output port.
597        else if (strstr (obj_kind,"in"))
598                dir = IN;
599        else if (strstr (obj_kind,"out"))
600                dir = OUT;
601        else if (obj_kind == sc_clock::kind_string)
602                dir = SIGNAL;
603        else if (obj_kind == sc_signal_base::kind_string)
604    dir = REGISTER;
605  // to do : dir = REGISTER;
606        //         dir = SIGNAL;
607
608        if ( t.bit_size % 4 == 0)
609                format = "x";
610        else
611                format = "b";
612
613  if ( t.bit_size == 1) {
614                downto = "";
615        }
616        else 
617        {
618                std::ostringstream nbits;
619                nbits << t.bit_size-1;
620                downto = nbits.str();
621                downto += " downto 0";
622        }
623       
624#if 0
625  printf ("DECLAR (\"%s\", \":1\", \"%s\", %s, \"%s\", \"\" );\n",
626    name.c_str (),
627    format,
628    dir,
629    downto.c_str());
630#endif
631        DECLAR ((char*)(name.c_str ()), ":1", format, dir,(char *) downto.c_str(), "" );
632#endif // PAT_TRACE_FORMAT
633}
634
635void
636sc_trace( sc_trace_file* tf, const signal2trace &t, const std::string &name )
637{
638  if (tf == NULL)
639    return;
640        if (t.bit_size > 64)
641                cerr << "Warning : tracing functions do not support data types larger than 64 bits.\n";
642        if (already_initialized)
643                cerr << "Warning : please call tracing functions BEFORE sc_initialize.\n";
644        //ajout du signal dans la liste des signaux à tracer:
645        (tf->sig_list).push_back (t); 
646
647        switch (tf->flag) {
648        case VCD_FORMAT : 
649    vcd_sc_trace (tf, t, name);
650                break;
651       
652        case PAT_FORMAT :
653    pat_sc_trace (tf, t, name);
654                break;
655        default :
656                {
657                cerr << "Unknown trace format.\n";
658                exit (1);
659                }
660        }// fin switch format pour sc_trace
661       
662}
663
664//---------------------------------------------------------------------------
665
666#if 0
667static
668ostream&
669operator << (ostream &o,
670             const signal2trace &s2t)
671{
672  o << "signal2trace {"
673    << "inter = " << hex << s2t.inter
674    << ",alias = '" << s2t.alias << "'"
675    << ",bitsize = " << dec << s2t.bit_size
676    << ",pointer = " << hex << s2t.pointer
677    << ",nomSig  = " << s2t.nomSig << "}";
678  return o;
679}
680#endif
681
682//----------------------------------------------------------------------------
683
684#define DEF_SC_TRACE(T) /*inline \*/ \
685  void   \
686  sc_trace (sc_trace_file* tf, const T& object, const std::string &name) \
687  { \
688                signal2trace t;                                      \
689                sc_interface *inter = new sc_localvar<T> (object);   \
690                t.inter = inter;                                     \
691                t.alias = alias();                                   \
692                t.bit_size = get_bits_number(object);                \
693                t.nomSig = name;                                     \
694                sc_trace (tf, t, name);                              \
695  } \
696
697        DEF_SC_TRACE(bool)
698        DEF_SC_TRACE(float)
699        DEF_SC_TRACE(double)
700        DEF_SC_TRACE(unsigned char)
701        DEF_SC_TRACE(unsigned short)
702        DEF_SC_TRACE(unsigned int)
703        DEF_SC_TRACE(unsigned long)
704        DEF_SC_TRACE(char)
705        DEF_SC_TRACE(short)
706        DEF_SC_TRACE(int)
707        DEF_SC_TRACE(long)
708        DEF_SC_TRACE(uint64)
709        DEF_SC_TRACE(int64)
710
711#undef DEF_SC_TRACE
712
713//---------------------------------------------------------------------------
714} // end of sc_core namespace
715
Note: See TracBrowser for help on using the repository browser.