source: sources/src/global_functions.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: 12.5 KB
Line 
1/*------------------------------------------------------------\
2  |                                                             |
3  | Tool    :                  systemcass                       |
4  |                                                             |
5  | File    :                 global_functions.cc               |
6  |                                                             |
7  | Author  :                 Buchmann Richard                  |
8  |                           Nicolas Pouillon                  |
9  |                                                             |
10  | Date    :                   21_09_2005                      |
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#include <cstdio>
38#include <iostream>
39#include <dlfcn.h>
40#include <signal.h>
41
42#include "schedulers.h"   // get_scheduling & run_schedule_editor
43#include "sc_module.h"    // check_all_method_process
44#include "gen_code.h"     // gen_scheduling_code_for_dynamic_link & gen_scheduling_code_for_static_func
45#include "sc_clock_ext.h" // clock list
46#include "usage.h"
47#include "module_hierarchy2dot.h"
48#include "assert.h"
49
50#ifdef HAVE_CONFIG_H
51#include "config.h"
52#endif
53
54using namespace std;
55
56namespace sc_core {
57
58const char * temporary_dir = "/tmp";
59const char * generated_files_dir = "./generated_by_systemcass";
60
61static usage_t usage;
62
63/* ***************************** */
64/* Dumping functions (for debug) */
65/* ***************************** */
66
67template < typename T > ostream & operator <<(ostream & o, const vector < T * > & v) {
68    typename vector < T * >::const_iterator i;
69    for (i = v.begin(); i != v.end(); ++i) {
70        o << **i << " ";
71    } return o;
72}
73
74/* ************ */
75/*  clock list  */
76/****************/
77
78typedef std::set<const sc_clock *> clock_list_t;
79
80ostream & operator <<(ostream & o, const clock_list_t & cl) {
81    clock_list_t::const_iterator i;
82    for (i = cl.begin(); i != cl.end(); ++i) {
83        o << (*i)->name() << " ";
84    }
85    return o;
86}
87
88
89// clock list
90void create_clock_list(clock_list_t & c, const equi_list_t & el) {
91    equi_list_t::const_iterator i;
92    for (i = el.begin(); i != el.end(); ++i) {
93        equi_t::const_iterator j;
94        for (j = i->begin(); j != i->end(); ++j) {
95            if (j->kind() == sc_clock::kind_string)
96                c.insert((const sc_clock *) j->object);
97        }
98    }
99}
100
101/* ************ */
102/*  functions   */
103/****************/
104
105// function pointer to the simulation core (compiled and linked dynamically)
106evaluation_fct_t func_simulate_1_cycle = NULL;
107evaluation_fct_t func_combinationals = NULL;
108
109/* ************ */
110/* dynamic link */
111/* ************ */
112
113static void * handle = NULL;
114
115static void link(const char * lib) {
116    // chargement du code de simulate_1_cycle
117    handle = dlopen(lib, RTLD_GLOBAL | RTLD_NOW);
118    //handle = dlopen(lib, RTLD_LAZY | RTLD_GLOBAL | RTLD_NOW);
119
120    if (handle == NULL) {
121        const char * error = dlerror();
122        if (error) {
123            fprintf(stderr, "dlopen: %s\n", error);
124        }
125        fprintf(stderr, "Is there -rdynamic option into your command line ? If not, please do it.\n");
126        exit(18);
127    }
128
129    union uni_fct_t {
130        evaluation_fct_t fct_type;
131        void * dl_pointer_type;
132    };
133    uni_fct_t temp;
134    temp.dl_pointer_type = dlsym(handle, "initialize");
135    if (temp.dl_pointer_type == NULL) {
136        const char * error = dlerror();
137        if (error) {
138            fprintf(stderr, "dlsym: %s\n", error);
139        }
140        exit(19);
141    }
142    evaluation_fct_t func_initialize;
143    func_initialize = temp.fct_type;
144    func_initialize();
145
146    temp.dl_pointer_type = dlsym(handle, "simulate_1_cycle");
147    if (temp.dl_pointer_type == NULL) {
148        const char * error = dlerror();
149        if (error) {
150            fprintf(stderr, "dlsym: %s\n", error);
151            exit(20);
152        }
153        func_simulate_1_cycle = temp.fct_type;
154
155        temp.dl_pointer_type = dlsym(handle, "mealy_generation");
156        if (temp.dl_pointer_type == NULL) {
157            const char * error = dlerror();
158            if (error) {
159                fprintf(stderr, "dlsym: %s\n", error);
160            }
161            exit(21);
162        }
163        func_combinationals = temp.fct_type;
164
165        /*
166         *
167         */
168        if (dump_stage) {
169            cerr << "dynamic link done\n";
170        }
171    }
172}
173
174
175static void unlink() {
176    if (handle) {
177        if (dlclose(handle) != 0) {
178            cerr << "Warning : dlclose returns an error.\n" << dlerror() << endl;
179        }
180        handle = NULL;
181    }
182}
183
184/* ************ */
185/* initializing */
186/* ************ */
187
188bool already_initialized = false;
189
190static void use_static_func() {
191    if (dump_stage) {
192        cerr << "Using static functions to schedule SystemC processes.\n";
193    }
194    if (scheduling_method == CASS_SCHEDULING) {
195        func_simulate_1_cycle = (evaluation_fct_t) sc_core::quasistatic_simulate_1_cycle;
196        func_combinationals = (evaluation_fct_t) sc_core::quasistatic_mealy_generation;
197    }
198    else {
199        func_simulate_1_cycle = (evaluation_fct_t) sc_core::static_simulate_1_cycle;
200        func_combinationals = (evaluation_fct_t) sc_core::static_mealy_generation;
201    }
202}
203
204
205static void compile_and_link(const char *base_name) {
206    if (dump_stage) {
207        cerr << "Using dynamically loaded functions to schedule SystemC processes.\n";
208    }
209    // compilation du code de simulate_1_cycle
210    compile_code(base_name);
211
212    char lib_absolutepath[256];
213#if defined(CONFIG_OS_DARWIN)
214    sprintf(lib_absolutepath, "/tmp/%s.so", base_name);
215#elif defined(CONFIG_OS_LINUX)
216    sprintf(lib_absolutepath, "/tmp/.libs/%s.so.0", base_name);
217#else
218    cerr << "ERROR\n";
219    exit(126);
220#endif
221    link(lib_absolutepath);
222}
223
224
225static void internal_sc_initialize(void) {
226    sort_equi_list();
227
228    check_all_method_process();
229
230    if (dump_netlist_info) {
231        cerr << "Module instance list\n--------------------\n" << instances_set << endl;
232    }
233
234  /*
235   * Initialize the signals table
236   */
237  create_signals_table ();
238  bind_to_table ();
239  if (dump_netlist_info)
240  {
241    print_table (cerr);
242    cerr << endl;
243    print_table_stats (cerr);
244    cerr << endl;
245  }
246
247  // Init variables to be able to run combinational functions
248  pending_write_vector_capacity = get_signal_table_size ();
249
250  assert(pending_write_vector_capacity != 0);
251
252#ifdef _OPENMP
253#define LINE_SIZE 128L
254  int malloc_size =
255      (sizeof (pending_write_t) * (pending_write_vector_capacity + 1) + (LINE_SIZE - 1)) & ~(LINE_SIZE - 1);
256  assert((sizeof (pending_write_t) * (pending_write_vector_capacity + 1)) <= malloc_size && "bad allocation size");
257
258#pragma omp parallel
259  {
260          posix_memalign((void **)&pending_write_vector, LINE_SIZE, malloc_size);
261          pending_write_vector_nb = (int32_t *)&pending_write_vector[0];
262          pending_write_vector = &pending_write_vector[1];
263          printf("malloc 0x%x @%p, idx @0x%x\n", malloc_size, pending_write_vector, pending_write_vector_nb);
264          *pending_write_vector_nb = 0;
265  }
266#else
267        pending_write_vector_nb = (int32_t *)malloc(sizeof(int32_t));
268        pending_write_vector = (pending_write_vector_t) 
269            malloc(sizeof (pending_write_t) * pending_write_vector_capacity);
270#endif
271 
272  // create the clock list
273  clock_list_t clock_list;
274  create_clock_list (clock_list, get_equi_list ());
275  if (dump_netlist_info)
276    cerr << "Clock list\n"
277         << "----------\n"
278         << clock_list << "\n\n";
279  // Check if a clock exists in the system
280  if (clock_list.empty()) {
281      cerr << "System need a clock.\n" <<
282          "Please define system clock using special type \"sc_clock\".\n";
283      exit(22);
284  }
285
286  string base_name = get_scheduling (scheduling_method);
287
288  if (dynamic_link_of_scheduling_code)
289    compile_and_link (base_name.c_str());
290  else
291    use_static_func ();
292 
293  *pending_write_vector_nb = 0;
294 
295  check_all_ports ();
296  usage.start ();
297
298    if (dump_stage) {
299        cerr << "sc_initialize () done.\n";
300    }
301
302    already_initialized = true;
303}
304
305
306inline void check_and_initialize() {
307    if (already_initialized == false) {
308#if defined(SYSTEMC_VERSION_1_0)
309        cerr << "Warning : call sc_initialize before executiong simulation.\n";
310#endif
311        internal_sc_initialize();
312        if (dump_module_hierarchy) {
313            module_hierarchy2dot(dump_module_hierarchy);
314        }
315        if (nosimulation) {
316            exit(0);
317        }
318    }
319}
320
321
322void sc_initialize(void) {
323    cerr << "Warning : 'sc_initialize' function is deprecated since SystemC 2.1.\n";
324    cerr << "Use 'sc_start(0)' instead.\n";
325    check_and_initialize();
326}
327
328/* ********** */
329/* simulating */
330/* ********** */
331
332inline void sc_cycle(double duration) {
333    check_and_initialize();
334    sc_core::internal_sc_cycle0(duration);
335    if (have_to_stop) {
336        std::vector<method_process_t *>::iterator i;
337        for (i = sc_core::method_process_list.begin(); i != sc_core::method_process_list.end(); i++) {
338            delete *i;
339        }
340        std::vector<const char *>::iterator j;
341        for (j = sc_core::allocated_names.begin(); j != sc_core::allocated_names.end(); j++) {
342            free((char *) *j);
343        }
344    }
345}
346
347
348inline void sc_cycle(double duration, sc_time_unit time_unit) {
349    check_and_initialize();
350    sc_core::internal_sc_cycle0(duration);
351    if (have_to_stop) {
352        std::vector<method_process_t *>::iterator i;
353        for (i = sc_core::method_process_list.begin(); i != sc_core::method_process_list.end(); i++) {
354            delete *i;
355        }
356        std::vector<const char *>::iterator j;
357        for (j = sc_core::allocated_names.begin(); j != sc_core::allocated_names.end(); j++) {
358            free((char *) *j);
359        }
360    }
361}
362
363
364void sc_start(double d_val) {
365    sc_cycle(d_val);
366#ifdef DUMP_SIGNAL_STATS
367    print_registers_writing_stats(cerr);
368#endif
369#ifdef DUMP_SCHEDULE_STATS
370    print_schedule_stats(cerr);
371#endif
372}
373
374
375void sc_start() {
376    sc_cycle(-1);
377#ifdef DUMP_SIGNAL_STATS
378    print_registers_writing_stats(cerr);
379#endif
380#ifdef DUMP_SCHEDULE_STATS
381    print_schedule_stats(cerr);
382#endif
383}
384
385
386void sc_start(double d_val, sc_time_unit d_tu) {
387    sc_start(sc_time(d_val, d_tu));
388}
389
390
391void sc_start(const sc_time & duration) {
392    sc_cycle((double) duration);
393#ifdef DUMP_SIGNAL_STATS
394    print_registers_writing_stats(cerr);
395#endif
396#ifdef DUMP_SCHEDULE_STATS
397    print_schedule_stats(cerr);
398#endif
399}
400
401
402/* ****************** */
403/* stoping simulation */
404/* ****************** */
405
406bool have_to_stop = false;
407sc_stop_mode stop_mode = SC_STOP_FINISH_DELTA;
408
409void sc_stop() {
410    switch (stop_mode) {
411        case SC_STOP_IMMEDIATE:
412            exit(54);
413            break;
414        case SC_STOP_FINISH_DELTA:
415        default:
416            have_to_stop = true;
417            break;
418    }
419}
420
421
422void sc_set_stop_mode(sc_stop_mode new_mode) {
423    if (new_mode == SC_STOP_IMMEDIATE) {
424        stop_mode = SC_STOP_IMMEDIATE;
425    }
426}
427
428
429sc_stop_mode sc_get_stop_mode() {
430    return stop_mode;
431}
432
433
434void close_systemcass() {
435    unlink();
436    if (print_user_resources) {
437        usage.stop();
438        unsigned int d = usage;
439        cerr << "Performances\n" "------------\n";
440        cerr << "Time elapsed (sec) : " << d << endl;
441        cerr << "Cycles done        : " << nb_cycles << endl;
442        if (d == 0) {
443            cerr << "Performance (c/s)  : N/A" << endl;
444        }
445        else {
446            cerr << "Performance (c/s)  : " << nb_cycles / d << endl;
447        }
448        // cerr << "Memory used        : " << usage.get_memory_size () << endl;
449    }
450}
451
452} // end of sc_core namespace
453
454/*
455# Local Variables:
456# tab-width: 4;
457# c-basic-offset: 4;
458# c-file-offsets:((innamespace . 0)(inline-open . 0));
459# indent-tabs-mode: nil;
460# End:
461#
462# vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
463*/
464
Note: See TracBrowser for help on using the repository browser.