source: sources/src/sc_port.cc @ 65

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

Various performance improvements for the parallel systemcass: cache-aligned
data structures, write only when needed, disable some unneeded barriers.

Fix bug in the non-openmp case: a pointer was not initialized

various style updates

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