source: sources/src/sc_trace.cc @ 56

Last change on this file since 56 was 52, checked in by meunier, 12 years ago

Code formatting in all source files.

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