source: sources/src/gen_code.cc @ 34

Last change on this file since 34 was 31, checked in by nipo, 16 years ago

Picky compiler prefer spaces in #include lines

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