dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cell / CellModuleVisitor.java
1 package dol.visitor.cell;
2
3 import java.io.FileOutputStream;
4 import java.io.OutputStream;
5 import java.util.ArrayList;
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.visitor.PNVisitor;
14 import dol.main.UserInterface;
15 import dol.util.CodePrintStream;
16
17 /**
18  * This class is a class for a visitor that is used to generate the main
19  * program.
20  *
21  * @author lschor, 2008-10-30
22  *
23  *         Remarks: Based on a original file from khuang for rtems
24  *
25  *         Revision: 2008-10-30: Updated the file for the CBE 2008-11-08: Add
26  *         double buffering 2008-11-16: Add new fifo implementation and defines
27  *         for measurement 2008-11-21: Sink/Source do not run on the SPE, but on
28  *         the PPE (as Linux thread) 2009-03-17: Added Protothread Support
29  *         2009-04-07: Several modifications, so that one only writes if there
30  *         is enough memory, do not allocate all queues on PPU
31  */
32 public class CellModuleVisitor extends PNVisitor {
33
34     /**
35      * Constructor.
36      *
37      * @param dir
38      *            path of this file
39      */
40     public CellModuleVisitor(String dir, HashMap<Port, Integer> portMap,
41             CellMapping mapping) {
42         _dir = dir;
43         _portMap = portMap;
44         _mapping = mapping;
45     }
46
47     /**
48      * Visit process network.
49      *
50      * @param x
51      *            process network that needs to be rendered
52      */
53     public void visitComponent(ProcessNetwork x) {
54         try {
55             // Create in a first step the different SPU OS Layers
56             ArrayList<Vector<Process>> spuList = _mapping.getSPUList();
57             Vector<Process> ppu = _mapping.getPPU();
58
59             // Create the main file for the PPU
60             _ui = UserInterface.getInstance();
61             String filename = _dir + _delimiter + "ppu_main.cpp";
62             OutputStream file = new FileOutputStream(filename);
63             _mainPS = new CodePrintStream(file);
64
65             // create header section
66             _mainPS.println("// ========================");
67             _mainPS.println("// ppu_main.cpp file");
68             _mainPS.println("// ========================");
69             _mainPS.println("");
70
71             // Includes
72             _mainPS.println("#include \"ppu_main.h\"");
73             _mainPS.println("");
74
75             // Function to create and run one SPE thread
76             _mainPS.println("// create and run one SPE thread");
77             _mainPS.println("void *spu_pthread(void *arg) {");
78             _mainPS.println("    spu_data_t *datp = (spu_data_t *)arg;");
79             _mainPS.println("    uint32_t entry = SPE_DEFAULT_ENTRY;");
80             _mainPS.println("    printf(\")PPE: spe thread start run\\n\" );");
81             _mainPS.println("    if(spe_context_run(datp->spe_ctx,&entry,0,datp->argp,NULL,NULL)<0){");
82             _mainPS.println("        perror (\"Failed running context\"); exit (1);");
83             _mainPS.println("    }");
84             _mainPS.println("    printf(\")PPE: spe thread finish run\\n\");");
85             _mainPS.println("    pthread_exit(NULL);");
86             _mainPS.println("}");
87             _mainPS.println("");
88
89             // Declaration of the Header function for the PPE-Wrappers
90             /*
91              * for (Process p : ppu) { _mainPS.println("void *"+ p.getBasename()
92              * + "_wrapper( void *ptr );"); }
93              */
94             _mainPS.println("void *ppu( void *ptr );");
95             _mainPS.println();
96
97             // Create the port_id and the port_queue_id arrays to send over the
98             // DMA
99             for (Process process : _mapping.getAllSpuProcess()) {
100                 String processName = process.getName();
101                 _mainPS.println("volatile char " + processName
102                         + "_name[256] __attribute__ ((aligned(16)));");
103             }
104             _mainPS.println();
105
106             // Go through all SPEs
107             for (Vector<Process> spu : spuList) {
108                 _mainPS.println("volatile uint64_t spu_"
109                         + spuList.indexOf(spu) + "[" + spu.size()
110                         + "] __attribute__ ((aligned(16)));");
111             }
112             _mainPS.println();
113             _mainPS.println("// The input queue of a process is always on the SPU of the receiver, negative means that the queue is on the PPE");
114             _mainPS.println("volatile int32_t queueOnSPU [NUM_FIFO] __attribute__ ((aligned(16)));");
115             _mainPS.println();
116             _mainPS.println(" // The queue comes from this SPU");
117             _mainPS.println("volatile int32_t queueFromSPU [NUM_FIFO] __attribute__ ((aligned(16)));");
118             _mainPS.println();
119             _mainPS.println(" volatile uint64_t ea_ls_base[NUM_SPES] __attribute__ ((aligned(16)));");
120             _mainPS.println("volatile uint64_t context_addr[NUM_SPES] __attribute__ ((aligned(16)));");
121             _mainPS.println("volatile spe_spu_control_area_t* mfc_ctl[NUM_SPES] __attribute__ ((aligned(16)));");
122             _mainPS.println("volatile uint64_t fifoTails[NUM_FIFO] __attribute__ ((aligned(16)));");
123             _mainPS.println();
124
125             // Create the main function
126             _mainPS.println("int main()");
127             _mainPS.println("{");
128
129             // List with all SPU to be open
130             _mainPS.println("    char spe_names[NUM_SPES][60] = {");
131             for (Vector<Process> spu : spuList) {
132                 _mainPS.println("        \"spu/spu_os_" + spuList.indexOf(spu)
133                         + "\",");
134             }
135             _mainPS.println("    };");
136
137             _mainPS.println();
138
139             for (Channel c : x.getChannelList()) {
140                 // Search for the origin spe
141                 int origin = -1;
142
143                 for (Vector<Process> spu : spuList) {
144
145                     if (spu.contains(c.getOrigin())) {
146                         origin = spuList.indexOf(spu);
147                         break;
148                     }
149                 }
150
151                 // Origin on the PPU
152                 if (origin == -1) {
153                     origin = (-1) * (ppu.indexOf(c.getOrigin()) + 1);
154                 }
155
156                 _mainPS.println("    queueFromSPU["
157                         + x.getChannelList().indexOf(c) + "] = " + origin
158                         + ";");
159             }
160
161             _mainPS.println();
162
163             for (Channel c : x.getChannelList()) {
164                 // Search for the origin spe
165                 int origin = -1;
166
167                 for (Vector<Process> spu : spuList) {
168                     if (spu.contains(c.getTarget())) {
169                         origin = spuList.indexOf(spu);
170                         break;
171                     }
172                 }
173
174                 // Origin on the PPU
175                 if (origin == -1) {
176                     origin = (-1) * (ppu.indexOf(c.getTarget()) + 1);
177                 }
178
179                 _mainPS.println("    queueOnSPU["
180                         + x.getChannelList().indexOf(c) + "] = " + origin
181                         + ";");
182             }
183
184             _mainPS.println();
185
186             // connect ports to channels
187             HashMap<Channel, Integer> channel_map = new HashMap<Channel, Integer>();
188
189             int j = 0;
190             for (Channel c : x.getChannelList()) {
191                 channel_map.put(c, j++);
192             }
193
194             // Add to each process the ports and the queues
195             _mainPS
196                     .println("     //Add to each process the ports and the queues");
197             j = 0;
198
199             // SPU Process
200             for (Process process : _mapping.getAllSpuProcess()) {
201                 String processName = process.getName();
202                 _mainPS.println("    ctx_proc[" + j + "]"
203                         + ".is_detached = 0;");
204                 _mainPS.println("    strcpy((char *)" + processName
205                         + "_name, " + "\"" + processName + "\");");
206                 _mainPS.println("    ctx_proc[" + j + "]"
207                         + ".processName = (uint64_t) " + processName
208                         + "_name;");
209                 _mainPS.println("    ctx_proc[" + j + "]"
210                         + ".processNameLen = ((strlen((char *)"
211                         + processName + "_name) + 15) & ~15);");
212                 _mainPS.println();
213                 j++;
214             }
215
216             _mainPS.println("    // Mapping tasks -> What to map to which SPE?");
217             _mainPS.println("    // Example: Square 0-2 to SPE 0 AND Square 3-5 to SPE 1");
218             j = 0;
219             for (Process process : _mapping.getAllSpuProcess()) {
220                 for (Vector<Process> spu : spuList) {
221                     if (spu.contains(process)) {
222                         _mainPS.println("    spu_" + spuList.indexOf(spu)
223                                         + "[" + spu.indexOf(process)
224                                         + "] = (uint64_t) &(ctx_proc[" + j
225                                         + "]);");
226                         j++;
227                         break;
228                     }
229                 }
230             }
231
232             for (Vector<Process> spu : spuList) {
233                 _mainPS.println("    ctx_spu[" + spuList.indexOf(spu)
234                         + "].procContents = (uint64_t) spu_"
235                         + spuList.indexOf(spu) + ";");
236                 _mainPS.println("    ctx_spu[" + spuList.indexOf(spu)
237                         + "].procContentsLen = " + spu.size() + ";");
238             }
239
240             _mainPS.println();
241
242             // Init the SPE control structure
243             _mainPS.println("    //Initiate SPEs control structure");
244             _mainPS.println("    int num = 0; ");
245             _mainPS.println("    for( num=0; num<NUM_SPES; num++){");
246             _mainPS.println("        data[num].argp = (void *)&(ctx_spu[num]);");
247             _mainPS.println("    }");
248             _mainPS.println();
249
250             _mainPS.println("    // Loop on all SPEs and for each perform three steps:");
251             _mainPS.println("    // - create SPE context");
252             _mainPS.println("    // - open images of SPE programs into main storage");
253             _mainPS.println("    //         <spe_names> variable store the executable name");
254             _mainPS.println("    // - Load SPEs objects into SPE context local store");
255             _mainPS.println("    for( num=0; num<NUM_SPES; num++){");
256             _mainPS.println("        if ((data[num].spe_ctx = spe_context_create (SPE_MAP_PS, NULL)) == NULL) {");
257             _mainPS.println("            perror(\"Failed creating context\"); exit(1);");
258             _mainPS.println("        }");
259             _mainPS.println("        if (!(program[num] = spe_image_open(&spe_names[num][0]))) {");
260             _mainPS.println("             perror(\"Fail opening image\"); exit(1);");
261             _mainPS.println("        }");
262             _mainPS.println("        if (spe_program_load ( data[num].spe_ctx, program[num])) {");
263             _mainPS.println("            perror(\"Failed loading program\"); exit(1);");
264             _mainPS.println("        }      ");
265             _mainPS.println("    }");
266             _mainPS.println("");
267
268             _mainPS.println("    // update the parameters of each SPE");
269             _mainPS.println("    for( num=0; num<NUM_SPES; num++){");
270             _mainPS.println("        if( (ea_ls_base[num] = (uint64_t)(spe_ls_area_get(data[num].spe_ctx))) == 0) {");
271             _mainPS.println("            perror(\"Failed map LS to main storage\"); exit(1);");
272             _mainPS.println("        }");
273             _mainPS.println("        ctx_spu[num].ea_base = ea_ls_base[num];");
274             _mainPS.println("        context_addr[num] = (uint64_t)data[num].spe_ctx;");
275             _mainPS.println("    }");
276
277             _mainPS.println("    for (num=0; num<NUM_SPES; num++) {");
278             _mainPS.println("        if ((mfc_ctl[num] = (spe_spu_control_area_t*) spe_ps_area_get(data[num].spe_ctx, SPE_CONTROL_AREA))==NULL){");
279             _mainPS.println("            perror(\"Failed mapping MFC control area\"); exit(1);");
280             _mainPS.println("        }");
281             _mainPS.println("    }");
282             _mainPS.println("    ");
283
284             _mainPS.println("    for (num=0; num<NUM_SPES; num++) {");
285             _mainPS.println("        ctx_spu[num].queueFromSPU = (uint64_t) queueFromSPU;");
286             _mainPS.println("        ctx_spu[num].queueOnSPU = (uint64_t) queueOnSPU;");
287             _mainPS.println("        ctx_spu[num].procContentsAll = (uint64_t) mfc_ctl;");
288             _mainPS.println("        ctx_spu[num].fifoTails = (uint64_t) fifoTails;");
289             _mainPS.println("    }");
290             _mainPS.println("");
291             _mainPS.println("// This is the PPU");
292             _mainPS.println("    ProcessData *ppu_Process_Wrapper = (ProcessData *)malloc(sizeof(ProcessData));");
293             _mainPS.println("    ppu_Process_Wrapper->procContentsAll = (uint64_t *) context_addr;");
294             _mainPS.println("    ppu_Process_Wrapper->queueFromSPU = (int32_t *)queueFromSPU;");
295             _mainPS.println("    ppu_Process_Wrapper->queueOnSPU = (int32_t *)queueOnSPU;");
296             _mainPS.println("    ppu_Process_Wrapper->ea_ls_base = (uint64_t *)ea_ls_base;");
297             _mainPS.println("    ppu_Process_Wrapper->fifoTails = (uint64_t *) fifoTails;");
298             _mainPS.println("    ");
299
300             _mainPS.println("    // create SPE pthreads");
301             _mainPS.println("    for( num=0; num<NUM_SPES; num++){");
302             _mainPS.println("        if(pthread_create(&data[num].pthread,NULL,&spu_pthread, &data[num])){");
303             _mainPS.println("            perror(\"Failed creating thread\");  exit(1);");
304             _mainPS.println("        }");
305             _mainPS.println("    }");
306             _mainPS.println("    ");
307             _mainPS.println("    // create PPE pthreads");
308             _mainPS.println("    pthread_t thread_ppu;");
309             _mainPS.println("    pthread_create( &thread_ppu, NULL, ppu, ppu_Process_Wrapper);");
310             _mainPS.println("    ");
311
312             _mainPS.println();
313             _mainPS.println("    // Loop on all SPEs and for each perform two steps:");
314             _mainPS.println("    //   - wait for all the SPE pthread to complete");
315             _mainPS.println("    //   - destroy the SPE contexts");
316             _mainPS.println("    for( num=0; num<NUM_SPES; num++){");
317             _mainPS.println("        if(pthread_join (data[num].pthread, NULL)) {");
318             _mainPS.println("            perror(\"Failed joining thread\"); exit (1);");
319             _mainPS.println("        }");
320             _mainPS.println("        ");
321             _mainPS.println("        if (spe_context_destroy( data[num].spe_ctx   )) {");
322             _mainPS.println("            perror(\"Failed spe_context_destroy\"); exit(1);");
323             _mainPS.println("        }");
324             _mainPS.println("    }");
325             _mainPS.println("    ");
326             _mainPS.println("    // Join with PPU");
327             _mainPS.println("    if(pthread_join (thread_ppu, NULL)) {");
328             _mainPS.println("        perror(\"Failed joining thread\"); exit (1);");
329             _mainPS.println("    }");
330             _mainPS.println("    ");
331             _mainPS.println("    printf(\")PPE:) Complete running all super-fast SPEs and PPE\\n\");");
332             _mainPS.println("");
333
334             _mainPS.println("    return (0);");
335             _mainPS.println("}");
336         } catch (Exception e) {
337             System.out.println("CellModuleVisitor: exception occured: "
338                     + e.getMessage());
339             e.printStackTrace();
340         }
341     }
342
343     /**
344      *
345      * @param x
346      *            process that needs to be processed
347      */
348     public void visitComponent(Process x) {
349     }
350
351     /**
352      *
353      * @param x
354      *            channel that needs to be processed
355      */
356     public void visitComponent(Channel x) {
357     }
358
359     /**
360      * Round the parameter to the next DMA-number up. Example: 23 gives 32.
361      *
362      * @param number
363      *            number to round up
364      * @return next DMA-number
365      */
366     protected int roundDMA(int number) {
367         if (number > 16)
368             return number + 16 - (number % 16);
369         else if (number > 8)
370             return 16;
371         else if (number > 4)
372             return 8;
373         else if (number > 2)
374             return 4;
375         else if (number > 1)
376             return 2;
377         else
378             return 1;
379     }
380
381     protected CodePrintStream _mainPS = null;
382     protected String _dir = null;
383     protected HashMap<Port, Integer> _portMap;
384     protected CellMapping _mapping;
385
386 }