From: Sebastian Date: Tue, 10 Dec 2013 21:11:06 +0000 (+0100) Subject: dol: initial epiphany code generator (untested) X-Git-Url: http://sraa.de/git/?a=commitdiff_plain;h=2858109405a90a4d9df149b10444678d42e41c59;p=jump.git dol: initial epiphany code generator (untested) 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! --- diff --git a/dol/build.xml b/dol/build.xml index 27e1207..8538220 100644 --- a/dol/build.xml +++ b/dol/build.xml @@ -62,6 +62,8 @@ _buffers = new Vector(); + 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 index 0000000..fed6ca4 --- /dev/null +++ b/dol/src/dol/visitor/epiphany/lib/dol.c @@ -0,0 +1,94 @@ +/* DOL Block Implementation */ + +#include +#include +#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 index 0000000..f8424d1 --- /dev/null +++ b/dol/src/dol/visitor/epiphany/lib/dol.h @@ -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 index 0000000..4841b7d --- /dev/null +++ b/dol/src/dol/visitor/epiphany/lib/index.c @@ -0,0 +1,20 @@ +/* index.c: some index calculations */ + +#include + +#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 index 0000000..6327333 --- /dev/null +++ b/dol/src/dol/visitor/epiphany/lib/index.h @@ -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 index 0000000..240474b --- /dev/null +++ b/dol/src/dol/visitor/epiphany/lib/ports.c @@ -0,0 +1,69 @@ +/* ports implementation */ +#include + +#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 index 0000000..40d88d0 --- /dev/null +++ b/dol/src/dol/visitor/epiphany/lib/ports.h @@ -0,0 +1,24 @@ +/* ports header */ +#ifndef _PORTS_H_ +#define _PORTS_H_ + +#include +#include + +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 index 0000000..90cc3bf --- /dev/null +++ b/dol/src/dol/visitor/epiphany/template/Makefile @@ -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 index 0000000..e729879 --- /dev/null +++ b/dol/src/dol/visitor/epiphany/template/main.c @@ -0,0 +1,149 @@ +/* Epiphany Host Application */ + +#include +#include +#include +#include +#include + +#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 index 0000000..def5887 --- /dev/null +++ b/dol/src/dol/visitor/epiphany/template/process_Wrapper.c @@ -0,0 +1,65 @@ +/* @@PROCESSNAME@@_Wrapper + * ===================================================================== */ +#include +#include +#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 index 0000000..467b09f --- /dev/null +++ b/dol/src/dol/visitor/epiphany/template/shared.h @@ -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 + +#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_ */