dol: initial epiphany code generator (untested)
authorSebastian <basti@sraa.de>
Tue, 10 Dec 2013 21:11:06 +0000 (22:11 +0100)
committerSebastian <basti@sraa.de>
Tue, 10 Dec 2013 21:11:06 +0000 (22:11 +0100)
First shot of a DOL code generator for Epiphany.
Our Epiphany currently does not have access to the internet.

notes:
- all communication channels in shared memory (slow)
- no architecture specification used (hard-coded for our board)
- no manual mapping possible (processes are placed left-right, top-bottom)
- no usable input/output to the processes possible
- completely untested!

13 files changed:
dol/build.xml
dol/src/dol/visitor/epiphany/EpiphanyBuffer.java [new file with mode: 0644]
dol/src/dol/visitor/epiphany/EpiphanyVisitor.java
dol/src/dol/visitor/epiphany/lib/dol.c [new file with mode: 0644]
dol/src/dol/visitor/epiphany/lib/dol.h [new file with mode: 0644]
dol/src/dol/visitor/epiphany/lib/index.c [new file with mode: 0644]
dol/src/dol/visitor/epiphany/lib/index.h [new file with mode: 0644]
dol/src/dol/visitor/epiphany/lib/ports.c [new file with mode: 0644]
dol/src/dol/visitor/epiphany/lib/ports.h [new file with mode: 0644]
dol/src/dol/visitor/epiphany/template/Makefile [new file with mode: 0644]
dol/src/dol/visitor/epiphany/template/main.c [new file with mode: 0644]
dol/src/dol/visitor/epiphany/template/process_Wrapper.c [new file with mode: 0644]
dol/src/dol/visitor/epiphany/template/shared.h [new file with mode: 0644]

index 27e1207cb3d96651801efab8ee2520ee8cbb6de8..8538220ee34b055bb40607519b94aecce81711de 100644 (file)
@@ -62,6 +62,8 @@
       <fileset dir="${src.dir}"
         includes="dol/visitor/systemC/lib/**
                   dol/visitor/hds/lib/**
+                  dol/visitor/epiphany/lib/**
+                  dol/visitor/epiphany/template/**
                   dol/visitor/PipeAndFilter/lib/**
                   dol/visitor/hdsd/lib/**
                   dol/visitor/hdsd/scd/**
diff --git a/dol/src/dol/visitor/epiphany/EpiphanyBuffer.java b/dol/src/dol/visitor/epiphany/EpiphanyBuffer.java
new file mode 100644 (file)
index 0000000..8d5a19f
--- /dev/null
@@ -0,0 +1,18 @@
+package dol.visitor.Epiphany;
+
+import java.util.Vector;
+
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.Port;
+
+public class EpiphanyBuffer {
+       public String type;     // "shm"
+
+       /* fields for "shm" buffers */
+       Integer size; Integer shmIndex;
+       Process srcProcess; Port srcPort;
+       Process dstProcess; Port dstPort;
+
+       EpiphanyBuffer() { type="shm"; }
+
+}
index d2a39e8978b85ba7382b6e38071ba402caf98ad2..2c0c642a5a0b173c44276cafaf668f9d815942e8 100644 (file)
 package dol.visitor.Epiphany;
 
+import java.util.Vector;
+
+/* file management */
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.jar.JarFile;
+import dol.util.JarCopier;
+import dol.util.Copier;
+import dol.util.Sed;
+
+/* DOL elements */
 import dol.visitor.PNVisitor;
