source: sources/src/sc_trace.cc @ 30

Last change on this file since 30 was 27, checked in by buchmann, 16 years ago

SystemCASS now uses autoconf/automake to build the API. Regression tests still
use the old Makefiles.
(thanks to Nicolas Pouillon)

The library directory no longer is "lib-arch-system". The directory now is "lib-linux". Everyone needs to pay attention about SYSTEMCASS environment variable.

Changes:

  • system header includes
  • Add includes to config.h (generated by autoconf/automake)
  • test:
    • linux preprocessor macro instead of _WIN32
    • CONFIG_DEBUG instead of DEBUG

Removes:

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