source: sources/src/sc_port.cc @ 63

Last change on this file since 63 was 63, checked in by bouyer, 5 years ago

Remplace USE_OPENMP with _OPENMP, the latter is automagically defined
by the compiler.

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