source: sources/src/schedulers.cc

Last change on this file was 65, checked in by bouyer, 7 years ago

Various performance improvements for the parallel systemcass: cache-aligned
data structures, write only when needed, disable some unneeded barriers.

Fix bug in the non-openmp case: a pointer was not initialized

various style updates

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