source: sources/src/sc_port.cc @ 47

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

This patch simplifies SystemCASS.

Remove:

  • ckeckings about multiwriting on registers and ports
  • checkings related to FSM modeling
  • regression tests related to the checkings
File size: 9.0 KB
Line 
1/*------------------------------------------------------------\
2|                                                             |
3| Tool    :                  systemcass                       |
4|                                                             |
5| File    :                   sc_port.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
38#include <iomanip>
39#include <map>
40#include <cassert>
41
42#include "sc_port.h"
43#include "sc_signal.h"
44#include "sc_module.h"
45#include "entity.h"
46#include "global_functions.h"
47
48#ifdef HAVE_CONFIG_H
49#include "config.h"
50#endif
51
52extern "C" {
53        extern char unstable;
54  char unstable = 0; // not in sc_core namespace because dynamic link support C linkage only
55  int32_t pending_write_vector_nb = 0;
56}
57
58using namespace std;
59
60namespace sc_core {
61
62const char *const sc_port_base::kind_string = "sc_port";
63const char *const sc_signal_base::kind_string = "sc_signal";
64
65unsigned int pending_write_vector_capacity = 512;
66pending_write_vector_t pending_write_vector = NULL;
67extern equi_list_t equi_list;
68
69const char* get_module_name (const tab_t *pointer)
70{
71        const equi_t &eq = get_equi (pointer);
72  return get_module_name (eq);
73}
74
75//typedef std::map<const sc_port_base*, const sc_module*> port2module_t;
76port2module_t port2module;
77
78// KIND STRING
79const char * const sc_inout_string = "sc_inout";
80const char * const sc_in_string    = "sc_in";
81const char * const sc_out_string   = "sc_out";
82
83// ----------------------------------------------------------------------------
84//  CLASS : sc_port_base
85//
86//                                               
87// ----------------------------------------------------------------------------
88
89sc_port_base::sc_port_base()
90{
91        init ();
92}
93
94sc_port_base::sc_port_base(const char* name_) : sc_object(name_)
95{
96        init ();
97}
98
99sc_port_base::sc_port_base(const sc_port_base& parent_) : sc_object (parent_.name ())
100{
101        init ();
102}
103
104void
105sc_port_base::init ()
106{
107#ifdef CONFIG_DEBUG
108        if (modules_stack.empty ()) {
109                cerr << "Internal error : modules stack empty\n";
110                exit (9);
111        }
112#endif
113        const sc_module *last_module = sc_core::modules_stack.top ();
114        port2module[this] = last_module;
115        set_kind (kind_string);
116}
117
118const sc_module &
119sc_port_base::get_module () const
120{
121        port2module_t::iterator i = port2module.find ((sc_port_base*)this);
122        if (i == port2module.end ()) {
123                cerr << "Internal error : Modules contain ports. "
124            "SystemCASS needs to identify the module that contains the following port : '" 
125        << name()
126                          << "'\n";
127                exit (17);
128        }
129  const sc_module *m = i->second;
130        return *m;
131}
132
133static bool check_multiwriting2port_error_message = true;
134void
135sc_port_base::check_multiwriting2port () const
136{
137  static std::map<sc_port_base*, double> s;
138  double t = sc_simulation_time ();
139  if (t == 0)
140    return;
141  sc_port_base *port = (sc_port_base*)this;
142  if ((s[port] == t) && (check_multiwriting2port_error_message))
143  {
144    check_multiwriting2port_error_message = 0;
145    if (use_port_dependency)
146    {
147      std::cerr << "Error at cycle #" << t << " : "
148                   "SystemCASS allows only 1 writing for each ports/signals.\n"
149                << "Functions write several times into '" << name () << "'.\n";
150    } else {
151      std::cerr << "Error : "
152                   "Multiwriting to port assertion works only "
153                   "when SystemCASS uses port dependency information "
154                   "(--p parameter).\n";
155    }
156    sc_core::sc_stop ();
157    exit (31072006); // 6
158  } else
159    s[port] = t;
160}
161
162std::ostream& 
163operator << (std::ostream &o, const sc_port_base &p)
164{
165  return o << p.name ();
166}
167// ----------------------------------------------------------------------------
168//  CLASS : sc_signal_base
169//
170//  The sc_signal<T> primitive channel class.
171// ----------------------------------------------------------------------------
172
173void
174sc_signal_base::init ()
175{
176        set_kind (kind_string);
177        bind (*this);
178}
179
180sc_signal_base::sc_signal_base() { 
181  init ();
182}
183
184sc_signal_base::sc_signal_base(const char* name_) : sc_object(name_) { 
185  init ();
186}
187
188sc_signal_base::sc_signal_base(const char* name_, void*) : sc_object(name_) {
189        // this overload is only used for SC_BIND_PROXY_NIL constant.
190        // this signal should not be added to the signal list.
191}
192
193sc_signal_base::~sc_signal_base() { 
194}
195
196/*
197 * Signals copy
198 */
199
200#ifdef DUMP_SIGNAL_STATS
201typedef map<tab_t*,long long int> counter_t;
202static counter_t  counter;
203long long int unnecessary = 0;
204long long int total_assig = 0;
205#endif
206
207} // end of sc_core namespace
208
209extern "C" {
210void
211update ()
212{
213#if defined(DUMP_STAGE)
214  cerr << "Updating... ";
215#endif
216// stl vectors are too slow
217// memcopy is not better
218// signal table sorting doesn't give any better performance     
219#if 0
220        cerr << pending_write_vector_nb << " " << pending_write_vector_capacity << endl;
221#endif
222#if defined(DUMP_STAGE)
223  cerr << "(" << pending_write_vector_nb
224       << " internal pending writings) ";
225#endif
226        unsigned int i;
227        for (i = 0; i < pending_write_vector_nb; ++i) {
228#if 0
229                cerr << "pending_write[" << i << "] : " << pending_write_vector[i];
230#endif
231#define iter (sc_core::pending_write_vector[i])
232#ifdef CONFIG_DEBUG
233                if (iter.pointer == NULL) {
234                        cerr << "Internal error : trying to apply a posted write from an unassigned signal/port\n";
235                        exit (8);
236                }
237#endif 
238#ifdef DUMP_SIGNAL_STATS
239                if (*(iter.pointer) == iter.value)
240                        unnecessary++;
241                counter[iter.pointer]++;
242#endif
243                *(iter.pointer) = iter.value;   
244#undef iter
245  }
246#ifdef DUMP_SIGNAL_STATS
247        total_assig += pending_write_vector_nb;
248#endif
249        pending_write_vector_nb = 0;
250
251#if defined(DUMP_STAGE)
252  cerr << "done.\n";
253#endif
254}
255
256} // end of extern "C"
257
258namespace sc_core {
259
260void
261print_registers_writing_stats (ostream &o)
262{
263#ifdef DUMP_SIGNAL_STATS
264        o << "signal index / name / usage (>1%)\n";
265        o << setprecision (2);
266        double t = sc_simulation_time ();
267        if (t == 0) {
268                o << "Warning : simulation too short.\n";
269                t = 0.01;
270        }
271        if (total_assig == 0)
272                return;
273        counter_t::iterator k;
274        for (k = counter.begin (); k != counter.end (); ++k) {
275                double usage = k->second / t * 100;
276                if (usage <= 1)
277                        continue;
278                o << k->first
279                        << "   " << get_name (k->first) 
280                        << "   " << usage << "%\n";
281        }
282        typedef map<string,int> counter_module_t;
283        counter_module_t counter_by_module;
284        for (k = counter.begin (); k != counter.end (); ++k) {
285                string module_name = get_module_name (k->first);
286                counter_by_module[module_name] += k->second;   
287        }
288        o << "module name / usage\n";
289        counter_module_t::iterator i;
290        for (i = counter_by_module.begin (); i != counter_by_module.end (); ++i) {
291                o << i->first
292                        << "   " << (i->second * 100 / total_assig) << "%\n";
293        }
294        cerr << "average of assignment number per cycle " << (total_assig / t) << "\n";
295        cerr << (unnecessary * 100 / total_assig) << "% of assignment are unecessary\n";
296#else
297        cerr << "Register usage not available.\n";
298#endif
299}
300
301static
302bool
303is_bound (/*const*/ sc_port_base &port)
304{
305  const tab_t *pointer = port.get_pointer ();
306  //assert(pointer != NULL);
307  if (pointer == NULL)
308    return false; // case : sc_in not bound
309/*
310  equi_t &e = get_equi (pointer);
311  if (e.size () == 1)
312    return true; // case : sc_out not bound
313*/
314  return has_equi (port);
315}
316
317static
318void
319check_port (/*const*/ sc_port_base &port)
320{
321  if (!is_bound (port))
322  {
323    cerr << "Error : '" << port.name () << "' port"
324            " (" << port.kind() << ")"
325            " is not bound.\n";
326    exit (29);
327  }
328}
329
330void
331check_all_ports ()
332{
333  if (dump_stage)
334    cerr << "checking ports...";
335        port2module_t::/*const_*/iterator i;
336  for (i = port2module.begin (); i != port2module.end (); ++i)
337  {
338    /*const*/ sc_port_base *port = i->first;
339    assert(port != NULL);
340    check_port (*port);
341  }
342  if (dump_stage)
343    cerr << " done.";
344}
345
346} // end of sc_core namespace
347
348
Note: See TracBrowser for help on using the repository browser.