dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cell / CellPPEVisitor.java
diff --git a/dol/src/dol/visitor/cell/CellPPEVisitor.java b/dol/src/dol/visitor/cell/CellPPEVisitor.java
new file mode 100644 (file)
index 0000000..e283fa6
--- /dev/null
@@ -0,0 +1,421 @@
+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;
+
+}