dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cell / CellModuleVisitor.java
diff --git a/dol/src/dol/visitor/cell/CellModuleVisitor.java b/dol/src/dol/visitor/cell/CellModuleVisitor.java
new file mode 100644 (file)
index 0000000..10c700b
--- /dev/null
@@ -0,0 +1,386 @@
+package dol.visitor.cell;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+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.visitor.PNVisitor;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+
+/**
+ * This class is a class for a visitor that is used to generate the main
+ * program.
+ *
+ * @author lschor, 2008-10-30
+ *
+ *         Remarks: Based on a original file from khuang for rtems
+ *
+ *         Revision: 2008-10-30: Updated the file for the CBE 2008-11-08: Add
+ *         double buffering 2008-11-16: Add new fifo implementation and defines
+ *         for measurement 2008-11-21: Sink/Source do not run on the SPE, but on
+ *         the PPE (as Linux thread) 2009-03-17: Added Protothread Support
+ *         2009-04-07: Several modifications, so that one only writes if there
+ *         is enough memory, do not allocate all queues on PPU
+ */
+public class CellModuleVisitor extends PNVisitor {
+
+    /**
+     * Constructor.
+     *
+     * @param dir
+     *            path of this file
+     */
+    public CellModuleVisitor(String dir, HashMap<Port, Integer> portMap,
+            CellMapping mapping) {
+        _dir = dir;
+        _portMap = portMap;
+        _mapping = mapping;
+    }
+
+    /**
+     * Visit process network.
+     *
+     * @param x
+     *            process network that needs to be rendered
+     */
+    public void visitComponent(ProcessNetwork x) {
+        try {
+            // Create in a first step the different SPU OS Layers
+            ArrayList<Vector<Process>> spuList = _mapping.getSPUList();
+            Vector<Process> ppu = _mapping.getPPU();
+
+            // Create the main file for the PPU
+            _ui = UserInterface.getInstance();
+            String filename = _dir + _delimiter + "ppu_main.cpp";
+            OutputStream file = new FileOutputStream(filename);
+            _mainPS = new CodePrintStream(file);
+
+            // create header section
+            _mainPS.println("// ========================");
+            _mainPS.println("// ppu_main.cpp file");
+            _mainPS.println("// ========================");
+            _mainPS.println("");
+
+            // Includes
+            _mainPS.println("#include \"ppu_main.h\"");
+            _mainPS.println("");
+
+            // Function to create and run one SPE thread
+            _mainPS.println("// create and run one SPE thread");
+            _mainPS.println("void *spu_pthread(void *arg) {");
+            _mainPS.println("    spu_data_t *datp = (spu_data_t *)arg;");
+            _mainPS.println("    uint32_t entry = SPE_DEFAULT_ENTRY;");
+            _mainPS.println("    printf(\")PPE: spe thread start run\\n\" );");
+            _mainPS.println("    if(spe_context_run(datp->spe_ctx,&entry,0,datp->argp,NULL,NULL)<0){");
+            _mainPS.println("        perror (\"Failed running context\"); exit (1);");
+            _mainPS.println("    }");
+            _mainPS.println("    printf(\")PPE: spe thread finish run\\n\");");
+            _mainPS.println("    pthread_exit(NULL);");
+            _mainPS.println("}");
+            _mainPS.println("");
+
+            // Declaration of the Header function for the PPE-Wrappers
+            /*
+             * for (Process p : ppu) { _mainPS.println("void *"+ p.getBasename()
+             * + "_wrapper( void *ptr );"); }
+             */
+            _mainPS.println("void *ppu( void *ptr );");
+            _mainPS.println();
+
+            // Create the port_id and the port_queue_id arrays to send over the
+            // DMA
+            for (Process process : _mapping.getAllSpuProcess()) {
+                String processName = process.getName();
+                _mainPS.println("volatile char " + processName
+                        + "_name[256] __attribute__ ((aligned(16)));");
+            }
+            _mainPS.println();
+
+            // Go through all SPEs
+            for (Vector<Process> spu : spuList) {
+                _mainPS.println("volatile uint64_t spu_"
+                        + spuList.indexOf(spu) + "[" + spu.size()
+                        + "] __attribute__ ((aligned(16)));");
+            }
+            _mainPS.println();
+            _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");
+            _mainPS.println("volatile int32_t queueOnSPU [NUM_FIFO] __attribute__ ((aligned(16)));");
+            _mainPS.println();
+            _mainPS.println(" // The queue comes from this SPU");
+            _mainPS.println("volatile int32_t queueFromSPU [NUM_FIFO] __attribute__ ((aligned(16)));");
+            _mainPS.println();
+            _mainPS.println(" volatile uint64_t ea_ls_base[NUM_SPES] __attribute__ ((aligned(16)));");
+            _mainPS.println("volatile uint64_t context_addr[NUM_SPES] __attribute__ ((aligned(16)));");
+            _mainPS.println("volatile spe_spu_control_area_t* mfc_ctl[NUM_SPES] __attribute__ ((aligned(16)));");
+            _mainPS.println("volatile uint64_t fifoTails[NUM_FIFO] __attribute__ ((aligned(16)));");
+            _mainPS.println();
+
+            // Create the main function
+            _mainPS.println("int main()");
+            _mainPS.println("{");
+
+            // List with all SPU to be open
+            _mainPS.println("    char spe_names[NUM_SPES][60] = {");
+            for (Vector<Process> spu : spuList) {
+                _mainPS.println("        \"spu/spu_os_" + spuList.indexOf(spu)
+                        + "\",");
+            }
+            _mainPS.println("    };");
+
+            _mainPS.println();
+
+            for (Channel c : x.getChannelList()) {
+                // Search for the origin spe
+                int origin = -1;
+
+                for (Vector<Process> spu : spuList) {
+
+                    if (spu.contains(c.getOrigin())) {
+                        origin = spuList.indexOf(spu);
+                        break;
+                    }
+                }
+
+                // Origin on the PPU
+                if (origin == -1) {
+                    origin = (-1) * (ppu.indexOf(c.getOrigin()) + 1);
+                }
+
+                _mainPS.println("    queueFromSPU["
+                        + x.getChannelList().indexOf(c) + "] = " + origin
+                        + ";");
+            }
+
+            _mainPS.println();
+
+            for (Channel c : x.getChannelList()) {
+                // Search for the origin spe
+                int origin = -1;
+
+                for (Vector<Process> spu : spuList) {
+                    if (spu.contains(c.getTarget())) {
+                        origin = spuList.indexOf(spu);
+                        break;
+                    }
+                }
+
+                // Origin on the PPU
+                if (origin == -1) {
+                    origin = (-1) * (ppu.indexOf(c.getTarget()) + 1);
+                }
+
+                _mainPS.println("    queueOnSPU["
+                        + x.getChannelList().indexOf(c) + "] = " + origin
+                        + ";");
+            }
+
+            _mainPS.println();
+
+            // connect ports to channels
+            HashMap<Channel, Integer> channel_map = new HashMap<Channel, Integer>();
+
+            int j = 0;
+            for (Channel c : x.getChannelList()) {
+                channel_map.put(c, j++);
+            }
+
+            // Add to each process the ports and the queues
+            _mainPS
+                    .println("     //Add to each process the ports and the queues");
+            j = 0;
+
+            // SPU Process
+            for (Process process : _mapping.getAllSpuProcess()) {
+                String processName = process.getName();
+                _mainPS.println("    ctx_proc[" + j + "]"
+                        + ".is_detached = 0;");
+                _mainPS.println("    strcpy((char *)" + processName
+                        + "_name, " + "\"" + processName + "\");");
+                _mainPS.println("    ctx_proc[" + j + "]"
+                        + ".processName = (uint64_t) " + processName
+                        + "_name;");
+                _mainPS.println("    ctx_proc[" + j + "]"
+                        + ".processNameLen = ((strlen((char *)"
+                        + processName + "_name) + 15) & ~15);");
+                _mainPS.println();
+                j++;
+            }
+
+            _mainPS.println("    // Mapping tasks -> What to map to which SPE?");
+            _mainPS.println("    // Example: Square 0-2 to SPE 0 AND Square 3-5 to SPE 1");
+            j = 0;
+            for (Process process : _mapping.getAllSpuProcess()) {
+                for (Vector<Process> spu : spuList) {
+                    if (spu.contains(process)) {
+                        _mainPS.println("    spu_" + spuList.indexOf(spu)
+                                        + "[" + spu.indexOf(process)
+                                        + "] = (uint64_t) &(ctx_proc[" + j
+                                        + "]);");
+                        j++;
+                        break;
+                    }
+                }
+            }
+
+            for (Vector<Process> spu : spuList) {
+                _mainPS.println("    ctx_spu[" + spuList.indexOf(spu)
+                        + "].procContents = (uint64_t) spu_"
+                        + spuList.indexOf(spu) + ";");
+                _mainPS.println("    ctx_spu[" + spuList.indexOf(spu)
+                        + "].procContentsLen = " + spu.size() + ";");
+            }
+
+            _mainPS.println();
+
+            // Init the SPE control structure
+            _mainPS.println("    //Initiate SPEs control structure");
+            _mainPS.println("    int num = 0; ");
+            _mainPS.println("    for( num=0; num<NUM_SPES; num++){");
+            _mainPS.println("        data[num].argp = (void *)&(ctx_spu[num]);");
+            _mainPS.println("    }");
+            _mainPS.println();
+
+            _mainPS.println("    // Loop on all SPEs and for each perform three steps:");
+            _mainPS.println("    // - create SPE context");
+            _mainPS.println("    // - open images of SPE programs into main storage");
+            _mainPS.println("    //         <spe_names> variable store the executable name");
+            _mainPS.println("    // - Load SPEs objects into SPE context local store");
+            _mainPS.println("    for( num=0; num<NUM_SPES; num++){");
+            _mainPS.println("        if ((data[num].spe_ctx = spe_context_create (SPE_MAP_PS, NULL)) == NULL) {");
+            _mainPS.println("            perror(\"Failed creating context\"); exit(1);");
+            _mainPS.println("        }");
+            _mainPS.println("        if (!(program[num] = spe_image_open(&spe_names[num][0]))) {");
+            _mainPS.println("             perror(\"Fail opening image\"); exit(1);");
+            _mainPS.println("        }");
+            _mainPS.println("        if (spe_program_load ( data[num].spe_ctx, program[num])) {");
+            _mainPS.println("            perror(\"Failed loading program\"); exit(1);");
+            _mainPS.println("        }      ");
+            _mainPS.println("    }");
+            _mainPS.println("");
+
+            _mainPS.println("    // update the parameters of each SPE");
+            _mainPS.println("    for( num=0; num<NUM_SPES; num++){");
+            _mainPS.println("        if( (ea_ls_base[num] = (uint64_t)(spe_ls_area_get(data[num].spe_ctx))) == 0) {");
+            _mainPS.println("            perror(\"Failed map LS to main storage\"); exit(1);");
+            _mainPS.println("        }");
+            _mainPS.println("        ctx_spu[num].ea_base = ea_ls_base[num];");
+            _mainPS.println("        context_addr[num] = (uint64_t)data[num].spe_ctx;");
+            _mainPS.println("    }");
+
+            _mainPS.println("    for (num=0; num<NUM_SPES; num++) {");
+            _mainPS.println("        if ((mfc_ctl[num] = (spe_spu_control_area_t*) spe_ps_area_get(data[num].spe_ctx, SPE_CONTROL_AREA))==NULL){");
+            _mainPS.println("            perror(\"Failed mapping MFC control area\"); exit(1);");
+            _mainPS.println("        }");
+            _mainPS.println("    }");
+            _mainPS.println("    ");
+
+            _mainPS.println("    for (num=0; num<NUM_SPES; num++) {");
+            _mainPS.println("        ctx_spu[num].queueFromSPU = (uint64_t) queueFromSPU;");
+            _mainPS.println("        ctx_spu[num].queueOnSPU = (uint64_t) queueOnSPU;");
+            _mainPS.println("        ctx_spu[num].procContentsAll = (uint64_t) mfc_ctl;");
+            _mainPS.println("        ctx_spu[num].fifoTails = (uint64_t) fifoTails;");
+            _mainPS.println("    }");
+            _mainPS.println("");
+            _mainPS.println("// This is the PPU");
+            _mainPS.println("    ProcessData *ppu_Process_Wrapper = (ProcessData *)malloc(sizeof(ProcessData));");
+            _mainPS.println("    ppu_Process_Wrapper->procContentsAll = (uint64_t *) context_addr;");
+            _mainPS.println("    ppu_Process_Wrapper->queueFromSPU = (int32_t *)queueFromSPU;");
+            _mainPS.println("    ppu_Process_Wrapper->queueOnSPU = (int32_t *)queueOnSPU;");
+            _mainPS.println("    ppu_Process_Wrapper->ea_ls_base = (uint64_t *)ea_ls_base;");
+            _mainPS.println("    ppu_Process_Wrapper->fifoTails = (uint64_t *) fifoTails;");
+            _mainPS.println("    ");
+
+            _mainPS.println("    // create SPE pthreads");
+            _mainPS.println("    for( num=0; num<NUM_SPES; num++){");
+            _mainPS.println("        if(pthread_create(&data[num].pthread,NULL,&spu_pthread, &data[num])){");
+            _mainPS.println("            perror(\"Failed creating thread\");  exit(1);");
+            _mainPS.println("        }");
+            _mainPS.println("    }");
+            _mainPS.println("    ");
+            _mainPS.println("    // create PPE pthreads");
+            _mainPS.println("    pthread_t thread_ppu;");
+            _mainPS.println("    pthread_create( &thread_ppu, NULL, ppu, ppu_Process_Wrapper);");
+            _mainPS.println("    ");
+
+            _mainPS.println();
+            _mainPS.println("    // Loop on all SPEs and for each perform two steps:");
+            _mainPS.println("    //   - wait for all the SPE pthread to complete");
+            _mainPS.println("    //   - destroy the SPE contexts");
+            _mainPS.println("    for( num=0; num<NUM_SPES; num++){");
+            _mainPS.println("        if(pthread_join (data[num].pthread, NULL)) {");
+            _mainPS.println("            perror(\"Failed joining thread\"); exit (1);");
+            _mainPS.println("        }");
+            _mainPS.println("        ");
+            _mainPS.println("        if (spe_context_destroy( data[num].spe_ctx   )) {");
+            _mainPS.println("            perror(\"Failed spe_context_destroy\"); exit(1);");
+            _mainPS.println("        }");
+            _mainPS.println("    }");
+            _mainPS.println("    ");
+            _mainPS.println("    // Join with PPU");
+            _mainPS.println("    if(pthread_join (thread_ppu, NULL)) {");
+            _mainPS.println("        perror(\"Failed joining thread\"); exit (1);");
+            _mainPS.println("    }");
+            _mainPS.println("    ");
+            _mainPS.println("    printf(\")PPE:) Complete running all super-fast SPEs and PPE\\n\");");
+            _mainPS.println("");
+
+            _mainPS.println("    return (0);");
+            _mainPS.println("}");
+        } catch (Exception e) {
+            System.out.println("CellModuleVisitor: exception occured: "
+                    + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *
+     * @param x
+     *            process that needs to be processed
+     */
+    public void visitComponent(Process x) {
+    }
+
+    /**
+     *
+     * @param x
+     *            channel that needs to be processed
+     */
+    public void visitComponent(Channel x) {
+    }
+
+    /**
+     * Round the parameter to the next DMA-number up. Example: 23 gives 32.
+     *
+     * @param number
+     *            number to round up
+     * @return next DMA-number
+     */
+    protected int roundDMA(int number) {
+        if (number > 16)
+            return number + 16 - (number % 16);
+        else if (number > 8)
+            return 16;
+        else if (number > 4)
+            return 8;
+        else if (number > 2)
+            return 4;
+        else if (number > 1)
+            return 2;
+        else
+            return 1;
+    }
+
+    protected CodePrintStream _mainPS = null;
+    protected String _dir = null;
+    protected HashMap<Port, Integer> _portMap;
+    protected CellMapping _mapping;
+
+}