source: branches/with_autoconf/src/sc_port.cc @ 20

Last change on this file since 20 was 20, checked in by nipo, 16 years ago

Sync up with trunk changes

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