source: sources/src/sc_port.cc @ 3

Last change on this file since 3 was 1, checked in by buchmann, 17 years ago

Initial import from CVS repository

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