source: latest/src/gen_code.cc @ 1

Last change on this file since 1 was 1, checked in by buchmann, 17 years ago

Initial import from CVS repository

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
48#ifdef CHECK_FSM_RULES
49#define fsm_check_flag "-DCHECK_FSM_RULES"
50#else
51#define fsm_check_flag
52#endif
53
54#define casc_cflags CFLAGS " " fsm_check_flag
55
56#if defined(darwin)
57#define macosx
58#endif
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#if 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 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#if 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#if defined(macosx)
416    sprintf(compil_str, 
417                                "(cd %s ; %s %s -DSCHEDULING_BY_CASC -I%s/include -fno-common -dynamic -o %s -c %s)",
418        temporary_dir,
419                                compiler, 
420                                casc_cflags, 
421                                systemc_dir, 
422                                target_name,
423                                source_name);
424//    sprintf(compil_str,"");
425#elif defined(linux)
426    sprintf(compil_str, 
427                                "(cd %s ; libtool --mode=compile %s %s -DSCHEDULING_BY_CASC -I%s/include -shared -o %s -c %s)",
428        temporary_dir,
429                                compiler, 
430                                casc_cflags, 
431                                systemc_dir, 
432                                target_name,
433                                source_name);
434#else
435    sprintf(compil_str, 
436                                "(cd %s ; %s %s -DSCHEDULING_BY_CASC -I%s/include -dynamiclib -o %s -c %s)",
437        temporary_dir,
438                                compiler, 
439                                casc_cflags, 
440                                systemc_dir, 
441                                target_name,
442                                source_name);
443#endif
444
445  if (dump_stage) 
446    cerr << "Executing command : " << compil_str << "\n";
447 
448  if (system(compil_str)) {
449    perror("compil : system");
450    exit(-1);
451  }
452
453  /* **** */
454  /* LINK */
455  /* **** */
456  sprintf (target_name, "%s.so", base_name);
457
458#if defined(linux)
459  sprintf (source_name, "%s.lo", base_name);
460  sprintf(compil_str, "(cd %s ; pwd ; libtool --mode=link %s %s -shared -rdynamic -o %s %s)", /* -L. -L%s/lib-%s */ 
461           temporary_dir, compiler, casc_cflags, /*systemc_dir, target_arch,*/ 
462     target_name, source_name);
463#else
464  sprintf (source_name, "%s.o", base_name);
465  sprintf(compil_str, "(cd %s ; pwd ; libtool -dynamic -o %s %s)", 
466           temporary_dir, target_name, source_name);
467#endif
468
469  if (dump_stage) 
470    cerr << "Executing command : " << compil_str << "\n";
471
472  if (system(compil_str)) {
473    perror("compil : system");
474    exit(-1);
475  }
476
477 /*
478  sprintf(compil_str, "(cd %s ; rm -f %s.o %s.lo)",
479          temporary_dir, base_name, base_name);
480  if (dump_stage)
481    cerr << "$ " << compil_str << "\n";
482*/
483
484  system(compil_str);
485  if (dump_stage) 
486    cerr << "Compiling done.\n";
487}
488
489/* ********************************
490 * Function for static scheduling
491 */
492struct function_call {
493  fct      *function;
494  void    **instance;
495  int       func_number;
496};
497static function_call pf[3];
498
499void
500get_function_call (function_call         &pf, 
501                   method_process_list_t &func_list)
502{
503  pf.func_number = func_list.size ();
504  pf.function = (fct*)   malloc (sizeof (fct)   * pf.func_number);
505  pf.instance = (void**) malloc (sizeof (void*) * pf.func_number);
506  method_process_list_t::iterator mm;
507  int i;
508  for (mm = func_list.begin(), i = 0; mm != func_list.end(); ++mm, ++i)
509  {
510    const method_process_t *mp = *mm;
511    pf.function[i].pmf = (mp->func);
512    pf.instance[i] = (void*)(mp->module);
513  }
514}
515
516void
517get_function_call (function_call &pf, 
518                   ProcessDependencyList &func_list)
519{
520  pf.func_number = func_list.size ();
521  pf.function = (fct*)   malloc (sizeof (fct)   * pf.func_number);
522  pf.instance = (void**) malloc (sizeof (void*) * pf.func_number);
523        ProcessDependencyList::iterator it;
524  int i;
525        for (i = 0, it = func_list.begin(); it != func_list.end(); ++it, ++i)
526        {
527                const method_process_t *mp = *it;
528    pf.function[i].pmf = (mp->func);
529    pf.instance[i] = (void*)(mp->module);
530  }
531}
532
533void
534gen_scheduling_code_for_static_func (
535            method_process_list_t &transition_func_list,
536            method_process_list_t &moore_func_list,
537            ProcessDependencyList &mealy_func_list)
538{
539  if (dump_stage)
540    cerr << "Generating scheduling...\n";
541
542  get_function_call (pf[0], transition_func_list);
543  get_function_call (pf[1], moore_func_list);
544  get_function_call (pf[2], mealy_func_list);
545
546  if (dump_stage)
547    cerr << "Generating scheduling done.\n";
548}
549
550void
551call_functions (function_call &fc)
552{
553  int n = fc.func_number;
554  int i;
555  for (i = 0; i < n; ++i)
556  {
557#if 0 //defined(DEBUG)
558    sc_module *m = (sc_module*)(fc.instance[i]);
559    cerr << m->name () << endl;
560#endif
561    fc.function[i].pf (fc.instance[i]);
562  }
563}
564
565void static_mealy_generation ()
566{
567  call_functions (pf[2]);
568}
569
570void static_simulate_1_cycle (void) 
571{
572#ifdef CHECK_FSM_RULES
573        casc_fsm_step = TRANSITION;
574#endif
575  call_functions (pf[0]); // transition
576  update     ();
577#ifdef CHECK_FSM_RULES
578        casc_fsm_step = GEN_MOORE;
579#endif
580  call_functions (pf[1]); // moore generation
581#ifdef CHECK_FSM_RULES
582        casc_fsm_step = GEN_MEALY;
583#endif
584  call_functions (pf[2]); // mealy generation
585#ifdef CHECK_FSM_RULES
586        casc_fsm_step = STIMULI;
587#endif
588}
589
590/* ***************************************
591 * Function for quasi static scheduling
592 */
593
594static method_process_list_t   func_list[2];
595static strong_component_list_t quasistatic_list;
596
597static 
598void
599Call         (const method_process_t &m)
600{
601  sc_module        *mod  = m.module;
602  SC_ENTRY_FUNC     func = m.func;
603//  CASC_ENTRY_FUNC   func = reinterpret_cast<CASC_ENTRY_FUNC> (m.func);
604  (mod->*func) ();
605}
606void quasistatic_mealy_generation ()
607{
608  strong_component_list_t::iterator ss;
609  for ( ss = quasistatic_list.begin(); ss != quasistatic_list.end(); ++ss) {
610    if ( (*ss)->size() == 1) {
611      /* un seul element dans le strong component */
612                        method_process_t *m = (method_process_t*)(*((*ss)->begin ()));
613      Call (*m);
614      continue;
615    } else {
616      /* plusieurs elements dans le strong component */
617      do {
618        unstable = 0;
619        component_list_t::reverse_iterator rev_mm;
620        for( rev_mm = (*ss)->rbegin(); rev_mm != (*ss)->rend(); ++rev_mm) {
621                                method_process_t *m = (method_process_t*) *rev_mm;
622          Call (*m);
623        }
624      } while ( unstable );
625    }
626  }
627}
628
629void quasistatic_simulate_1_cycle (void) 
630{
631#ifdef CHECK_FSM_RULES
632        casc_fsm_step = TRANSITION;
633#endif
634  method_process_list_t::iterator mm;
635  for( mm = func_list[0].begin(); mm != func_list[0].end(); ++mm)
636  {
637    method_process_t &m    = **mm;
638    Call (m);
639  }
640  update     ();
641#ifdef CHECK_FSM_RULES
642        casc_fsm_step = GEN_MOORE;
643#endif
644  for( mm = func_list[1].begin(); mm != func_list[1].end(); ++mm)
645  {
646    method_process_t &m    = **mm;
647    Call (m);
648  }
649#ifdef CHECK_FSM_RULES
650        casc_fsm_step = GEN_MEALY;
651#endif
652  quasistatic_mealy_generation ();
653#ifdef CHECK_FSM_RULES
654        casc_fsm_step = STIMULI;
655#endif
656}
657
658void
659gen_scheduling_code_for_quasistatic_func (
660            method_process_list_t   &transition_func_list,
661            method_process_list_t   &moore_func_list,
662            strong_component_list_t &mealy_func_list)
663{
664  if (dump_stage)
665    cerr << "Generating quasi static scheduling...\n";
666
667  func_list[0]     = transition_func_list;
668  func_list[1]     = moore_func_list;
669  quasistatic_list = mealy_func_list;
670
671  if (dump_stage)
672    cerr << "Generating quasi static scheduling done.\n";
673}
674} // end of sc_core namespace
675
676
Note: See TracBrowser for help on using the repository browser.