source: branches/with_autoconf/src/schedulers.cc

Last change on this file was 20, checked in by nipo, 16 years ago

Sync up with trunk changes

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