source: sources/src/sc_port.cc @ 35

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

Code cleanup.

Add --dynamiclink option to systemcass executable.

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