source: sources/src/schedulers.cc @ 63

Last change on this file since 63 was 63, checked in by bouyer, 5 years ago

Remplace USE_OPENMP with _OPENMP, the latter is automagically defined
by the compiler.

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