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!
<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/**
--- /dev/null
+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"; }
+
+}
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!");
}
}
--- /dev/null
+/* 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);
+}
+
--- /dev/null
+/* 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_ */
--- /dev/null
+/* 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);
+}
+
--- /dev/null
+/* 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_ */
--- /dev/null
+/* 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);
+}
+
--- /dev/null
+/* 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_ */
+
--- /dev/null
+# 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 $@ $^
+
--- /dev/null
+/* 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);
+}
+
--- /dev/null
+/* @@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);
+}
+
--- /dev/null
+/* 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_ */