dol: create target object folders when generating
[jump.git] / dol / src / dol / visitor / epiphany / EpiphanyVisitor.java
1 package dol.visitor.Epiphany;
2
3 import java.util.Vector;
4
5 /* file management */
6 import java.io.File;
7 import java.io.FileNotFoundException;
8 import java.io.IOException;
9 import java.util.jar.JarFile;
10 import dol.util.JarCopier;
11 import dol.util.Copier;
12 import dol.util.Sed;
13
14 /* DOL elements */
15 import dol.visitor.PNVisitor;
16 import dol.datamodel.pn.Resource;
17 import dol.datamodel.pn.ProcessNetwork;
18 import dol.datamodel.pn.Process;
19 import dol.datamodel.pn.Channel;
20 import dol.datamodel.pn.Connection;
21 import dol.datamodel.pn.Port;
22
23 public class EpiphanyVisitor extends PNVisitor {
24         private String _epiphanyHostName = "EpiphanyHost";
25         private String _packageName;
26         private Vector<EpiphanyBuffer> _buffers = new Vector<EpiphanyBuffer>();
27         private Integer _numShmBufs = 0;
28
29         /* Constructor */
30         public EpiphanyVisitor(String packageName) {
31                 _packageName = packageName + _delimiter + "src";
32         }
33
34         /* ProcessNetwork Visitor */
35         public void visitComponent(ProcessNetwork pn) {
36                 try {
37                         /* create list of buffers */
38                         createBuffers(pn);
39
40                         /* copy static files */
41                         copyStaticFiles();
42
43                         /* create process wrappers
44                            TODO: fix _epiphanyHostName ?? */
45                         for (Process p : pn.getProcessList()) {
46                                 if(!_epiphanyHostName.equals(p.getBasename()))
47                                         createProcessWrapper(p);
48                         }
49
50                         /* create and copy shared header */
51                         createSharedHeader();
52
53                         /* create and copy host main application */
54                         createHostApplication(pn);
55
56                         /* create and copy Makefile */
57                         createMakefile(pn);
58
59                 } catch (Exception e) {
60                         System.out.println("Exception: " + e.getMessage());
61                         e.printStackTrace();
62                 }
63         }
64
65         /* Search for all structures of type
66            "Process-Port-Connection-Port-Channel-Port-Connection-Port-Process"
67            and save src/dst Process, src/dst Port and Channel */
68         private void createBuffers(ProcessNetwork pn)
69         {
70                 for(Connection c1 : pn.getConnectionList()) {
71                         for(Connection c2 : pn.getConnectionList()) {
72                                 if(c1 == c2) continue;
73
74                                 if(c1.getTarget() == c2.getOrigin() &&
75                                    "fifo".equals(c1.getTarget().getType()) &&
76                                    "fifo".equals(c2.getOrigin().getType())) {
77
78                                         Process src  = (Process)c1.getOrigin();
79                                         Port    srcP = c1.getOriginPort();
80                                         Process dst  = (Process)c2.getTarget();
81                                         Port    dstP = c2.getTargetPort();
82                                         Channel ch   = (Channel)c1.getTarget();
83
84                                         createBuffer(ch, src, srcP, dst, dstP);
85                                 }
86                         }
87                 }
88         }
89
90         /* create a buffer assignment structure */
91         private void createBuffer(Channel ch,
92                 Process src, Port srcP,
93                 Process dst, Port dstP)
94         {
95 //              TODO: all buffers are SHM buffers for now
96 //              if(src.getBasename().equals(_epiphanyHostName) ||
97 //                 dst.getBasename().equals(_epiphanyHostName)) {
98                         /* this is an SHM buffer */
99                         System.out.println("\tBuffer: " +
100                                 src.getName() + ":" + srcP.getName() +
101                                 " ==> " +
102                                 dst.getName() + ":" + dstP.getName() +
103                                 " (size " + ch.getSize() + ")" +
104                                 " as SHM:" + _numShmBufs);
105
106                         EpiphanyBuffer buf = new EpiphanyBuffer();
107                         buf.type = "shm";
108                         buf.srcProcess = src; buf.srcPort = srcP;
109                         buf.dstProcess = dst; buf.dstPort = dstP;
110                         buf.shmIndex = _numShmBufs; buf.size = ch.getSize();
111                         _buffers.add(buf);
112                         _numShmBufs++;
113
114 //              } else {
115                         /* this is an C2C buffer */
116 //                      System.out.println("C2CBUF: " +
117 //                              src.getBasename() + ":" + srcP.getBasename() +
118 //                              " ==> " +
119 //                              dst.getBasename() + ":" + dstP.getBasename() +
120 //                              " (size " + ch.getSize() + ")");
121 //              }
122         }
123
124         /* return buffer structure for a given process:port combination */
125         private EpiphanyBuffer getBuffer(Process process, Port port)
126                 throws Exception
127         {
128                 for(EpiphanyBuffer buf : _buffers) {
129                         if(port == buf.srcPort ||
130                            port == buf.dstPort) {
131                                 return(buf);
132                         }
133                 }
134
135                 throw new Exception("No buffer for '" + port + "' found!");
136         }
137
138         /* Copy a file from the JAR-file to some destination.
139            Copier() supports JAR-sources for directories only,
140            although it has a copyFile method. */
141         private void copyFile(File src, File dst) throws IOException {
142                 if(src.toString().contains("dol.jar!"))
143         {
144                         String jarName = src.toString();
145                         jarName = jarName.substring(jarName.indexOf("file:") + 5, jarName.lastIndexOf("!"));
146                         String srcName = src.toString();
147                                srcName = srcName.substring(src.toString().lastIndexOf("!") + 2);
148                                srcName = srcName.replaceAll("\\\\", "/");
149                         JarFile jar = new JarFile(jarName);
150                         JarCopier copier = new JarCopier();
151                         copier.copyFile(jar, srcName, dst.toString());
152                 } else {
153                         throw new IOException("Source file must be in JAR file.");
154                 }
155         }
156
157         /* create directories, copy processes and library */
158         private void copyStaticFiles() throws IOException,FileNotFoundException
159         {
160                 System.out.print("\tcopyStaticFiles(): ");
161
162                 /* create folders */
163                 System.out.print("directories, ");
164                 File dir;
165                 dir = new File(_packageName);
166                 dir.mkdirs();
167                 dir = new File(_packageName + _delimiter + "esrc");
168                 dir.mkdirs();
169                 dir = new File(_packageName + _delimiter + "eobj");
170                 dir.mkdirs();
171                 dir = new File(_packageName + _delimiter + "hsrc");
172                 dir.mkdirs();
173                 dir = new File(_packageName + _delimiter + "hobj");
174                 dir.mkdirs();
175                 dir = new File(_packageName + _delimiter + "lib");
176                 dir.mkdirs();
177                 dir = new File(_packageName + _delimiter + "bin");
178                 dir.mkdirs();
179
180                 /* copy processes */
181                 System.out.print("processes, ");
182                 File src  = new File("src");
183                 File dest = new File(_packageName + _delimiter + "esrc");
184                 new Copier().copy(src, dest);
185
186                 /* copy library */
187                 System.out.print("lib, ");
188                 String libPath = _ui.getMySystemCLib();
189                        libPath = libPath.replaceAll("systemC", "epiphany");
190                 src  = new File(libPath);
191                 dest = new File(_packageName + _delimiter + "lib");
192                 new Copier().copy(src, dest);
193
194                 System.out.println("finished!");
195         }
196
197         /* create a process_Wrapper.c file */
198         private void createProcessWrapper(Process p) throws Exception
199         {
200                 System.out.println("\tcreateProcessWrapper(): " +
201                         p.getName());
202
203                 /* copy template file */
204                 String filename = _packageName + _delimiter + "esrc" +
205                                   _delimiter + p.getName() + "_Wrapper.c";
206                 String template = _ui.getMySystemCLib() + _delimiter +
207                                   "process_Wrapper.c";
208                        template = template.replaceAll("systemC", "epiphany");
209                        template = template.replaceAll("lib", "template");
210
211                 File fFilename = new File(filename);
212                 File fTemplate = new File(template);
213                 copyFile(fTemplate, fFilename);
214
215                 /* handle this process' iterators */
216                 String instance = "";
217                 Vector<Integer> indices = p.getIteratorIndices();
218                 switch(indices.size()) {
219                 case 0: instance =
220                                 "0,0,0,0"; break;
221                 case 1: instance =
222                                 indices.elementAt(0) +
223                                 ",0,0,0"; break;
224                 case 2: instance =
225                                 indices.elementAt(0) +
226                                 indices.elementAt(1) +
227                                 ",0,0"; break;
228                 case 3: instance =
229                                 indices.elementAt(0) +
230                                 "," + indices.elementAt(1) +
231                                 "," + indices.elementAt(2) +
232                                 ",0"; break;
233                 case 4: instance =
234                                 indices.elementAt(0) +
235                                 "," + indices.elementAt(1) +
236                                 "," + indices.elementAt(2) +
237                                 "," + indices.elementAt(3); break;
238                 default:
239                         throw new Exception("Unsupported iterator dimension");
240                 }
241
242
243                 /* handle this process' ports */
244                 Integer portNum       = 0;
245                 String  portMapping   = "";
246                 String  portFunctions = "";
247                 for (Port port : p.getPortList()) {
248                         EpiphanyBuffer buf = getBuffer(p, port);
249
250                         /* port mapping */
251                         portMapping += "\t{ \"" + port.getName() + "\", size_" + portNum + ", level_" + portNum + ", ";
252                         portMapping += port.isInPort() ? "read_" + portNum + ", " : "NULL, ";
253                         portMapping += port.isOutPort() ? "write_" + portNum + ", " : "NULL, ";
254                         portMapping += "},\n";
255
256                         /* port access functions  - TODO: c2c buffers */
257                         if("shm".equals(buf.type)) {
258                                 Integer bufNum = buf.shmIndex;
259
260                                 portFunctions += "int size_" + portNum + "(void) { return(size_shm(&shm.buf" + bufNum + ")); }\n";
261                                 portFunctions += "int level_" + portNum + "(void) { return(level_shm(&shm.buf" + bufNum + ")); }\n";
262                                 if(port.isInPort()) {
263                                         portFunctions += "int read_" + portNum + "(void *buf, int len) { return(read_shm(&shm.buf" + bufNum + ", buf, len)); }\n";
264                                 }
265
266                                 if(port.isOutPort()) {
267                                         portFunctions += "int write_" + portNum + "(void *buf, int len) { return(write_shm(&shm.buf" + bufNum + ", buf, len)); }\n";
268                                 }
269                         } else {
270                                 throw new Exception("unknown port type");
271                         }
272
273                         portNum++;
274                 }
275
276                 /* replace information */
277                 Sed sed = new Sed();
278                 sed.sed(filename, "@@PROCESSNAME@@",   p.getBasename());
279                 sed.sed(filename, "@@INSTANCE@@",      instance);
280                 sed.sed(filename, "@@NUM_PORTS@@",     portNum.toString());
281                 sed.sed(filename, "@@PORTMAPPING@@",   portMapping);
282                 sed.sed(filename, "@@PORTFUNCTIONS@@", portFunctions);
283         }
284
285         /* create the shared.h header file */
286         private void createSharedHeader() throws Exception
287         {
288                 System.out.print("\tcreateSharedHeader(): ");
289
290                 /* copy template file */
291                 String filename = _packageName + _delimiter + "shared.h";
292                 String template = _ui.getMySystemCLib() + _delimiter +
293                                   "shared.h";
294                        template = template.replaceAll("systemC", "epiphany");
295                        template = template.replaceAll("lib", "template");
296                 File fFilename = new File(filename);
297                 File fTemplate = new File(template);
298                 copyFile(fTemplate, fFilename);
299
300                 /* generate replacement strings */
301                 String shmBufTypes = "";
302                 String shmBufs = "";
303                 for(EpiphanyBuffer buf : _buffers) {
304                         if("shm".equals(buf.type)) {
305                                 shmBufTypes +=
306                                 "\ntypedef struct {\n" +
307                                 "\tuint32_t rp;\n" +
308                                 "\tuint32_t wp;\n" +
309                                 "\tuint32_t size;\n" +
310                                 "\tchar     buf[" + buf.size + "];\n" +
311                                 "} PACKED buf" + buf.shmIndex + "_t;\n";
312
313                                 shmBufs +=
314                                 "\tbuf" + buf.shmIndex + "_t" +
315                                 "\tbuf" + buf.shmIndex + ";\n";
316                         }
317                 }
318
319                 /* do the replace */
320                 Sed sed = new Sed();
321                 sed.sed(filename, "@@SHM_BUF_STRUCTS@@", shmBufTypes);
322                 sed.sed(filename, "@@SHM_BUFS@@",        shmBufs);
323                 System.out.println("done!");
324         }
325
326         /* create the host application */
327         private void createHostApplication(ProcessNetwork pn) throws Exception
328         {
329                 System.out.print("\tcreateHostApplication(): ");
330
331                 /* copy template file */
332                 String filename = _packageName + _delimiter + "hsrc/main.c";
333                 String template = _ui.getMySystemCLib() + _delimiter +
334                                   "main.c";
335                        template = template.replaceAll("systemC", "epiphany");
336                        template = template.replaceAll("lib", "template");
337                 File fFilename = new File(filename);
338                 File fTemplate = new File(template);
339                 copyFile(fTemplate, fFilename);
340
341                 /* generate srec filenames */
342                 String srecFiles = "";
343                 Integer srecNum = 0;
344                 for(Process p : pn.getProcessList()) {
345                         /* TODO: fix _epiphanyHostName */
346                         if(!_epiphanyHostName.equals(p.getBasename())) {
347                                 srecFiles += "\t\"bin/" + p.getBasename() + ".srec\",\n";
348                                 srecNum++;
349                         }
350                 }
351
352                 /* generate shm buffer initialization code sequence */
353                 String shmBufInit = "";
354                 for(EpiphanyBuffer buf : _buffers) {
355                         if("shm".equals(buf.type)) {
356                                 String tmp = "\tshm.buf" + buf.shmIndex;
357
358                                 shmBufInit +=
359                                         tmp + ".size = " + buf.size + ";\n" +
360                                         tmp + ".rp   = 0;\n" +
361                                         tmp + ".wp   = 0;\n";
362                         }
363                 }
364
365                 /* do the replace */
366                 Sed sed = new Sed();
367                 sed.sed(filename, "@@SREC_FILES@@",   srecFiles);
368                 sed.sed(filename, "@@SREC_NUM@@",     srecNum.toString());
369                 sed.sed(filename, "@@SHM_BUF_INIT@@", shmBufInit);
370                 System.out.println("done!");
371         }
372
373         /* create Makefile */
374         private void createMakefile(ProcessNetwork pn) throws Exception
375         {
376                 System.out.print("\tcreateMakefile(): ");
377
378                 /* copy template file */
379                 String filename = _packageName + _delimiter + "Makefile";
380                 String template = _ui.getMySystemCLib() + _delimiter +
381                                   "Makefile";
382                        template = template.replaceAll("systemC", "epiphany");
383                        template = template.replaceAll("lib", "template");
384                 File fFilename = new File(filename);
385                 File fTemplate = new File(template);
386                 copyFile(fTemplate, fFilename);
387
388                 /* generate srec filenames */
389                 String srecFiles = "";
390                 for(Process p : pn.getProcessList()) {
391                         /* TODO: fix _epiphanyHostName */
392                         if(!_epiphanyHostName.equals(p.getBasename())) {
393                                 srecFiles += "\\$(DEST)/" +
394                                         p.getName() + ".srec ";
395                         }
396                 }
397
398                 /* generate .elf rules, because wrapper file names are
399                    non-obvious with iterated processes... */
400                 String elfRules = "";
401                 for(Process p : pn.getProcessList()) {
402                         elfRules +=
403                                 "\\$(EDEST)/" + p.getName() + ".elf: " +
404                                 "\\$(EDEST)/" + p.getBasename() + ".o " +
405                                 "\\$(EDEST)/" + p.getName() + "_Wrapper.o " +
406                                 "\\$(ECOMMON)\n";
407                         elfRules +=
408                                 "\t@\\$(ECHO) \"\\\\t(EPIPHANY) LINK\\\\t\\\\t\\$@\"\n" +
409                                 "\t@\\$(CC) -o \\$@ \\$^ \\$(LFLAGS)\n\n";
410                 }
411
412                 /* do the replace */
413                 Sed sed = new Sed();
414                 sed.sed(filename, "@@SREC_FILES@@", srecFiles);
415                 sed.sed(filename, "@@ELF_RULES@@",  elfRules);
416                 System.out.println("done!");
417         }
418 }