dol: initial dol commit
[jump.git] / dol / src / dol / visitor / protothread / ProtothreadProcessVisitor.java
diff --git a/dol/src/dol/visitor/protothread/ProtothreadProcessVisitor.java b/dol/src/dol/visitor/protothread/ProtothreadProcessVisitor.java
new file mode 100644 (file)
index 0000000..e67ac18
--- /dev/null
@@ -0,0 +1,343 @@
+/* $Id: ProtothreadProcessVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.protothread;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+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.util.CodePrintStream;
+import dol.util.Sed;
+import dol.visitor.PNVisitor;
+
+/**
+ *
+ */
+public class ProtothreadProcessVisitor extends PNVisitor {
+
+    /**
+     * Constructor.
+     */
+    public ProtothreadProcessVisitor(String dir) {
+        _dir = dir;
+    }
+
+    /**
+     *
+     */
+    public void visitComponent(ProcessNetwork x) {
+        try {
+            Vector<String> processList = new Vector<String>();
+            for (Process p : x.getProcessList()) {
+                String basename = p.getBasename();
+                if (!processList.contains(basename)) {
+                    processList.add(basename);
+                    p.accept(this);
+                }
+            }
+        } catch (Exception e) {
+            System.out.println("Process Visitor: exception " +
+                               "occured: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *
+     */
+    public void visitComponent(Process p) {
+        try {
+            _createCppFile(p);
+            _createHeaderFile(p);
+            _adaptSources(p);
+        }
+        catch (Exception e) {
+            System.out.println("Process Visitor: exception "
+                    + "occured: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *
+     */
+    private void _createCppFile(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 \"" + "../processes/"
+                    + sr.getLocality() + "\"");
+        }
+        ps.println();
+        ps.printPrefixln(classname + "::" + classname
+                + "(char* name, int iteratorIndex[4]) :");
+        ps.printPrefixln("        ProcessWrapper(name, iteratorIndex)");
+        ps.printLeftBracket();
+        //ps.printPrefixln("_state = new struct _local_states;");
+        //ps.printPrefixln("memcpy(_state, " + p.getBasename() + ".local, "
+        //        + "sizeof(struct _local_states));");
+        //ps.printPrefixln("memcpy(&_process, &" + p.getBasename()
+        //        + ", sizeof(DOLProcess));");
+        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 _createHeaderFile(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");
+    }
+
+    /**
+     * 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
+     */
+    protected void _adaptSources(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 + ".."
+                        + _delimiter + "processes" + _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 + ".."
+                    + _delimiter + "processes" + _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 String _dir = null;
+    CodePrintStream _wrapperHeader;
+}