1 package dol.visitor.cell;
3 import java.io.BufferedReader;
4 import java.io.BufferedWriter;
6 import java.io.FileInputStream;
7 import java.io.FileNotFoundException;
8 import java.io.FileOutputStream;
9 import java.io.FileWriter;
10 import java.io.IOException;
11 import java.io.InputStreamReader;
12 import java.io.OutputStream;
13 import java.io.PrintStream;
14 import java.util.HashMap;
15 import java.util.StringTokenizer;
16 import java.util.Vector;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
20 import dol.datamodel.pn.Channel;
21 import dol.datamodel.pn.Port;
22 import dol.datamodel.pn.Process;
23 import dol.datamodel.pn.ProcessNetwork;
24 import dol.datamodel.pn.SourceCode;
25 import dol.visitor.PNVisitor;
26 import dol.util.CodePrintStream;
27 import dol.util.Copier;
31 * This class is a class for a visitor that is used to generate the main
32 * makefile for the application.
34 * @author lschor, 2008-10-30
36 * Remarks: Based on a original file from wolferl for rtems
38 * Revision: 2008-10-30: Updated the file for the CBE 2008-11-08: Add
39 * double buffering 2009-03-17: Add protothreads
41 public class CellProcessVisitor extends PNVisitor {
49 public CellProcessVisitor(String dir, HashMap<Port, Integer> portMap,
50 CellMapping mapping) {
59 * process network that needs to be processed
61 public void visitComponent(ProcessNetwork x) {
63 // Create the Process staff for all processes on the SPU
64 for (Process p : _mapping.getAllSpuBaseProcess()) {
66 createMakefileProcess(p);
67 _adaptSources("spu_" + p.getBasename(), p);
70 // Create the Process staff for all processes on the SPU
71 for (Process p : _mapping.getAllPPUBaseProcess()) {
74 } catch (Exception e) {
75 System.out.println("CellProcessVisitor: exception "
76 + "occured: " + e.getMessage());
82 * Creates a Wrapper for an SPE process
85 * process that needs to be processed
87 protected void createSPEWrapper(Process p) {
90 // Create of each process an own folder
91 // Insert into this folder the source, the wrapper and a makefile
92 String processDir = _dir + _delimiter + "spu_"
94 File dir = new File(processDir);
97 /***************** class File ******************************/
99 // Create the filename for the new wrapper
100 String filename = processDir + _delimiter + p.getBasename()
102 File process_file = new File(filename);
103 File pattern_file = new File(_dir + _delimiter + _tempDirName
104 + _delimiter + "spu_process_wrapper_template.cpp");
105 new Copier().copyFile(pattern_file, process_file);
107 String includes = "";
108 for (SourceCode code : p.getSrcList()) {
109 includes += "#include \"" + code.getLocality() + "\""
110 + System.getProperty("line.separator");
114 // Replace the include of the main c-file
115 sed.sed(filename, "//#include \"@PROCESSNAME@.c\"", includes);
116 // Replace the process-name in the whole file
117 sed.sed(filename, "@PROCESSNAME@", p.getBasename());
118 sed.sed(filename, "@PROCESSNAME_UPPER@", p.getBasename()
119 .substring(0, 1).toUpperCase()
120 + p.getBasename().substring(1));
122 /***************** header File ******************************/
123 // Create the filename for the new wrapper
124 filename = processDir + _delimiter + p.getBasename()
126 process_file = new File(filename);
127 pattern_file = new File(_dir + _delimiter + _tempDirName
128 + _delimiter + "spu_process_wrapper_template.h");
129 new Copier().copyFile(pattern_file, process_file);
132 for (SourceCode code : p.getSrcList()) {
133 includes += "#include \"" + code.getLocality() + "\""
134 + System.getProperty("line.separator");
138 // Replace the include of the main c-file
139 sed.sed(filename, "//#include \"@PROCESSNAME@.c\"", includes);
140 // Replace the process-name in the whole file
141 sed.sed(filename, "@PROCESSNAME@", p.getBasename());
143 // Create the correct Port and Fifo List
144 String fifolist = "";
145 Vector<String> basenames = new Vector<String>();
146 for (Port port : p.getPortList()) {
147 if (!basenames.contains(port.getBasename())) {
148 basenames.add(port.getBasename());
153 Channel c = (Channel) port.getPeerResource();
154 if (port.getName().equals(port.getBasename())) {
155 if (c.getType().equals("fifo")) {
156 fifolist += "Fifo* _port" + port.getName()
158 } else if (c.getType().equals("wfifo")) {
159 fifolist += "WindowedFifo* _port" + port.getName()
163 if (c.getType().equals("fifo")) {
164 fifolist += "Fifo* _port" + port.getBasename()
166 } else if (c.getType().equals("wfifo")) {
167 fifolist += "WindowedFifo* _port"
168 + port.getBasename() + "Fifo";
170 StringTokenizer tokenizer = new StringTokenizer(port
172 while (tokenizer.hasMoreTokens()) {
173 fifolist += "[" + tokenizer.nextToken() + "]";
179 // Set the correct Fifo's
180 sed.sed(filename, "@FIFO@", fifolist);
182 /***************** source File ******************************/
184 // Go through all source files
185 for (SourceCode sourceCode : p.getSrcList()) {
186 // Copy the files to the new folder
187 String oldFilename = _dir
189 + sourceCode.getLocality().replaceAll(
190 "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
191 filename = processDir
193 + sourceCode.getLocality().replaceAll(
194 "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
196 if (new File(filename).exists()) {
197 new File(filename).delete();
200 new File(oldFilename).renameTo(new File(filename));
202 // Copy also the c-files
203 if ((oldFilename.substring(oldFilename.length() - 2))
205 String newFileNameC = filename.substring(0, filename
208 if (new File(newFileNameC).exists()) {
209 new File(newFileNameC).delete();
211 // new Copier().copyFile(new File(oldFilename.substring(0,
212 // oldFilename.length() - 2) + ".c"), new
213 // File(filename.substring(0, filename.length() - 2) +
215 new File(oldFilename.substring(0,
216 oldFilename.length() - 2)
217 + ".c").renameTo(new File(newFileNameC));
220 // Update the files for the DOL project
221 sed.sed(filename, "<dol.h>", "\"dol.h\"");
224 } catch (Exception e) {
225 System.out.println("CbeProcessVisitor: exception "
226 + "occured: " + e.getMessage());
232 * Creates a Wrapper for a PPE process
235 * process that needs to be processed
237 protected void createPPEWrapper(Process p) {
239 // Create of each process an own folder
240 // Insert into this folder the source, the wrapper and a makefile
241 String processDir = _dir + _delimiter + "ppu_"
243 File dir = new File(processDir);
246 // Go through all source files
247 for (SourceCode sourceCode : p.getSrcList()) {
248 // Copy the files to the new folder
249 String oldFilename = _dir
251 + sourceCode.getLocality().replaceAll(
252 "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
253 String filename = processDir
255 + sourceCode.getLocality().replaceAll(
256 "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
258 if (new File(filename).exists()) {
259 new File(filename).delete();
262 new File(oldFilename).renameTo(new File(filename));
264 // Copy also the c-files
265 if ((oldFilename.substring(oldFilename.length() - 2))
267 String newFileNameC = filename.substring(0, filename
270 if (new File(newFileNameC).exists()) {
271 new File(newFileNameC).delete();
273 new File(oldFilename.substring(0,
274 oldFilename.length() - 2)
275 + ".c").renameTo(new File(newFileNameC));
279 _createPPECppFile(dir, p);
280 _createPPEHeaderFile(dir, p);
281 _adaptSources("ppu_" + p.getBasename(), p);
282 createMakeFilePPUProcess("ppu_" + p.getBasename(), p);
283 } catch (IOException e) {
291 private void _createPPECppFile(File dir, Process p) throws IOException {
292 String classname = p.getBasename() + "Wrapper";
293 String filename = dir + _delimiter + classname + ".cpp";
294 OutputStream file = new FileOutputStream(filename);
295 CodePrintStream ps = new CodePrintStream(file);
297 ps.printPrefixln("#include \"" + classname + ".h\"");
298 ps.printPrefixln("#include \"dolSupport.h\"");
299 ps.printPrefixln("#include <string.h>");
301 for (SourceCode sr : p.getSrcList()) {
302 ps.printPrefixln("#include \"" + sr.getLocality() + "\"");
305 ps.printPrefixln(classname + "::" + classname
306 + "(char* name, int iteratorIndex[4]) :");
307 ps.printPrefixln(" ProcessWrapper(name, iteratorIndex)");
308 ps.printLeftBracket();
309 ps.printPrefixln("_state = (LocalState)new "
310 + p.getBasename().substring(0, 1).toUpperCase()
311 + p.getBasename().substring(1) + "_State;");
312 ps.printPrefixln("_process.init = " + p.getBasename() + "_init;");
313 ps.printPrefixln("_process.fire = " + p.getBasename() + "_fire;");
314 ps.printPrefixln("_process.local = _state;");
315 ps.printPrefixln("_process.wptr = (void*)&_wrapper_data;");
316 ps.printPrefixln("_wrapper_data.wrapper = this;");
317 ps.printRightBracket();
319 ps.printPrefixln(classname + "::~" + classname + "()");
320 ps.printLeftBracket();
321 ps.printPrefixln("if (_state)");
322 ps.printPrefixln(" delete ("
323 + p.getBasename().substring(0, 1).toUpperCase()
324 + p.getBasename().substring(1) + "_State*)_state;");
325 // ps.printPrefixln(" delete _state;");
326 ps.printRightBracket();
332 private void _createPPEHeaderFile(File dir, Process p)
334 String classname = p.getBasename() + "Wrapper";
335 String filename = dir + _delimiter + classname + ".h";
336 OutputStream file = new FileOutputStream(filename);
337 CodePrintStream ps = new CodePrintStream(file);
339 ps.printPrefixln("#ifndef " + classname.toUpperCase() + "_H");
340 ps.printPrefixln("#define " + classname.toUpperCase() + "_H");
342 ps.printPrefixln("#include \"ProcessWrapper.h\"");
343 ps.printPrefixln("#include \"Fifo.h\"");
344 ps.printPrefixln("#include \"WindowedFifo.h\"");
346 ps.printPrefixln("class " + classname + ";");
348 ps.printPrefixln("typedef struct _" + p.getBasename() + "_data {");
349 ps.printPrefixln(" int lc;");
350 ps.printPrefixln(" " + classname + " *wrapper;");
351 ps.printPrefixln("} " + p.getBasename() + "_data;");
354 .printPrefixln("class " + classname
355 + " : public ProcessWrapper");
356 ps.printLeftBracket();
357 ps.printPrefixln("public:");
358 ps.printPrefixln(" " + classname + "(char* name, "
359 + "int iteratorIndex[4]);");
360 ps.printPrefixln(" virtual ~" + classname + "();");
363 Vector<String> basenames = new Vector<String>();
364 for (Port port : p.getPortList()) {
365 if (!basenames.contains(port.getBasename())) {
366 basenames.add(port.getBasename());
371 Channel c = (Channel) port.getPeerResource();
372 if (port.getName().equals(port.getBasename())) {
373 if (c.getType().equals("fifo")) {
374 ps.printPrefixln(" Fifo* _port" + port.getName()
376 } else if (c.getType().equals("wfifo")) {
377 ps.printPrefixln(" WindowedFifo* _port"
378 + port.getName() + "Fifo;");
381 if (c.getType().equals("fifo")) {
382 ps.printPrefix(" Fifo* _port" + port.getBasename()
384 } else if (c.getType().equals("wfifo")) {
385 ps.printPrefix(" WindowedFifo* _port"
386 + port.getBasename() + "Fifo");
388 StringTokenizer tokenizer = new StringTokenizer(port
390 while (tokenizer.hasMoreTokens()) {
391 ps.print("[" + tokenizer.nextToken() + "]");
397 ps.printPrefixln("protected:");
398 ps.printPrefixln(" struct _local_states *_state;");
400 .printPrefixln(" " + p.getBasename()
401 + "_data _wrapper_data;");
402 ps.printRightBracket();
404 ps.printPrefixln(";");
406 ps.printPrefixln("#endif");
410 * Create the makefile for a special process --> Each subprocess gets its
414 * process for which the makefile should be created
416 protected void createMakefileProcess(Process p) {
418 // Directory of the process
419 String processDir = _dir + _delimiter + "spu_"
422 // Create the filename for the new wrapper
423 String filename = processDir + _delimiter + "Makefile";
424 // File makefile = new File(filename);
428 file = new FileOutputStream(filename);
430 PrintStream _makefilePS = new CodePrintStream(file);
432 _makefilePS.println("# Makefile for process "
434 _makefilePS.println("");
436 String dependency = "all: " + p.getBasename() + "Wrapper.cpp";
438 for (SourceCode code : p.getSrcList()) {
439 dependency += " " + code.getLocality();
442 _makefilePS.println(dependency);
444 .println("\tspu-g++ -c -I .. -I ../lib -o "
448 + "Wrapper.cpp -ftree-vectorize -mtune=cell -O3 -fmodulo-sched -funroll-loops -ffast-math -fno-rtti -ffunction-sections -fdata-sections" );
449 _makefilePS.println("clean: ");
450 _makefilePS.println("\trm " + p.getBasename() + "Wrapper.o");
451 _makefilePS.println();
453 } catch (FileNotFoundException e) {
454 System.out.println("CbeProcessVisitor - Makefile: exception "
455 + "occured: " + e.getMessage());
460 private void createMakeFilePPUProcess(String subdir, Process p) {
462 // Directory of the process
463 String processDir = _dir + _delimiter + subdir;
465 // Create the filename for the new wrapper
466 String filename = processDir + _delimiter + "Makefile";
467 // File makefile = new File(filename);
471 file = new FileOutputStream(filename);
473 PrintStream _makefilePS = new CodePrintStream(file);
475 _makefilePS.println("# Makefile for process "
477 _makefilePS.println("");
479 String dependency = "all: " + p.getBasename() + "Wrapper.cpp";
481 for (SourceCode code : p.getSrcList()) {
482 dependency += " " + code.getLocality();
484 _makefilePS.println("# General definitions:");
485 _makefilePS.println("CC = ppu-g++");
487 .println("CCFLAGS = -ftree-vectorize -O3 -maltivec -funroll-loops -mabi=altivec -mcpu=cell");
488 _makefilePS.println("COMPILE = $(CC) $(CCFLAGS) -c");
490 _makefilePS.println(dependency);
492 .println("\t$(COMPILE) -o "
496 + "Wrapper.cpp -I .. -I ../lib -I ../lib/ppu -I ../lib/pt;");
497 _makefilePS.println("clean: ");
498 _makefilePS.println("\trm " + p.getBasename() + "Wrapper.o");
499 _makefilePS.println();
501 } catch (FileNotFoundException e) {
503 .println("CbeProcessVisitor - Makefile PPU: exception "
504 + "occured: " + e.getMessage());
510 * Make modifications to source files of a process. Port names need to be
511 * strings for the SystemC code generation. Therefore, in the header files
512 * integer port names are put into quotation marks.
515 * process whose sources should be adapted
516 * @throws IOException
519 protected void _adaptSources(String subdir, Process p)
522 // modify header file
523 for (Port port : p.getPortList()) {
524 String processHeaderFile;
526 for (SourceCode sr : p.getSrcList()) {
527 processHeaderFile = _dir
531 + sr.getLocality().replaceAll(
532 "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
534 sed.sed(processHeaderFile, "(#define[ ]*PORT_\\w*[ ]*)\"?"
535 + port.getBasename() + "\"?", "$1 "
536 + "static_cast<" + p.getBasename()
537 + "Wrapper *>((static_cast<" + p.getBasename()
538 + "_data *>(p->wptr))->wrapper)->_port"
539 + port.getBasename() + "Fifo");
543 // modify source file
544 for (SourceCode sr : p.getSrcList()) {
545 String processSourceFile = _dir + _delimiter + subdir
546 + _delimiter + sr.getLocality();
549 StringBuffer buffer = new StringBuffer();
550 FileInputStream fileInputStream = new FileInputStream(
552 BufferedReader reader = new BufferedReader(
553 new InputStreamReader(fileInputStream));
554 while ((line = reader.readLine()) != null) {
555 buffer.append(line + "\n");
559 String file = buffer.toString();
560 // insert PT_BEGIN() at beginning of fire() function
561 file = file.replaceAll("(int[ ]*" + p.getBasename()
562 + "_fire[ ]*\\([ ]*DOLProcess[ ]*\\*p[ ]*\\)"
563 + "[\\s\\S&&[^\\{]]*)\\{", "$1"
564 + System.getProperty("line.separator") + "{"
565 + System.getProperty("line.separator")
566 + " PT_BEGIN((pt*)(p->wptr));");
568 // replace last return statement in fire function by PT_END()
569 // find beginning of fire function
570 Matcher matcher = Pattern.compile(
571 "(int[ ]*" + p.getBasename()
572 + "_fire[ ]*\\([ ]*DOLProcess[ ]*\\*p[ ]*\\)"
573 + "[\\s\\S&&[^\\{]]*)\\{").matcher(file);
578 } catch (Exception e) {
579 System.out.println("Error: could not find "
580 + p.getBasename() + "_fire() function in "
581 + processSourceFile + ".");
584 int openBraces = 0; // counter for open curly braces
585 // position of last return statement
586 int lastReturnStartPosition = 0;
587 int lastReturnEndPosition = 0;
588 while (i < file.length()) {
589 // ignore single-line comments
590 if (i < (file.length() - 1)
591 && file.substring(i, i + 2).equals("//")) {
592 while (!file.substring(i, i + 1).equals("\n")) {
596 // ignore multi-line comments
597 else if (i < (file.length() - 1)
598 && file.substring(i, i + 2).equals("/*")) {
599 while (!file.substring(i, i + 2).equals("*/")) {
604 else if (file.substring(i, i + 1).equals("\"")) {
605 matcher = Pattern.compile("[\\s\\S&&[^\\\\]]\\\"")
608 i = matcher.start() + 1;
609 } else if (i < (file.length() - 5)
610 && file.substring(i, i + 6).equals("return")) {
611 lastReturnStartPosition = i;
612 while (!file.substring(i, i + 1).equals(";")) {
615 lastReturnEndPosition = i;
616 } else if (file.substring(i, i + 1).equals("{")) {
618 } else if (file.substring(i, i + 1).equals("}")) {
620 if (openBraces == 0) {
627 file = file.substring(0, lastReturnStartPosition)
629 + file.substring(lastReturnStartPosition,
630 lastReturnEndPosition + 1)
631 + " (commented out by DOL) */"
632 + System.getProperty("line.separator")
633 + " PT_END((pt*)(p->wptr));"
634 + System.getProperty("line.separator")
635 + file.substring(lastReturnEndPosition + 2, file
638 BufferedWriter out = new BufferedWriter(new FileWriter(
645 protected CellMapping _mapping;
646 protected String _dir = null;
647 protected HashMap<Port, Integer> _portMap;
649 protected static String _libDirName = "lib";
650 protected static String _tempDirName = "template";