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

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

Checkin autotools magic

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