X-Git-Url: http://sraa.de/git/?a=blobdiff_plain;f=dol%2Fsrc%2Fdol%2Fvisitor%2Fcell%2FCellSPEVisitor.java;fp=dol%2Fsrc%2Fdol%2Fvisitor%2Fcell%2FCellSPEVisitor.java;h=a8061ecefadb6cd79a624cdac70ab8194bdce7a4;hb=8c411cf24ed0eb889191aaeafd8fa1e69081df42;hp=0000000000000000000000000000000000000000;hpb=dea7a4fb1ed110d3ce6e6d9255103d724bd66c0e;p=jump.git diff --git a/dol/src/dol/visitor/cell/CellSPEVisitor.java b/dol/src/dol/visitor/cell/CellSPEVisitor.java new file mode 100644 index 0000000..a8061ec --- /dev/null +++ b/dol/src/dol/visitor/cell/CellSPEVisitor.java @@ -0,0 +1,416 @@ +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.ArrayList; +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.visitor.PNVisitor; +import dol.util.CodePrintStream; + +/** + * This class is a class for a visitor that is used to generate the the OS for + * the SPEs. + * + * @author lschor, 2009-03-24 * Revision: 2009-03-24: Created + */ +public class CellSPEVisitor extends PNVisitor { + + /** + * Constructor. + * + * @param dir + * path of this file + */ + public CellSPEVisitor(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 where all SPU's are stored: + _spuDir = _dir + _delimiter + "spu"; + File dir = new File(_spuDir); + 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 + "spu_os.h")) + .renameTo(new File(dir.getPath() + _delimiter + + "spu_os.h")); + + ArrayList> spuList = _mapping.getSPUList(); + + int i = 0; + for (Vector spu : spuList) { + createOSLayer(x, spu, i++); + } + + createMakefileSPU(); + + } catch (Exception e) { + System.out.println("CellSPEVisitor: exception occured: " + + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * Create the makefile for a SPU (so for the layer). Each SPU gets its own + * Makefile + * + * @param spu + * SPU for which the Makefile should be used + */ + protected void createMakefileSPU() { + try { + // Directory of the process + String spuDir = _dir + _delimiter + "spu"; + + // Create the filename for the new wrapper + String filename = spuDir + _delimiter + "Makefile"; + + OutputStream file = new FileOutputStream(filename); + + PrintStream _makefilePS = new CodePrintStream(file); + + _makefilePS.println("# Makefile for SPU OS"); + _makefilePS.println(""); + _makefilePS.println("src := $(wildcard ../lib/spu/*.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.getAllSpuBaseProcess()) { + dependency += " .." + _delimiter + "spu_" + + p.getBasename() + _delimiter + p.getBasename() + + "Wrapper.o"; + } + + _makefilePS.println("all: ${obj}" + dependency); + for (int i = 0; i < _mapping.getNrSPE(); i++) { + _makefilePS.println("\tspu-g++ -Wall -I .. -I ../lib -o " + + "spu_os_" + i + " spu_os_" + i + ".cpp " + + "../lib/spu/Fifo.o ../lib/spu/WindowedFifo.o " + + "../lib/spu/dolSupport.o " + + "../lib/spu/proc_wrapper.o ../lib/spu/common.o " + + "../lib/spu/FastCommunication.o" + dependency + + " -ftree-vectorize -lm -mtune=cell -O3" + + " -fmodulo-sched -funroll-loops " + + " -ffast-math -fno-rtti -ffunction-sections" + + " -fdata-sections -Wl,--gc-sections"); + } + _makefilePS.println(); + _makefilePS.println("clean: "); + for (int i = 0; i < _mapping.getNrSPE(); i++) { + _makefilePS.println("\trm spu_os_" + i); + } + _makefilePS.println(); + _makefilePS.println("%.o : "); + _makefilePS.println("\tspu-g++ -c -o $(*D)/$(*F).o " + + "$(*D)/$(*F).cpp -I .. -I" + + " ../lib -ftree-vectorize -mtune=cell -O3" + + " -fmodulo-sched -funroll-loops -ffast-math" + + " -fno-rtti -ffunction-sections -fdata-sections"); + _makefilePS.println(); + } catch (FileNotFoundException e) { + System.out.println("CbeProcessVisitor - Makefile: 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 spu, + int index) { + try { + // Create the filename for the new layer + String filename = _spuDir + _delimiter + "spu_os_" + index + + ".cpp"; + + // PrintStream for writing to the file + OutputStream file = new FileOutputStream(filename); + CodePrintStream _code = new CodePrintStream(file); + + _code.println("/****************************************************************"); + _code.println(" * SPU OS file"); + _code.println(" * Description: OS for one SPU"); + _code.println(" */"); + _code.println(); + _code.println("#include \"spu_os.h\""); + + // Must include all possible wrappers + Vector pList = new Vector(); + // Go through all possible processes + for (Process p : spu) { + String basename = p.getBasename(); + if (!pList.contains(basename)) { + pList.add(basename); + _code.println("#include \".." + _delimiter + "spu_" + + p.getBasename() + _delimiter + + p.getBasename() + "Wrapper.h\""); + } + } + + _code.println(""); + _code.println("// Main application"); + _code.println("int main(int speid , uint64_t argp)"); + _code.println("{"); + _code.println(" // reserve DMA tag ID"); + _code.println(" uint32_t tag_id;"); + _code.println(" if((tag_id=mfc_tag_reserve())==MFC_TAG_INVALID){"); + _code.println(" printf(\"SPE: ERROR - can't reserve a tag ID\"); return 1;"); + _code.println(" }"); + _code.println(" "); + _code.println(" // Get the context information for the whole system"); + _code.println(" mfc_get((void*) &ctx_spu, argp, sizeof(ctx_spu), tag_id, 0, 0);"); + _code.println(" mfc_write_tag_mask(1< channelList = new Vector(); + int indx = 0; + // instantiate channels + for (Channel c : x.getChannelList()) { + if (spu.contains(c.getOrigin()) + || spu.contains(c.getTarget())) { + channelList.add(c); + if (c.getType().equals("fifo")) { + _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(); + + // Go through all processes + for (Process p : spu) { + // Create the process wrapper + _code.println(" " + p.getBasename() + "Wrapper *" + p.getName() +";"); + _code.println(" try { " + + p.getName() + " = new " + p.getBasename() + + "Wrapper (context_addr[" + spu.indexOf(p) + + "]); }"); + _code.println(" catch(std::bad_alloc &e) {"); + _code.println(" fprintf(stderr, \"[" + p.getBasename() +"Wrapper] Memory allocation failure\\n\");"); + _code.println(" exit(1);"); + _code.println(" }"); + + // Create the port-mapping + 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(); + } + + // Count the effected channels + int countChannels = 0; + for (Channel c : channelList) { + if (spu.contains(c.getOrigin()) + && spu.contains(c.getTarget())) { + continue; + } else if (spu.contains(c.getOrigin())) + countChannels++; + else if (spu.contains(c.getTarget())) + countChannels++; + else + System.out.println("ERROR! Channel Mapping is wrong."); + } + + _code.println(" // inited all queues, now one has to know:"); + _code.println(" // sends out the start addresses to the SPU (of all out channels)"); + + // Check all out queues on the SPU + _code.println(" uint32_t queuemessage;"); + for (Channel c : channelList) { + if (spu.contains(c.getOrigin()) && !spu.contains(c.getTarget())) { + _code.println(" queuemessage = CREATEQUEUEMESSAGE(" + x.getChannelList().indexOf(c) + ", (uint32_t)" + c.getName() + ".getQueuePointer());"); + _code.println(" spu_write_out_mbox(queuemessage);"); + } + } + + _code.println(" "); + _code.println(" // Wait until we get the okey to read the tail pointers"); + _code.println(" uint32_t messageIn = spu_read_in_mbox();"); + _code.println(""); + _code.println(" mfc_get((void*)tailAddresses, ctx_spu.fifoTails, sizeof(uint64_t) * roundDMA(NUM_FIFO), tag_id,0,0);"); + _code.println(" mfc_write_tag_mask(1<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++; + } + + // The scheduler (yes, this could be optimized...) + _code.println(""); + _code.println(" printf(\"SPU " + index + ": start to execute\\n\"); "); + _code.println(""); + _code.println(" bool allBlocked = false;"); + _code.println(" while (!allBlocked)"); + _code.println(" {"); + _code.println(" allBlocked = true;"); + for (Process p : spu) { + _code.println(" if (!" + p.getName() + + "->isDetached())"); + _code.println(" {"); + _code.println(" " + p.getName() + "->fire();"); + _code.println(" allBlocked = false;"); + _code.println(" }"); + + // communication only if this process needs some communication + for (Channel c : channelList) { + // the channel may go away + if (!spu.contains(c.getOrigin()) || !spu.contains(c.getTarget())) { + if (c.getOrigin().equals(p) || c.getTarget().equals(p)) { + _code.println(" com->update();"); + break; + } + } + } + _code.println(); + } + _code.println(" }"); + _code.println(); + + // End --> wait until all communications are finished + _code + .println(" // Are there any open communication requests?"); + _code.println(" while (!com->empty())"); + _code.println(" {"); + _code.println(" com->update();"); + _code.println(" }"); + + for (Process p : spu) { + _code.println(" delete " + p.getName() + ";"); + } + + _code.println(" delete com;"); + _code.println(" "); + _code.println(" // release tag ID before exiting"); + _code.println(" mfc_tag_release(tag_id);"); + _code.println(" "); + _code.println(" uint32_t message = CREATEFASTMESSAGE(SPE_COMPLETE, 0, 0);"); + _code.println(" spu_write_out_mbox(message);"); + _code.println(" "); + _code.println(" messageIn = spu_read_in_mbox();"); + _code.println("}"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + + protected String _spuDir = null; + protected CodePrintStream _mainPS = null; + protected String _dir = null; + protected CellMapping _mapping = null; +}