--- /dev/null
+package dol.visitor.cell;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+public class CellPPEVisitor extends PNVisitor {
+ /**
+ * Constructor.
+ *
+ * @param dir
+ * path of this file
+ */
+ public CellPPEVisitor(String dir, CellMapping mapping) {
+ _dir = dir;
+ _mapping = mapping;
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param x
+ * process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ // Create a directory for the OS Layer:
+ _ppuDir = _dir + _delimiter + "ppu";
+ File dir = new File(_ppuDir);
+ dir.mkdirs();
+
+ // Copy the header file to this directory
+ // Some library files must be copied to the main directory
+ (new File(_dir + _delimiter + "lib" + _delimiter + "ppu_os.h"))
+ .renameTo(new File(dir.getPath() + _delimiter
+ + "spu_os.h"));
+
+ createOSLayer(x, _mapping.getPPU());
+
+ createMakefilePPU();
+ } catch (Exception e) {
+ System.out.println("CellPPEVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates the OS layer for one SPU
+ *
+ * @param spu
+ * List of all processes a SPU gets
+ * @param index
+ * index of the SPU in the SPU list
+ */
+ protected void createOSLayer(ProcessNetwork x, Vector<Process> ppu) {
+ try {
+ // Create the filename for the new layer
+ String filename = _ppuDir + _delimiter + "ppu_os.cpp";
+
+ // PrintStream for writing to the file
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream _code = new CodePrintStream(file);
+
+ _code = new CodePrintStream(file);
+
+ _code.printPrefixln("#include \"pt.h\"");
+ _code.printPrefixln("#include \"Fifo.h\"");
+ _code.printPrefixln("#include \"WindowedFifo.h\"");
+ _code.printPrefixln("#include \"FastCommunication.h\"");
+ _code.printPrefixln("#include \"common_ppu.h\"");
+ _code.printPrefixln("#include \"common.h\"");
+ for (Process p : ppu) {
+ _code.printPrefixln("#include \".." + _delimiter + "ppu_"
+ + p.getBasename() + _delimiter + p.getBasename()
+ + "Wrapper.h\"");
+ }
+
+ _code.println();
+ _code.printPrefixln("void *ppu( void *ptr )");
+ _code.printLeftBracket();
+
+ // instantiate channels
+ Vector<Channel> channelList = new Vector<Channel>();
+ int indx = 0;
+ for (Channel c : x.getChannelList()) {
+ if (ppu.contains(c.getOrigin())
+ || ppu.contains(c.getTarget())) {
+ channelList.add(c);
+
+ if (c.getType().equals("fifo")) {
+ // This is a IN-Channel --> Add an additional Factor to increase the speed
+ if (ppu.contains(c.getTarget()) && !ppu.contains(c.getOrigin())) {
+ _code.printPrefixln("Fifo " + c.getName()
+ + "(FIFO_SIZE[" + indx +"] * FIFO_SIZE_FACTOR);");
+ // OUT-Channel --> Do not add any factor as we like to stall sometimes
+ } else {
+ _code.printPrefixln("Fifo " + c.getName()
+ + "(FIFO_SIZE[" + indx + "]);");
+ }
+ } else if (c.getType().equals("wfifo")) {
+ _code.printPrefixln("WindowedFifo " + c.getName()
+ + "(FIFO_SIZE[" + indx + "]);");
+ }
+ }
+ indx++;
+ }
+ _code.println();
+
+ // instantiate processes
+ for (Process p : ppu) {
+ _code.printPrefix("int " + p.getName() + "Indices[] = { ");
+ Vector<Integer> iteratorIndex = p.getIteratorIndices();
+ if (iteratorIndex.size() < 4) {
+ while (iteratorIndex.size() < 4) {
+ iteratorIndex.add(-1);
+ }
+ } else if (iteratorIndex.size() > 4) {
+ new RuntimeException("Error: Currently not more than "
+ + "4 iterator dimensions are supported."
+ + "Consider revising " + p.getBasename() + ".");
+ }
+ for (int i = 0; i < 4; i++) {
+ if (i < 3) {
+ _code.print(iteratorIndex.elementAt(i) + ", ");
+ } else {
+ _code.println(iteratorIndex.elementAt(i) + " };");
+ }
+ }
+ _code.println();
+ _code.printPrefixln(p.getBasename() + "Wrapper *" + p.getName() + ";");
+ _code.printPrefixln("try { "
+ + p.getName() + " = new " + p.getBasename()
+ + "Wrapper(\"" + p.getName() + "\", "
+ + p.getName() + "Indices); }");
+ _code.println(" catch(std::bad_alloc &e) {");
+ _code.println(" fprintf(stderr, \"[" + p.getBasename() +"Wrapper] Memory allocation failure\\n\");");
+ _code.println(" exit(1);");
+ _code.println(" }");
+ }
+ _code.println();
+
+ // connect the network
+ for (Process p : ppu) {
+ for (Port port : p.getPortList()) {
+ if (port.getName().equals(port.getBasename())) {
+ _code.printPrefixln(p.getName() + "->_port"
+ + port.getName() + "Fifo = &"
+ + port.getPeerResource().getName() + ";");
+ } else {
+ _code.printPrefix(p.getName() + "->_port"
+ + port.getBasename() + "Fifo");
+ StringTokenizer tokenizer = new StringTokenizer(
+ port.getName().replaceFirst(
+ port.getBasename(), ""), "_");
+ while (tokenizer.hasMoreTokens()) {
+ _code.print("[" + tokenizer.nextToken() + "]");
+ }
+ _code.println(" = &"
+ + port.getPeerResource().getName() + ";");
+ }
+ }
+ }
+ _code.println();
+
+ /**************************************************************************/
+ // This is the synchronisation code
+ _code.println(" for (int i = 0; i < NUM_FIFO; i++)");
+ _code.println(" ((ProcessData *)ptr)->fifoTails[i] = 0;");
+ _code.println(" ");
+
+ int outQueues = 0;
+
+ // Check all out queues on the SPU
+ for (Channel c : x.getChannelList()) {
+
+ // Check all SPUs
+ for (Vector<Process> spu : _mapping.getSPUList()) {
+ if (spu.contains(c.getOrigin()) && !spu.contains(c.getTarget())) {
+ outQueues++;
+ }
+ }
+
+ // Check the PPU
+ if (ppu.contains(c.getOrigin()) && !ppu.contains(c.getTarget())) {
+ outQueues++;
+ }
+ }
+
+ // On how much queues we have to wait
+ _code.println(" uint32_t nrOutQueues = NUM_FIFO;");
+ _code.println(" uint32_t countOutQueues = 0;");
+ _code.println(" uint32_t processNr = 0;");
+ _code.println(" uint32_t message;");
+ _code.println("");
+
+ // Add all out queues of the PPE
+
+ for (Channel c : channelList) {
+ if (ppu.contains(c.getOrigin()) && !ppu.contains(c.getTarget())) {
+ _code.println(" ((ProcessData *)ptr)->fifoTails[" + x.getChannelList().indexOf(c) + "] = (uint64_t) " + c.getName() + ".getQueuePointer();");
+ _code.println(" countOutQueues++;");
+ }
+ }
+
+ // Check to get all messages back
+ _code.println(" ");
+ _code.println(" // Get the offset of the queues");
+ _code.println(" while (countOutQueues < nrOutQueues) {");
+ _code.println(" for (processNr = 0; processNr < NUM_SPES; processNr++) {");
+ _code.println(" if (!spe_out_mbox_status((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr])) continue;");
+ _code.println(" ");
+ _code.println(" spe_out_mbox_read((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr], &message, 1);");
+ _code.println(" ");
+ _code.println(" uint32_t queue = ((message >> 24) & 0xFF);");
+ _code.println(" uint32_t offset = ((message >> 0) & 0xFFFFFF);");
+ _code.println(" ");
+ _code.println(" if (((ProcessData *)ptr)->queueOnSPU[queue] < 0)");
+ _code.println(" ((ProcessData *)ptr)->fifoTails[queue] = offset; // Only the offset if the PPE needs to access the data");
+ _code.println(" else");
+ _code.println(" ((ProcessData *)ptr)->fifoTails[queue] = offset + ((ProcessData *)ptr)->ea_ls_base[processNr];");
+ _code.println(" countOutQueues++;");
+ _code.println(" }");
+ _code.println(" }");
+ _code.println(" ");
+
+ // Send a message that each SPE knows that he can access the list
+ _code.println(" // Send the Okay to all SPEs for that they can start reading the tail pointers of the fifos");
+ _code.println(" message = MSG_OK;");
+ _code.println(" for (processNr = 0; processNr < NUM_SPES; processNr++) {");
+ _code.println(" spe_in_mbox_write((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr], (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);");
+ _code.println(" }");
+
+ /**************************************************************************/
+
+ // initialize processes
+ for (Process p : ppu) {
+ _code.printPrefixln(p.getName() + "->init();");
+ }
+ _code.println();
+
+ // Count the effected channels
+ int countChannels = 0;
+ for (Channel c : channelList) {
+ if (ppu.contains(c.getOrigin())
+ && ppu.contains(c.getTarget())) {
+ continue;
+ } else if (ppu.contains(c.getOrigin()))
+ countChannels++;
+ else if (ppu.contains(c.getTarget()))
+ countChannels++;
+ else
+ System.out.println("ERROR! Channel Mapping is wrong.");
+ }
+
+
+ _code.println(" FastCommunication * com;");
+ _code
+ .println(" try { com = new FastCommunication("
+ + countChannels
+ + ", ((ProcessData *)ptr)->procContentsAll, ((ProcessData *)ptr)->ea_ls_base, ((ProcessData *)ptr)->queueFromSPU, ((ProcessData *)ptr)->queueOnSPU, ((ProcessData *)ptr)->fifoTails); }");
+ _code.println(" catch(std::bad_alloc &e) {");
+ _code.println(" fprintf(stderr, \"[FastCommunication] Memory allocation failure\\n\");");
+ _code.println(" exit(1);");
+ _code.println(" }");
+
+ String channelTyp = "";
+ int i = 0;
+ for (Channel c : channelList) {
+ if (ppu.contains(c.getOrigin())
+ && ppu.contains(c.getTarget())) {
+ // Local channels have no influence on external
+ // communication (should be Windowed Fifos...)
+ channelTyp = "local";
+ continue;
+ } else if (ppu.contains(c.getOrigin())) {
+ channelTyp = "out";
+ } else if (ppu.contains(c.getTarget())) {
+ channelTyp = "in";
+ } else {
+ System.out.println("ERROR! Channel Mapping is wrong.");
+ }
+
+ if (c.getType().equals("fifo")) {
+ _code.println(" com->addFifo(" + (i) + ", &"
+ + c.getName() + ", com->" + channelTyp + ", "
+ + x.getChannelList().indexOf(c) + ");");
+ } else if (c.getType().equals("wfifo")) {
+ _code.println(" com->addWFifo(" + (i) + ", &"
+ + c.getName() + ", com->" + channelTyp + ", "
+ + x.getChannelList().indexOf(c) + ");");
+ }
+ i++;
+ }
+
+ _code.printPrefixln("bool allBlocked = false;");
+ _code.printPrefixln("while(!allBlocked)");
+ _code.printLeftBracket();
+ _code.printPrefixln("allBlocked = true;");
+ for (Process p : ppu) {
+ _code.printPrefixln("if (!" + p.getName()
+ + "->isDetached()) {");
+ _code.printPrefixln(" " + p.getName() + "->fire();");
+ _code.printPrefixln(" allBlocked = false;");
+ _code.printPrefixln("}");
+ _code.printPrefixln("");
+
+
+
+ // Communication only if this process needs some communication
+ for (Channel c : channelList) {
+ // The channel may goes away
+ if (!ppu.contains(c.getOrigin()) || !ppu.contains(c.getTarget())) {
+ if (c.getOrigin().equals(p) || c.getTarget().equals(p)) {
+ _code.printPrefixln("com->update();");
+ _code.printPrefixln("");
+ break;
+ }
+ }
+ }
+
+ }
+ _code.printRightBracket();
+ _code.println();
+
+ _code.println();
+ _code.println(" // Are there any open communication requests?");
+ _code.println(" while (!com->empty())");
+ _code.println(" {");
+ _code.println(" com->update();");
+ _code.println(" }");
+ _code.println(" ");
+ _code.println(" // Send all SPUs the complete message");
+ _code.println(" message = MSG_OK;");
+ _code.println(" for (processNr = 0; processNr < NUM_SPES; processNr++) {");
+ _code.println(" spe_in_mbox_write((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr], (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);");
+ _code.println(" }");
+ _code.println("");
+ for (Process p : ppu) {
+ _code.printPrefixln("delete " + p.getName() + ";");
+ }
+ _code.printPrefixln("delete com;");
+ _code.println();
+ _code.printPrefixln("pthread_exit(NULL);");
+ _code.printRightBracket();
+ } catch (Exception e) {
+ System.out.println("ProtothreadModuleVisitor: "
+ + "exception occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ protected void createMakefilePPU() {
+ try {
+ // Directory of the process
+ String ppuDir = _dir + _delimiter + "ppu";
+
+ // Create the filename for the new wrapper
+ String filename = ppuDir + _delimiter + "Makefile";
+
+ OutputStream file = new FileOutputStream(filename);
+
+ PrintStream _makefilePS = new CodePrintStream(file);
+
+ _makefilePS.println("# Makefile for PPU OS");
+ _makefilePS.println("");
+ _makefilePS.println("src := $(wildcard ../lib/ppu/*.cpp)");
+ _makefilePS.println("obj = $(src:.cpp=.o)");
+ _makefilePS.println("");
+
+ // The Makefile must include all o-Files of the processes needed
+ String dependency = "";
+
+ // Go through all possible processes
+ for (Process p : _mapping.getAllPPUBaseProcess()) {
+ dependency += " .." + _delimiter + "ppu_"
+ + p.getBasename() + _delimiter + p.getBasename()
+ + "Wrapper.o";
+ }
+
+ _makefilePS.println("all: ${obj}");
+ _makefilePS
+ .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");
+
+ _makefilePS.println();
+ _makefilePS.println("clean: ");
+ _makefilePS.println("\trm ppu_os");
+
+ _makefilePS.println();
+ _makefilePS.println("%.o : ");
+ _makefilePS
+ .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");
+ _makefilePS.println();
+
+ } catch (FileNotFoundException e) {
+ System.out.println("CbeProcessVisitor - Makefile: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _ppuDir = null;
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+ protected CellMapping _mapping = null;
+
+}