source: branches/with_autoconf/src/sc_trace.cc @ 20

Last change on this file since 20 was 20, checked in by nipo, 15 years ago

Sync up with trunk changes

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