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

Last change on this file since 13 was 8, checked in by nipo, 16 years ago

Checkin autotools magic

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