source: sources/src/gen_code.cc @ 26

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

Fix :

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