+import dol.datamodel.pn.Resource;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Connection;
+import dol.datamodel.pn.Port;
 
 public class EpiphanyVisitor extends PNVisitor {
+       private String _epiphanyHostName = "EpiphanyHost";
+       private String _packageName;
+       private Vector<EpiphanyBuffer> _buffers = new Vector<EpiphanyBuffer>();
+       private Integer _numShmBufs = 0;
+
        /* Constructor */
        public EpiphanyVisitor(String packageName) {
-               System.out.println("EPIPHANY VISITOR CONSTRUCTOR");
+               _packageName = packageName + _delimiter + "src";
+       }
+
+       /* ProcessNetwork Visitor */
+       public void visitComponent(ProcessNetwork pn) {
+               try {
+                       /* create list of buffers */
+                       createBuffers(pn);
+
+                       /* copy static files */
+                       copyStaticFiles();
+
+                       /* create process wrappers
+                          TODO: fix _epiphanyHostName ?? */
+                       for (Process p : pn.getProcessList()) {
+                               if(!_epiphanyHostName.equals(p.getBasename()))
+                                       createProcessWrapper(p);
+                       }
+
+                       /* create and copy shared header */
+                       createSharedHeader();
+
+                       /* create and copy host main application */
+                       createHostApplication(pn);
+
+                       /* create and copy Makefile */
+                       createMakefile(pn);
+
+               } catch (Exception e) {
+                       System.out.println("Exception: " + e.getMessage());
+                       e.printStackTrace();
+               }
+       }
+
+       /* Search for all structures of type
+          "Process-Port-Connection-Port-Channel-Port-Connection-Port-Process"
+          and save src/dst Process, src/dst Port and Channel */
+       private void createBuffers(ProcessNetwork pn)
+       {
+               for(Connection c1 : pn.getConnectionList()) {
+                       for(Connection c2 : pn.getConnectionList()) {
+                               if(c1 == c2) continue;
+
+                               if(c1.getTarget() == c2.getOrigin() &&
+                                  "fifo".equals(c1.getTarget().getType()) &&
+                                  "fifo".equals(c2.getOrigin().getType())) {
+
+                                       Process src  = (Process)c1.getOrigin();
+                                       Port    srcP = c1.getOriginPort();
+                                       Process dst  = (Process)c2.getTarget();
+                                       Port    dstP = c2.getTargetPort();
+                                       Channel ch   = (Channel)c1.getTarget();
+
+                                       createBuffer(ch, src, srcP, dst, dstP);
+                               }
+                       }
+               }
+       }
+
+       /* create a buffer assignment structure */
+       private void createBuffer(Channel ch,
+               Process src, Port srcP,
+               Process dst, Port dstP)
+       {
+//             TODO: all buffers are SHM buffers for now
+//             if(src.getBasename().equals(_epiphanyHostName) ||
+//                dst.getBasename().equals(_epiphanyHostName)) {
+                       /* this is an SHM buffer */
+                       System.out.println("\tBuffer: " +
+                               src.getBasename() + ":" + srcP.getBasename() +
+                               " ==> " +
+                               dst.getBasename() + ":" + dstP.getBasename() +
+                               " (size " + ch.getSize() + ")" +
+                               " as SHM:" + _numShmBufs);
+
+                       EpiphanyBuffer buf = new EpiphanyBuffer();
+                       buf.type = "shm";
+                       buf.srcProcess = src; buf.srcPort = srcP;
+                       buf.dstProcess = dst; buf.dstPort = dstP;
+                       buf.shmIndex = _numShmBufs; buf.size = ch.getSize();
+                       _buffers.add(buf);
+                       _numShmBufs++;
+
+//             } else {
+                       /* this is an C2C buffer */
+//                     System.out.println("C2CBUF: " +
+//                             src.getBasename() + ":" + srcP.getBasename() +
+//                             " ==> " +
+//                             dst.getBasename() + ":" + dstP.getBasename() +
+//                             " (size " + ch.getSize() + ")");
+//             }
+       }
+
+       /* return buffer structure for a given process:port combination */
+       private EpiphanyBuffer getBuffer(Process process, Port port)
+               throws Exception
+       {
+               for(EpiphanyBuffer buf : _buffers) {
+                       if(port == buf.srcPort ||
+                          port == buf.dstPort) {
+                               return(buf);
+                       }
+               }
+
+               throw new Exception("No buffer for '" + port + "' found!");
+       }
+
+       /* Copy a file from the JAR-file to some destination.
+          Copier() supports JAR-sources for directories only,
+          although it has a copyFile method. */
+       private void copyFile(File src, File dst) throws IOException {
+               if(src.toString().contains("dol.jar!"))
+       {
+                       String jarName = src.toString();
+                       jarName = jarName.substring(jarName.indexOf("file:") + 5, jarName.lastIndexOf("!"));
+                       String srcName = src.toString();
+                              srcName = srcName.substring(src.toString().lastIndexOf("!") + 2);
+                              srcName = srcName.replaceAll("\\\\", "/");
+                       JarFile jar = new JarFile(jarName);
+                       JarCopier copier = new JarCopier();
+                       copier.copyFile(jar, srcName, dst.toString());
+               } else {
+                       throw new IOException("Source file must be in JAR file.");
+               }
+       }
+
+       /* create directories, copy processes and library */
+       private void copyStaticFiles() throws IOException,FileNotFoundException
+       {
+               System.out.print("\tcopyStaticFiles(): ");
+
+               /* create folders */
+               System.out.print("directories, ");
+               File dir;
+               dir = new File(_packageName);
+               dir.mkdirs();
+               dir = new File(_packageName + _delimiter + "esrc");
+               dir.mkdirs();
+               dir = new File(_packageName + _delimiter + "hsrc");
+               dir.mkdirs();
+               dir = new File(_packageName + _delimiter + "lib");
+               dir.mkdirs();
+               dir = new File(_packageName + _delimiter + "bin");
+               dir.mkdirs();
+
+               /* copy processes */
+               System.out.print("processes, ");
+               File src  = new File("src");
+               File dest = new File(_packageName + _delimiter + "esrc");
+               new Copier().copy(src, dest);
+
+               /* copy library */
+               System.out.print("lib, ");
+               String libPath = _ui.getMySystemCLib();
+                      libPath = libPath.replaceAll("systemC", "epiphany");
+               src  = new File(libPath);
+               dest = new File(_packageName + _delimiter + "lib");
+               new Copier().copy(src, dest);
+
+               System.out.println("finished!");
+       }
+
+       /* create a process_Wrapper.c file */
+       private void createProcessWrapper(Process p) throws Exception
+       {
+               System.out.println("\tcreateProcessWrapper(): " +
+                       p.getBasename());
+
+               /* copy template file */
+               String filename = _packageName + _delimiter + "esrc" +
+                                 _delimiter + p.getBasename() + "_Wrapper.c";
+               String template = _ui.getMySystemCLib() + _delimiter +
+                                 "process_Wrapper.c";
+                      template = template.replaceAll("systemC", "epiphany");
+                      template = template.replaceAll("lib", "template");
+
+               File fFilename = new File(filename);
+               File fTemplate = new File(template);
+               copyFile(fTemplate, fFilename);
+
+               /* handle this process' ports */
+               Integer portNum       = 0;
+               String  portMapping   = "";
+               String  portFunctions = "";
+               for (Port port : p.getPortList()) {
+                       EpiphanyBuffer buf = getBuffer(p, port);
+
+                       /* port mapping */
+                       portMapping += "\t{ \"" + port.getBasename() + "\", size_" + portNum + ", level_" + portNum + ", ";
+                       portMapping += port.isInPort() ? "read_" + portNum + ", " : "NULL, ";
+                       portMapping += port.isOutPort() ? "write_" + portNum + ", " : "NULL, ";
+                       portMapping += "},\n";
+
+                       /* port access functions  - TODO: c2c buffers */
+                       if("shm".equals(buf.type)) {
+                               Integer bufNum = buf.shmIndex;
+
+                               portFunctions += "int size_" + portNum + "(void) { return(size_shm(&shm.buf" + bufNum + ")); }\n";
+                               portFunctions += "int level_" + portNum + "(void) { return(level_shm(&shm.buf" + bufNum + ")); }\n";
+                               if(port.isInPort()) {
+                                       portFunctions += "int read_" + portNum + "(void *buf, int len) { return(read_shm(&shm.buf" + bufNum + ", buf, len)); }\n";
+                               }
+
+                               if(port.isOutPort()) {
+                                       portFunctions += "int write_" + portNum + "(void *buf, int len) { return(write_shm(&shm.buf" + bufNum + ", buf, len)); }\n";
+                               }
+                       } else {
+                               throw new Exception("unknown port type");
+                       }
+
+                       portNum++;
+               }
+
+               /* replace information */
+               Sed sed = new Sed();
+               sed.sed(filename, "@@PROCESSNAME@@",   p.getBasename());
+               sed.sed(filename, "@@NUM_PORTS@@",     portNum.toString());
+               sed.sed(filename, "@@PORTMAPPING@@",   portMapping);
+               sed.sed(filename, "@@PORTFUNCTIONS@@", portFunctions);
+       }
+
+       /* create the shared.h header file */
+       private void createSharedHeader() throws Exception
+       {
+               System.out.print("\tcreateSharedHeader(): ");
+
+               /* copy template file */
+               String filename = _packageName + _delimiter + "shared.h";
+               String template = _ui.getMySystemCLib() + _delimiter +
+                                 "shared.h";
+                      template = template.replaceAll("systemC", "epiphany");
+                      template = template.replaceAll("lib", "template");
+               File fFilename = new File(filename);
+               File fTemplate = new File(template);
+               copyFile(fTemplate, fFilename);
+
+               /* generate replacement string */
+               String shmBufs = "";
+               for(EpiphanyBuffer buf : _buffers) {
+                       if("shm".equals(buf.type)) {
+                               shmBufs +=
+                               "\ntypedef struct {\n" +
+                               "\tuint32_t rp;\n" +
+                               "\tuint32_t wp;\n" +
+                               "\tuint32_t size;\n" +
+                               "\tchar     buf[" + buf.size + "];\n" +
+                               "} PACKED buf" + buf.shmIndex + "_t;\n";
+                       }
+               }
+
+               /* do the replace */
+               Sed sed = new Sed();
+               sed.sed(filename, "@@SHM_BUF_STRUCTS@@", shmBufs);
+               System.out.println("done!");
+       }
+
+       /* create the host application */
+       private void createHostApplication(ProcessNetwork pn) throws Exception
+       {
+               System.out.print("\tcreateHostApplication(): ");
+
+               /* copy template file */
+               String filename = _packageName + _delimiter + "hsrc/main.c";
+               String template = _ui.getMySystemCLib() + _delimiter +
+                                 "main.c";
+                      template = template.replaceAll("systemC", "epiphany");
+                      template = template.replaceAll("lib", "template");
+               File fFilename = new File(filename);
+               File fTemplate = new File(template);
+               copyFile(fTemplate, fFilename);
+
+               /* generate srec filenames */
+               String srecFiles = "";
+               Integer srecNum = 0;
+               for(Process p : pn.getProcessList()) {
+                       if(!_epiphanyHostName.equals(p.getBasename())) {
+                               srecFiles += "\t\"bin/" + p.getBasename() + ".srec\",\n";
+                               srecNum++;
+                       }
+               }
+
+               /* generate shm buffer initialization code sequence */
+               String shmBufInit = "";
+               for(EpiphanyBuffer buf : _buffers) {
+                       if("shm".equals(buf.type)) {
+                               String tmp = "\tshm.buf" + buf.shmIndex;
+
+                               shmBufInit +=
+                                       tmp + ".size = " + buf.size + ";\n" +
+                                       tmp + ".rp   = 0;\n" +
+                                       tmp + ".wp   = 0;\n";
+                       }
+               }
+
+               /* do the replace */
+               Sed sed = new Sed();
+               sed.sed(filename, "@@SREC_FILES@@",   srecFiles);
+               sed.sed(filename, "@@SREC_NUM@@",     srecNum.toString());
+               sed.sed(filename, "@@SHM_BUF_INIT@@", shmBufInit);
+               System.out.println("done!");
+       }
+
+       /* create Makefile */
+       private void createMakefile(ProcessNetwork pn) throws Exception
+       {
+               System.out.print("\tcreateMakefile(): ");
+
+               /* copy template file */
+               String filename = _packageName + _delimiter + "Makefile";
+               String template = _ui.getMySystemCLib() + _delimiter +
+                                 "Makefile";
+                      template = template.replaceAll("systemC", "epiphany");
+                      template = template.replaceAll("lib", "template");
+               File fFilename = new File(filename);
+               File fTemplate = new File(template);
+               copyFile(fTemplate, fFilename);
+
+               /* generate srec filenames */
+               String srecFiles = "";
+               for(Process p : pn.getProcessList()) {
+                       if(!_epiphanyHostName.equals(p.getBasename())) {
+                               srecFiles += "\\$(DEST)/" +
+                                       p.getBasename() + ".srec ";
+                       }
+               }
+
+               /* do the replace */
+               Sed sed = new Sed();
+               sed.sed(filename, "@@SREC_FILES@@",   srecFiles);
+               System.out.println("done!");
        }
 }
