source: sources/src/entity.cc @ 14

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

Initial import from CVS repository

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