source: sources/src/schedulers.cc @ 23

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

Fix :

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