source: sources/src/global_functions.cc @ 63

Last change on this file since 63 was 63, checked in by bouyer, 5 years ago

Remplace USE_OPENMP with _OPENMP, the latter is automagically defined
by the compiler.

File size: 13.1 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        print_table(cerr);
241        cerr << endl;
242        print_table_stats(cerr);
243        cerr << endl;
244    }
245    // Init variables to be able to run combinational functions
246    pending_write_vector_capacity = get_signal_table_size();
247
248    assert(pending_write_vector_capacity != 0);
249
250#ifdef _OPENMP
251    #define LINE_SIZE 128L
252    int malloc_size = (sizeof (pending_write_t) * (pending_write_vector_capacity + 1) + (LINE_SIZE - 1)) & ~(LINE_SIZE - 1);
253    assert((sizeof(pending_write_t) * (pending_write_vector_capacity + 1)) <= malloc_size && "bad allocation size");
254
255    #pragma omp parallel
256    {
257        posix_memalign((void **) &pending_write_vector, LINE_SIZE, malloc_size);
258        pending_write_vector_nb = (int32_t *) &pending_write_vector[0];
259        pending_write_vector = &pending_write_vector[1];
260        //printf("malloc 0x%x @%p, idx @0x%x\n", malloc_size, pending_write_vector, pending_write_vector_nb);
261        *pending_write_vector_nb = 0;
262    }
263#else
264    pending_write_vector = (pending_write_vector_t) malloc(sizeof(pending_write_t) * pending_write_vector_capacity);
265    pending_write_vector_nb = (int32_t *) malloc(sizeof(int32_t));
266    *pending_write_vector_nb = 0;
267#endif
268
269
270    // create the clock list
271    clock_list_t clock_list;
272    create_clock_list(clock_list, get_equi_list());
273    if (dump_netlist_info) {
274        cerr << "Clock list\n" << "----------\n" << clock_list << "\n\n";
275    }
276
277    // Check if a clock exists in the system
278    if (clock_list.empty()) {
279        cerr << "System need a clock.\n" <<
280            "Please define system clock using special type \"sc_clock\".\n";
281        exit(22);
282    }
283    // Check if any constructor wrote into registers
284    if (*pending_write_vector_nb != 0) {
285        cerr <<
286            "Error : Register/Signal writing is not allowed before sc_initialize.\n"
287            "Move initializations from constructors/sc_main to module reset sequences.\n";
288        // we are unable to dump register(s) name(s)
289        // because the table binding is not yet completed.
290        exit(24);
291    }
292
293    string base_name = get_scheduling(scheduling_method);
294
295    if (dynamic_link_of_scheduling_code) {
296        compile_and_link(base_name.c_str());
297    }
298    else {
299        use_static_func();
300    }
301
302    *pending_write_vector_nb = 0;
303
304    check_all_ports();
305    usage.start();
306
307    if (dump_stage) {
308        cerr << "sc_initialize () done.\n";
309    }
310
311    already_initialized = true;
312}
313
314
315inline void check_and_initialize() {
316    if (already_initialized == false) {
317#if defined(SYSTEMC_VERSION_1_0)
318        cerr << "Warning : call sc_initialize before executiong simulation.\n";
319#endif
320        internal_sc_initialize();
321        if (dump_module_hierarchy) {
322            module_hierarchy2dot(dump_module_hierarchy);
323        }
324        if (nosimulation) {
325            exit(0);
326        }
327    }
328}
329
330
331void sc_initialize(void) {
332    cerr << "Warning : 'sc_initialize' function is deprecated since SystemC 2.1.\n";
333    cerr << "Use 'sc_start(0)' instead.\n";
334    check_and_initialize();
335}
336
337/* ********** */
338/* simulating */
339/* ********** */
340
341inline void sc_cycle(double duration) {
342    check_and_initialize();
343    sc_core::internal_sc_cycle0(duration);
344    if (have_to_stop) {
345        std::vector<method_process_t *>::iterator i;
346        for (i = sc_core::method_process_list.begin(); i != sc_core::method_process_list.end(); i++) {
347            delete *i;
348        }
349        std::vector<const char *>::iterator j;
350        for (j = sc_core::allocated_names.begin(); j != sc_core::allocated_names.end(); j++) {
351            free((char *) *j);
352        }
353    }
354}
355
356
357inline void sc_cycle(double duration, sc_time_unit time_unit) {
358    check_and_initialize();
359    sc_core::internal_sc_cycle0(duration);
360    if (have_to_stop) {
361        std::vector<method_process_t *>::iterator i;
362        for (i = sc_core::method_process_list.begin(); i != sc_core::method_process_list.end(); i++) {
363            delete *i;
364        }
365        std::vector<const char *>::iterator j;
366        for (j = sc_core::allocated_names.begin(); j != sc_core::allocated_names.end(); j++) {
367            free((char *) *j);
368        }
369    }
370}
371
372
373void sc_start(double d_val) {
374    sc_cycle(d_val);
375#ifdef DUMP_SIGNAL_STATS
376    print_registers_writing_stats(cerr);
377#endif
378#ifdef DUMP_SCHEDULE_STATS
379    print_schedule_stats(cerr);
380#endif
381}
382
383
384void sc_start() {
385    sc_cycle(-1);
386#ifdef DUMP_SIGNAL_STATS
387    print_registers_writing_stats(cerr);
388#endif
389#ifdef DUMP_SCHEDULE_STATS
390    print_schedule_stats(cerr);
391#endif
392}
393
394
395void sc_start(double d_val, sc_time_unit d_tu) {
396    sc_start(sc_time(d_val, d_tu));
397}
398
399
400void sc_start(const sc_time & duration) {
401    sc_cycle((double) duration);
402#ifdef DUMP_SIGNAL_STATS
403    print_registers_writing_stats(cerr);
404#endif
405#ifdef DUMP_SCHEDULE_STATS
406    print_schedule_stats(cerr);
407#endif
408}
409
410
411/* ****************** */
412/* stoping simulation */
413/* ****************** */
414
415bool have_to_stop = false;
416sc_stop_mode stop_mode = SC_STOP_FINISH_DELTA;
417
418void sc_stop() {
419    switch (stop_mode) {
420        case SC_STOP_IMMEDIATE:
421            exit(54);
422            break;
423        case SC_STOP_FINISH_DELTA:
424        default:
425            have_to_stop = true;
426            break;
427    }
428}
429
430
431void sc_set_stop_mode(sc_stop_mode new_mode) {
432    if (new_mode == SC_STOP_IMMEDIATE) {
433        stop_mode = SC_STOP_IMMEDIATE;
434    }
435}
436
437
438sc_stop_mode sc_get_stop_mode() {
439    return stop_mode;
440}
441
442
443void close_systemcass() {
444    unlink();
445    if (print_user_resources) {
446        usage.stop();
447        unsigned int d = usage;
448        cerr << "Performances\n" "------------\n";
449        cerr << "Time elapsed (sec) : " << d << endl;
450        cerr << "Cycles done        : " << nb_cycles << endl;
451        if (d == 0) {
452            cerr << "Performance (c/s)  : N/A" << endl;
453        }
454        else {
455            cerr << "Performance (c/s)  : " << nb_cycles / d << endl;
456        }
457        // cerr << "Memory used        : " << usage.get_memory_size () << endl;
458    }
459}
460
461} // end of sc_core namespace
462
463/*
464# Local Variables:
465# tab-width: 4;
466# c-basic-offset: 4;
467# c-file-offsets:((innamespace . 0)(inline-open . 0));
468# indent-tabs-mode: nil;
469# End:
470#
471# vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
472*/
473
Note: See TracBrowser for help on using the repository browser.