1 package dol.visitor.cell;
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;
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;
18 * This class is a class for a visitor that is used to generate the main
21 * @author lschor, 2008-10-30
23 * Remarks: Based on a original file from khuang for rtems
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
32 public class CellModuleVisitor extends PNVisitor {
40 public CellModuleVisitor(String dir, HashMap<Port, Integer> portMap,
41 CellMapping mapping) {
48 * Visit process network.
51 * process network that needs to be rendered
53 public void visitComponent(ProcessNetwork x) {
55 // Create in a first step the different SPU OS Layers
56 ArrayList<Vector<Process>> spuList = _mapping.getSPUList();
57 Vector<Process> ppu = _mapping.getPPU();
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);
65 // create header section
66 _mainPS.println("// ========================");
67 _mainPS.println("// ppu_main.cpp file");
68 _mainPS.println("// ========================");
72 _mainPS.println("#include \"ppu_main.h\"");
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);");
89 // Declaration of the Header function for the PPE-Wrappers
91 * for (Process p : ppu) { _mainPS.println("void *"+ p.getBasename()
92 * + "_wrapper( void *ptr );"); }
94 _mainPS.println("void *ppu( void *ptr );");
97 // Create the port_id and the port_queue_id arrays to send over the
99 for (Process process : _mapping.getAllSpuProcess()) {
100 String processName = process.getName();
101 _mainPS.println("volatile char " + processName
102 + "_name[256] __attribute__ ((aligned(16)));");
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)));");
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)));");
116 _mainPS.println(" // The queue comes from this SPU");
117 _mainPS.println("volatile int32_t queueFromSPU [NUM_FIFO] __attribute__ ((aligned(16)));");
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)));");
125 // Create the main function
126 _mainPS.println("int main()");
127 _mainPS.println("{");
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)
135 _mainPS.println(" };");
139 for (Channel c : x.getChannelList()) {
140 // Search for the origin spe
143 for (Vector<Process> spu : spuList) {
145 if (spu.contains(c.getOrigin())) {
146 origin = spuList.indexOf(spu);
153 origin = (-1) * (ppu.indexOf(c.getOrigin()) + 1);
156 _mainPS.println(" queueFromSPU["
157 + x.getChannelList().indexOf(c) + "] = " + origin
163 for (Channel c : x.getChannelList()) {
164 // Search for the origin spe
167 for (Vector<Process> spu : spuList) {
168 if (spu.contains(c.getTarget())) {
169 origin = spuList.indexOf(spu);
176 origin = (-1) * (ppu.indexOf(c.getTarget()) + 1);
179 _mainPS.println(" queueOnSPU["
180 + x.getChannelList().indexOf(c) + "] = " + origin
186 // connect ports to channels
187 HashMap<Channel, Integer> channel_map = new HashMap<Channel, Integer>();
190 for (Channel c : x.getChannelList()) {
191 channel_map.put(c, j++);
194 // Add to each process the ports and the queues
196 .println(" //Add to each process the ports and the queues");
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
209 _mainPS.println(" ctx_proc[" + j + "]"
210 + ".processNameLen = ((strlen((char *)"
211 + processName + "_name) + 15) & ~15);");
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");
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
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() + ";");
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(" }");
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(" }");
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(" }");
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(" ");
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(" }");
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(" ");
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(" ");
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\");");
334 _mainPS.println(" return (0);");
335 _mainPS.println("}");
336 } catch (Exception e) {
337 System.out.println("CellModuleVisitor: exception occured: "
346 * process that needs to be processed
348 public void visitComponent(Process x) {
354 * channel that needs to be processed
356 public void visitComponent(Channel x) {
360 * Round the parameter to the next DMA-number up. Example: 23 gives 32.
364 * @return next DMA-number
366 protected int roundDMA(int number) {
368 return number + 16 - (number % 16);
381 protected CodePrintStream _mainPS = null;
382 protected String _dir = null;
383 protected HashMap<Port, Integer> _portMap;
384 protected CellMapping _mapping;