source: sources/src/entity.cc @ 60

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