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
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
[65]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  }
[1]246
[65]247  // Init variables to be able to run combinational functions
248  pending_write_vector_capacity = get_signal_table_size ();
[60]249
[65]250  assert(pending_write_vector_capacity != 0);
251
[63]252#ifdef _OPENMP
[65]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");
[60]257
[65]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  }
[60]266#else
[65]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);
[60]270#endif
[65]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  }
[1]285
[65]286  string base_name = get_scheduling (scheduling_method);
[60]287
[65]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 ();
[1]297
[52]298    if (dump_stage) {
299        cerr << "sc_initialize () done.\n";
300    }
301
302    already_initialized = true;
[1]303}
304
[52]305
306inline void check_and_initialize() {
307    if (already_initialized == false) {
[1]308#if defined(SYSTEMC_VERSION_1_0)
[52]309        cerr << "Warning : call sc_initialize before executiong simulation.\n";
[1]310#endif
[52]311        internal_sc_initialize();
312        if (dump_module_hierarchy) {
313            module_hierarchy2dot(dump_module_hierarchy);
314        }
315        if (nosimulation) {
316            exit(0);
317        }
[1]318    }
319}
320
[52]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();
[1]326}
327
328/* ********** */
329/* simulating */
330/* ********** */
331
[52]332inline void sc_cycle(double duration) {
333    check_and_initialize();
334    sc_core::internal_sc_cycle0(duration);
[59]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    }
[1]345}
346
[52]347
348inline void sc_cycle(double duration, sc_time_unit time_unit) {
349    check_and_initialize();
350    sc_core::internal_sc_cycle0(duration);
[59]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    }
[1]361}
362
[52]363
364void sc_start(double d_val) {
365    sc_cycle(d_val);
[1]366#ifdef DUMP_SIGNAL_STATS
[52]367    print_registers_writing_stats(cerr);
[1]368#endif
369#ifdef DUMP_SCHEDULE_STATS
[52]370    print_schedule_stats(cerr);
[1]371#endif
372}
373
[52]374
375void sc_start() {
376    sc_cycle(-1);
[4]377#ifdef DUMP_SIGNAL_STATS
[52]378    print_registers_writing_stats(cerr);
[4]379#endif
380#ifdef DUMP_SCHEDULE_STATS
[52]381    print_schedule_stats(cerr);
[4]382#endif
383}
384
[52]385
386void sc_start(double d_val, sc_time_unit d_tu) {
387    sc_start(sc_time(d_val, d_tu));
[1]388}
389
[52]390
391void sc_start(const sc_time & duration) {
392    sc_cycle((double) duration);
[4]393#ifdef DUMP_SIGNAL_STATS
[52]394    print_registers_writing_stats(cerr);
[4]395#endif
396#ifdef DUMP_SCHEDULE_STATS
[52]397    print_schedule_stats(cerr);
[4]398#endif
[1]399}
400
[52]401
[1]402/* ****************** */
403/* stoping simulation */
404/* ****************** */
405
[52]406bool have_to_stop = false;
407sc_stop_mode stop_mode = SC_STOP_FINISH_DELTA;
[1]408
[52]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    }
[1]419}
420
[52]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    }
[1]426}
427
[52]428
429sc_stop_mode sc_get_stop_mode() {
430    return stop_mode;
[1]431}
432
[52]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    }
[1]450}
451
452} // end of sc_core namespace
453
[52]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.