+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<Port, Integer> 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<String> basenames = new Vector<String>();
+ 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>", "\"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 <string.h>");
+ 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<String> basenames = new Vector<String>();
+ 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<Port, Integer> _portMap;
+
+ protected static String _libDirName = "lib";
+ protected static String _tempDirName = "template";
+
+}