source: sources/src/entity.cc @ 59

Last change on this file since 59 was 59, checked in by meunier, 8 years ago
  • Fixed memory leaks
  • Fixed indentation in some files
File size: 16.3 KB
RevLine 
[1]1/*------------------------------------------------------------\
[52]2  |                                                             |
3  | Tool    :                  systemcass                       |
4  |                                                             |
5  | File    :                   entity.cc                       |
6  |                                                             |
7  | Author  :                 Buchmann Richard                  |
8  |                           Taktak Sami                       |
9  |                                                             |
10  | Date    :                   09_07_2004                      |
11  |                                                             |
12  \------------------------------------------------------------*/
[1]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
[27]37#include <cstring>
38#include <iomanip>
39#include <list>
40#include <map>
41#include <vector>
[52]42#include <cassert>
[1]43
[27]44#include "entity.h"
45#include "sc_port.h"
46#include "sc_signal.h"
47#include "sc_module.h"
[52]48
[27]49#ifdef HAVE_CONFIG_H
50#include "config.h"
51#endif
[1]52
53using namespace std;
54
55namespace sc_core {
56
[52]57equi_list_t equi_list;
58equi_table_t equi_table = NULL;
[1]59
[52]60ostream & operator << (ostream &, const entity &);
61ostream & operator << (ostream &, const equi_t &);
62
63struct predic4entity2equi_t_t {
64    bool operator() (const entity & e1, const entity & e2) const {
65        return e1.interface < e2.interface;
[1]66    }
[52]67};
[1]68
[52]69typedef std::map <entity, equi_list_t::iterator, predic4entity2equi_t_t> entity2equi_it_t;
[1]70
[52]71
72ostream & operator << (ostream & o, const entity2equi_it_t & m) {
[1]73    entity2equi_it_t::const_iterator i;
[52]74    for (i = m.begin(); i != m.end(); ++i) {
75        o << (i->first) << " : " << *(i->second) << "\n";
[1]76    }
77    return o;
[52]78}
79
80entity2equi_it_t equi_map;
81
82
83const equi_list_t & get_equi_list() {
[1]84    return equi_list;
[52]85}
[1]86
87
[52]88unsigned int max(unsigned int a, unsigned int b) {
89    return (a > b) ? a : b;
90}
91
92
93static int get_signal_table_size(const equi_list_t & e) {
94    // bug fix : remove the 0x0 equi from the list
[1]95    equi_list_t::const_iterator i;
96    int capacity = 0;
[52]97    for (i = e.begin(); i != e.end(); ++i) {
98        //cerr << i->begin()->object->name ();
99        const entity & ent = *(i->begin());
100        int data_size = ent.data_size_in_bytes();
101        int number_of_part = ((data_size - 1) / sizeof(tab_t)) + 1;
102        capacity += number_of_part;
[1]103    }
104    return capacity;
[52]105}
[1]106
107
[52]108int get_signal_table_size() {
109    return get_signal_table_size(equi_list);
110}
[1]111
112
[52]113sc_port_base * get_out_port(const equi_t & eq) {
114    equi_t::const_iterator i;
115    for (i = eq.begin(); i != eq.end(); ++i) {
116        const char * type = i->kind();
117        if ((type == sc_core::sc_out_string) || (type == sc_core::sc_inout_string)) {
118            return i->port;
119        }
120    }
121    return NULL;
122}
[1]123
[59]124static sc_port_base * get_localvar(equi_t & eq) {
[52]125    equi_t::iterator i;
126    for (i = eq.begin(); i != eq.end(); ++i) {
127        const char *type = i->kind();
128        if (strcmp(type, "sc_localvar") == 0) {
129            return i->port;
130        }
[1]131    }
[52]132    return NULL;
133}
[1]134
[52]135
[59]136static sc_port_base * get_signal(equi_t & eq) {
[52]137    equi_t::iterator i;
138    for (i = eq.begin(); i != eq.end(); ++i) {
139        const char * type = i->kind();
140        if (strcmp(type, "sc_signal") == 0) {
141            return i->port;
142        }
143    }
144    return NULL;
145}
146
147
148equi_t & get_equi(const sc_interface & i) {
149    return get_equi(i.get_pointer());
150}
151
152
153struct predic4tab_t2equi_t_t {
154    bool operator() (const tab_t * t1, const tab_t * t2) const {
155        return t1 < t2;
156    }
157};
158
159
[1]160#define get_equi_SPEEDUP
[52]161equi_t & get_equi(const tab_t * pointer) {
[1]162    // result variable
[52]163    equi_list_t::iterator i;
[1]164#if defined(get_equi_SPEEDUP)
[52]165    typedef std::map <const tab_t *, equi_list_t::iterator, predic4tab_t2equi_t_t> tab_t2equi_it_t;
[1]166    static tab_t2equi_it_t tab2equi_map;
[27]167    assert(pointer != NULL);
[1]168
[52]169    tab_t2equi_it_t:: /*const_ */ iterator it = tab2equi_map.find(pointer);
170    if (it != tab2equi_map.end()) {
171        i = it->second;
172        return *i;
[1]173    }
174#endif
[52]175
176   
177    for (i = equi_list.begin(); i != equi_list.end(); ++i) {
178        const equi_t::iterator & j = i->begin();
179        const entity & e = *j;
180        const sc_interface * f = e.interface;
181        const tab_t * p = f->get_pointer();
182        if (p == pointer) {
[1]183#if defined(get_equi_SPEEDUP)
[52]184            tab2equi_map[pointer] = i;
[1]185#endif
[52]186            return *i;
187        }
188    }
189    cerr << "Internal error : get_equi(" << pointer << ")\n";
190    exit(11);
191}
[1]192#undef get_equi_SPEEDUP
193
[52]194
195bool has_equi( /*const */ sc_port_base & port) {
[1]196    entity e(port);
[52]197    entity2equi_it_t::/*const_ */iterator it = equi_map.find(e);
198    if (it == equi_map.end()) {
199        return false;
[1]200    }
201    return true;
[52]202}
[1]203
[52]204
205static bool is_register(const equi_t & eq) {
206    return eq.size() == 1;
207}
208
209static int count_level(const char * s, char c) {
210    int i;
211    int counter = 0;
212    for (i = 0; s[i] != '\0'; ++i) {
213        if (s[i] == c) {
214            ++counter;
215        }
216    }
217    return counter;
218}
219
220
221const char * get_name(const equi_t & e) {
222    equi_t::const_iterator top_iter = e.begin();
[27]223#ifdef CONFIG_DEBUG
[52]224    if (top_iter == e.end()) {
225        cerr << "Internal error : no signal in " << e << endl;
226        exit(25);
227    }
228    if (top_iter->object == NULL) {
229        cerr << "Internal error : no object bound to ";
230        cerr << *top_iter;
231        cerr << endl;
232        exit(26);
233    }
234    if (top_iter->object->name() == NULL) {
235        cerr << "Internal error : signal has no name.\n";
236        cerr << *top_iter;
237        cerr << endl;
238    }
[1]239#endif
[52]240    int top_level = count_level(top_iter->object->name(), '.');
241    equi_t::const_iterator i;
242    for (i = ++(e.begin()); i != e.end(); ++i) {
243        int current_level = count_level(i->object->name(), '.');
244        if (current_level < top_level) {
245            top_iter = i;
246            top_level = current_level;
247        }
248    }
[1]249#if 0
[52]250    cerr << "get_name of " << e;
251    cerr << " return " << top_iter->object->name() << endl;
[1]252#endif
[52]253    return top_iter->object->name();
254}
[1]255
[52]256
257const char *get_name(const tab_t * pointer) {
258    return get_name(get_equi(pointer));
259}
260
261
262static const sc_module & get_module(const string & s) {
263    instances_set_t::iterator i;
264    for (i = instances_set.begin(); i != instances_set.end(); ++i) {
265        if (strcmp((*i)->name(), s.c_str()) == 0) {
266            return **i;
267        }
[1]268    }
[52]269    cerr << "Internal error : get_module\n";
270    exit(27);
271}
272
273
274template < typename T > static equi_list_t::iterator get_equi(T & e) {
[59]275    // QM debug
276    //cout << "equi_map : " << equi_map << endl;
277
[52]278    entity2equi_it_t::iterator it = equi_map.find(entity(e));
279    if (it == equi_map.end()) {
280        return equi_list.end();
281    }
[1]282    return it->second;
[52]283}
[1]284
[52]285
286template < typename T > static void add_equi(equi_list_t::iterator & x, T & y) {
[1]287    entity e(y);
[52]288    x->push_back(e);
[1]289    equi_map[e] = x;
[52]290}
291
292
293template < typename T > static
294equi_list_t::iterator new_equi(T & x) { /* parameter is not 'const' because we need to modify pointer port/signal at end of elaboration step */
295    equi_list_t::iterator it = equi_list.insert(equi_list.begin(), equi_t(1, entity(x)));
[1]296    equi_map[entity(x)] = it;
297    return it;
[52]298}
[1]299
300
[52]301// sort by number of connected ports  bound to the signal
302static int operator <(const equi_t & e1, const equi_t & e2) {
303    return (e1.size() < e2.size());
304}
305
306// sort by data size
307/*
308    int operator<(const equi_t &e1, const equi_t &e2)
309    {
310    return (e1.begin()->data_size () < e2.begin()->data_size ());
311    }
312    */
313// random sort
314/*
315    int operator<(const equi_t &e1, const equi_t &e2)
316    {
317    typedef std::map<const equi_t*,int> m_t;
318    static m_t m;
319    if (m[&e1] == 0)
320    m[&e1] = rand ();
321    if (m[&e2] == 0)
322    m[&e2] = rand ();
323    return m[&e1] < m[&e2];
324    }
325    */
326
327void sort_equi_list() {
328    //load ();
329    equi_list.sort();
[1]330    //equi_list.reverse ();
[52]331}
332
333
[27]334#if defined(DUMP_SIGNAL_STATS)
[52]335static unsigned int equi_real_size;
[1]336#endif
337
[52]338unsigned int get_sizeof_signals_table() {
[1]339    equi_list_t::iterator i;
340    int table_size = 0;
[52]341    //cerr << "external table includes :\n";
342    for (i = equi_list.begin(); i != equi_list.end(); ++i) {
343        if (get_out_port(*i)) {
344            continue;
345        }
346        if (get_signal(*i)) {
347            continue;
348        }
349        //cerr << get_name (*i) << " ";
350        const entity & ent = *(i->begin());
351        int data_size = ent.data_size_in_bytes();
352        int number_of_part = ((data_size - 1) / sizeof(tab_t)) + 1;
353        table_size += number_of_part;
354    }
[1]355    return table_size;
[52]356}
[1]357
[52]358
359void create_signals_table() {
360    if (dump_stage) {
361        cerr << "Allocating signals table.\n";
362    }
363    unsigned int table_size = get_sizeof_signals_table();
364    equi_table = new tab_t[table_size]; //(0xCD);
[27]365#if defined(DUMP_SIGNAL_STATS)
[52]366    equi_real_size = table_size;
[1]367#endif
368#if defined(INIT_SIGNALS_TO_ZERO)
[52]369    memset(equi_table, 0, sizeof(tab_t) * table_size);
[1]370#else
[52]371    memset(equi_table, 0xCD, sizeof(tab_t) * table_size);
[1]372#endif
[52]373}
[1]374
[52]375
376static void bind_equi_to_table(equi_t & e, tab_t * const pointer) {
[27]377    assert(pointer != NULL);
[1]378    equi_t::iterator i;
[52]379    for (i = e.begin(); i != e.end(); ++i) {
380        sc_interface *const inter = i->interface;
381        inter->set_pointer(pointer);
382        // We can't initialize data to zero there
383        // because we can't write the right amount of bits.
384        // It may produce some segmentation fault errors.
385        // The pointer is aligned to 32 bits.
[1]386    }
[52]387}
388
389
390void bind_to_table() {
391    if (dump_stage) {
392        cerr << "Binding ports/signals to the table.\n";
393    }
[1]394    equi_list_t::iterator i;
395    int index = 0;
[52]396    for (i = equi_list.begin(); i != equi_list.end(); ++i) {
397        sc_interface *out = get_out_port(*i);
398        if (out) {
399            bind_equi_to_table(*i, out->get_pointer());
400        }
401        else {
402            sc_interface * reg = get_signal(*i);
403            if (reg == NULL) {
404                reg = get_localvar(*i);
405            }
406            if (reg) {
407                bind_equi_to_table(*i, reg->get_pointer());
408            }
409            else {
410                bind_equi_to_table(*i, &(equi_table[index]));
411                index += (i->begin()->data_size_in_bytes() - 1) / sizeof(tab_t) + 1;
412            }
413        }
[1]414    }
[52]415}
[1]416
[52]417
418ostream & operator <<(ostream & o, const entity & e) {
[1]419#if 0
420    o << "entity (";
421    if (e.object)
[52]422        o << e.object->name();
[1]423    else
[52]424        o << "no object";
[1]425    if (e.interface)
[52]426        o << ", pointer = 0x" << hex << e.interface->get_pointer();
[1]427    else
[52]428        o << ", no interface";
[1]429    o << ")";
430#else
[52]431    assert(e.object != NULL);
432    o << e.object->name();
[1]433#endif
434    return o;
[52]435}
436
437ostream & operator <<(ostream & o, const equi_t & e) {
[1]438    bool nb = 0;
439    equi_t::const_iterator i;
[52]440    for (i = e.begin(); i != e.end(); ++i) {
441        const entity & ity = *i;
442        o << ((nb++) ? " = " : "") << ity;
443    }
[1]444    return o;
[52]445}
446
447
448void print_table(ostream & o) {
449    o << "Signal list\n" << "-----------\n";
[1]450    equi_list_t::const_iterator i;
[52]451    for (i = equi_list.begin(); i != equi_list.end(); ++i) {
452        const equi_t & eq = *i;
[1]453#if 0
[52]454        o << i->begin()->interface->get_pointer() << " : ";
455        o << (*i);
456        o << "\n";
[1]457#else
[52]458        o << "(" << get_name(eq) << ") <=> " << eq << ".\n";
[1]459#endif
460    }
[52]461}
[1]462
[52]463void print_table_stats(ostream & o) {
[27]464#if defined(DUMP_SIGNAL_STATS)
[52]465    int nb_reg = 0;
466    int nb_sig = 0;
467    int real_size = 0;
468
469    // count
[1]470    equi_list_t::const_iterator i;
[52]471    int num;
472    for (num = 0, i = equi_list.begin(); i != equi_list.end(); ++num, ++i) {
473        if (is_register(*i)) {
474            ++nb_reg;
475        }
476        else {
477            ++nb_sig;
478        }
[1]479    }
[52]480
481    // print results
482    o << "Statistics :\n";
483    o << "#registers : " << nb_reg << endl;
484    o << "#signals : " << nb_sig << endl;
485    o << "current table size : " << equi_real_size << endl;
[1]486#endif
[52]487}
[1]488
[52]489
[1]490#ifdef DUMP_SIGNAL_STATS
[52]491typedef map < tab_t *, long long int > counter_t;
492static counter_t counter;
[1]493long long int unnecessary = 0;
494long long int total_assig = 0;
495#endif
496
[52]497const char * get_module_name(const equi_t & eq) {
498    if (!is_register(eq)) {
499        /*
500        cerr << "get_module_name doesn't work yet upon non-register.\n";
501        */
502        return "top_level";
503    }
504    const entity & ent = *(eq.begin());
505
[27]506#ifdef CONFIG_DEBUG
[52]507    if (ent.type != sc_core::entity::SIGNAL) {
508        exit(28);
509    }
[1]510#endif
[52]511
512    // get module name from sc_signal used like a register
513    const char * sig_name = ent.object->name();
514    const char * sep = strchr(sig_name, '.');
515
[27]516#ifdef CONFIG_DEBUG
[52]517    if (sep == NULL) {
518        exit(30);
519    }
[1]520#endif
[52]521
522    int end_pos = sep - sig_name;
523    string module_name(sig_name, end_pos);
524    // can't return the char* pointer from string since it will be invalid.
525    return get_module(module_name).name();
[1]526}
527
528
[52]529static void merge_equi(equi_list_t::iterator & x, equi_list_t::iterator & y) {
530    equi_t::iterator i;
531    equi_t & y2 = *y;
532    for (i = y2.begin(); i != y2.end(); ++i) {
533        entity & e = *i;
534        equi_map[e] = x;
535    }
536
537    x->merge(*y);
538    equi_list.erase(y);
[1]539}
[52]540
541
[1]542// sort by data size
543#ifdef DATASIZE_SORT
[52]544int operator< (const equi_t & e1, const equi_t & e2) {
545    return (e1.begin()->data_size() < e2.begin()->data_size());
[1]546}
547#endif
548
[52]549
[1]550// random sort
551#ifdef RANDOM_SORT
[52]552int operator< (const equi_t & e1, const equi_t & e2) {
553    typedef std::map < const equi_t *, int > m_t;
554    static m_t m;
555    if (m[&e1] == 0) {
556        m[&e1] = rand();
557    }
558    if (m[&e2] == 0) {
559        m[&e2] = rand();
560    }
561    return m[&e1] < m[&e2];
[1]562}
563#endif
564
[52]565
[27]566#if defined(DUMP_SIGNAL_STATS)
[1]567static unsigned int equi_real_size;
568#endif
569
[52]570
571void bind(sc_signal_base & x) {
572#if 0
573    //defined(CONFIG_DEBUG)
574    equi_list_t::iterator x_equi = get_equi(x);
575    if ((x_equi != equi_list.end())) {
576        cerr << "Internal error : Signal already in the table\n";
577        return;
578    }
[1]579#endif
[52]580    new_equi(x);
[1]581}
582
[52]583
584void bind(sc_port_base & x) {
585    new_equi(x);
[1]586}
587
[52]588
589template < typename T > static void test_before_bind(sc_port_base & p1, T & p2) {
590    bool t1 = (p1.kind() != NULL);
591    bool t2 = (p2.kind() != NULL);
592    if (t1 && t2) {
593        return;
594    }
595    if (t1 == true) {
596        cerr << "Trying to bind '" << p1.name() << "' to an unknown type.\n";
597    }
598    else if (t2 == true) {
599        cerr << "Trying to bind '" << p2.name() << "' to an unknown type.\n";
600    }
601    else {
602        cerr << "Binding failed. Please check the netlist description.\n";
603    }
604    exit(20040525);
[1]605}
606
[52]607
608template < typename T > static void tbind(sc_port_base & x, T & y) {
609    // assert(x.get_pointer () != NULL); // x pointer may be NULL
610    // assert(y.get_pointer () != NULL); // y pointer may be NULL
611    equi_list_t::iterator x_equi = get_equi(x);
612    equi_list_t::iterator y_equi = get_equi(y);
613    if ((x_equi != equi_list.end()) && (y_equi != equi_list.end())) {
614        // 2 equipotentials are equals
615        merge_equi(x_equi, y_equi);
616    }
617    else if ((x_equi != equi_list.end())) {
618        // add y
619        add_equi(x_equi, y);
620    }
621    else if ((y_equi != equi_list.end())) {
622        // add y
623        add_equi(y_equi, x);
624    }
625    else {
626        // add a new equi
627        x_equi = new_equi(x);
628        add_equi(x_equi, y);
629    }
[1]630}
631
632
[52]633void bind(sc_port_base & p1, sc_port_base & p2) {
634    test_before_bind(p1, p2);
635    tbind(p1, p2);
636}
[1]637
638
[52]639void bind(sc_port_base & p1, sc_signal_base & s1) {
640    test_before_bind(p1, s1);
641    tbind(p1, s1);
642}
643
644
[1]645} // end of sc_core namespace
646
[52]647/*
648# Local Variables:
649# tab-width: 4;
650# c-basic-offset: 4;
651# c-file-offsets:((innamespace . 0)(inline-open . 0));
652# indent-tabs-mode: nil;
653# End:
654#
655# vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
656*/
657
Note: See TracBrowser for help on using the repository browser.