e67ac18ab66c4ef75dccdb9708ebe8c9f64f20ea
[jump.git] / dol / src / dol / visitor / protothread / ProtothreadProcessVisitor.java
1 /* $Id: ProtothreadProcessVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
2 package dol.visitor.protothread;
3
4 import java.io.BufferedReader;
5 import java.io.BufferedWriter;
6 import java.io.FileInputStream;
7 import java.io.FileOutputStream;
8 import java.io.FileWriter;
9 import java.io.IOException;
10 import java.io.InputStreamReader;
11 import java.io.OutputStream;
12 import java.util.StringTokenizer;
13 import java.util.Vector;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
16
17 import dol.datamodel.pn.Channel;
18 import dol.datamodel.pn.Port;
19 import dol.datamodel.pn.Process;
20 import dol.datamodel.pn.ProcessNetwork;
21 import dol.datamodel.pn.SourceCode;
22 import dol.util.CodePrintStream;
23 import dol.util.Sed;
24 import dol.visitor.PNVisitor;
25
26 /**
27  *
28  */
29 public class ProtothreadProcessVisitor extends PNVisitor {
30
31     /**
32      * Constructor.
33      */
34     public ProtothreadProcessVisitor(String dir) {
35         _dir = dir;
36     }
37
38     /**
39      *
40      */
41     public void visitComponent(ProcessNetwork x) {
42         try {
43             Vector<String> processList = new Vector<String>();
44             for (Process p : x.getProcessList()) {
45                 String basename = p.getBasename();
46                 if (!processList.contains(basename)) {
47                     processList.add(basename);
48                     p.accept(this);
49                 }
50             }
51         } catch (Exception e) {
52             System.out.println("Process Visitor: exception " +
53                                "occured: " + e.getMessage());
54             e.printStackTrace();
55         }
56     }
57
58     /**
59      *
60      */
61     public void visitComponent(Process p) {
62         try {
63             _createCppFile(p);
64             _createHeaderFile(p);
65             _adaptSources(p);
66         }
67         catch (Exception e) {
68             System.out.println("Process Visitor: exception "
69                     + "occured: " + e.getMessage());
70             e.printStackTrace();
71         }
72     }
73
74     /**
75      *
76      */
77     private void _createCppFile(Process p)
78         throws IOException {
79         String classname = p.getBasename() + "Wrapper";
80         String filename = _dir + _delimiter + classname + ".cpp";
81         OutputStream file = new FileOutputStream(filename);
82         CodePrintStream ps = new CodePrintStream(file);
83
84         ps.printPrefixln("#include \"" + classname + ".h\"");
85         ps.printPrefixln("#include \"dolSupport.h\"");
86         ps.printPrefixln("#include <string.h>");
87         ps.println();
88         for (SourceCode sr : p.getSrcList()) {
89             ps.printPrefixln("#include \"" + "../processes/"
90                     + sr.getLocality() + "\"");
91         }
92         ps.println();
93         ps.printPrefixln(classname + "::" + classname
94                 + "(char* name, int iteratorIndex[4]) :");
95         ps.printPrefixln("        ProcessWrapper(name, iteratorIndex)");
96         ps.printLeftBracket();
97         //ps.printPrefixln("_state = new struct _local_states;");
98         //ps.printPrefixln("memcpy(_state, " + p.getBasename() + ".local, "
99         //        + "sizeof(struct _local_states));");
100         //ps.printPrefixln("memcpy(&_process, &" + p.getBasename()
101         //        + ", sizeof(DOLProcess));");
102         ps.printPrefixln("_state = (LocalState)new "
103                 + p.getBasename().substring(0, 1).toUpperCase()
104                 + p.getBasename().substring(1) + "_State;");
105         ps.printPrefixln("_process.init = " + p.getBasename() + "_init;");
106         ps.printPrefixln("_process.fire = " + p.getBasename() + "_fire;");
107         ps.printPrefixln("_process.local = _state;");
108         ps.printPrefixln("_process.wptr = (void*)&_wrapper_data;");
109         ps.printPrefixln("_wrapper_data.wrapper = this;");
110         ps.printRightBracket();
111         ps.println();
112         ps.printPrefixln(classname + "::~" + classname + "()");
113         ps.printLeftBracket();
114         ps.printPrefixln("if (_state)");
115         ps.printPrefixln("    delete ("
116                 + p.getBasename().substring(0, 1).toUpperCase()
117                 + p.getBasename().substring(1) + "_State*)_state;");
118         //ps.printPrefixln("    delete _state;");
119         ps.printRightBracket();
120     }
121
122     /**
123      *
124      */
125     private void _createHeaderFile(Process p)
126         throws IOException {
127         String classname = p.getBasename() + "Wrapper";
128         String filename = _dir + _delimiter + classname + ".h";
129         OutputStream file = new FileOutputStream(filename);
130         CodePrintStream ps = new CodePrintStream(file);
131
132         ps.printPrefixln("#ifndef " + classname.toUpperCase()
133                 + "_H");
134         ps.printPrefixln("#define " + classname.toUpperCase()
135                 + "_H");
136         ps.println();
137         ps.printPrefixln("#include \"ProcessWrapper.h\"");
138         ps.printPrefixln("#include \"Fifo.h\"");
139         ps.printPrefixln("#include \"WindowedFifo.h\"");
140         ps.println();
141         ps.printPrefixln("class " + classname + ";");
142         ps.println();
143         ps.printPrefixln("typedef struct _" + p.getBasename()
144                 + "_data {");
145         ps.printPrefixln("    int lc;");
146         ps.printPrefixln("    " + classname + " *wrapper;");
147         ps.printPrefixln("} " + p.getBasename() + "_data;");
148         ps.println();
149         ps.printPrefixln("class " + classname +
150                 " : public ProcessWrapper");
151         ps.printLeftBracket();
152         ps.printPrefixln("public:");
153         ps.printPrefixln("    " + classname + "(char* name, "
154                 + "int iteratorIndex[4]);");
155         ps.printPrefixln("    virtual ~" + classname + "();");
156         ps.println();
157
158         Vector<String> basenames = new Vector<String>();
159         for (Port port : p.getPortList()) {
160             if (!basenames.contains(port.getBasename())) {
161                 basenames.add(port.getBasename());
162             } else {
163                 continue;
164             }
165
166             Channel c = (Channel)port.getPeerResource();
167             if (port.getName().equals(port.getBasename())) {
168                 if (c.getType().equals("fifo")) {
169                     ps.printPrefixln("    Fifo* _port" + port.getName()
170                             + "Fifo;");
171                 } else if (c.getType().equals("wfifo")) {
172                     ps.printPrefixln("    WindowedFifo* _port"
173                             + port.getName() + "Fifo;");
174                 }
175             } else {
176                 if (c.getType().equals("fifo")) {
177                     ps.printPrefix("    Fifo* _port"
178                             + port.getBasename()
179                             + "Fifo");
180                 } else if (c.getType().equals("wfifo")) {
181                     ps.printPrefix("    WindowedFifo* _port"
182                             + port.getBasename()
183                             + "Fifo");
184                 }
185                 StringTokenizer tokenizer =
186                     new StringTokenizer(port.getRange(), ";");
187                 while (tokenizer.hasMoreTokens()) {
188                     ps.print("[" + tokenizer.nextToken()
189                             + "]");
190                 }
191                 ps.println(";");
192             }
193         }
194         ps.println("");
195         ps.printPrefixln("protected:");
196         ps.printPrefixln("    struct _local_states *_state;");
197         ps.printPrefixln("    " + p.getBasename()
198                 + "_data _wrapper_data;");
199         ps.printRightBracket();
200
201         ps.printPrefixln(";");
202         ps.println();
203         ps.printPrefixln("#endif");
204     }
205
206     /**
207      * Make modifications to source files of a process.
208      * Port names need to be strings for the SystemC code generation.
209      * Therefore, in the header files integer port names are put into
210      * quotation marks.
211      *
212      * @param p process whose sources should be adapted
213      * @throws IOException
214      */
215     protected void _adaptSources(Process p) throws IOException {
216         Sed sed = new Sed();
217         //modify header file
218         for (Port port : p.getPortList()) {
219             String processHeaderFile;
220
221             for (SourceCode sr : p.getSrcList()) {
222                 processHeaderFile = _dir + _delimiter + ".."
223                         + _delimiter + "processes" + _delimiter
224                         + sr.getLocality().
225                         replaceAll("(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
226
227                 sed.sed(processHeaderFile,
228                         "(#define[ ]+PORT_\\w*[ ]+)\"?"
229                         + port.getBasename() + "\"?",
230                         "$1 " + "static_cast<" + p.getBasename()
231                         + "Wrapper *>((static_cast<" + p.getBasename()
232                         + "_data *>(p->wptr))->wrapper)->_port"
233                         + port.getBasename() + "Fifo");
234             }
235         }
236
237         //modify source file
238         for (SourceCode sr : p.getSrcList()) {
239             String processSourceFile = _dir + _delimiter + ".."
240                     + _delimiter + "processes" + _delimiter
241                     + sr.getLocality();
242
243             String line;
244             StringBuffer buffer = new StringBuffer();
245             FileInputStream fileInputStream = new FileInputStream(
246                     processSourceFile);
247             BufferedReader reader = new BufferedReader(
248                     new InputStreamReader(fileInputStream));
249             while((line = reader.readLine()) != null) {
250                 buffer.append(line + "\n");
251             }
252             reader.close();
253
254             String file = buffer.toString();
255             //insert PT_BEGIN() at beginning of fire() function
256             file = file.replaceAll(
257                     "(int[ ]*" + p.getBasename()
258                     + "_fire[ ]*\\([ ]*DOLProcess[ ]*\\*p[ ]*\\)"
259                     + "[\\s\\S&&[^\\{]]*)\\{",
260                     "$1" + System.getProperty("line.separator") + "{"
261                     + System.getProperty("line.separator") +
262                     "    PT_BEGIN((pt*)(p->wptr));");
263
264             //replace last return statement in fire function by PT_END()
265             //find beginning of fire function
266             Matcher matcher = Pattern.compile(
267                     "(int[ ]*" + p.getBasename()
268                     + "_fire[ ]*\\([ ]*DOLProcess[ ]*\\*p[ ]*\\)"
269                     + "[\\s\\S&&[^\\{]]*)\\{").matcher(file);
270             matcher.find();
271             int i = 0;
272             try {
273                 i = matcher.start();
274             } catch (Exception e) {
275                 System.out.println("Error: could not find "
276                         + p.getBasename() + "_fire() function in "
277                         + processSourceFile + ".");
278                 e.printStackTrace();
279             }
280             int openBraces = 0; //counter for open curly braces
281             //position of last return statement
282             int lastReturnStartPosition = 0;
283             int lastReturnEndPosition = 0;
284             while (i < file.length()) {
285                 //ignore single-line comments
286                 if (i < (file.length() - 1) &&
287                         file.substring(i, i + 2).equals("//")) {
288                     while (!file.substring(i, i + 1).equals("\n")) {
289                         i++;
290                     }
291                 }
292                 //ignore multi-line comments
293                 else if (i < (file.length() - 1) &&
294                         file.substring(i, i + 2).equals("/*")) {
295                     while (!file.substring(i, i + 2).equals("*/")) {
296                         i++;
297                     }
298                 }
299                 //ignore strings
300                 else if (file.substring(i, i + 1).equals("\"")) {
301                     matcher = Pattern.compile("[\\s\\S&&[^\\\\]]\\\"").
302                             matcher(file);
303                     matcher.find(i + 1);
304                     i = matcher.start() + 1;
305                 }
306                 else if (i < (file.length() - 5) &&
307                         file.substring(i, i + 6).equals("return")) {
308                     lastReturnStartPosition = i;
309                     while (!file.substring(i, i + 1).equals(";")) {
310                         i++;
311                     }
312                     lastReturnEndPosition = i;
313                 } else if (file.substring(i, i + 1).equals("{")) {
314                     openBraces++;
315                 } else if (file.substring(i, i + 1).equals("}")) {
316                     openBraces--;
317                     if (openBraces == 0) {
318                         break;
319                     }
320                 }
321                 i++;
322             }
323
324             file = file.substring(0, lastReturnStartPosition) + "/* "
325                 + file.substring(lastReturnStartPosition,
326                         lastReturnEndPosition + 1)
327                 + " (commented out by DOL) */"
328                 + System.getProperty("line.separator")
329                 + "    PT_END((pt*)(p->wptr));"
330                 + System.getProperty("line.separator")
331                 + file.substring(lastReturnEndPosition + 2,
332                         file.length());
333
334             BufferedWriter out = new BufferedWriter(new
335                     FileWriter(processSourceFile));
336             out.write(file);
337             out.close();
338         }
339     }
340
341     protected String _dir = null;
342     CodePrintStream _wrapperHeader;
343 }