source: sources/src/sc_port.cc

Last change on this file 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
RevLine 
[1]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
[27]38#include <iomanip>
39#include <map>
40#include <cassert>
[1]41
[27]42#include "sc_port.h"
43#include "sc_signal.h"
44#include "sc_module.h"
45#include "entity.h"
46#include "global_functions.h"
[1]47
[27]48#ifdef HAVE_CONFIG_H
49#include "config.h"
50#endif
51
[65]52
[1]53extern "C" {
[52]54    extern char unstable;
55    char unstable = 0; // not in sc_core namespace because dynamic link support C linkage only
[62]56    int32_t * pending_write_vector_nb = 0;
[60]57    unsigned long long int total_assig = 0;
[63]58#ifdef _OPENMP
[60]59#pragma omp threadprivate (pending_write_vector_nb, total_assig)
[62]60#endif
[1]61}
62
63using namespace std;
64
65namespace sc_core {
66
[52]67const char * const sc_port_base::kind_string = "sc_port";
68const char * const sc_signal_base::kind_string = "sc_signal";
[1]69
[62]70unsigned int pending_write_vector_capacity;
[1]71pending_write_vector_t pending_write_vector = NULL;
[63]72#ifdef _OPENMP
[60]73#pragma omp threadprivate (pending_write_vector)
[62]74#endif
[1]75extern equi_list_t equi_list;
76
[59]77const char * get_module_name(const tab_t * pointer) {
78    const equi_t & eq = get_equi(pointer);
79    return get_module_name(eq);
[1]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
[52]89
[1]90// ----------------------------------------------------------------------------
91//  CLASS : sc_port_base
92//
93//                                               
94// ----------------------------------------------------------------------------
95
[52]96sc_port_base::sc_port_base() {
[59]97    init ();
[1]98}
99
[52]100
101sc_port_base::sc_port_base(const char * name_) : sc_object(name_) {
102    init ();
[1]103}
104
[52]105
106sc_port_base::sc_port_base(const sc_port_base & parent_) : sc_object (parent_.name ()) {
107    init ();
[1]108}
109
[52]110
111void sc_port_base::init() {
[27]112#ifdef CONFIG_DEBUG
[52]113    if (modules_stack.empty()) {
114        cerr << "Internal error : modules stack empty\n";
115        exit (9);
116    }
[1]117#endif
[52]118    const sc_module * last_module = sc_core::modules_stack.top();
119    port2module[this] = last_module;
120    set_kind(kind_string);
[1]121}
122
[52]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. "
[1]128            "SystemCASS needs to identify the module that contains the following port : '" 
[52]129            << name()
130            << "'\n";
131        exit (17);
132    }
133    const sc_module * m = i->second;
134    return *m;
[1]135}
136
[52]137
[35]138static bool check_multiwriting2port_error_message = true;
[52]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"
[1]152                << "Functions write several times into '" << name () << "'.\n";
[52]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
[1]162    }
[52]163    else {
164        s[port] = t;
165    }
[1]166}
167
[52]168
169std::ostream & operator << (std::ostream & o, const sc_port_base & p) {
170    return o << p.name();
[1]171}
[52]172
173
[1]174// ----------------------------------------------------------------------------
175//  CLASS : sc_signal_base
176//
177//  The sc_signal<T> primitive channel class.
178// ----------------------------------------------------------------------------
[52]179void sc_signal_base::init() {
180    set_kind(kind_string);
181    bind(*this);
[1]182}
183
[52]184
[1]185sc_signal_base::sc_signal_base() { 
[52]186    init();
[1]187}
188
189
[52]190sc_signal_base::sc_signal_base(const char * name_) : sc_object(name_) { 
191    init ();
[1]192}
193
[52]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.
[1]198}
199
[52]200
201sc_signal_base::~sc_signal_base() {}
202
203
[1]204/*
205 * Signals copy
206 */
207
208#ifdef DUMP_SIGNAL_STATS
[52]209typedef map<tab_t *, long long int> counter_t;
210static counter_t counter;
[1]211long long int unnecessary = 0;
212long long int total_assig = 0;
213#endif
214
215} // end of sc_core namespace
216
[52]217
[1]218extern "C" {
[52]219
220    void update() {
[1]221#if defined(DUMP_STAGE)
[62]222        cerr << "Updating... ";
[1]223#endif
[62]224        // stl vectors are too slow
225        // memcopy is not better
226        // signal table sorting doesn't give any better performance
[1]227#if defined(DUMP_STAGE)
[62]228        cerr << "(" << *pending_write_vector_nb
229            << " internal pending writings) ";
[1]230#endif
[65]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
[1]236#define iter (sc_core::pending_write_vector[i])
[27]237#ifdef CONFIG_DEBUG
[62]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            }
[59]242#endif
[1]243#ifdef DUMP_SIGNAL_STATS
[62]244            if (*(iter.pointer) == iter.value) {
245                unnecessary++;
246            }
247            counter[iter.pointer]++;
[1]248#endif
[62]249            *(iter.pointer) = iter.value;
[1]250#undef iter
[62]251        }
[1]252#ifdef DUMP_SIGNAL_STATS
[62]253        total_assig += *pending_write_vector_nb;
[1]254#endif
[62]255        total_assig += *pending_write_vector_nb;
256        *pending_write_vector_nb = 0;
[1]257
258#if defined(DUMP_STAGE)
[62]259        cerr << "done.\n";
[1]260#endif
[62]261    }
[1]262
263} // end of extern "C"
264
265namespace sc_core {
266
[52]267void print_registers_writing_stats (ostream & o) {
[1]268#ifdef DUMP_SIGNAL_STATS
[52]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);
[59]291        counter_by_module[module_name] += k->second;
[52]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";
[1]300#else
[52]301    cerr << "Register usage not available.\n";
[1]302#endif
303}
304
[59]305
[52]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    }
[59]312    return has_equi(port);
[1]313}
314
[59]315
[52]316static void check_port(/*const*/ sc_port_base & port) {
[59]317    if (!is_bound(port)) {
[52]318        cerr << "Error : '" << port.name() << "' port"
[1]319            " (" << port.kind() << ")"
320            " is not bound.\n";
[52]321        exit (29);
322    }
[1]323}
324
[52]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) {
[59]332        /*const*/ sc_port_base * port = i->first;
[52]333        assert(port != NULL);
334        check_port(*port);
335    }
336    if (dump_stage) {
337        cerr << " done.";
338    }
[1]339}
340
[52]341
[1]342} // end of sc_core namespace
343
344
[52]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.