diff --git a/dol/src/dol/visitor/epiphany/lib/dol.c b/dol/src/dol/visitor/epiphany/lib/dol.c
new file mode 100644 (file)
index 0000000..fed6ca4
--- /dev/null
@@ -0,0 +1,94 @@
+/* DOL Block Implementation */
+
+#include <stdio.h>
+#include <dol.h>
+#include "ports.h"
+
+/* DOL support functions
+ * ===================================================================== */
+int DOL_read(void *port, void *buf, int len, DOLProcess *p)
+{
+       port_t *pp = get_port(port);
+       if(!pp || !pp->read) return 0;
+
+       return(pp->read(buf, len));
+}
+
+int DOL_write(void *port, void *buf, int len, DOLProcess *p)
+{
+       port_t *pp = get_port(port);
+       if(!pp || !pp->write) return 0;
+
+       return(pp->write(buf, len));
+}
+
+int DOL_rtest(void *port, int len, DOLProcess *p)
+{
+       /* check if channel contains at least 'len' bytes */
+       port_t *pp = get_port(port);
+       if(!pp || !pp->level) return 0;
+
+       int level = pp->level();
+       return (level >= len) ? 1 : 0;
+}
+
+int DOL_wtest(void *port, int len, DOLProcess *p)
+{
+       /* check if channel has space for at least 'len' bytes */
+       port_t *pp = get_port(port);
+       if(!pp || !pp->level) return 0;
+
+       int level = pp->level();
+       return (level < (pp->size() - len)) ? 1 : 0;
+}
+
+void DOL_detach(DOLProcess *p)
+{
+       p->wptr->active = 0;
+       return;
+}
+
+int DOL_get_index(int dim, DOLProcess *p)
+{
+       if((dim < 0) || (dim > 4)) return(-1);
+
+       return(p->wptr->instance[dim]);
+}
+
+char* DOL_create_port(char* port, char* base, int ndim, int index0, int range0,
+       int index1, int range1, int index2, int range2, int index3, int range3)
+{
+       /* hang on invalid input */
+       if(range0 && (index0 >= range0)) while(1);
+       if(range1 && (index1 >= range1)) while(1);
+       if(range2 && (index2 >= range2)) while(1);
+       if(range3 && (index3 >= range3)) while(1);
+
+       switch(ndim) {
+       case 1:
+               snprintf(port, PORTNAME_MAXLEN-1,
+                       "%s_%i", base, index0);
+               port[PORTNAME_MAXLEN-1] = '\0';
+               break;
+       case 2:
+               snprintf(port, PORTNAME_MAXLEN-1,
+                       "%s_%i_%i", base, index0, index1);
+               port[PORTNAME_MAXLEN-1] = '\0';
+               break;
+       case 3:
+               snprintf(port, PORTNAME_MAXLEN-1,
+                       "%s_%i_%i_%i", base, index0, index1, index2),
+               port[PORTNAME_MAXLEN-1] = '\0';
+               break;
+       case 4:
+               snprintf(port, PORTNAME_MAXLEN-1,
+                       "%s_%i_%i_%i_%i", base, index0, index1, index2, index3);
+               port[PORTNAME_MAXLEN-1] = '\0';
+               break;
+       default:
+               while(1);
+       }
+
+       return(port);
+}
+
diff --git a/dol/src/dol/visitor/epiphany/lib/dol.h b/dol/src/dol/visitor/epiphany/lib/dol.h
new file mode 100644 (file)
index 0000000..f8424d1
--- /dev/null
@@ -0,0 +1,66 @@
+/* DOL Block Header */
+#ifndef _DOL_H_
+#define _DOL_H_
+
+/* defined by the blocks */
+typedef struct _local_states *LocalState;
+
+/* process functions */
+struct _DOLProcess_struct;
+typedef void (*ProcessInit)(struct _DOLProcess_struct*);
+typedef int  (*ProcessFire)(struct _DOLProcess_struct*);
+
+/* WPTR definition */
+struct _DOL_wptr {
+       int active;
+       int instance[4];
+};
+typedef struct _DOL_wptr *WPTR;
+
+/* DOL process */
+typedef struct _DOLProcess_struct {
+       LocalState      local;
+       ProcessInit     init;
+       ProcessFire     fire;
+       WPTR            wptr;
+} DOLProcess;
+
+/* DOL-specific functions */
+int  DOL_read (void*, void*, int, DOLProcess*);
+int  DOL_write(void*, void*, int, DOLProcess*);
+int  DOL_rtest(void*, int, DOLProcess*);
+int  DOL_wtest(void*, int, DOLProcess*);
+void DOL_detach(DOLProcess*);
+#define GETINDEX(dim) DOL_get_index(dim, p)
+int  DOL_get_index(int, DOLProcess*);
+
+/* port generation */
+#define PORTNAME_MAXLEN 64
+#define CREATEPORTVAR(name) char name[PORTNAME_MAXLEN]
+
+#define CREATEPORT_FUNCTION(_1, _2, _3, _4, _5, \
+       _6, _7, _8, _9, _10, _11, NAME, ...) NAME
+#define CREATEPORT(...) CREATEPORT_FUNCTION(__VA_ARGS__, \
+       CREATEPORT_4, CREATEPORT_BAD_PARAMETERS, \
+       CREATEPORT_3, CREATEPORT_BAD_PARAMETERS, \
+       CREATEPORT_2, CREATEPORT_BAD_PARAMETERS, \
+       CREATEPORT_1, CREATEPORT_BAD_PARAMETERS, \
+       CREATEPORT_BAD_PARAMETERS, CREATEPORT_BAD_PARAMETERS, \
+       CREATEPORT_BAD_PARAMETERS, CREATEPORT_BAD_PARAMETERS)(__VA_ARGS__)
+
+#define CREATEPORT_1(port, base, ndim, i0, r0) \
+       DOL_create_port(port, base, ndim, i0, r0, 0, 0, 0, 0, 0, 0)
+
+#define CREATEPORT_2(port, base, ndim, i0, r0, i1, r1) \
+       DOL_create_port(port, base, ndim, i0, r0, i1, r1, 0, 0, 0, 0)
+
+#define CREATEPORT_3(port, base, ndim, i0, r0, i1, r1, i2, r2) \
+       DOL_create_port(port, base, ndim, i0, r0, i1, r1, i2, r2, 0, 0)
+
+#define CREATEPORT_4(port, base, ndim, i0, r0, i1, r1, i2, r2, i3, r3) \
+       DOL_create_port(port, base, ndim, i0, r0, i1, r1, i2, r2, i3, r3)
+
+char* DOL_create_port(char*, char*, int,
+       int, int, int, int, int, int, int, int);
+
+#endif /* _DOL_H_ */
diff --git a/dol/src/dol/visitor/epiphany/lib/index.c b/dol/src/dol/visitor/epiphany/lib/index.c
new file mode 100644 (file)
index 0000000..4841b7d
--- /dev/null
@@ -0,0 +1,20 @@
+/* index.c: some index calculations */
+
+#include <stdint.h>
+
+#include "e_lib.h"
+
+/* some defines */
+#define CORE0          0x808   /* coreid of first core */
+#define CORES_PER_ROW  4       /* cores per row - 4 on E16G3 */
+
+uint32_t core_id2lin(e_coreid_t coreid)
+{      /* take coreid, return linear index */
+       return((coreid-CORE0) / (64/CORES_PER_ROW) + (coreid-CORE0)%64);
+}
+
+uint32_t core_lin2id(uint32_t eidx)
+{      /* take linear index, return coreid */
+       return(64 * eidx / CORES_PER_ROW + eidx % CORES_PER_ROW + CORE0);
+}
+
diff --git a/dol/src/dol/visitor/epiphany/lib/index.h b/dol/src/dol/visitor/epiphany/lib/index.h
new file mode 100644 (file)
index 0000000..6327333
--- /dev/null
@@ -0,0 +1,11 @@
+/* index.h */
+#ifndef _INDEX_H_
+#define _INDEX_H_
+
+#include "e_lib.h"
+
+/* core id <-> linear id conversion */
+uint32_t core_id2lin(e_coreid_t id);
+uint32_t core_lin2id(uint32_t lin);
+
+#endif /* _INDEX_H_ */
diff --git a/dol/src/dol/visitor/epiphany/lib/ports.c b/dol/src/dol/visitor/epiphany/lib/ports.c
new file mode 100644 (file)
index 0000000..240474b
--- /dev/null
@@ -0,0 +1,69 @@
+/* ports implementation */
+#include <string.h>
+
+#include "../shared.h"
+
+extern shm_t shm;
+
+int size_shm(void *hwbuf)
+{
+       hwbuf_t *b = (hwbuf_t*)hwbuf;
+       return(b->size);
+}
+
+int level_shm(void *hwbuf)
+{
+       hwbuf_t *b = (hwbuf_t*)hwbuf;
+
+       int level = (b->wp - b->rp) % b->size;
+       if(level < 0) level += b->size;
+
+       return(level);
+}
+
+int read_shm (void *hwbuf, void *buf, int len)
+{
+       hwbuf_t *b = (hwbuf_t*)hwbuf;
+
+       /* block if necessary */
+       while(level_shm(hwbuf) < len);
+
+       /* copy data */
+       if(b->rp + len > b->size) {
+               /* wrap-around -> split access */
+               uint32_t amount = b->size - b->rp;
+               memcpy(buf, &b->buf[b->rp], amount);
+               memcpy(buf + amount, &b->buf[0], len - amount);
+       } else {
+               memcpy(buf, &b->buf[b->rp], len);
+       }
+
+       /* update read pointer */
+       b->rp = (b->rp + len) % b->size;
+
+       return(len);
+}
+
+int write_shm(void *hwbuf, void *buf, int len)
+{
+       hwbuf_t *b = (hwbuf_t*)hwbuf;
+
+       /* block if necessary */
+       while(b->size - level_shm(hwbuf) < len);
+
+       /* copy data */
+       if(b->wp + len > b->size) {
+               /* wrap-around -> split access */
+               uint32_t amount = b->size - b->wp;
+               memcpy(&b->buf[b->wp], buf, amount);
+               memcpy(&b->buf[0], buf + amount, len - amount);
+       } else {
+               memcpy(&b->buf[b->wp], buf, len);
+       }
+
+       /* update write pointer */
+       b->wp = (b->wp + len) % b->size;
+
+       return(len);
+}
+
diff --git a/dol/src/dol/visitor/epiphany/lib/ports.h b/dol/src/dol/visitor/epiphany/lib/ports.h
new file mode 100644 (file)
index 0000000..40d88d0
--- /dev/null
@@ -0,0 +1,24 @@
+/* ports header */
+#ifndef _PORTS_H_
+#define _PORTS_H_
+
+#include <unistd.h>
+#include <dol.h>
+
+typedef struct {
+       char  name[PORTNAME_MAXLEN];
+       int   (*size) (void);   /* size */
+       int   (*level)(void);   /* how many bytes in buf */
+       int   (*read) (void *buf, int len);
+       int   (*write)(void *buf, int len);
+} port_t;
+
+port_t* get_port(void* port);
+
+int size_shm (void *hwbuf);
+int level_shm(void *hwbuf);
+int read_shm (void *hwbuf, void *buf, int len);
+int write_shm(void *hwbuf, void *buf, int len);
+
+#endif /* _PORTS_H_ */
+
diff --git a/dol/src/dol/visitor/epiphany/template/Makefile b/dol/src/dol/visitor/epiphany/template/Makefile
new file mode 100644 (file)
index 0000000..90cc3bf
--- /dev/null
@@ -0,0 +1,80 @@
+# Makefile
+
+# Host and Epiphany application destination
+DEST   := bin
+
+# Host source and object folder
+HSRC   := hsrc
+HDEST  := hobj
+
+# Epiphany source, library and object folder
+ESRC   := esrc
+EDEST  := eobj
+ELIB   := lib
+
+# Host application and host objects
+HOSTAPP        = $(DEST)/ep_application
+HOBJS  = $(HDEST)/main.o
+
+# Epiphany applications and common objects
+EPAPPS = @@SREC_FILES@@
+EWRAPPERS = $(patsubst $(DEST)%,$(EDEST)%,$(EPAPPS:.srec=_Wrapper.o))
+ECOMMON        = $(EDEST)/dol.o $(EDEST)/ports.o $(EDEST)/index.o
+
+# Epiphany build flags
+CC     = e-gcc
+OBJCOPY        = e-objcopy
+CFLAGS = -Os -std=c99 -Ilib -falign-loops=8 -falign-functions=8 -Wall
+LFLAGS = -T$(EPIPHANY_HOME)/bsps/current/fast.ldf -le-lib
+OCFLAGS        = -R .shared_dram -R .data_bank3
+
+# Host build flags
+HOSTCC = gcc
+HCFLAGS        = -O2 -std=c99 -I$(EPIPHANY_HOME)/tools/host/include -Wall
+HLFLAGS        = -L$(EPIPHANY_HOME)/tools/host/lib -le-hal
+
+# Global rules
+.SECONDARY:
+.PHONY: all run host cores clean
+all: run
+
+host: $(HOSTAPP)
+
+cores: $(ECOMMON) $(EWRAPPERS) $(EPAPPS)
+
+run: host cores
+       @echo -e "\tRUN"
+       @sudo LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
+             EPIPHANY_HDF=$(EPIPHANY_HDF) \
+             $(HOSTAPP)
+
+clean:
+       @echo -e "\tCLEAN"
+       @rm -v -f $(HOSTAPP) $(EPAPPS) $(EDEST)/* $(HDEST)/*
+
+# Host rules
+$(HOSTAPP): $(HOBJS)
+       @echo -e "\t(HOST)     LINK\t$@"
+       @$(HOSTCC) -o $@ $^ $(HLFLAGS)
+
+$(HDEST)/%.o: $(HSRC)/%.c
+       @echo -e "\t(HOST)     CC\t$@"
+       @$(HOSTCC) $(HCFLAGS) -c -o $@ $^
+
+# Epiphany rules
+$(DEST)/%.srec: $(EDEST)/%.elf
+       @echo -e "\t(EPIPHANY) OBJCOPY $@"
+       @$(OBJCOPY) $(OCFLAGS) --output-target srec --srec-forceS3 $^ $@
+
+$(EDEST)/%.elf: $(EDEST)/%.o $(EDEST)/%_Wrapper.o $(ECOMMON)
+       @echo -e "\t(EPIPHANY) LINK\t$@"
+       @$(CC) -o $@ $^ $(LFLAGS)
+
+$(EDEST)/%.o: $(ESRC)/%.c
+       @echo -e "\t(EPIPHANY) CC\t$@"
+       @$(CC) $(CFLAGS) -c -o $@ $^
+
+$(EDEST)/%.o: $(ELIB)/%.c
+       @echo -e "\t(EPIPHANY) CC\t$@"
+       @$(CC) $(CFLAGS) -c -o $@ $^
+
diff --git a/dol/src/dol/visitor/epiphany/template/main.c b/dol/src/dol/visitor/epiphany/template/main.c
new file mode 100644 (file)
index 0000000..e729879
--- /dev/null
@@ -0,0 +1,149 @@
+/* Epiphany Host Application */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "e-hal.h"
+
+/* common data structures */
+#include "../shared.h"
+
+#define FAIL(...) { fprintf(stderr, __VA_ARGS__); exit(1); }
+#define SHM_OFFSET 0x01000000
+
+#define ROW(X) (X/CORES_PER_ROW)
+#define COL(X) (X%CORES_PER_ROW)
+
+#define NUM_PROGRAMS   @@SREC_NUM@@
+
+#if NUM_PROGRAMS > NUM_CORES
+  #error "Please limit the number of processes to the number of cores."
+#endif
+
+/* programs to run */
+char programs[NUM_PROGRAMS][64] = {
+@@SREC_FILES@@
+};
+
+/* local copy of shared memory */
+shm_t  shm = {{ 0 }};
+
+void shm_init(void) {
+@@SHM_BUF_INIT@@
+}
+
+int main(int argc, char *argv[])
+{
+       char filename[255];     /* filename to load */
+
+       /* core states */
+       int32_t states[NUM_CORES]     = { 0 };
+       int32_t laststates[NUM_CORES] = { 0 };
+
+       e_epiphany_t dev;
+       e_mem_t      emem;
+
+       e_set_host_verbosity(H_D0);
+       e_set_loader_verbosity(L_D0);
+
+       /* init board, reset epiphany, open workgroup */
+       if(e_init(NULL) != E_OK)
+               FAIL("Can't init!\n");
+       e_reset_system();
+       if(e_open(&dev, 0, 0, 4, 4) != E_OK)
+               FAIL("Can't open!\n");
+
+       /* initialize, allocate and update shared memory buffer */
+       shm_init();
+       if(e_alloc(&emem, SHM_OFFSET, sizeof(shm_t)) != E_OK)
+               FAIL("Can't alloc!\n");
+       if(e_write(&emem, 0, 0, (off_t)0, &shm, sizeof(shm_t)) == E_ERR)
+               FAIL("Can't clear shm!\n");
+       if(e_write(&emem, 0, 0, (off_t)0, &states, sizeof(states)) == E_ERR)
+               FAIL("Can't clear states!\n");
+
+       /* load and start all programs */
+       for(int i = 0; i < NUM_PROGRAMS; i++) {
+               snprintf(filename, 255, "%s", programs[i]);
+               printf("Kicking core %i = (%i, %i) with '%s'\n",
+                       i, ROW(i), COL(i), filename);
+               if(e_load(filename, &dev, ROW(i), COL(i), E_TRUE) != E_OK)
+                       FAIL("Can't load %i!\n", i);
+       }
+
+       /* =============================================================== */
+       printf("Started %i cores.\n", NUM_PROGRAMS);
+       while(1) {
+               int done = 1;
+
+               /* poll shm states for changes */
+               printf("Polling shared memory.\n");
+
+               while(1) {
+                       /* read epiphany core states */
+                       if(e_read(&emem, 0, 0, (off_t)0, &states,
+                               sizeof(states)) == E_ERR)
+                                       FAIL("Can't poll!\n");
+
+                       /* check for state changes */
+                       if(memcmp(laststates, states, sizeof(states)))
+                               break;
+               };
+
+               /* save current states */
+               memcpy(laststates, states, sizeof(states));
+
+               /* print core states */
+               for(int i = 0; i < NUM_PROGRAMS; i++) {
+                       printf("CORE %i: ", i);
+                       switch(states[i]) {
+                       case -1: printf("done "); break;
+                       default: printf("state %i ", states[i]); done=0; break;
+                       }
+                       printf("\n");
+               }
+               printf("CORE14: 0x%x\n", states[14]);
+               printf("CORE15: 0x%x\n", states[15]);
+
+               /* stop polling if all cores finished */
+               if(done) break;
+       }
+       /* =============================================================== */
+
+       printf("All cores finished.\n");
+
+       /* read whole shm buffer */
+       if(e_read(&emem, 0, 0, (off_t)0, &shm, sizeof(shm)) == E_ERR)
+               FAIL("Can't read full shm!\n");
+
+       /* print buffer 0 and buffer 1 */
+       for(int i = 0; i < 16; i++) {
+               printf("0x%x ", shm.buf0.buf[i]);
+       } printf("\n");
+       for(int i = 0; i < 16; i++) {
+               printf("0x%x ", shm.buf1.buf[i]);
+       } printf("\n");
+
+
+       for(int i = 0; i < 4; i++) {
+               printf("%.2f\t", ((float*)shm.buf0.buf)[i]);
+       } printf("\n");
+
+       for(int i = 0; i < 8; i++) {
+               printf("%.2f\t", ((float*)shm.buf1.buf)[i]);
+       } printf("\n");
+
+       /* free shm buffer, close workgroup and finalize */
+       if(e_free(&emem) != E_OK)
+               FAIL("Can't free!\n");
+       if(e_close(&dev) != E_OK)
+               FAIL("Can't close!\n");
+       if(e_finalize() != E_OK)
+               FAIL("Can't finalize!\n");
+
+       return(0);
+}
+
diff --git a/dol/src/dol/visitor/epiphany/template/process_Wrapper.c b/dol/src/dol/visitor/epiphany/template/process_Wrapper.c
new file mode 100644 (file)
index 0000000..def5887
--- /dev/null
@@ -0,0 +1,65 @@
+/* @@PROCESSNAME@@_Wrapper
+ * ===================================================================== */
+#include <e_lib.h>
+#include <string.h>
+#include "../esrc/@@PROCESSNAME@@.h"
+#include "../shared.h"
+#include "ports.h"
+#include "index.h"
+
+shm_t shm SECTION(".shared_dram");
+
+/* DOL structures
+ * ===================================================================== */
+struct _DOL_wptr @@PROCESSNAME@@_wptr = {
+       1,              /* active   */
+       {0,0,0,0}       /* instance */
+};
+
+@@PROCESSNAME@@_State @@PROCESSNAME@@_local;
+DOLProcess @@PROCESSNAME@@_process = {
+       &@@PROCESSNAME@@_local,
+       &@@PROCESSNAME@@_init,
+       &@@PROCESSNAME@@_fire,
+       &@@PROCESSNAME@@_wptr,
+};
+
+/* Port Read/Write Functions
+ * ===================================================================== */
+@@PORTFUNCTIONS@@
+
+/* Port Mapping
+ * ===================================================================== */
+#define NUM_PORTS @@NUM_PORTS@@
+port_t ports[NUM_PORTS] = {
+@@PORTMAPPING@@
+};
+
+port_t *get_port(void *port)
+{
+       for(int i = 0; i < NUM_PORTS; i++) {
+               if(!strncmp(ports[i].name, port, PORTNAME_MAXLEN)) {
+                       /* found the port */
+                       return(&ports[i]);
+               }
+       }
+       return(NULL);
+}
+
+/* eCore entry point
+ * ===================================================================== */
+int main(void)
+{
+       int index = core_id2lin(e_get_coreid());
+       int state = 0;
+
+       @@PROCESSNAME@@_process.init((struct _DOLProcess_struct*)&@@PROCESSNAME@@_process);
+       while(@@PROCESSNAME@@_process.wptr->active) {
+               shm.states[index] = ++state;
+               @@PROCESSNAME@@_process.fire((struct _DOLProcess_struct*)&@@PROCESSNAME@@_process);
+       }
+
+       shm.states[index] = -1;
+       while(1);
+}
+
diff --git a/dol/src/dol/visitor/epiphany/template/shared.h b/dol/src/dol/visitor/epiphany/template/shared.h
new file mode 100644 (file)
index 0000000..467b09f
--- /dev/null
@@ -0,0 +1,33 @@
+/* shared.h
+ * NOTE: shared between Host and Epiphany */
+#ifndef _SHARED_H_
+#define _SHARED_H_
+
+#ifndef PACKED
+#define PACKED __attribute__((packed))
+#endif
+
+#include <stdint.h>
+
+#define NUM_CORES      16
+#define CORES_PER_ROW  4
+
+typedef struct {
+       volatile uint32_t rp;
+       volatile uint32_t wp;
+       volatile uint32_t size;
+       char     buf[];
+} PACKED hwbuf_t;
+@@SHM_BUF_STRUCTS@@
+typedef struct {
+       uint32_t counters[2];
+} PACKED coredata_t;
+
+typedef struct {
+       int32_t    states[NUM_CORES];
+       coredata_t cores[NUM_CORES];
+       buf0_t     buf0;
+       buf1_t     buf1;
+} PACKED shm_t;
+
+#endif /* _SHARED_H_ */