source: sources/src/sc_port.cc @ 53

Last change on this file since 53 was 52, checked in by meunier, 12 years ago

Code formatting in all source files.

File size: 9.5 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
[1]52extern "C" {
[52]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;
[1]56}
57
58using namespace std;
59
60namespace sc_core {
61
[52]62const char * const sc_port_base::kind_string = "sc_port";
63const char * const sc_signal_base::kind_string = "sc_signal";
[1]64
65unsigned int pending_write_vector_capacity = 512;
66pending_write_vector_t pending_write_vector = NULL;
67extern equi_list_t equi_list;
68
[52]69const char * get_module_name (const tab_t * pointer) {
70        const equi_t & eq = get_equi (pointer);
71    return get_module_name (eq);
[1]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
[52]81
[1]82// ----------------------------------------------------------------------------
83//  CLASS : sc_port_base
84//
85//                                               
86// ----------------------------------------------------------------------------
87
[52]88sc_port_base::sc_port_base() {
[1]89        init ();
90}
91
[52]92
93sc_port_base::sc_port_base(const char * name_) : sc_object(name_) {
94    init ();
[1]95}
96
[52]97
98sc_port_base::sc_port_base(const sc_port_base & parent_) : sc_object (parent_.name ()) {
99    init ();
[1]100}
101
[52]102
103void sc_port_base::init() {
[27]104#ifdef CONFIG_DEBUG
[52]105    if (modules_stack.empty()) {
106        cerr << "Internal error : modules stack empty\n";
107        exit (9);
108    }
[1]109#endif
[52]110    const sc_module * last_module = sc_core::modules_stack.top();
111    port2module[this] = last_module;
112    set_kind(kind_string);
[1]113}
114
[52]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. "
[1]120            "SystemCASS needs to identify the module that contains the following port : '" 
[52]121            << name()
122            << "'\n";
123        exit (17);
124    }
125    const sc_module * m = i->second;
126    return *m;
[1]127}
128
[52]129
[35]130static bool check_multiwriting2port_error_message = true;
[52]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"
[1]144                << "Functions write several times into '" << name () << "'.\n";
[52]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
[1]154    }
[52]155    else {
156        s[port] = t;
157    }
[1]158}
159
[52]160
161std::ostream & operator << (std::ostream & o, const sc_port_base & p) {
162    return o << p.name();
[1]163}
[52]164
165
[1]166// ----------------------------------------------------------------------------
167//  CLASS : sc_signal_base
168//
169//  The sc_signal<T> primitive channel class.
170// ----------------------------------------------------------------------------
[52]171void sc_signal_base::init() {
172    set_kind(kind_string);
173    bind(*this);
[1]174}
175
[52]176
[1]177sc_signal_base::sc_signal_base() { 
[52]178    init();
[1]179}
180
181
[52]182sc_signal_base::sc_signal_base(const char * name_) : sc_object(name_) { 
183    init ();
[1]184}
185
[52]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.
[1]190}
191
[52]192
193sc_signal_base::~sc_signal_base() {}
194
195
[1]196/*
197 * Signals copy
198 */
199
200#ifdef DUMP_SIGNAL_STATS
[52]201typedef map<tab_t *, long long int> counter_t;
202static counter_t counter;
[1]203long long int unnecessary = 0;
204long long int total_assig = 0;
205#endif
206
207} // end of sc_core namespace
208
[52]209
[1]210extern "C" {
[52]211
212    void update() {
[1]213#if defined(DUMP_STAGE)
[52]214            cerr << "Updating... ";
[1]215#endif
[52]216            // stl vectors are too slow
217            // memcopy is not better
218            // signal table sorting doesn't give any better performance
[1]219#if defined(DUMP_STAGE)
[52]220            cerr << "(" << pending_write_vector_nb
221                << " internal pending writings) ";
[1]222#endif
[52]223            unsigned int i;
224            for (i = 0; i < pending_write_vector_nb; ++i) {
[1]225#define iter (sc_core::pending_write_vector[i])
[27]226#ifdef CONFIG_DEBUG
[52]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                }
[1]231#endif 
232#ifdef DUMP_SIGNAL_STATS
[52]233                if (*(iter.pointer) == iter.value) {
234                    unnecessary++;
235                }
236                counter[iter.pointer]++;
[1]237#endif
[52]238                *(iter.pointer) = iter.value;   
[1]239#undef iter
[52]240            }
[1]241#ifdef DUMP_SIGNAL_STATS
[52]242            total_assig += pending_write_vector_nb;
[1]243#endif
[52]244            pending_write_vector_nb = 0;
[1]245
246#if defined(DUMP_STAGE)
[52]247            cerr << "done.\n";
[1]248#endif
[52]249        }
[1]250
251} // end of extern "C"
252
253namespace sc_core {
254
[52]255void print_registers_writing_stats (ostream & o) {
[1]256#ifdef DUMP_SIGNAL_STATS
[52]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";
[1]288#else
[52]289    cerr << "Register usage not available.\n";
[1]290#endif
291}
292
[52]293static bool is_bound(/*const*/ sc_port_base & port) {
294    const tab_t * pointer = port.get_pointer();
295    //assert(pointer != NULL);
296    if (pointer == NULL) {
297        return false; // case : sc_in not bound
298    }
299    return has_equi (port);
[1]300}
301
[52]302static void check_port(/*const*/ sc_port_base & port) {
303    if (!is_bound (port)) {
304        cerr << "Error : '" << port.name() << "' port"
[1]305            " (" << port.kind() << ")"
306            " is not bound.\n";
[52]307        exit (29);
308    }
[1]309}
310
[52]311
312void check_all_ports() {
313    if (dump_stage) {
314        cerr << "checking ports...";
315    }
316    port2module_t::/*const_*/iterator i;
317    for (i = port2module.begin(); i != port2module.end(); ++i) {
318        /*const*/ sc_port_base *port = i->first;
319        assert(port != NULL);
320        check_port(*port);
321    }
322    if (dump_stage) {
323        cerr << " done.";
324    }
[1]325}
326
[52]327
[1]328} // end of sc_core namespace
329
330
[52]331/*
332# Local Variables:
333# tab-width: 4;
334# c-basic-offset: 4;
335# c-file-offsets:((innamespace . 0)(inline-open . 0));
336# indent-tabs-mode: nil;
337# End:
338#
339# vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
340*/
341
Note: See TracBrowser for help on using the repository browser.