source: sources/src/schedulers.cc @ 33

Last change on this file since 33 was 33, checked in by joel.porquet@…, 15 years ago

Make systemcass compile with gcc 4.4.* and remove redundancies in header install.

File size: 10.4 KB
Line 
1/*------------------------------------------------------------\
2|                                                             |
3| Tool    :                  systemcass                       |
4|                                                             |
5| File    :                 schedulers.cc                     |
6|                                                             |
7| Author  :                 Buchmann Richard                  |
8|                           Nicolas Pouillon                  |
9|                                                             |
10| Date    :                   23_03_2007                      |
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 "sc_module.h" // method_process_t
38#include "gen_code.h"  // gen_scheduling_code_for_dynamic_link & gen_scheduling_code_for_static_func
39#include "internal.h"  // dump_all_graph
40#include "graph_cass.h" // makegraph
41#include "process_dependency.h" // MakeProcessDependencyList
42#include "signal_dependency.h" // MakeSignalDependencyGraph
43#include "mouchard_scheduling.h" // MakeMouchardScheduling
44#include "graph_signals.h" // makegraph
45//#include "module_hierarchy2dot.h"
46
47#include <cstdio>
48#include <cassert>
49#include <iostream>
50#include <algorithm> //std::sort
51
52#ifdef HAVE_CONFIG_H
53#include "config.h"
54#endif
55
56using namespace std;
57
58namespace sc_core {
59
60/* ***************************** */
61/* Dumping functions (for debug) */
62/* ***************************** */
63
64template <typename T>
65ostream& operator << (ostream &o, const vector<T*> &v)
66{
67  typename vector<T*>::const_iterator i;
68  for (i = v.begin(); i != v.end(); ++i) {
69    o << **i << " ";
70  }
71  return o;
72}
73
74/* ************ */
75/*  functions   */
76/****************/
77
78//
79// sort_functions splits and sorts instances_list into three functions lists :
80method_process_list_t transition_func_list;
81method_process_list_t moore_func_list;
82method_process_list_t combinational_func_list;
83
84#if 0
85static
86bool
87isCostly (const char *n)
88{
89  const char *costly[] = {/*"vgmn", */"mips", "cache", NULL};
90  int i = 0;
91  do {
92    if (strstr (n, costly[i]) != NULL)
93      return true;
94  } while (costly[++i] != NULL);
95  return false;
96}
97
98static
99bool
100only_sort_by_module_ptr (const method_process_t *a1,
101                         const method_process_t *a2)
102{
103  assert(a1 != NULL);
104  assert(a2 != NULL);
105  sc_module *m1 = a1->module;
106  sc_module *m2 = a2->module;
107  const char* n1 = m1->basename ();
108  const char* n2 = m2->basename ();
109  bool        h1 = isCostly (n1);
110  bool        h2 = isCostly (n2);
111  if ((h1 ^ h2) == true)
112    return h1 > h2;
113  if (a1->module == a2->module)
114  {
115    union {
116        SC_ENTRY_FUNC func;
117        unsigned long addr_l;
118        unsigned long long addr_ll;
119    } addr1, addr2;
120    addr1.func = a1->func;
121    addr2.func = a2->func;
122    assert(addr1.addr_ll != addr2.addr_ll);
123    if ( sizeof(SC_ENTRY_FUNC) == 4 ) {
124        return (addr1.addr_l < addr2.addr_l);
125    } else {
126        return (addr1.addr_ll < addr2.addr_ll);
127    }
128  }
129  return (a1->module < a2->module);
130}
131#endif
132#if 1
133static
134bool 
135sort_by_module_ptr (const method_process_t *a1, 
136                    const method_process_t *a2)
137{
138  assert(a1 != NULL);
139  assert(a2 != NULL);
140  return (a1->module < a2->module);
141}
142
143static
144bool 
145sort_by_fct_ptr (const method_process_t *a1, 
146                 const method_process_t *a2)
147{
148    assert(a1 != NULL);
149    assert(a2 != NULL);
150    union {
151        SC_ENTRY_FUNC func;
152        unsigned long addr_l;
153        unsigned long long addr_ll;
154    } addr1, addr2;
155    addr1.func = a1->func;
156    addr2.func = a2->func;
157    if (a1->func == a2->func)
158      return sort_by_module_ptr (a1,a2);
159    if ( sizeof(SC_ENTRY_FUNC) == 4 ) {
160        return (addr1.addr_l < addr2.addr_l);
161    } else {
162        return (addr1.addr_ll < addr2.addr_ll);
163    }
164}
165#endif
166void
167sort_functions ()
168{
169#if 0
170  cerr << method_process_list << endl;
171#endif
172  method_process_list_t::const_iterator m;
173  for (m = method_process_list.begin(); m != method_process_list.end(); ++m) {
174      if ((*m)->is_combinational()) combinational_func_list.push_back(*m);
175      else if ((*m)->is_transition ()) transition_func_list.push_back(*m);
176      else if ((*m)->is_genmoore ())   moore_func_list.push_back(*m);
177  }
178#if 1
179  // Sort transition functions by method pointer (1) and by module pointer (2)
180  std::sort (transition_func_list.begin(), transition_func_list.end(), sort_by_fct_ptr);
181  // Sort generation functions by method pointer (1) and by module pointer (2)
182  std::sort (moore_func_list.begin(), moore_func_list.end(), sort_by_fct_ptr);
183#endif
184#if 0
185  std::sort (transition_func_list.begin(), transition_func_list.end(), only_sort_by_module_ptr);
186  std::sort (moore_func_list.begin(), moore_func_list.end(), only_sort_by_module_ptr);
187#endif
188}
189
190/* ****************** */
191/* process dependency */
192/* ****************** */
193
194static
195SignalDependencyGraph*
196MakeAcyclicSignalDependencyGraph ()
197{
198  if (dump_all_graph) {
199    const PortDependencyGraph &port_graph = get_port_dependency_graph ();
200    PortDependencyGraph2dot ("port_graph", port_graph);
201  }
202
203        SignalDependencyGraph* sig_graph = MakeSignalDependencyGraph ();
204
205  if (dump_all_graph)
206    SignalDependencyGraph2dot ("signal_graph",*sig_graph);
207
208        if (!Check (*sig_graph))
209        {
210                cerr << "The signal dependency graph is not valid.\n";
211    exit (29092004);
212        }
213
214#if 1
215  if (!Check (method_process_list,*sig_graph))
216  {
217    cerr << "Sensitivity list is not valid.\n";
218    exit (30092004);
219  }
220#endif
221       
222        // There is a cycle in the signal dependency graph ?
223  Graph *sig_knuth = makegraph (*sig_graph);
224        strong_component_list_t *s = strong_component(sig_knuth);
225
226  if (dump_all_graph)
227    SignalDependencyOrder2txt ("signal_order",*s);
228
229        if (has_cycle (*s))
230        {
231                cerr << "Error : There is a cycle in the signal dependency graph.\n";
232#if 0
233    print_cycle (cerr, get_cycle (*s));
234#endif
235    exit (24092004);
236        }
237  return sig_graph;
238}
239
240static
241ProcessDependencyList*
242MouchardScheduling ()
243{
244  SignalDependencyGraph *sig_graph = MakeAcyclicSignalDependencyGraph ();
245  assert(sig_graph != NULL);
246  // Create the process evaluation list
247  ProcessDependencyList* process_list = MakeMouchardScheduling (*sig_graph);
248  assert(process_list != NULL);
249
250  if (dump_all_graph)
251        ProcessDependencyList2dot  ("process_order",*process_list);
252
253        return process_list;
254}
255
256static
257ProcessDependencyList*
258BuchmannScheduling ()
259{
260  SignalDependencyGraph *sig_graph = MakeAcyclicSignalDependencyGraph ();
261  // Create the process evaluation list
262        ProcessDependencyList* process_list = MakeProcessDependencyList (*sig_graph);
263
264  if (dump_all_graph)
265        ProcessDependencyList2dot  ("process_order",*process_list);
266
267        return process_list;
268}
269
270string
271get_scheduling (int scheduling_method) 
272{
273  /* marque les fonctions comme fonction de mealy ou non */
274  if (dump_funclist_info)
275    cerr << "method process list : " << method_process_list << "\n";
276  sort_functions ();
277  if (dump_funclist_info)
278  {
279    cerr << "Transition functions : " << transition_func_list << "\n";
280    cerr << "Moore generation functions : " << moore_func_list << "\n";
281    cerr << "Mealy generation functions : " << combinational_func_list << "\n";
282  }
283
284  /* Schedule */ 
285  string base_name;
286  switch (scheduling_method) {
287  case BUCHMANN_SCHEDULING : {
288    // Generate the scheduled code, compile and link.
289    // Buchmann's thesis explains this scheduling method.
290    // Uses port dependancies like Dr. Mouchard.
291    ProcessDependencyList* process_list = BuchmannScheduling ();
292        if (dynamic_link_of_scheduling_code)
293                base_name = gen_scheduling_code_for_dynamic_link (transition_func_list, moore_func_list,*process_list);
294        else
295                gen_scheduling_code_for_static_func (transition_func_list, moore_func_list, *process_list);
296    break;
297  }
298  case MOUCHARD_SCHEDULING : {
299    // Generate the scheduled code, compile and link.
300    // Mouchard's thesis explains this scheduling method.
301    // Uses port dependancies like Dr. Mouchard.
302    // CAUTION : unlike FastSysC, this scheduling is totally static
303    // and does not use an event-driven scheduler.
304    ProcessDependencyList* process_list = MouchardScheduling ();
305        if (dynamic_link_of_scheduling_code)
306                base_name = gen_scheduling_code_for_dynamic_link(transition_func_list, moore_func_list,*process_list);
307        else
308                gen_scheduling_code_for_static_func (transition_func_list, moore_func_list, *process_list);
309    break;
310  }
311  case CASS_SCHEDULING : {
312    // Generate the scheduled code, compile and link
313    // Hommais's thesis explains this scheduling method (like CASS strategy)
314    // Doesn't use port dependancies
315    Graph *g = makegraph (&combinational_func_list);
316    if (dump_all_graph && g)
317      graph2dot("module_graph", *g);
318    strong_component_list_t *strong_list = strong_component (g);
319        if (dynamic_link_of_scheduling_code)
320                base_name = gen_scheduling_code_for_dynamic_link(transition_func_list, moore_func_list,*strong_list);
321        else
322                gen_scheduling_code_for_quasistatic_func (transition_func_list, moore_func_list, *strong_list);
323    break;
324  }
325  default :
326    cerr << "Error : Unable to schedule SystemC process."
327            "Please select a scheduling method.\n";
328    exit (35);
329  }
330  return base_name;
331}
332
333bool
334run_schedule_editor (const char *schedule)
335{
336  char buf[128];
337  const char *editor = getenv ("EDITOR");
338  if (editor == NULL)
339    editor = "vim";
340  sprintf (buf, "(cd '%s' ; %s '%s')", temporary_dir, editor, schedule);
341  if (dump_stage)
342    cerr << "Executing : " << buf << endl;
343  return (system(buf) == 0);
344}
345
346/////////////////////////
347
348} // end of sc_core namespace
349
Note: See TracBrowser for help on using the repository browser.