source: sources/src/sc_port.cc

Last change on this file was 65, checked in by bouyer, 7 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.