source: sources/src/sc_port.cc @ 26

Last change on this file since 26 was 12, checked in by buchmann, 16 years ago

Changes:

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