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
RevLine 
[1]1/*------------------------------------------------------------\
[52]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  \------------------------------------------------------------*/
[1]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
[33]37#include <cstdio>
[27]38#include <iostream>
39#include <dlfcn.h>
[59]40#include <signal.h>
[52]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
[27]45#include "sc_clock_ext.h" // clock list
46#include "usage.h"
47#include "module_hierarchy2dot.h"
48#include "assert.h"
[52]49
[27]50#ifdef HAVE_CONFIG_H
51#include "config.h"
52#endif
[1]53
54using namespace std;
55
56namespace sc_core {
57
[52]58const char * temporary_dir = "/tmp";
59const char * generated_files_dir = "./generated_by_systemcass";
[1]60
61static usage_t usage;
62
63/* ***************************** */
64/* Dumping functions (for debug) */
65/* ***************************** */
66
[52]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;
[1]72}
73
74/* ************ */
75/*  clock list  */
76/****************/
77
[52]78typedef std::set<const sc_clock *> clock_list_t;
[1]79
[52]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;
[1]86}
87
[52]88
[1]89// clock list
[52]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        }
[42]98    }
[1]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
[52]113static void * handle = NULL;
[1]114
[52]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);
[1]119
[52]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    }
[1]128
[52]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();
[1]145
[52]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    }
[1]172}
173
[52]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    }
[1]182}
183
184/* ************ */
185/* initializing */
186/* ************ */
187
[52]188bool already_initialized = false;
[1]189
[52]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    }
[1]202}
203
[52]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];
[27]213#if defined(CONFIG_OS_DARWIN)
[52]214    sprintf(lib_absolutepath, "/tmp/%s.so", base_name);
[27]215#elif defined(CONFIG_OS_LINUX)
[52]216    sprintf(lib_absolutepath, "/tmp/.libs/%s.so.0", base_name);
[1]217#else
[52]218    cerr << "ERROR\n";
219    exit(126);
[1]220#endif
[52]221    link(lib_absolutepath);
[1]222}
223
224
[52]225static void internal_sc_initialize(void) {
226    sort_equi_list();
[1]227
[52]228    check_all_method_process();
[32]229
[52]230    if (dump_netlist_info) {
231        cerr << "Module instance list\n--------------------\n" << instances_set << endl;
232    }
[1]233
[52]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();
[1]247
[60]248    assert(pending_write_vector_capacity != 0);
249
[63]250#ifdef _OPENMP
[62]251    #define LINE_SIZE 128L
[60]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
[62]255    #pragma omp parallel
[60]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;
[52]262    }
[60]263#else
264    pending_write_vector = (pending_write_vector_t) malloc(sizeof(pending_write_t) * pending_write_vector_capacity);
[62]265    pending_write_vector_nb = (int32_t *) malloc(sizeof(int32_t));
266    *pending_write_vector_nb = 0;
[60]267#endif
[1]268
[60]269
[52]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    }
[1]276
[52]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
[60]284    if (*pending_write_vector_nb != 0) {
[52]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    }
[32]292
[52]293    string base_name = get_scheduling(scheduling_method);
[32]294
[52]295    if (dynamic_link_of_scheduling_code) {
296        compile_and_link(base_name.c_str());
297    }
298    else {
299        use_static_func();
300    }
301
[60]302    *pending_write_vector_nb = 0;
[52]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;
[1]312}
313
[52]314
315inline void check_and_initialize() {
316    if (already_initialized == false) {
[1]317#if defined(SYSTEMC_VERSION_1_0)
[52]318        cerr << "Warning : call sc_initialize before executiong simulation.\n";
[1]319#endif
[52]320        internal_sc_initialize();
321        if (dump_module_hierarchy) {
322            module_hierarchy2dot(dump_module_hierarchy);
323        }
324        if (nosimulation) {
325            exit(0);
326        }
[1]327    }
328}
329
[52]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();
[1]335}
336
337/* ********** */
338/* simulating */
339/* ********** */
340
[52]341inline void sc_cycle(double duration) {
342    check_and_initialize();
343    sc_core::internal_sc_cycle0(duration);
[59]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    }
[1]354}
355
[52]356
357inline void sc_cycle(double duration, sc_time_unit time_unit) {
358    check_and_initialize();
359    sc_core::internal_sc_cycle0(duration);
[59]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    }
[1]370}
371
[52]372
373void sc_start(double d_val) {
374    sc_cycle(d_val);
[1]375#ifdef DUMP_SIGNAL_STATS
[52]376    print_registers_writing_stats(cerr);
[1]377#endif
378#ifdef DUMP_SCHEDULE_STATS
[52]379    print_schedule_stats(cerr);
[1]380#endif
381}
382
[52]383
384void sc_start() {
385    sc_cycle(-1);
[4]386#ifdef DUMP_SIGNAL_STATS
[52]387    print_registers_writing_stats(cerr);
[4]388#endif
389#ifdef DUMP_SCHEDULE_STATS
[52]390    print_schedule_stats(cerr);
[4]391#endif
392}
393
[52]394
395void sc_start(double d_val, sc_time_unit d_tu) {
396    sc_start(sc_time(d_val, d_tu));
[1]397}
398
[52]399
400void sc_start(const sc_time & duration) {
401    sc_cycle((double) duration);
[4]402#ifdef DUMP_SIGNAL_STATS
[52]403    print_registers_writing_stats(cerr);
[4]404#endif
405#ifdef DUMP_SCHEDULE_STATS
[52]406    print_schedule_stats(cerr);
[4]407#endif
[1]408}
409
[52]410
[1]411/* ****************** */
412/* stoping simulation */
413/* ****************** */
414
[52]415bool have_to_stop = false;
416sc_stop_mode stop_mode = SC_STOP_FINISH_DELTA;
[1]417
[52]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    }
[1]428}
429
[52]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    }
[1]435}
436
[52]437
438sc_stop_mode sc_get_stop_mode() {
439    return stop_mode;
[1]440}
441
[52]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    }
[1]459}
460
461} // end of sc_core namespace
462
[52]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.