source: sources/src/schedulers.cc @ 27

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

SystemCASS now uses autoconf/automake to build the API. Regression tests still
use the old Makefiles.
(thanks to Nicolas Pouillon)

The library directory no longer is "lib-arch-system". The directory now is "lib-linux". Everyone needs to pay attention about SYSTEMCASS environment variable.

Changes:

  • system header includes
  • Add includes to config.h (generated by autoconf/automake)
  • test:
    • linux preprocessor macro instead of _WIN32
    • CONFIG_DEBUG instead of DEBUG

Removes:

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