1 package dol.visitor.cell;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.OutputStream;
7 import java.io.PrintStream;
8 import java.util.StringTokenizer;
9 import java.util.Vector;
11 import dol.datamodel.pn.Channel;
12 import dol.datamodel.pn.Port;
13 import dol.datamodel.pn.Process;
14 import dol.datamodel.pn.ProcessNetwork;
15 import dol.util.CodePrintStream;
16 import dol.visitor.PNVisitor;
18 public class CellPPEVisitor extends PNVisitor {
25 public CellPPEVisitor(String dir, CellMapping mapping) {
31 * Visit process network.
34 * process network that needs to be rendered
36 public void visitComponent(ProcessNetwork x) {
38 // Create a directory for the OS Layer:
39 _ppuDir = _dir + _delimiter + "ppu";
40 File dir = new File(_ppuDir);
43 // Copy the header file to this directory
44 // Some library files must be copied to the main directory
45 (new File(_dir + _delimiter + "lib" + _delimiter + "ppu_os.h"))
46 .renameTo(new File(dir.getPath() + _delimiter
49 createOSLayer(x, _mapping.getPPU());
52 } catch (Exception e) {
53 System.out.println("CellPPEVisitor: exception occured: "
60 * Creates the OS layer for one SPU
63 * List of all processes a SPU gets
65 * index of the SPU in the SPU list
67 protected void createOSLayer(ProcessNetwork x, Vector<Process> ppu) {
69 // Create the filename for the new layer
70 String filename = _ppuDir + _delimiter + "ppu_os.cpp";
72 // PrintStream for writing to the file
73 OutputStream file = new FileOutputStream(filename);
74 CodePrintStream _code = new CodePrintStream(file);
76 _code = new CodePrintStream(file);
78 _code.printPrefixln("#include \"pt.h\"");
79 _code.printPrefixln("#include \"Fifo.h\"");
80 _code.printPrefixln("#include \"WindowedFifo.h\"");
81 _code.printPrefixln("#include \"FastCommunication.h\"");
82 _code.printPrefixln("#include \"common_ppu.h\"");
83 _code.printPrefixln("#include \"common.h\"");
84 for (Process p : ppu) {
85 _code.printPrefixln("#include \".." + _delimiter + "ppu_"
86 + p.getBasename() + _delimiter + p.getBasename()
91 _code.printPrefixln("void *ppu( void *ptr )");
92 _code.printLeftBracket();
94 // instantiate channels
95 Vector<Channel> channelList = new Vector<Channel>();
97 for (Channel c : x.getChannelList()) {
98 if (ppu.contains(c.getOrigin())
99 || ppu.contains(c.getTarget())) {
102 if (c.getType().equals("fifo")) {
103 // This is a IN-Channel --> Add an additional Factor to increase the speed
104 if (ppu.contains(c.getTarget()) && !ppu.contains(c.getOrigin())) {
105 _code.printPrefixln("Fifo " + c.getName()
106 + "(FIFO_SIZE[" + indx +"] * FIFO_SIZE_FACTOR);");
107 // OUT-Channel --> Do not add any factor as we like to stall sometimes
109 _code.printPrefixln("Fifo " + c.getName()
110 + "(FIFO_SIZE[" + indx + "]);");
112 } else if (c.getType().equals("wfifo")) {
113 _code.printPrefixln("WindowedFifo " + c.getName()
114 + "(FIFO_SIZE[" + indx + "]);");
121 // instantiate processes
122 for (Process p : ppu) {
123 _code.printPrefix("int " + p.getName() + "Indices[] = { ");
124 Vector<Integer> iteratorIndex = p.getIteratorIndices();
125 if (iteratorIndex.size() < 4) {
126 while (iteratorIndex.size() < 4) {
127 iteratorIndex.add(-1);
129 } else if (iteratorIndex.size() > 4) {
130 new RuntimeException("Error: Currently not more than "
131 + "4 iterator dimensions are supported."
132 + "Consider revising " + p.getBasename() + ".");
134 for (int i = 0; i < 4; i++) {
136 _code.print(iteratorIndex.elementAt(i) + ", ");
138 _code.println(iteratorIndex.elementAt(i) + " };");
142 _code.printPrefixln(p.getBasename() + "Wrapper *" + p.getName() + ";");
143 _code.printPrefixln("try { "
144 + p.getName() + " = new " + p.getBasename()
145 + "Wrapper(\"" + p.getName() + "\", "
146 + p.getName() + "Indices); }");
147 _code.println(" catch(std::bad_alloc &e) {");
148 _code.println(" fprintf(stderr, \"[" + p.getBasename() +"Wrapper] Memory allocation failure\\n\");");
149 _code.println(" exit(1);");
154 // connect the network
155 for (Process p : ppu) {
156 for (Port port : p.getPortList()) {
157 if (port.getName().equals(port.getBasename())) {
158 _code.printPrefixln(p.getName() + "->_port"
159 + port.getName() + "Fifo = &"
160 + port.getPeerResource().getName() + ";");
162 _code.printPrefix(p.getName() + "->_port"
163 + port.getBasename() + "Fifo");
164 StringTokenizer tokenizer = new StringTokenizer(
165 port.getName().replaceFirst(
166 port.getBasename(), ""), "_");
167 while (tokenizer.hasMoreTokens()) {
168 _code.print("[" + tokenizer.nextToken() + "]");
171 + port.getPeerResource().getName() + ";");
177 /**************************************************************************/
178 // This is the synchronisation code
179 _code.println(" for (int i = 0; i < NUM_FIFO; i++)");
180 _code.println(" ((ProcessData *)ptr)->fifoTails[i] = 0;");
185 // Check all out queues on the SPU
186 for (Channel c : x.getChannelList()) {
189 for (Vector<Process> spu : _mapping.getSPUList()) {
190 if (spu.contains(c.getOrigin()) && !spu.contains(c.getTarget())) {
196 if (ppu.contains(c.getOrigin()) && !ppu.contains(c.getTarget())) {
201 // On how much queues we have to wait
202 _code.println(" uint32_t nrOutQueues = NUM_FIFO;");
203 _code.println(" uint32_t countOutQueues = 0;");
204 _code.println(" uint32_t processNr = 0;");
205 _code.println(" uint32_t message;");
208 // Add all out queues of the PPE
210 for (Channel c : channelList) {
211 if (ppu.contains(c.getOrigin()) && !ppu.contains(c.getTarget())) {
212 _code.println(" ((ProcessData *)ptr)->fifoTails[" + x.getChannelList().indexOf(c) + "] = (uint64_t) " + c.getName() + ".getQueuePointer();");
213 _code.println(" countOutQueues++;");
217 // Check to get all messages back
219 _code.println(" // Get the offset of the queues");
220 _code.println(" while (countOutQueues < nrOutQueues) {");
221 _code.println(" for (processNr = 0; processNr < NUM_SPES; processNr++) {");
222 _code.println(" if (!spe_out_mbox_status((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr])) continue;");
224 _code.println(" spe_out_mbox_read((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr], &message, 1);");
226 _code.println(" uint32_t queue = ((message >> 24) & 0xFF);");
227 _code.println(" uint32_t offset = ((message >> 0) & 0xFFFFFF);");
229 _code.println(" if (((ProcessData *)ptr)->queueOnSPU[queue] < 0)");
230 _code.println(" ((ProcessData *)ptr)->fifoTails[queue] = offset; // Only the offset if the PPE needs to access the data");
231 _code.println(" else");
232 _code.println(" ((ProcessData *)ptr)->fifoTails[queue] = offset + ((ProcessData *)ptr)->ea_ls_base[processNr];");
233 _code.println(" countOutQueues++;");
238 // Send a message that each SPE knows that he can access the list
239 _code.println(" // Send the Okay to all SPEs for that they can start reading the tail pointers of the fifos");
240 _code.println(" message = MSG_OK;");
241 _code.println(" for (processNr = 0; processNr < NUM_SPES; processNr++) {");
242 _code.println(" spe_in_mbox_write((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr], (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);");
245 /**************************************************************************/
247 // initialize processes
248 for (Process p : ppu) {
249 _code.printPrefixln(p.getName() + "->init();");
253 // Count the effected channels
254 int countChannels = 0;
255 for (Channel c : channelList) {
256 if (ppu.contains(c.getOrigin())
257 && ppu.contains(c.getTarget())) {
259 } else if (ppu.contains(c.getOrigin()))
261 else if (ppu.contains(c.getTarget()))
264 System.out.println("ERROR! Channel Mapping is wrong.");
268 _code.println(" FastCommunication * com;");
270 .println(" try { com = new FastCommunication("
272 + ", ((ProcessData *)ptr)->procContentsAll, ((ProcessData *)ptr)->ea_ls_base, ((ProcessData *)ptr)->queueFromSPU, ((ProcessData *)ptr)->queueOnSPU, ((ProcessData *)ptr)->fifoTails); }");
273 _code.println(" catch(std::bad_alloc &e) {");
274 _code.println(" fprintf(stderr, \"[FastCommunication] Memory allocation failure\\n\");");
275 _code.println(" exit(1);");
278 String channelTyp = "";
280 for (Channel c : channelList) {
281 if (ppu.contains(c.getOrigin())
282 && ppu.contains(c.getTarget())) {
283 // Local channels have no influence on external
284 // communication (should be Windowed Fifos...)
285 channelTyp = "local";
287 } else if (ppu.contains(c.getOrigin())) {
289 } else if (ppu.contains(c.getTarget())) {
292 System.out.println("ERROR! Channel Mapping is wrong.");
295 if (c.getType().equals("fifo")) {
296 _code.println(" com->addFifo(" + (i) + ", &"
297 + c.getName() + ", com->" + channelTyp + ", "
298 + x.getChannelList().indexOf(c) + ");");
299 } else if (c.getType().equals("wfifo")) {
300 _code.println(" com->addWFifo(" + (i) + ", &"
301 + c.getName() + ", com->" + channelTyp + ", "
302 + x.getChannelList().indexOf(c) + ");");
307 _code.printPrefixln("bool allBlocked = false;");
308 _code.printPrefixln("while(!allBlocked)");
309 _code.printLeftBracket();
310 _code.printPrefixln("allBlocked = true;");
311 for (Process p : ppu) {
312 _code.printPrefixln("if (!" + p.getName()
313 + "->isDetached()) {");
314 _code.printPrefixln(" " + p.getName() + "->fire();");
315 _code.printPrefixln(" allBlocked = false;");
316 _code.printPrefixln("}");
317 _code.printPrefixln("");
321 // Communication only if this process needs some communication
322 for (Channel c : channelList) {
323 // The channel may goes away
324 if (!ppu.contains(c.getOrigin()) || !ppu.contains(c.getTarget())) {
325 if (c.getOrigin().equals(p) || c.getTarget().equals(p)) {
326 _code.printPrefixln("com->update();");
327 _code.printPrefixln("");
334 _code.printRightBracket();
338 _code.println(" // Are there any open communication requests?");
339 _code.println(" while (!com->empty())");
341 _code.println(" com->update();");
344 _code.println(" // Send all SPUs the complete message");
345 _code.println(" message = MSG_OK;");
346 _code.println(" for (processNr = 0; processNr < NUM_SPES; processNr++) {");
347 _code.println(" spe_in_mbox_write((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr], (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);");
350 for (Process p : ppu) {
351 _code.printPrefixln("delete " + p.getName() + ";");
353 _code.printPrefixln("delete com;");
355 _code.printPrefixln("pthread_exit(NULL);");
356 _code.printRightBracket();
357 } catch (Exception e) {
358 System.out.println("ProtothreadModuleVisitor: "
359 + "exception occured: " + e.getMessage());
367 protected void createMakefilePPU() {
369 // Directory of the process
370 String ppuDir = _dir + _delimiter + "ppu";
372 // Create the filename for the new wrapper
373 String filename = ppuDir + _delimiter + "Makefile";
375 OutputStream file = new FileOutputStream(filename);
377 PrintStream _makefilePS = new CodePrintStream(file);
379 _makefilePS.println("# Makefile for PPU OS");
380 _makefilePS.println("");
381 _makefilePS.println("src := $(wildcard ../lib/ppu/*.cpp)");
382 _makefilePS.println("obj = $(src:.cpp=.o)");
383 _makefilePS.println("");
385 // The Makefile must include all o-Files of the processes needed
386 String dependency = "";
388 // Go through all possible processes
389 for (Process p : _mapping.getAllPPUBaseProcess()) {
390 dependency += " .." + _delimiter + "ppu_"
391 + p.getBasename() + _delimiter + p.getBasename()
395 _makefilePS.println("all: ${obj}");
397 .println("\tppu-g++ -c -I .. -I ../lib -I ../lib/pt -I ../lib/ppu -o ppu_os.o ppu_os.cpp -ftree-vectorize -lm -mtune=cell -O3 -fmodulo-sched -funroll-loops -ffast-math");
399 _makefilePS.println();
400 _makefilePS.println("clean: ");
401 _makefilePS.println("\trm ppu_os");
403 _makefilePS.println();
404 _makefilePS.println("%.o : ");
406 .println("\tppu-g++ -c -o $(*D)/$(*F).o $(*D)/$(*F).cpp -I .. -I ../lib -I ../lib/pt -I ../lib/ppu -ftree-vectorize -lm -mtune=cell -O3 -fmodulo-sched -funroll-loops -ffast-math");
407 _makefilePS.println();
409 } catch (FileNotFoundException e) {
410 System.out.println("CbeProcessVisitor - Makefile: exception "
411 + "occured: " + e.getMessage());
416 protected String _ppuDir = null;
417 protected CodePrintStream _mainPS = null;
418 protected String _dir = null;
419 protected CellMapping _mapping = null;