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

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

Checkin autotools magic

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