source: sources/src/sc_port.cc @ 60

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