source: sources/src/sc_port.cc @ 59

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