X-Git-Url: http://sraa.de/git/?a=blobdiff_plain;f=dol%2Fsrc%2Fdol%2Fvisitor%2Fcell%2FCellPPEVisitor.java;fp=dol%2Fsrc%2Fdol%2Fvisitor%2Fcell%2FCellPPEVisitor.java;h=e283fa6ebf5069b3787cfed3ce95a431a51983c3;hb=8c411cf24ed0eb889191aaeafd8fa1e69081df42;hp=0000000000000000000000000000000000000000;hpb=dea7a4fb1ed110d3ce6e6d9255103d724bd66c0e;p=jump.git diff --git a/dol/src/dol/visitor/cell/CellPPEVisitor.java b/dol/src/dol/visitor/cell/CellPPEVisitor.java new file mode 100644 index 0000000..e283fa6 --- /dev/null +++ b/dol/src/dol/visitor/cell/CellPPEVisitor.java @@ -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 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 channelList = new Vector(); + 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 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 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; + +}