source: branches/with_autoconf/src/schedulers.cc @ 13

Last change on this file since 13 was 8, checked in by nipo, 16 years ago

Checkin autotools magic

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