source: sources/src/sc_trace.cc@ 30

Last change on this file since 30 was 27, checked in by buchmann, 17 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.