source: sources/src/entity.cc @ 27

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

SystemCASS now uses autoconf/automake to build the API. Regression tests still
use the old Makefiles.
(thanks to Nicolas Pouillon)

The library directory no longer is "lib-arch-system". The directory now is "lib-linux". Everyone needs to pay attention about SYSTEMCASS environment variable.

Changes:

  • system header includes
  • Add includes to config.h (generated by autoconf/automake)
  • test:
    • linux preprocessor macro instead of _WIN32
    • CONFIG_DEBUG instead of DEBUG

Removes:

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