source: sources/src/schedulers.cc @ 46

Last change on this file since 46 was 38, checked in by buchmann, 15 years ago

Now detects if SystemCASS correctly handles runtime compilation with the current architecture. SystemCASS exits if runtime compilation is not supported. Use --nodynamiclink options if it exits. This may occur on 64 bits machines.

Usage help is more readable.

Code cleanup.

Add some code for the coming soon openMP feature.

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.