source: branches/with_autoconf/src/gen_code.cc @ 10

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

Enable CPP call

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