dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cbe / CbeModuleVisitor.java
1 /* $Id: CbeModuleVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
2 package dol.visitor.cbe;
3
4 import java.io.FileOutputStream;
5 import java.io.OutputStream;
6 import java.util.HashMap;
7 import java.util.Vector;
8
9 import dol.datamodel.pn.Channel;
10 import dol.datamodel.pn.Port;
11 import dol.datamodel.pn.Process;
12 import dol.datamodel.pn.ProcessNetwork;
13 import dol.main.UserInterface;
14 import dol.util.CodePrintStream;
15 import dol.visitor.PNVisitor;
16
17 /**
18  * This class is a class for a visitor that is used to generate
19  * the main program.
20  *
21  * @author lschor, 2008-10-30
22  *
23  * Revision:
24  * 2008-10-30: Updated the file for the CBE
25  * 2008-11-08: Add double buffering
26  * 2008-11-16: Add new fifo implementation and defines for measurement
27  * 2008-11-21: Sink/Source do not run on the SPE, but on the PPE (as Linux
28  *             thread)
29  */
30 public class CbeModuleVisitor extends PNVisitor {
31
32     /**
33      * Constructor.
34      *
35      * @param dir path of this file
36      */
37     public CbeModuleVisitor(String dir, HashMap<Port, Integer> portMap) {
38         _dir = dir;
39         _portMap = portMap;
40     }
41
42     /**
43      * Visit process network.
44      *
45      * @param x process network that needs to be rendered
46      */
47     public void visitComponent(ProcessNetwork x) {
48         try {
49             _ui = UserInterface.getInstance();
50             String filename = _dir + _delimiter + "ppu_main.c";
51             OutputStream file = new FileOutputStream(filename);
52             _mainPS = new CodePrintStream(file);
53
54             //create header section
55             _mainPS.println("// ========================");
56             _mainPS.println("// ppu_main.c file");
57             _mainPS.println("// ========================");
58             _mainPS.println("");
59
60             // Includes
61             _mainPS.println("#include \"ppu_main.h\"");
62             _mainPS.println("");
63
64             _mainPS.println("");
65             _mainPS.println("// include main function for a workloop");
66             _mainPS.println("#include \"ppu_main_workloop.h\"");
67             _mainPS.println("");
68
69             // Function to create and run one SPE thread
70             _mainPS.println("// create and run one SPE thread");
71             _mainPS.println("void *spu_pthread(void *arg) {");
72             _mainPS.println("\t spu_data_t *datp = (spu_data_t *)arg;");
73             _mainPS.println("\t uint32_t entry = SPE_DEFAULT_ENTRY;");
74             _mainPS.println("\t printf(\")PPE: spe thread starts\\n\");");
75             _mainPS.println("\t if (spe_context_run(datp->spe_ctx, "
76                     + "&entry, 0, datp->argp, NULL, NULL) < 0) {");
77             _mainPS.println("\t\t perror (\"Failed running context\"); "
78                     + "exit (1);");
79             _mainPS.println("\t}");
80             _mainPS.println("\t printf(\")PPE: spe thread stops\\n\");");
81             _mainPS.println("\t pthread_exit(NULL);");
82             _mainPS.println("}");
83             _mainPS.println("");
84
85             // Declaration of the Header function for the PPE-Wrappers
86             Vector<String> processList = new Vector<String>();
87             for (Process p : x.getProcessList()) {
88                 String basename = p.getBasename();
89                 if (!processList.contains(basename)) {
90                     processList.add(basename);
91                     if (!(p.getNumOfInports() > 0
92                             && p.getNumOfOutports() > 0))
93                         _mainPS.println("void *" + basename
94                                 + "_wrapper( void *ptr );");
95                 }
96             }
97             _mainPS.println();
98
99             // Create the port_id and the port_queue_id arrays to send
100             // over the DMA
101             for (Process process : x.getProcessList()) {
102                 String processName = process.getName();
103                 _mainPS.println("volatile uint32_t "+ processName
104                         + "_port_id["
105                         + roundDMA(process.getPortList().size())
106                         + "] __attribute__ ((aligned(16))); ");
107                 _mainPS.println("volatile uint32_t " + processName
108                         + "_port_queue_id["
109                         + roundDMA(process.getPortList().size())
110                         + "] __attribute__ ((aligned(16)));");
111                 _mainPS.println("volatile char " + processName
112                         + "_name[256] __attribute__ ((aligned(16)));");
113             }
114             _mainPS.println();
115
116             // Create the main function
117             _mainPS.println("int main()");
118             _mainPS.println("{");
119
120             // For Measure
121             _mainPS.println("#ifdef MEASURE_APPLICATION");
122             _mainPS.println("\tstruct timeval t_ppe_start, t_ppe_end;");
123             _mainPS.println("\tgettimeofday(&t_ppe_start,NULL);");
124             _mainPS.println("#endif");
125             _mainPS.println();
126
127             _mainPS.println("#ifdef MEASURE_SET_UP_SPE_THREAD");
128             _mainPS.println("\tstruct timeval t_ppe_setup_start, "
129                     + "t_ppe_setup_end;");
130             _mainPS.println("\tgettimeofday(&t_ppe_setup_start,NULL);");
131             _mainPS.println("#endif");
132             _mainPS.println();
133
134             // List with all process to be open
135             _mainPS.println("\tchar spe_names[NUM_SPES][60] = {");
136             int count = 0;
137             for (Process process : x.getProcessList()) {
138                 if (process.getNumOfInports() > 0
139                         && process.getNumOfOutports() > 0) {
140                     count++;
141                     String processName = process.getBasename();
142                     _mainPS.println("\t\t\"spu_" + processName + "/spu_"
143                             + processName + "_wrapper\""
144                             + (count == x.getProcessList().size()
145                             ? "" : ", ") );
146                 }
147             }
148             _mainPS.println("\t};");
149             _mainPS.println();
150             _mainPS.println("\t// Initialize the fifo, we use");
151             _mainPS.println("\tint j; ");
152             _mainPS.println("\tfor (j = 0; j < NUM_FIFO; j++)");
153             _mainPS.println("\t{");
154             _mainPS.println("\t\tlocBuf[j] = "
155                     + "(char*)malloc(MAXELEMENT * sizeof(char));");
156             _mainPS.println("\t\tlocBufCount[j] = 0;");
157             _mainPS.println("\t\tlocBufStart[j] = 0;");
158             _mainPS.println("\t\tpthread_mutex_init(&(mutex[j]), NULL);");
159             _mainPS.println("\t}");
160
161             //connect ports to channels
162             HashMap<Channel, Integer> channel_map =
163                 new HashMap<Channel, Integer>();
164
165             int j = 0;
166             for (Channel c : x.getChannelList()) {
167                 channel_map.put(c, j++);
168             }
169
170             // Init the SPE control structure
171             _mainPS.println("\t//Initiate SPEs control structure");
172             _mainPS.println("\tint num = 0; ");
173             _mainPS.println("\tfor( num=0; num<NUM_SPES; num++){");
174             _mainPS.println("\t\tdata[num].argp = (void *)&(ctx[num]);");
175             _mainPS.println("\t}");
176             _mainPS.println();
177
178             // Add to each process the ports and the queues
179             _mainPS.println("\t //Add to each process the ports and the "
180                     + "queues");
181             j = 0;
182             for (Process process : x.getProcessList()) {
183                 String processName = process.getName();
184                 int i = 0;
185                 for (Port port : process.getPortList()) {
186                     Channel c = (Channel)(port.getPeerResource());
187
188                     _mainPS.println("\t" + processName + "_port_id["
189                                     + i + "] = "
190                                     + _portMap.get(port) + ";");
191                     _mainPS.println("\t" + processName + "_port_queue_id["
192                                     + i + "] = "
193                                     + channel_map.get(c) + ";");
194                     i++;
195                 }
196
197                 // Normal process
198                 if (process.getNumOfInports() > 0
199                         && process.getNumOfOutports() > 0) {
200                     _mainPS.println("\tctx[" + j + "]"
201                                     + ".port_id = (uint64_t)"
202                                     + processName + "_port_id;");
203                     _mainPS.println("\tctx[" + j + "]"
204                                     + ".port_queue_id = (uint64_t)"
205                                     + processName + "_port_queue_id;");
206                     _mainPS.println("\tctx[" + j + "]"
207                                     + ".number_of_ports = " + i + ";");
208                     _mainPS.println("\tctx[" + j + "]"
209                                     + ".is_detached = 0;");
210                     _mainPS.println("\tstrcpy((char *)" + processName
211                             + "_name, " + "\""
212                             + processName + "\");");
213                     _mainPS.println("\tctx[" + j + "]"
214                             + ".processName = (uint64_t) " + processName
215                             + "_name;");
216                     _mainPS.println("\tctx[" + j + "]"
217                             + ".processNameLen = ((strlen((char *)"
218                             + processName + "_name) + 15) & ~15);");
219                     _mainPS.println();
220                     j++;
221                 }
222                 // Process is Sink or source
223                 else {
224                     _mainPS.println("\tProcessWrapper *"
225                             + process.getName()
226                             + "_Process_Wrapper = (ProcessWrapper*)"
227                             + "malloc(sizeof(ProcessWrapper)); ");
228                     _mainPS.println("\t" + process.getName()
229                             + "_Process_Wrapper->port_id = " + processName
230                             + "_port_id;");
231                     _mainPS.println("\t" + process.getName()
232                             + "_Process_Wrapper->port_queue_id = "
233                             + processName + "_port_queue_id;");
234                     _mainPS.println("\t" + process.getName()
235                             + "_Process_Wrapper->number_of_ports = "
236                             + i + ";");
237                     _mainPS.println("\t" + process.getName()
238                             + "_Process_Wrapper->is_detached = 0;");
239                     _mainPS.println("\t" + process.getName()
240                             + "_Process_Wrapper->name = (char*)malloc("
241                             + "strlen(\"" + processName + "\"));");
242                     _mainPS.println("\tstrcpy(" + process.getName()
243                             + "_Process_Wrapper->name, \"" + processName
244                             + "\");");
245                     _mainPS.println("\t" + process.getName()
246                             + "_Process_Wrapper->locBuf = locBuf;");
247                     _mainPS.println("\t" + process.getName()
248                             + "_Process_Wrapper->MAXELEMENT = "
249                             + "MAXELEMENT;");
250                     _mainPS.println("\t" + process.getName()
251                             + "_Process_Wrapper->locBufCount = "
252                             + "locBufCount;");
253                     _mainPS.println("\t" + process.getName()
254                             + "_Process_Wrapper->locBufStart = "
255                             + "locBufStart;");
256                     _mainPS.println("\t" + process.getName()
257                             + "_Process_Wrapper->processFinished = "
258                             + "&processFinished;");
259                     _mainPS.println("\t" + process.getName()
260                             + "_Process_Wrapper->mutex = mutex;");
261                     _mainPS.println("\t" + process.getName()
262                             + "_Process_Wrapper->mutexProcessNr = "
263                             + "&mutexProcessNr;");
264                     _mainPS.println();
265                 }
266             }
267
268             _mainPS.println("\t// Loop on all SPEs and for each perform "
269                     + "three steps:");
270             _mainPS.println("\t// - create SPE context");
271             _mainPS.println("\t// - open images of SPE programs into main "
272                     + "storage");
273             _mainPS.println("\t//         <spe_names> variable store the "
274                     + "executable name");
275             _mainPS.println("\t// - Load SPEs objects into SPE context "
276                     + "local store");
277             _mainPS.println("\tfor( num=0; num<NUM_SPES; num++){");
278             _mainPS.println("\t\tif ((data[num].spe_ctx = "
279                     + "spe_context_create(0, NULL)) == NULL) {");
280             _mainPS.println("\t\t\tperror(\"Failed creating context\"); "
281                     + "exit(1);");
282             _mainPS.println("\t\t}");
283             _mainPS.println("\t\tif (!(program[num] = spe_image_open("
284                     + "&spe_names[num][0]))) {");
285             _mainPS.println("\t\t\t perror(\"Fail opening image\"); "
286                     + "exit(1);");
287             _mainPS.println("\t\t}");
288             _mainPS.println("\t\tif (spe_program_load(data[num].spe_ctx, "
289                     + "program[num])) {");
290             _mainPS.println("\t\t\tperror(\"Failed loading program\"); "
291                     + "exit(1);");
292             _mainPS.println("\t\t}      ");
293             _mainPS.println("\t}");
294             _mainPS.println("");
295
296             _mainPS.println("\t// create PPE pthreads");
297             for (Process process : x.getProcessList()) {
298                 if (!(process.getNumOfInports() > 0
299                         && process.getNumOfOutports() > 0)) {
300                     _mainPS.println("\tpthread_t thread_"
301                             + process.getName() + ";");
302                     _mainPS.println("\tpthread_create( &thread_"
303                             + process.getName() + ", NULL, "
304                             + process.getBasename() + "_wrapper, "
305                             + process.getName() + "_Process_Wrapper);");
306                 }
307             }
308             _mainPS.println("\t");
309
310             _mainPS.println("\t// create SPE pthreads");
311             _mainPS.println("\tfor( num=0; num<NUM_SPES; num++){");
312             _mainPS.println("\t\tif(pthread_create(&data[num].pthread, "
313                     + "NULL, &spu_pthread, &data[num])){");
314             _mainPS.println("\t\t\tperror(\"Failed creating thread\"); "
315                     + "exit(1);");
316             _mainPS.println("\t\t}");
317             _mainPS.println("\t}");
318
319             _mainPS.println();
320             _mainPS.println("#ifdef MEASURE_SET_UP_SPE_THREAD");
321             _mainPS.println("\tgettimeofday(&t_ppe_setup_end, NULL);");
322             _mainPS.println("\tprintf(\"PPE_SETUP;%f\\n\", "
323                     + "(t_ppe_setup_end.tv_sec "
324                     + "- t_ppe_setup_start.tv_sec) + 0.000001 "
325                     + "* (t_ppe_setup_end.tv_usec "
326                     + "- t_ppe_setup_start.tv_usec));");
327             _mainPS.println("#endif");
328             _mainPS.println();
329
330             _mainPS.println("\t//Start the main loop");
331             _mainPS.println("\tworkloop();");
332             _mainPS.println("");
333
334             _mainPS.println("\t// Loop on all SPEs and for each perform "
335                     + "two steps:");
336             _mainPS.println("\t//   - wait for all the SPE pthread to "
337                     + "complete");
338             _mainPS.println("\t//   - destroy the SPE contexts");
339             _mainPS.println("\tfor( num=0; num<NUM_SPES; num++){");
340             _mainPS.println("\t\tif(pthread_join(data[num].pthread, "
341                     + "NULL)) {");
342             _mainPS.println("\t\t\tperror(\"Failed joining thread\"); "
343                     + "exit(1);");
344             _mainPS.println("\t\t}");
345             _mainPS.println("\t\t");
346             _mainPS.println("\t\tif (spe_context_destroy("
347                     + "data[num].spe_ctx)) {");
348             _mainPS.println("\t\t\tperror(\"Failed "
349                     + "spe_context_destroy\"); exit(1);");
350             _mainPS.println("\t\t}");
351             _mainPS.println("\t}");
352             _mainPS.println("\tprintf(\")PPE:) Complete running "
353                     + "all SPEs\\n\");");
354             _mainPS.println("");
355             _mainPS.println("\tfor (j = 0; j < NUM_FIFO; j++)");
356             _mainPS.println("\t{");
357             _mainPS.println("\t\tfree(locBuf[j]);");
358             _mainPS.println("\t\tpthread_mutex_destroy (&(mutex[j]));");
359             _mainPS.println("\t}");
360             _mainPS.println("");
361             _mainPS.println("#ifdef MEASURE_APPLICATION");
362             _mainPS.println("\tgettimeofday(&t_ppe_end, NULL);");
363             _mainPS.println("\tprintf(\"PPE;%f\\n\",(t_ppe_end.tv_sec "
364                     + "- t_ppe_start.tv_sec) + 0.000001 "
365                     + "* (t_ppe_end.tv_usec - t_ppe_start.tv_usec));");
366             _mainPS.println("#endif");
367             _mainPS.println("");
368             _mainPS.println("\treturn (0);");
369             _mainPS.println("}");
370         }
371         catch (Exception e) {
372             System.out.println("CbeDBModuleVisitor: exception occured: "
373                     + e.getMessage());
374             e.printStackTrace();
375         }
376     }
377
378     /**
379      *
380      * @param x process that needs to be processed
381      */
382     public void visitComponent(Process x) {
383     }
384
385     /**
386      *
387      * @param x channel that needs to be processed
388      */
389     public void visitComponent(Channel x) {
390     }
391
392     /**
393      * Round the parameter to the next DMA-number up.
394      * Example: 23 gives 32.
395      * @param number number to round up
396      * @return next DMA-number
397      */
398     protected int roundDMA(int number) {
399         if (number > 16) {
400             return number + 16 - (number % 16);
401         } else if (number > 8) {
402             return 16;
403         } else if (number > 4) {
404             return 8;
405         } else if (number > 2) {
406             return 4;
407         } else if (number > 1) {
408             return 2;
409         } else {
410             return 1;
411         }
412     }
413
414     protected CodePrintStream _mainPS = null;
415     protected String _dir = null;
416     protected HashMap<Port, Integer> _portMap;
417 }