source: sources/src/schedulers.cc @ 3

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

Initial import from CVS repository

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