source: sources/src/gen_code.cc@ 53

Last change on this file since 53 was 52, checked in by meunier, 14 years ago

Code formatting in all source files.

File size: 18.5 KB
RevLine 
[1]1/*------------------------------------------------------------\
[52]2 | |
3 | Tool : systemcass |
4 | |
5 | File : gen_code.cc |
6 | |
7 | Author : Taktak Sami |
8 | Buchmann Richard |
9 | |
10 | Date : 09_07_2004 |
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 */
[52]36
[27]37#if defined(__linux__)
[17]38#include <linux/limits.h>
[27]39#elif defined(WIN32)
[17]40#include <windows.h>
41#endif
[52]42
[31]43#include <cstring>
44#include <cstdio>
45#include <cstdlib>
46#include <iostream>
47#include <fstream>
[1]48
[27]49#include "internal.h"
50#include "gen_code.h"
51#include "sc_module.h"
52#include "sc_ver.h"
53#include "process_dependency.h"
[52]54
[27]55#ifdef HAVE_CONFIG_H
56#include "config.h"
57#endif
[1]58
[41]59#ifdef _OPENMP
60#include <omp.h>
61#endif
62
[47]63#define casc_cflags GENERATED_MODULE_CFLAGS
[1]64
[27]65// Enable CPP call, this is useful for typeinfo-enabled classes
66#define CPP_CALL
[1]67
68using namespace std;
69
70namespace sc_core {
71
[52]72static void PrintCall(std::ostream &, const method_process_t &);
73static void open_temp(std::ofstream &, char *);
[1]74typedef void (*CASC_ENTRY_FUNC) (void *);
[52]75typedef union {
76 unsigned long long int integer;
77 SC_ENTRY_FUNC pmf;
78 CASC_ENTRY_FUNC pf;
79} fct;
[1]80
[52]81
82const char * get_pmf_type() {
83 switch (sizeof(SC_ENTRY_FUNC)) {
84 case 4:
85 // G4 pointer-to-member-function style
86 return "unsigned long int";
87 case 8:
88 // PC pointer-to-member-function style
89 return "unsigned long long int";
90 default:
91 cerr <<
92 "Internal Error : Unsupported pointer-to-member-function"
93 "(size: " << sizeof(SC_ENTRY_FUNC) << ").\n"
94 "Please try --nodynamiclink option.\n";
95 exit(21072009);
96 };
[38]97}
98
[52]99
100static ostream & operator <<(ostream & o, const SC_ENTRY_FUNC & f) {
101 register fct p;
102 p.integer = 0;
103 p.pmf = f;
104 return o << "0x" << hex << p.integer << "ULL";
[1]105}
106
[52]107
108static void PrintCall(std::ostream & o, const method_process_t & m) {
109 SC_ENTRY_FUNC func = m.func;
110 if (print_schedule) {
111 o << " fprintf(stderr,\"evaluation de " << m.module->name() << "->" << m.name << "()\\n\");\n";
112 }
113 o << " p.integer = " << func << ";\n";
[27]114#ifdef CPP_CALL
[52]115 o << " (((sc_module*)(" << m.module << "))->*(p.pmf)) (); /* " << m.module->name() << "->" << m.name << "() */\n";
[1]116#else
[52]117 o << " p.pf((void *)" << m.module << "); /* " << m.module->name() << "->" << m.name << "() */\n";
[1]118#endif
119}
120
[52]121
122static bool is_exist(const char * temp) {
123 ifstream o;
124 o.open(temp, ios::in);
125 if (o.is_open() == false) {
126 return false;
127 }
128 if (o.peek() == -1) {
129 return false;
130 }
131 return true;
[1]132}
133
134
[52]135static void open_temp(ofstream & o, char * temp) {
136 /*
137 srand (time (NULL));
138 int r = rand () % 1000;
139 */
140 pid_t pid = getpid();
141 int r = -1;
142 do {
143 sprintf(temp, "%s/scheduling-%d-%x.cc", temporary_dir, pid, ++r);
144 } while (is_exist(temp));
[1]145
[52]146 o.open(temp, ios::out);
147 if (o.is_open() == false) {
148 cerr << "Error : Unable to open a file to write scheduling code.\n";
149 exit(30032005);
150 }
[27]151#ifdef CONFIG_DEBUG
[52]152 cerr << "opened temporary filename : " << temp << "\n";
[1]153#endif
[52]154 sprintf(temp, "scheduling-%d-%x", pid, r++);
[1]155}
156
[52]157
158static char * gen_transition(ofstream & o, method_process_list_t & transition_func_list) {
159 // transitions
160 o << "\ninline void transition(void)\n{\n";
161 if (transition_func_list.empty() == false) {
162 o << " /* fonctions de transition */\n" << " register fct p;\n";
163 method_process_list_t::iterator mm;
164 for (mm = transition_func_list.begin(); mm != transition_func_list.end(); ++mm) {
165 PrintCall(o, **mm);
166 }
[1]167 }
[52]168 o << "}\n";
[1]169}
170
[52]171
172static char * gen_moore(ofstream & o, method_process_list_t & moore_func_list) {
173 // Moore generations (sequential functions)
174 o << "\ninline void moore_generation (void)\n{\n";
175 if (moore_func_list.empty() == false) {
176 o << " /* fonctions de generation de Moore */\n"
177 << " register fct p;\n";
178 method_process_list_t::reverse_iterator mm;
179 for (mm = moore_func_list.rbegin();
180 mm != moore_func_list.rend(); ++mm) {
181 PrintCall(o, **mm);
182 }
[1]183 }
[52]184 o << " \n}\n";
[1]185}
186
[52]187
188static char * gen_mealy(ofstream & o, strong_component_list_t & strongcomponents) {
189 // Mealy generations (combinational functions only)
190 o << "\nextern void mealy_generation (void)\n{\n";
191 if (strongcomponents.empty()) {
192 return NULL;
193 }
194 o << " register fct p;\n" << "\n\n /* fonctions de mealy */\n";
[1]195#ifdef NO_STATIC_SCHEDULE
[52]196 o << "\n do {\n unstable = 0;\n";
[1]197#endif
[52]198 strong_component_list_t::iterator ss;
199 for (ss = strongcomponents.begin(); ss != strongcomponents.end(); ++ss) {
200 if ((*ss)->size() == 1) {
201 /* un seul element dans le strong component */
202 method_process_t *m = (method_process_t *) (*((*ss)->begin()));
203 PrintCall(o, *m);
204 continue;
205 }
206 else {
207 /* plusieurs elements dans le strong component */
[1]208#ifndef NO_STATIC_SCHEDULE
[52]209 o << "\n do {\n unstable = 0;\n";
[1]210#endif
[52]211 component_list_t::reverse_iterator rev_mm;
212 for (rev_mm = (*ss)->rbegin(); rev_mm != (*ss)->rend(); ++rev_mm) {
213 method_process_t * m = (method_process_t *) * rev_mm;
214 PrintCall(o, *m);
215 }
[1]216#ifndef NO_STATIC_SCHEDULE
[52]217 o << " } while ( unstable );\n\n";
[1]218#endif
[52]219 }
[1]220 }
221#ifdef NO_STATIC_SCHEDULE
[52]222 o << " } while ( unstable );\n\n";
[1]223#else
[52]224 o << "\tunstable = 0;\n";
[1]225#endif
226}
227
[52]228
229static char * gen_mealy(ofstream & o, ProcessDependencyList & mealy_func_list) {
230 // Mealy generations (combinational functions only)
231 o << "\nextern void mealy_generation (void)\n{\n";
232 o << " register fct p;\n" << "\n\n /* fonctions de mealy */\n";
233 ProcessDependencyList::iterator it;
234 for (it = mealy_func_list.begin(); it != mealy_func_list.end(); ++it) {
235 const method_process_t * m = *it;
236 PrintCall(o, *m);
237 }
[1]238}
239
240
[52]241char * gen_scheduling_code_for_dynamic_link(method_process_list_t &
242 transition_func_list,
243 method_process_list_t &
244 moore_func_list,
245 strong_component_list_t &
246 strongcomponents) {
247 if (dump_stage) {
248 cerr << "Generating C code for scheduling...\n";
249 }
[1]250
[52]251 // open temporary file
252 ofstream o;
253 char base_name[PATH_MAX];
254 open_temp(o, base_name);
[38]255
[52]256 if (!o.good()) {
257 perror("scheduling: open file\n");
258 exit(-1);
259 }
[38]260
[52]261 o << "// generated by " << sc_version() << endl
262 << "#include <casc.h>\n\n" << "#include <cstdio>\n\n"
263 // << "#include <iostream>\n\n"
264 << "namespace sc_core {\n"
265 << " typedef void (sc_module::*SC_ENTRY_FUNC)();\n"
266 << " typedef void (*CASC_ENTRY_FUNC)(void *);\n";
[1]267
[52]268 const char * pmf_type = get_pmf_type();
[1]269
[52]270 o << " typedef union { "
271 << pmf_type
272 << " integer; SC_ENTRY_FUNC pmf; CASC_ENTRY_FUNC pf; } fct;\n";
[1]273
[52]274 gen_transition(o, transition_func_list);
275 gen_moore(o, moore_func_list);
276 gen_mealy(o, strongcomponents);
277
278 o << " \n}\n";
279 o << "\n} // end of sc_core namespace\n";
280
281 o.flush();
282 o.close();
283
284 // add "cc" extension
285 char file_name[PATH_MAX];
286 strncpy(file_name, base_name, PATH_MAX);
287 file_name[strlen(base_name)] = '\0';
288 strcat(file_name, ".cc");
289 rename(base_name, file_name);
290
291 if (edit_schedule) {
292 run_schedule_editor(file_name);
293 }
294
295 if (dump_stage) {
296 cerr << "Generating C code for scheduling done.\n";
297 }
298
299 return strdup(base_name);
[1]300}
301
302
[52]303char * gen_scheduling_code_for_dynamic_link(method_process_list_t &
304 transition_func_list,
305 method_process_list_t &
306 moore_func_list,
307 ProcessDependencyList &
308 mealy_func_list) {
309 if (dump_stage) {
310 cerr << "Generating C code for scheduling...\n";
311 }
[1]312
[52]313 // open temporary file
314 ofstream o;
315 char base_name[PATH_MAX];
316 open_temp(o, base_name);
[1]317
[52]318 if (!o.good()) {
319 perror("scheduling: open file\n");
320 exit(-1);
321 }
[1]322
[52]323 o << "// generated by " << sc_version() << endl
324 << "#include <casc.h>\n\n" << "#include <cstdio>\n\n"
325 << "namespace sc_core {\n"
326 << " typedef void (sc_module::*SC_ENTRY_FUNC)();\n"
327 << " typedef void (*CASC_ENTRY_FUNC)(void *);\n"
328 <<
329 " typedef union { unsigned long long int integer; SC_ENTRY_FUNC pmf; CASC_ENTRY_FUNC pf; } fct;\n";
[1]330
[52]331 gen_transition(o, transition_func_list);
332 gen_moore(o, moore_func_list);
333 gen_mealy(o, mealy_func_list);
334
335 o << "\n}\n";
336 o << "\n} // end of sc_core namespace\n";
337
338 o.flush();
339 o.close();
340
341 // add "cc" extension
342 char file_name[PATH_MAX];
343 strncpy(file_name, base_name, PATH_MAX);
344 file_name[strlen(base_name)] = '\0';
345 strcat(file_name, ".cc");
346 rename(base_name, file_name);
347
348 if (edit_schedule) {
349 run_schedule_editor(file_name);
350 }
351
352 if (dump_stage) {
353 cerr << "Generating C code for scheduling done.\n";
354 }
355
356 return strdup(base_name);
[1]357}
358
[52]359
[1]360/* base_name est la base du nom du fichier C++
361 * casc_cflags est une string qui correspond à $(INCLUDE) d'un Makefile
362 */
[52]363void compile_code(const char * base_name, const char * casc_cflags2) {
364 if (dump_stage) {
365 cerr << "Compiling C/C++ code for scheduling...\n";
366 }
367 char compil_str[512];
368 const char * compiler = getenv("CXX");
369 const char * systemc_dir = getenv("SYSTEMCASS");
370 const char * default_compiler =
[27]371#ifdef CPP_CALL
[52]372 "g++";
[1]373#else
[41]374 "gcc";
[1]375#endif
376
[52]377 compiler = (compiler == NULL) ? default_compiler : compiler;
[1]378 if (systemc_dir == NULL) {
[52]379 systemc_dir = getenv("SYSTEMC");
380 if (systemc_dir == NULL) {
381 cerr << "Error : set SYSTEMCASS or SYSTEMC environnement variable to the SYSTEMCASS directory.\n";
382 exit(-1);
383 }
[1]384 }
[52]385
386 char target_name[128];
387 char source_name[128];
388 sprintf(target_name, "%s.lo", base_name);
389 sprintf(source_name, "%s.cc", base_name);
390
391 if (keep_generated_code) {
392 char lg_cde[256];
393 sprintf(lg_cde, "mkdir -p %s", generated_files_dir);
394 system(lg_cde);
395 sprintf(lg_cde, "cp %s/%s %s/", temporary_dir, source_name, generated_files_dir);
396 if (dump_stage) {
397 cerr << "$ " << lg_cde << "\n";
398 }
399 system(lg_cde);
400 sprintf(lg_cde, "(cd %s ; indent %s)", generated_files_dir, source_name);
401 if (dump_stage) {
402 cerr << "$ " << lg_cde << "\n";
403 }
404 system(lg_cde);
405 }
406 /* ******* */
407 /* COMPILE */
408 /* ******* */
409 const char * commandline_template =
[27]410#if defined(CONFIG_OS_DARWIN)
[52]411 "(cd %s ;"
412 " %s %s -DSCHEDULING_BY_CASC -I%s/include -fno-common -dynamic -o %s -c %s)"
[27]413#elif defined(CONFIG_OS_LINUX)
[52]414 "(cd %s ; libtool --mode=compile %s %s -DSCHEDULING_BY_CASC -I%s/include -shared -o %s -c %s)"
[1]415#else
[52]416 "(cd %s ;"
417 " %s %s -DSCHEDULING_BY_CASC -I%s/include -dynamiclib -o %s -c %s)"
[1]418#endif
[52]419 ;
[38]420
[52]421 string cflags = casc_cflags;
422 if (use_openmp) {
423 cflags += " -fopenmp";
424 }
[38]425
[52]426 sprintf(compil_str, commandline_template, temporary_dir, compiler, cflags.c_str(), systemc_dir, target_name, source_name);
[1]427
[52]428 if (dump_stage) {
429 cerr << "Executing command : " << compil_str << "\n";
430 }
[1]431
[52]432 if (system(compil_str)) {
433 perror("compil : system");
434 exit(-1);
435 }
[1]436
[52]437 /* **** */
438 /* LINK */
439 /* **** */
440 sprintf(target_name, "%s.la", base_name);
441
[27]442#ifdef CONFIG_OS_LINUX
[52]443 sprintf(source_name, "%s.lo", base_name);
444 sprintf(compil_str, "(cd %s ; pwd ; libtool --mode=link %s %s -module -shared -o %s %s -rpath /tmp)", /* -L. -L%s/lib-%s */
445 temporary_dir, compiler, casc_cflags, /*systemc_dir, target_arch, */
446 target_name, source_name);
[1]447#else
[52]448 sprintf(source_name, "%s.o", base_name);
449 sprintf(compil_str, "(cd %s ; pwd ; libtool -dynamic -o %s %s)", temporary_dir, target_name, source_name);
[1]450#endif
451
[52]452 if (dump_stage) {
453 cerr << "Executing command : " << compil_str << "\n";
454 }
[1]455
[52]456 if (system(compil_str)) {
457 perror("compil : system");
458 exit(-1);
459 }
[1]460
[52]461 system(compil_str);
462 if (dump_stage) {
463 cerr << "Compiling done.\n";
464 }
[1]465}
466
[52]467
[1]468/* ********************************
469 * Function for static scheduling
470 */
471struct function_call {
[52]472 fct * function;
473 void ** instance;
474 int func_number;
[1]475};
476static function_call pf[3];
477
[52]478
479void get_function_call(function_call & pf, method_process_list_t & func_list) {
480 pf.func_number = func_list.size();
481 pf.function = (fct *) malloc(sizeof(fct) * pf.func_number);
482 pf.instance = (void **) malloc(sizeof(void *) * pf.func_number);
483 method_process_list_t::iterator mm;
484 int i;
485 for (mm = func_list.begin(), i = 0; mm != func_list.end(); ++mm, ++i) {
486 const method_process_t * mp = *mm;
487 pf.function[i].pmf = (mp->func);
488 pf.instance[i] = (void *) (mp->module);
489 }
[1]490}
491
[52]492
493void get_function_call(function_call & pf, ProcessDependencyList & func_list) {
494 pf.func_number = func_list.size();
495 pf.function = (fct *) malloc(sizeof(fct) * pf.func_number);
496 pf.instance = (void **) malloc(sizeof(void *) * pf.func_number);
497 ProcessDependencyList::iterator it;
498 int i;
499 for (i = 0, it = func_list.begin(); it != func_list.end(); ++it, ++i) {
500 const method_process_t * mp = *it;
501 pf.function[i].pmf = (mp->func);
502 pf.instance[i] = (void *) (mp->module);
503 }
[1]504}
505
506
[52]507void gen_scheduling_code_for_static_func(method_process_list_t &
508 transition_func_list,
509 method_process_list_t &
510 moore_func_list,
511 ProcessDependencyList &
512 mealy_func_list) {
513 if (dump_stage) {
514 cerr << "Generating scheduling...\n";
515 }
[1]516
[52]517 get_function_call(pf[0], transition_func_list);
518 get_function_call(pf[1], moore_func_list);
519 get_function_call(pf[2], mealy_func_list);
520
521 if (dump_stage) {
522 cerr << "Generating scheduling done.\n";
523 }
[1]524}
525
[52]526
527void call_functions(function_call & fc) {
528 int n = fc.func_number;
529 int i;
530 for (i = 0; i < n; ++i) {
531#if 0
532 //defined(CONFIG_DEBUG)
533 sc_module *m = (sc_module *) (fc.instance[i]);
534 cerr << m->name() << endl;
[1]535#endif
[52]536 fc.function[i].pf(fc.instance[i]);
537 }
[1]538}
539
[52]540
541void call_functions_in_parallel(function_call & fc) {
542 int n = fc.func_number;
543 int i;
544#pragma omp parallel for
545 for (i = 0; i < n; ++i) {
546#if 0
547 //defined(CONFIG_DEBUG)
548 sc_module *m = (sc_module *) (fc.instance[i]);
549 cerr << m->name() << endl;
550 cerr << "thread #" << omp_get_thread_num() << endl;
[41]551#endif
[52]552 fc.function[i].pf(fc.instance[i]);
553 }
[41]554}
555
[52]556
557void static_mealy_generation() {
558 call_functions(pf[2]);
[1]559}
560
[52]561
562void static_simulate_1_cycle(void) {
563 call_functions(pf[0]); // transition
564 update();
565 call_functions_in_parallel(pf[1]); // moore generation
566 call_functions(pf[2]); // mealy generation
[1]567}
568
[52]569
[1]570/* ***************************************
571 * Function for quasi static scheduling
572 */
573
[52]574static method_process_list_t func_list[2];
[1]575static strong_component_list_t quasistatic_list;
576
[52]577static void Call(const method_process_t & m) {
578 sc_module * mod = m.module;
579 SC_ENTRY_FUNC func = m.func;
580 // CASC_ENTRY_FUNC func = reinterpret_cast<CASC_ENTRY_FUNC> (m.func);
581 (mod->*func) ();
[1]582}
[41]583
[52]584
585void quasistatic_mealy_generation() {
586 strong_component_list_t::iterator ss;
587 for (ss = quasistatic_list.begin(); ss != quasistatic_list.end(); ++ss) {
588 if ((*ss)->size() == 1) {
589 /* un seul element dans le strong component */
590 method_process_t * m = (method_process_t *) (*((*ss)->begin()));
591 Call(*m);
592 continue;
[1]593 }
[52]594 else {
595 /* plusieurs elements dans le strong component */
596 do {
597 unstable = 0;
598 component_list_t::reverse_iterator rev_mm;
599 for (rev_mm = (*ss)->rbegin(); rev_mm != (*ss)->rend(); ++rev_mm) {
600 method_process_t * m = (method_process_t *) * rev_mm;
601 Call(*m);
602 }
603 } while (unstable);
604 }
[1]605 }
606}
607
[52]608
609void quasistatic_simulate_1_cycle(void) {
610 method_process_list_t::iterator mm;
611 for (mm = func_list[0].begin(); mm != func_list[0].end(); ++mm) {
612 method_process_t & m = **mm;
613 Call(m);
614 }
615 update();
616 for (mm = func_list[1].begin(); mm != func_list[1].end(); ++mm) {
617 method_process_t & m = **mm;
618 Call(m);
619 }
620 quasistatic_mealy_generation();
[1]621}
622
623
[52]624void gen_scheduling_code_for_quasistatic_func(method_process_list_t &
625 transition_func_list,
626 method_process_list_t &
627 moore_func_list,
628 strong_component_list_t &
629 mealy_func_list) {
630 if (dump_stage) {
631 cerr << "Generating quasi static scheduling...\n";
632 }
[1]633
[52]634 func_list[0] = transition_func_list;
635 func_list[1] = moore_func_list;
636 quasistatic_list = mealy_func_list;
637
638 if (dump_stage) {
639 cerr << "Generating quasi static scheduling done.\n";
640 }
[1]641}
642} // end of sc_core namespace
643
644
[52]645/*
646# Local Variables:
647# tab-width: 4;
648# c-basic-offset: 4;
649# c-file-offsets:((innamespace . 0)(inline-open . 0));
650# indent-tabs-mode: nil;
651# End:
652#
653# vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
654*/
Note: See TracBrowser for help on using the repository browser.