source: sources/src/sc_trace.cc @ 8

Last change on this file since 8 was 1, checked in by buchmann, 17 years ago

Initial import from CVS repository

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