source: sources/src/global_functions.cc @ 60

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