source: sources/src/entity.cc @ 17

Last change on this file since 17 was 17, checked in by buchmann, 15 years ago

Fix :

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