X-Git-Url: http://sraa.de/git/?a=blobdiff_plain;f=dol%2Fsrc%2Fdol%2Fvisitor%2Fcell%2FCellProcessVisitor.java;fp=dol%2Fsrc%2Fdol%2Fvisitor%2Fcell%2FCellProcessVisitor.java;h=a0c70e468a50931fd76d29b3b4e9d44cc1502d4c;hb=8c411cf24ed0eb889191aaeafd8fa1e69081df42;hp=0000000000000000000000000000000000000000;hpb=dea7a4fb1ed110d3ce6e6d9255103d724bd66c0e;p=jump.git diff --git a/dol/src/dol/visitor/cell/CellProcessVisitor.java b/dol/src/dol/visitor/cell/CellProcessVisitor.java new file mode 100644 index 0000000..a0c70e4 --- /dev/null +++ b/dol/src/dol/visitor/cell/CellProcessVisitor.java @@ -0,0 +1,652 @@ +package dol.visitor.cell; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.HashMap; +import java.util.StringTokenizer; +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import dol.datamodel.pn.Channel; +import dol.datamodel.pn.Port; +import dol.datamodel.pn.Process; +import dol.datamodel.pn.ProcessNetwork; +import dol.datamodel.pn.SourceCode; +import dol.visitor.PNVisitor; +import dol.util.CodePrintStream; +import dol.util.Copier; +import dol.util.Sed; + +/** + * This class is a class for a visitor that is used to generate the main + * makefile for the application. + * + * @author lschor, 2008-10-30 + * + * Remarks: Based on a original file from wolferl for rtems + * + * Revision: 2008-10-30: Updated the file for the CBE 2008-11-08: Add + * double buffering 2009-03-17: Add protothreads + */ +public class CellProcessVisitor extends PNVisitor { + + /** + * Constructor. + * + * @param dir + * target directory + */ + public CellProcessVisitor(String dir, HashMap portMap, + CellMapping mapping) { + _dir = dir; + _portMap = portMap; + _mapping = mapping; + } + + /** + * + * @param x + * process network that needs to be processed + */ + public void visitComponent(ProcessNetwork x) { + try { + // Create the Process staff for all processes on the SPU + for (Process p : _mapping.getAllSpuBaseProcess()) { + createSPEWrapper(p); + createMakefileProcess(p); + _adaptSources("spu_" + p.getBasename(), p); + } + + // Create the Process staff for all processes on the SPU + for (Process p : _mapping.getAllPPUBaseProcess()) { + createPPEWrapper(p); + } + } catch (Exception e) { + System.out.println("CellProcessVisitor: exception " + + "occured: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * Creates a Wrapper for an SPE process + * + * @param p + * process that needs to be processed + */ + protected void createSPEWrapper(Process p) { + try { + + // Create of each process an own folder + // Insert into this folder the source, the wrapper and a makefile + String processDir = _dir + _delimiter + "spu_" + + p.getBasename(); + File dir = new File(processDir); + dir.mkdirs(); + + /***************** class File ******************************/ + + // Create the filename for the new wrapper + String filename = processDir + _delimiter + p.getBasename() + + "Wrapper.cpp"; + File process_file = new File(filename); + File pattern_file = new File(_dir + _delimiter + _tempDirName + + _delimiter + "spu_process_wrapper_template.cpp"); + new Copier().copyFile(pattern_file, process_file); + + String includes = ""; + for (SourceCode code : p.getSrcList()) { + includes += "#include \"" + code.getLocality() + "\"" + + System.getProperty("line.separator"); + } + + Sed sed = new Sed(); + // Replace the include of the main c-file + sed.sed(filename, "//#include \"@PROCESSNAME@.c\"", includes); + // Replace the process-name in the whole file + sed.sed(filename, "@PROCESSNAME@", p.getBasename()); + sed.sed(filename, "@PROCESSNAME_UPPER@", p.getBasename() + .substring(0, 1).toUpperCase() + + p.getBasename().substring(1)); + + /***************** header File ******************************/ + // Create the filename for the new wrapper + filename = processDir + _delimiter + p.getBasename() + + "Wrapper.h"; + process_file = new File(filename); + pattern_file = new File(_dir + _delimiter + _tempDirName + + _delimiter + "spu_process_wrapper_template.h"); + new Copier().copyFile(pattern_file, process_file); + + includes = ""; + for (SourceCode code : p.getSrcList()) { + includes += "#include \"" + code.getLocality() + "\"" + + System.getProperty("line.separator"); + } + + sed = new Sed(); + // Replace the include of the main c-file + sed.sed(filename, "//#include \"@PROCESSNAME@.c\"", includes); + // Replace the process-name in the whole file + sed.sed(filename, "@PROCESSNAME@", p.getBasename()); + + // Create the correct Port and Fifo List + String fifolist = ""; + Vector basenames = new Vector(); + for (Port port : p.getPortList()) { + if (!basenames.contains(port.getBasename())) { + basenames.add(port.getBasename()); + } else { + continue; + } + + Channel c = (Channel) port.getPeerResource(); + if (port.getName().equals(port.getBasename())) { + if (c.getType().equals("fifo")) { + fifolist += "Fifo* _port" + port.getName() + + "Fifo;"; + } else if (c.getType().equals("wfifo")) { + fifolist += "WindowedFifo* _port" + port.getName() + + "Fifo;"; + } + } else { + if (c.getType().equals("fifo")) { + fifolist += "Fifo* _port" + port.getBasename() + + "Fifo"; + } else if (c.getType().equals("wfifo")) { + fifolist += "WindowedFifo* _port" + + port.getBasename() + "Fifo"; + } + StringTokenizer tokenizer = new StringTokenizer(port + .getRange(), ";"); + while (tokenizer.hasMoreTokens()) { + fifolist += "[" + tokenizer.nextToken() + "]"; + } + fifolist += ";"; + } + } + + // Set the correct Fifo's + sed.sed(filename, "@FIFO@", fifolist); + + /***************** source File ******************************/ + + // Go through all source files + for (SourceCode sourceCode : p.getSrcList()) { + // Copy the files to the new folder + String oldFilename = _dir + + _delimiter + + sourceCode.getLocality().replaceAll( + "(.*)\\.[cC][pP]*[pP]*", "$1\\.h"); + filename = processDir + + _delimiter + + sourceCode.getLocality().replaceAll( + "(.*)\\.[cC][pP]*[pP]*", "$1\\.h"); + + if (new File(filename).exists()) { + new File(filename).delete(); + } + + new File(oldFilename).renameTo(new File(filename)); + + // Copy also the c-files + if ((oldFilename.substring(oldFilename.length() - 2)) + .equals(".h")) { + String newFileNameC = filename.substring(0, filename + .length() - 2) + + ".c"; + if (new File(newFileNameC).exists()) { + new File(newFileNameC).delete(); + } + // new Copier().copyFile(new File(oldFilename.substring(0, + // oldFilename.length() - 2) + ".c"), new + // File(filename.substring(0, filename.length() - 2) + + // ".c")); + new File(oldFilename.substring(0, + oldFilename.length() - 2) + + ".c").renameTo(new File(newFileNameC)); + } + + // Update the files for the DOL project + sed.sed(filename, "", "\"dol.h\""); + + } + } catch (Exception e) { + System.out.println("CbeProcessVisitor: exception " + + "occured: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * Creates a Wrapper for a PPE process + * + * @param p + * process that needs to be processed + */ + protected void createPPEWrapper(Process p) { + try { + // Create of each process an own folder + // Insert into this folder the source, the wrapper and a makefile + String processDir = _dir + _delimiter + "ppu_" + + p.getBasename(); + File dir = new File(processDir); + dir.mkdirs(); + + // Go through all source files + for (SourceCode sourceCode : p.getSrcList()) { + // Copy the files to the new folder + String oldFilename = _dir + + _delimiter + + sourceCode.getLocality().replaceAll( + "(.*)\\.[cC][pP]*[pP]*", "$1\\.h"); + String filename = processDir + + _delimiter + + sourceCode.getLocality().replaceAll( + "(.*)\\.[cC][pP]*[pP]*", "$1\\.h"); + + if (new File(filename).exists()) { + new File(filename).delete(); + } + + new File(oldFilename).renameTo(new File(filename)); + + // Copy also the c-files + if ((oldFilename.substring(oldFilename.length() - 2)) + .equals(".h")) { + String newFileNameC = filename.substring(0, filename + .length() - 2) + + ".c"; + if (new File(newFileNameC).exists()) { + new File(newFileNameC).delete(); + } + new File(oldFilename.substring(0, + oldFilename.length() - 2) + + ".c").renameTo(new File(newFileNameC)); + } + } + + _createPPECppFile(dir, p); + _createPPEHeaderFile(dir, p); + _adaptSources("ppu_" + p.getBasename(), p); + createMakeFilePPUProcess("ppu_" + p.getBasename(), p); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * + */ + private void _createPPECppFile(File dir, Process p) throws IOException { + String classname = p.getBasename() + "Wrapper"; + String filename = dir + _delimiter + classname + ".cpp"; + OutputStream file = new FileOutputStream(filename); + CodePrintStream ps = new CodePrintStream(file); + + ps.printPrefixln("#include \"" + classname + ".h\""); + ps.printPrefixln("#include \"dolSupport.h\""); + ps.printPrefixln("#include "); + ps.println(); + for (SourceCode sr : p.getSrcList()) { + ps.printPrefixln("#include \"" + sr.getLocality() + "\""); + } + ps.println(); + ps.printPrefixln(classname + "::" + classname + + "(char* name, int iteratorIndex[4]) :"); + ps.printPrefixln(" ProcessWrapper(name, iteratorIndex)"); + ps.printLeftBracket(); + ps.printPrefixln("_state = (LocalState)new " + + p.getBasename().substring(0, 1).toUpperCase() + + p.getBasename().substring(1) + "_State;"); + ps.printPrefixln("_process.init = " + p.getBasename() + "_init;"); + ps.printPrefixln("_process.fire = " + p.getBasename() + "_fire;"); + ps.printPrefixln("_process.local = _state;"); + ps.printPrefixln("_process.wptr = (void*)&_wrapper_data;"); + ps.printPrefixln("_wrapper_data.wrapper = this;"); + ps.printRightBracket(); + ps.println(); + ps.printPrefixln(classname + "::~" + classname + "()"); + ps.printLeftBracket(); + ps.printPrefixln("if (_state)"); + ps.printPrefixln(" delete (" + + p.getBasename().substring(0, 1).toUpperCase() + + p.getBasename().substring(1) + "_State*)_state;"); + // ps.printPrefixln(" delete _state;"); + ps.printRightBracket(); + } + + /** + * + */ + private void _createPPEHeaderFile(File dir, Process p) + throws IOException { + String classname = p.getBasename() + "Wrapper"; + String filename = dir + _delimiter + classname + ".h"; + OutputStream file = new FileOutputStream(filename); + CodePrintStream ps = new CodePrintStream(file); + + ps.printPrefixln("#ifndef " + classname.toUpperCase() + "_H"); + ps.printPrefixln("#define " + classname.toUpperCase() + "_H"); + ps.println(); + ps.printPrefixln("#include \"ProcessWrapper.h\""); + ps.printPrefixln("#include \"Fifo.h\""); + ps.printPrefixln("#include \"WindowedFifo.h\""); + ps.println(); + ps.printPrefixln("class " + classname + ";"); + ps.println(); + ps.printPrefixln("typedef struct _" + p.getBasename() + "_data {"); + ps.printPrefixln(" int lc;"); + ps.printPrefixln(" " + classname + " *wrapper;"); + ps.printPrefixln("} " + p.getBasename() + "_data;"); + ps.println(); + ps + .printPrefixln("class " + classname + + " : public ProcessWrapper"); + ps.printLeftBracket(); + ps.printPrefixln("public:"); + ps.printPrefixln(" " + classname + "(char* name, " + + "int iteratorIndex[4]);"); + ps.printPrefixln(" virtual ~" + classname + "();"); + ps.println(); + + Vector basenames = new Vector(); + for (Port port : p.getPortList()) { + if (!basenames.contains(port.getBasename())) { + basenames.add(port.getBasename()); + } else { + continue; + } + + Channel c = (Channel) port.getPeerResource(); + if (port.getName().equals(port.getBasename())) { + if (c.getType().equals("fifo")) { + ps.printPrefixln(" Fifo* _port" + port.getName() + + "Fifo;"); + } else if (c.getType().equals("wfifo")) { + ps.printPrefixln(" WindowedFifo* _port" + + port.getName() + "Fifo;"); + } + } else { + if (c.getType().equals("fifo")) { + ps.printPrefix(" Fifo* _port" + port.getBasename() + + "Fifo"); + } else if (c.getType().equals("wfifo")) { + ps.printPrefix(" WindowedFifo* _port" + + port.getBasename() + "Fifo"); + } + StringTokenizer tokenizer = new StringTokenizer(port + .getRange(), ";"); + while (tokenizer.hasMoreTokens()) { + ps.print("[" + tokenizer.nextToken() + "]"); + } + ps.println(";"); + } + } + ps.println(""); + ps.printPrefixln("protected:"); + ps.printPrefixln(" struct _local_states *_state;"); + ps + .printPrefixln(" " + p.getBasename() + + "_data _wrapper_data;"); + ps.printRightBracket(); + + ps.printPrefixln(";"); + ps.println(); + ps.printPrefixln("#endif"); + } + + /** + * Create the makefile for a special process --> Each subprocess gets its + * own makefile + * + * @param p + * process for which the makefile should be created + */ + protected void createMakefileProcess(Process p) { + try { + // Directory of the process + String processDir = _dir + _delimiter + "spu_" + + p.getBasename(); + + // Create the filename for the new wrapper + String filename = processDir + _delimiter + "Makefile"; + // File makefile = new File(filename); + + OutputStream file; + + file = new FileOutputStream(filename); + + PrintStream _makefilePS = new CodePrintStream(file); + + _makefilePS.println("# Makefile for process " + + p.getBasename()); + _makefilePS.println(""); + + String dependency = "all: " + p.getBasename() + "Wrapper.cpp"; + + for (SourceCode code : p.getSrcList()) { + dependency += " " + code.getLocality(); + } + + _makefilePS.println(dependency); + _makefilePS + .println("\tspu-g++ -c -I .. -I ../lib -o " + + p.getBasename() + + "Wrapper.o " + + p.getBasename() + + "Wrapper.cpp -ftree-vectorize -mtune=cell -O3 -fmodulo-sched -funroll-loops -ffast-math -fno-rtti -ffunction-sections -fdata-sections" ); + _makefilePS.println("clean: "); + _makefilePS.println("\trm " + p.getBasename() + "Wrapper.o"); + _makefilePS.println(); + + } catch (FileNotFoundException e) { + System.out.println("CbeProcessVisitor - Makefile: exception " + + "occured: " + e.getMessage()); + e.printStackTrace(); + } + } + + private void createMakeFilePPUProcess(String subdir, Process p) { + try { + // Directory of the process + String processDir = _dir + _delimiter + subdir; + + // Create the filename for the new wrapper + String filename = processDir + _delimiter + "Makefile"; + // File makefile = new File(filename); + + OutputStream file; + + file = new FileOutputStream(filename); + + PrintStream _makefilePS = new CodePrintStream(file); + + _makefilePS.println("# Makefile for process " + + p.getBasename()); + _makefilePS.println(""); + + String dependency = "all: " + p.getBasename() + "Wrapper.cpp"; + + for (SourceCode code : p.getSrcList()) { + dependency += " " + code.getLocality(); + } + _makefilePS.println("# General definitions:"); + _makefilePS.println("CC = ppu-g++"); + _makefilePS + .println("CCFLAGS = -ftree-vectorize -O3 -maltivec -funroll-loops -mabi=altivec -mcpu=cell"); + _makefilePS.println("COMPILE = $(CC) $(CCFLAGS) -c"); + + _makefilePS.println(dependency); + _makefilePS + .println("\t$(COMPILE) -o " + + p.getBasename() + + "Wrapper.o " + + p.getBasename() + + "Wrapper.cpp -I .. -I ../lib -I ../lib/ppu -I ../lib/pt;"); + _makefilePS.println("clean: "); + _makefilePS.println("\trm " + p.getBasename() + "Wrapper.o"); + _makefilePS.println(); + + } catch (FileNotFoundException e) { + System.out + .println("CbeProcessVisitor - Makefile PPU: exception " + + "occured: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * Make modifications to source files of a process. Port names need to be + * strings for the SystemC code generation. Therefore, in the header files + * integer port names are put into quotation marks. + * + * @param p + * process whose sources should be adapted + * @throws IOException + * @author haidw + */ + protected void _adaptSources(String subdir, Process p) + throws IOException { + Sed sed = new Sed(); + // modify header file + for (Port port : p.getPortList()) { + String processHeaderFile; + + for (SourceCode sr : p.getSrcList()) { + processHeaderFile = _dir + + _delimiter + + subdir + + _delimiter + + sr.getLocality().replaceAll( + "(.*)\\.[cC][pP]*[pP]*", "$1\\.h"); + + sed.sed(processHeaderFile, "(#define[ ]*PORT_\\w*[ ]*)\"?" + + port.getBasename() + "\"?", "$1 " + + "static_cast<" + p.getBasename() + + "Wrapper *>((static_cast<" + p.getBasename() + + "_data *>(p->wptr))->wrapper)->_port" + + port.getBasename() + "Fifo"); + } + } + + // modify source file + for (SourceCode sr : p.getSrcList()) { + String processSourceFile = _dir + _delimiter + subdir + + _delimiter + sr.getLocality(); + + String line; + StringBuffer buffer = new StringBuffer(); + FileInputStream fileInputStream = new FileInputStream( + processSourceFile); + BufferedReader reader = new BufferedReader( + new InputStreamReader(fileInputStream)); + while ((line = reader.readLine()) != null) { + buffer.append(line + "\n"); + } + reader.close(); + + String file = buffer.toString(); + // insert PT_BEGIN() at beginning of fire() function + file = file.replaceAll("(int[ ]*" + p.getBasename() + + "_fire[ ]*\\([ ]*DOLProcess[ ]*\\*p[ ]*\\)" + + "[\\s\\S&&[^\\{]]*)\\{", "$1" + + System.getProperty("line.separator") + "{" + + System.getProperty("line.separator") + + " PT_BEGIN((pt*)(p->wptr));"); + + // replace last return statement in fire function by PT_END() + // find beginning of fire function + Matcher matcher = Pattern.compile( + "(int[ ]*" + p.getBasename() + + "_fire[ ]*\\([ ]*DOLProcess[ ]*\\*p[ ]*\\)" + + "[\\s\\S&&[^\\{]]*)\\{").matcher(file); + matcher.find(); + int i = 0; + try { + i = matcher.start(); + } catch (Exception e) { + System.out.println("Error: could not find " + + p.getBasename() + "_fire() function in " + + processSourceFile + "."); + e.printStackTrace(); + } + int openBraces = 0; // counter for open curly braces + // position of last return statement + int lastReturnStartPosition = 0; + int lastReturnEndPosition = 0; + while (i < file.length()) { + // ignore single-line comments + if (i < (file.length() - 1) + && file.substring(i, i + 2).equals("//")) { + while (!file.substring(i, i + 1).equals("\n")) { + i++; + } + } + // ignore multi-line comments + else if (i < (file.length() - 1) + && file.substring(i, i + 2).equals("/*")) { + while (!file.substring(i, i + 2).equals("*/")) { + i++; + } + } + // ignore strings + else if (file.substring(i, i + 1).equals("\"")) { + matcher = Pattern.compile("[\\s\\S&&[^\\\\]]\\\"") + .matcher(file); + matcher.find(i + 1); + i = matcher.start() + 1; + } else if (i < (file.length() - 5) + && file.substring(i, i + 6).equals("return")) { + lastReturnStartPosition = i; + while (!file.substring(i, i + 1).equals(";")) { + i++; + } + lastReturnEndPosition = i; + } else if (file.substring(i, i + 1).equals("{")) { + openBraces++; + } else if (file.substring(i, i + 1).equals("}")) { + openBraces--; + if (openBraces == 0) { + break; + } + } + i++; + } + + file = file.substring(0, lastReturnStartPosition) + + "/* " + + file.substring(lastReturnStartPosition, + lastReturnEndPosition + 1) + + " (commented out by DOL) */" + + System.getProperty("line.separator") + + " PT_END((pt*)(p->wptr));" + + System.getProperty("line.separator") + + file.substring(lastReturnEndPosition + 2, file + .length()); + + BufferedWriter out = new BufferedWriter(new FileWriter( + processSourceFile)); + out.write(file); + out.close(); + } + } + + protected CellMapping _mapping; + protected String _dir = null; + protected HashMap _portMap; + + protected static String _libDirName = "lib"; + protected static String _tempDirName = "template"; + +}