dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / HdsdModuleArchVisitor.java
1 package dol.visitor.hdsd;
2
3 import java.io.FileOutputStream;
4 import java.io.OutputStream;
5 import java.util.Iterator;
6 import java.util.LinkedHashSet;
7 import java.util.Set;
8 import java.util.Vector;
9
10 import dol.datamodel.architecture.Configuration;
11 import dol.datamodel.architecture.Processor;
12 import dol.datamodel.mapping.Mapping;
13 import dol.datamodel.pn.Channel;
14 import dol.datamodel.pn.Port;
15 import dol.datamodel.pn.Process;
16 import dol.datamodel.pn.Resource;
17 import dol.main.UserInterface;
18 import dol.util.CodePrintStream;
19 import dol.visitor.ArchiVisitor;
20
21 /**
22  * Visitor that generates the main program for one distributed simulator.
23  */
24 public class HdsdModuleArchVisitor extends ArchiVisitor {
25
26     /**
27      * Constructor.
28      * @param map mapping of this code generation
29      * @param dir path of this file
30      */
31     public HdsdModuleArchVisitor(Mapping map, String dir) {
32         _map = map;
33         _dir = dir;
34         _channels = new LinkedHashSet<String>();
35         _remInChannels = new LinkedHashSet<String>();
36         _remOutChannels = new LinkedHashSet<String>();
37         _locChannels = new LinkedHashSet<String>();
38     }
39
40     /**
41      *
42      * @param x Processor that needs to be rendered
43      */
44     public void visitComponent(Processor x) {
45         
46         // get channels for this processor
47         _getChannels(x);
48         
49         try {
50             String filename = _dir + "/" + "scd_" + 
51                     x.getName() + ".cpp";
52             OutputStream file = new FileOutputStream(filename);
53             _mainPS = new CodePrintStream(file);
54
55             _mainPS.printPrefixln("#include <systemc>");
56             _mainPS.printPrefixln("#include <list>");
57
58             /* begin of profiling: standard i/o file handling routines */
59             _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
60             _mainPS.printPrefixln("#include <stdio.h>");
61             _mainPS.printPrefixln("#endif");
62             /* end of profiling */
63
64             _mainPS.printPrefixln("#include \"dol_sched_if.h\"");
65             _mainPS.printPrefixln("#include \"simple_fifo.h\"");
66             _mainPS.printPrefixln("#include \"scd_logging.h\"");
67             _mainPS.printPrefixln("#include \"scd_simulator.h\"");
68             _mainPS.printPrefixln("#include \"scd_rem_fifo_in.h\"");
69             _mainPS.printPrefixln("#include \"scd_rem_fifo_out.h\"");
70             _mainPS.println();
71
72             // include process files
73             Iterator<Process> pIt = x.getProcessList().iterator();
74             Vector<String> pList = new Vector<String>();
75             while (pIt.hasNext()) {
76                 Process p = pIt.next();
77                 String basename = p.getBasename();
78                 if (!pList.contains(basename)) {
79                     _mainPS.printPrefixln("#include \"" + p.getBasename()
80                             + "_wrapper.h\"");
81                     pList.add(basename);
82                 }
83             }
84             _mainPS.println();
85             
86             // namespaces
87             _mainPS.printPrefixln("using namespace std;");
88             _mainPS.printPrefixln("using sc_core::sc_module;");
89             _mainPS.printPrefixln("using sc_core::sc_event;");
90             _mainPS.printPrefixln("using sc_core::sc_prim_channel;");
91
92
93             /* begin of profiling: global variables */
94             _mainPS.println();
95             _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
96             _mainPS.printPrefixln("#define PROFILER_OUTPUT_FILENAME "
97                     + "\"profile_" + x.getName() + ".txt\"");
98             _mainPS.printPrefixln("FILE *profiler_output_file;");
99             _mainPS.printPrefixln("unsigned int profiler_event_counter;");
100             _mainPS.printPrefixln("#endif");
101             /* end of profiling */
102
103             _mainPS.println();
104             _mainPS.printPrefixln("class sc_application : public sc_module ");
105             _mainPS.printLeftBracket();
106
107             _mainPS.printPrefixln("public:");
108             _mainPS.printPrefixln("SC_HAS_PROCESS(sc_application);");
109
110             //declare processes
111             _mainPS.println();
112             pIt = x.getProcessList().iterator();
113             while (pIt.hasNext()) {
114                 Process p = pIt.next();
115                 _mainPS.printPrefixln(p.getBasename() + "_wrapper "
116                         + p.getName() + "_ins"+ ";");
117                 _mainPS.printPrefixln("sc_event " + p.getName()
118                         + "_event;");
119             }
120             _mainPS.println();
121
122             //define the scheduler
123             _mainPS.printPrefixln("sc_event sched_event;");
124             _mainPS.printPrefixln("list<sc_event* > eventList;");
125             _mainPS.printPrefixln("list<sc_event* >::iterator iter;");
126             _mainPS.println();
127
128             //declare channels
129             _mainPS.println();
130             Iterator<String> cIt;
131             cIt = _locChannels.iterator();
132             while (cIt.hasNext())
133                 _mainPS.printPrefixln("fifo " + cIt.next() + "_ins;");
134             cIt = _remInChannels.iterator();
135             while (cIt.hasNext())
136                 _mainPS.printPrefixln("scd_rem_fifo_in " + cIt.next() + "_ins;");
137             cIt = _remOutChannels.iterator();
138             while (cIt.hasNext())
139                 _mainPS.printPrefixln("scd_rem_fifo_out " + cIt.next() + "_ins;");
140             _mainPS.println();
141
142             // model constructor
143             _mainPS.printPrefixln("sc_application(sc_module_name name)");
144
145             // parameter of constructor (processes)
146             _mainPS.printPrefixln(":       sc_module(name),");
147             pIt = x.getProcessList().iterator();
148             while (pIt.hasNext()) {
149                 Process p = pIt.next();
150                 _mainPS.printPrefixln(p.getName() + "_ins(\""
151                         + p.getName() +"\"),");
152             }
153             
154             // parameter of constructor (channels)
155             cIt = _channels.iterator();
156             while (cIt.hasNext()) {
157                 Channel c = _map.getPN().getChannel( cIt.next() );
158                 _mainPS.printPrefix(c.getName() + "_ins(\""
159                                     + c.getName() +"\", "
160                                     + c.getSize()*c.getTokenSize()
161                                     + ")");
162                 if (cIt.hasNext())
163                     _mainPS.println(",");
164                 else
165                     _mainPS.println();
166             }
167             _mainPS.printLeftBracket();
168
169             //construtor content
170             //build the network
171             cIt = _channels.iterator();
172             while (cIt.hasNext())
173             {
174                 Channel c = _map.getPN().getChannel(cIt.next());
175                 c.accept( new HdsdModulePNVisitor(x, _mainPS) );
176             }
177             _mainPS.println();
178
179             _mainPS.println();
180
181             _mainPS.printPrefixln("SC_THREAD(thread_init);");
182             // init thread
183             _mainPS.printPrefixln("SC_THREAD(thread_sched);");
184
185             // declare concurrent non-terminating threads
186             pIt = x.getProcessList().iterator();
187             while (pIt.hasNext()) {
188                 _mainPS.printPrefixln("SC_THREAD(thread_" +
189                         pIt.next().getName() + ");");
190             }
191             _mainPS.printRightBracket();
192             _mainPS.println();
193
194             //define scheduler thread
195             _mainPS.printPrefixln("void thread_init()");
196             _mainPS.printLeftBracket();
197             //init
198             pIt = x.getProcessList().iterator();
199             while (pIt.hasNext()) {
200                 Process p = pIt.next();
201                 _mainPS.printPrefixln(p.getName() + "_ins.initialize();");
202             }
203             _mainPS.printRightBracket();
204             _mainPS.println();
205
206
207             //different scheduling algorithm can be put here
208             _mainPS.printPrefixln("void thread_sched()");
209             _mainPS.printLeftBracket();
210             _mainPS.printPrefixln("while (1)");
211             _mainPS.printLeftBracket();
212             _mainPS.printPrefixln("for (iter=eventList.begin(); iter != "
213                     + "eventList.end(); ++iter)");
214             _mainPS.printLeftBracket();
215             _mainPS.printPrefixln("sc_event* e = (*iter);");
216             _mainPS.printPrefixln("e->notify();");
217             _mainPS.printRightBracket();
218             _mainPS.printPrefixln("eventList.clear();");
219             _mainPS.printPrefixln("wait(sched_event);");
220             _mainPS.printRightBracket();
221             _mainPS.printRightBracket();
222             _mainPS.println();
223
224             //define threads
225             pIt = x.getProcessList().iterator();
226             while (pIt.hasNext())
227                 pIt.next().accept( new HdsdModulePNVisitor(x, _mainPS) );
228
229             /* begin of profiling: initialization function. */
230             /* - opens file */
231             /* - writes a list of all channels with the connected ports to the file. */
232             _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
233             _mainPS.printPrefixln("void initialize_profiler()");
234             _mainPS.printLeftBracket();
235             _mainPS.printPrefixln("if ((profiler_output_file = fopen(PROFILER_OUTPUT_FILENAME,\"w\"))==NULL)");
236             _mainPS.printLeftBracket();
237             _mainPS.printPrefixln("printf(\"Unable to open profiler output file. No profiling output is written.\\n\");");
238             _mainPS.printPrefixln("return;");
239             _mainPS.printRightBracket();
240             //_mainPS.printPrefixln("printf(\"Profiling data is written to %s.\\n\", PROFILER_OUTPUT_FILENAME);");
241             _mainPS.println();
242
243             cIt = _channels.iterator();
244             while (cIt.hasNext()) {
245                 String cName = cIt.next();
246                 Channel ch = _map.getPN().getChannel(cName);
247                 Iterator<Port> poIt = ch.getPortList().iterator();
248                 String outputString = "fprintf(profiler_output_file, \"c " + ch.getName() + " " + ch.getSize();
249                 String outputStringAppendix = "";
250                 while (poIt.hasNext()) {
251                     Port p = poIt.next();
252                     Port peerPort = p.getPeerPort();
253                     Resource peerResource = p.getPeerResource();
254
255                     if (p.isOutPort()) {
256                         // channel.out == process.in
257                         String portAddr = null;
258                         if ( x.hasProcess(peerResource.getName()) )
259                             portAddr = "&(" + peerResource.getName()
260                             + "_ins.INPORT_" + peerPort.getBasename()
261                             + peerPort.getName().replace(
262                             peerPort.getBasename(), "").replaceAll(
263                             "_([0-9]+)", "[$1]") + ")";
264                         else
265                             portAddr = "0x00000000";
266                         outputString += " i " + peerResource.getName() + " %p";// + p.getPeerPort().getName();
267                         outputStringAppendix += "," + portAddr;
268                     } else {
269                         String portAddr = null;
270                         if ( x.hasProcess(peerResource.getName()) )
271                             portAddr = "&(" + peerResource.getName()
272                             + "_ins.OUTPORT_" + peerPort.getBasename()
273                             + peerPort.getName().replace(
274                             peerPort.getBasename(), "").replaceAll(
275                             "_([0-9]+)", "[$1]") + ")";
276                         else
277                             portAddr = "0x00000000";
278                         outputString += " o " + peerResource.getName() + " %p";// + p.getPeerPort().getName();
279                         outputStringAppendix += "," + portAddr;
280                     }
281                 }
282                 outputString += "\\n\"" + outputStringAppendix + ");";
283                 _mainPS.printPrefixln(outputString);
284             }
285             _mainPS.printRightBracket();
286             _mainPS.printPrefixln("#endif");
287             _mainPS.println();
288             /* end of profiling */
289
290             _mainPS.printRightBracket(); // end of class
291             _mainPS.println(";");
292
293             //create and run the simulator
294             _mainPS.printPrefixln("int sc_main (int argc, char *argv[])");
295             _mainPS.printLeftBracket();
296
297             //create an instance of the application model
298             //remove potential whitespaces before using the process
299             //network name as a systemc identifier
300             _mainPS.printPrefixln("sc_application my_app_mdl(\""
301                     + x.getName().replaceAll(" ", "")  + "\");");
302
303             /* begin of profiling: initialize the profiler */
304             _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
305             _mainPS.printPrefixln("my_app_mdl.initialize_profiler();");
306             _mainPS.printPrefixln("#endif");
307             _mainPS.printPrefixln();
308             /* end of profiling */
309
310             /* begin distributed simulation */
311             if (UserInterface.getInstance().getDebugFlag())
312                 _mainPS.printPrefixln("scd_set_loglevel(SCD_DEBUG);");
313             else
314                 _mainPS.printPrefixln("scd_set_loglevel(SCD_INFO);");
315             // simulator && master/slaves
316             Configuration opt = x.getCfg("master"); 
317             if (opt != null && opt.getValue().equals("true")) // master
318             {
319                 // simulator constructor
320                 _mainPS.printPrefixln("scd_simulator sim(\"" 
321                         + x.getName() + "\", \""
322                         + x.getCfg("address").getValue() + "\", "
323                         + x.getCfg("port").getValue() + ", SCD_MASTER);");
324                 // register slaves
325                 Iterator<Processor> iter = _map.getProcessorList().iterator();
326                 while (iter.hasNext())
327                 {
328                     Processor p = iter.next();
329                     opt = p.getCfg("master");
330                     if ( !(opt != null && opt.getValue().equals("true")) )
331                     {
332                         _mainPS.printPrefixln("sim.get_cont_man()."
333                                 + "register_slave(\"" + p.getName()
334                                 + "\");");
335                     }
336                 }
337             } // end master
338             else // slave
339             {
340                 // simulator constructor
341                 _mainPS.printPrefixln("scd_simulator sim(\"" 
342                         + x.getName() + "\", \""
343                         + x.getCfg("address").getValue() + "\", "
344                         + x.getCfg("port").getValue() + ", SCD_SLAVE);");
345                 // find and set master
346                 Iterator<Processor> iter = _map.getProcessorList().iterator();
347                 while (iter.hasNext())
348                 {
349                     Processor p = iter.next();
350                     opt = p.getCfg("master");
351                     if (opt != null && opt.getValue().equals("true"))
352                     {
353                         _mainPS.printPrefixln("sim.get_cont_man().set_master(\""
354                                 + p.getCfg("address").getValue() + "\", "
355                                 + p.getCfg("port").getValue() + ");");
356                         break;
357                     }
358                 }
359             } // end slave
360             
361             // register channels
362             // remote out channels
363             cIt = _remOutChannels.iterator();
364             while (cIt.hasNext())
365             {
366                 String cName = cIt.next();
367                 Channel c = _map.getPN().getChannel(cName);
368                 Iterator<Port> poIt = c.getPortList().iterator();
369                 Processor p = null;
370                 while (poIt.hasNext())
371                 {
372                     Port po = poIt.next();
373                     if (po.isOutPort())
374                     {
375                         Process pr = _map.getProcess(
376                                 po.getPeerResource().getName() );
377                         p = pr.getProcessor();
378                     }
379                 }
380                 _mainPS.printPrefixln("sim.get_chan_man()."
381                         + "register_channel(\"" + cName + "\",");
382                 _mainPS.printPrefixln("        my_app_mdl." + cName
383                         + "_ins, \"" + p.getCfg("address").getValue() + "\", "
384                         + p.getCfg("port").getValue() + ");");
385             }
386             // remote in channels
387             cIt = _remInChannels.iterator();
388             while (cIt.hasNext())
389             {
390                 String cName = cIt.next();
391                 _mainPS.printPrefixln("sim.get_chan_man().register_channel("
392                         + "\"" + cName + "\",");
393                 _mainPS.printPrefixln("        my_app_mdl." + cName + "_ins);");
394             }
395             
396             // init & start
397             _mainPS.printPrefixln("bool ret = sim.init();");
398             _mainPS.printPrefixln("if (ret)");
399             _mainPS.prefixInc();
400                 _mainPS.printPrefixln("ret = sim.start();");
401             _mainPS.prefixDec();
402             _mainPS.printPrefixln();
403             /* end distributed simulation */
404             
405             /* begin of profiling: close the output file */
406             _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
407             _mainPS.printPrefixln("if (profiler_output_file != NULL) fclose(profiler_output_file);");
408             _mainPS.printPrefixln("#endif");
409             /* end of profiling */
410
411             _mainPS.printPrefixln("if (ret)");
412             _mainPS.prefixInc();
413             _mainPS.printPrefixln("return 0;");
414             _mainPS.prefixDec();
415             _mainPS.printPrefixln("else");
416             _mainPS.prefixInc();
417             _mainPS.printPrefixln("return 1;");
418             _mainPS.prefixDec();
419             
420             _mainPS.printRightBracket();
421
422         }
423         catch (Exception e) {
424             System.out.println("HdsdModuleVisitor: exception occured: "
425                     + e.getMessage());
426             e.printStackTrace();
427         }
428     }
429     
430     
431     /**
432      * Retrieves all channels that have an endpoint on the specified
433      * processor and fills them into the channel sets.
434      * @param x the processor to get the channels for
435      */
436     private void _getChannels(Processor x)
437     {
438         Iterator<Channel> iter = _map.getPN().getChannelList().iterator();
439         
440         while (iter.hasNext())
441         {
442             Channel c = iter.next();
443             
444             boolean isIn = false;
445             boolean isOut = false;
446             
447             /* check if the in/out endpoint of this channel is on this
448              * processor
449              */
450             Iterator<Port> poIt = c.getPortList().iterator();
451             while (poIt.hasNext())
452             {
453                 Port p = poIt.next();
454                 if (x.hasProcess(p.getPeerResource().getName()))
455                 {
456                     if (p.isInPort())   // inPort of channel = outport
457                         isOut = true;
458                     if (p.isOutPort()) // outPort of channel  = inport
459                         isIn = true;
460                 }
461             }
462             
463             // add name to channel lists
464             if (isIn && isOut)
465             {
466                 _channels.add(c.getName());
467                 _locChannels.add(c.getName());
468             }
469             else if (isIn && !isOut)
470             {
471                 _channels.add(c.getName());
472                 _remInChannels.add(c.getName());
473             }
474             else if (!isIn && isOut)
475             {
476                 _channels.add(c.getName());
477                 _remOutChannels.add(c.getName());
478             }
479         }
480     } // _getChannels()
481     
482
483     protected CodePrintStream _mainPS = null;
484     protected String _dir = null;
485     protected Mapping _map = null;
486     
487     protected Set<String> _channels = null;
488     protected Set<String> _remInChannels = null;
489     protected Set<String> _remOutChannels = null;
490     protected Set<String> _locChannels = null;
491 }