source: branches/with_autoconf/src/entity.cc @ 8

Last change on this file since 8 was 8, checked in by nipo, 16 years ago

Checkin autotools magic

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