HOBJS = $(HDEST)/main.o
# Epiphany applications and common objects
-EPAPPS = $(DEST)/Beam_Former.srec
+EPAPPS = $(DEST)/Gen.srec $(DEST)/Square.srec #$(DEST)/Beam_Former.srec
EWRAPPERS = $(patsubst $(DEST)%,$(EDEST)%,$(EPAPPS:.srec=_Wrapper.o))
-ECOMMON = $(EDEST)/dol.o $(EDEST)/buffers.o
+ECOMMON = $(EDEST)/dol.o $(EDEST)/ports.o $(EDEST)/index.o
# Epiphany build flags
CC = e-gcc
OBJCOPY = e-objcopy
-CFLAGS = -O2 -falign-loops=8 -falign-functions=8 -Wall -Ilib
+CFLAGS = -O2 -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 = -I$(EPIPHANY_HOME)/tools/host/include -std=c99 -Wall
+HCFLAGS = -O2 -std=c99 -I$(EPIPHANY_HOME)/tools/host/include -Wall
HLFLAGS = -L$(EPIPHANY_HOME)/tools/host/lib -le-hal
# Global rules
--- /dev/null
+#include <stdio.h>
+#include "Gen.h"
+
+void Gen_delay(void)
+{
+ for(volatile int a = 0; a < 50; a++)
+ for(volatile int b = 0; b < 2000000; b++)
+ ;
+}
+
+void Gen_init(DOLProcess *p) {
+ ((Gen_State*)p->local)->index = 0;
+}
+
+int Gen_fire(DOLProcess *p) {
+ float i;
+
+ if (p->local->index < LENGTH) {
+Gen_delay();
+ p->local->index++;
+ i = p->local->index;
+ DOL_write(PORT_OUTPUT, &i, sizeof(float), p);
+ } else {
+ DOL_detach(p);
+ }
+
+ return 0;
+}
--- /dev/null
+#ifndef GEN_H
+#define GEN_H
+
+#include <dol.h>
+
+#define PORT_OUTPUT "0"
+
+#define LENGTH 8
+
+typedef struct _local_states {
+ int index;
+} Gen_State;
+
+void Gen_init(DOLProcess *);
+int Gen_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include "Square.h"
+
+#include "../shared.h"
+extern shm_t shm;
+
+void Square_delay(void)
+{
+ for(volatile int a = 0; a < 25; a++)
+ for(volatile int b = 0; b < 25; b++)
+ ;
+}
+
+void Square_init(DOLProcess *p) {
+ ((Square_State*)p->local)->index = 0;
+}
+
+int Square_fire(DOLProcess *p) {
+ float i;
+
+ if (((Square_State*)p->local)->index < LENGTH) {
+ DOL_read(PORT_INPUT, &i, sizeof(float), p);
+ i = i*i;
+ DOL_write(PORT_OUTPUT, &i, sizeof(float), p);
+ ((Square_State*)p->local)->index++;
+ } else {
+ DOL_detach(p);
+ }
+
+ return 0;
+}
--- /dev/null
+#ifndef SQUARE_H
+#define SQUARE_H
+
+#include <dol.h>
+
+#define PORT_INPUT "0"
+#define PORT_OUTPUT "1"
+
+#define LENGTH 8
+
+typedef struct _local_states {
+ int index;
+} Square_State;
+
+void Square_init(DOLProcess *);
+int Square_fire(DOLProcess *);
+
+#endif
--- /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/4)
+#define COL(X) (X%4)
+
+#define NUM_PROGRAMS 2
+
+/* programs to run */
+char programs[NUM_PROGRAMS][64] = {
+ "bin/Square.srec",
+ "bin/Gen.srec",
+};
+
+/* local copy of shared memory */
+shm_t shm = {{ 0 }};
+
+#if 0
+static uint32_t xorshift32(void)
+{
+ static uint32_t x = 314159265;
+ x ^= x << 17;
+ x ^= x >> 13;
+ x ^= x << 5;
+ return(x);
+}
+#endif
+
+void shm_init(void) {
+ /* input data */
+ shm.buf0.size = 8;
+ shm.buf0.rp = 0;
+ shm.buf0.wp = 0;
+
+ /* output data */
+ shm.buf1.size = 32;
+ shm.buf1.rp = 0;
+ shm.buf1.wp = 0;
+}
+
+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
+/* Gen_Wrapper
+ * ===================================================================== */
+#include <e_lib.h>
+#include <string.h>
+#include "../esrc/Gen.h"
+#include "../shared.h"
+#include "ports.h"
+#include "index.h"
+
+shm_t shm SECTION(".shared_dram");
+
+/* DOL structures
+ * ===================================================================== */
+struct _DOL_wptr Gen_wptr = {
+ 1, /* active */
+ {0,0,0,0} /* instance */
+};
+
+Gen_State Gen_local;
+DOLProcess Gen_process = {
+ &Gen_local,
+ &Gen_init,
+ &Gen_fire,
+ &Gen_wptr,
+};
+
+/* Port Read/Write Functions
+ * ===================================================================== */
+int size_0 (void) { return(size_shm (&shm.buf0)); }
+int level_0(void) { return(level_shm(&shm.buf0)); }
+int read_0 (void *buf, int len) { return(read_shm (&shm.buf0, buf, len)); }
+int write_0(void *buf, int len) { return(write_shm(&shm.buf0, buf, len)); }
+
+/* Port Mapping
+ * ===================================================================== */
+#define NUM_PORTS 1
+port_t ports[NUM_PORTS] = {
+ { "0", size_0, level_0, NULL, write_0},
+};
+
+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;
+
+ Gen_process.init((struct _DOLProcess_struct*)&Gen_process);
+ while(Gen_process.wptr->active) {
+ shm.states[index] = ++state;
+ Gen_process.fire((struct _DOLProcess_struct*)&Gen_process);
+ }
+
+ shm.states[index] = -1;
+ while(1);
+}
+
--- /dev/null
+/* Square_Wrapper
+ * ===================================================================== */
+#include <e_lib.h>
+#include <string.h>
+#include "../esrc/Square.h"
+#include "../shared.h"
+#include "ports.h"
+#include "index.h"
+
+shm_t shm SECTION(".shared_dram");
+
+/* DOL structures
+ * ===================================================================== */
+struct _DOL_wptr Square_wptr = {
+ 1, /* active */
+ {0,0,0,0} /* instance */
+};
+
+Square_State Square_local;
+DOLProcess Square_process = {
+ &Square_local,
+ &Square_init,
+ &Square_fire,
+ &Square_wptr,
+};
+
+/* Port Read/Write Functions
+ * ===================================================================== */
+int size_0 (void) { return(size_shm (&shm.buf0)); }
+int level_0(void) { return(level_shm(&shm.buf0)); }
+int read_0 (void *buf, int len) { return(read_shm (&shm.buf0, buf, len)); }
+int write_0(void *buf, int len) { return(write_shm(&shm.buf0, buf, len)); }
+int size_1 (void) { return(size_shm (&shm.buf1)); }
+int level_1(void) { return(level_shm(&shm.buf1)); }
+int read_1 (void *buf, int len) { return(read_shm (&shm.buf1, buf, len)); }
+int write_1(void *buf, int len) { return(write_shm(&shm.buf1, buf, len)); }
+
+/* Port Mapping
+ * ===================================================================== */
+#define NUM_PORTS 2
+port_t ports[NUM_PORTS] = {
+ { "0", size_0, level_0, read_0, NULL },
+ { "1", size_1, level_1, NULL, write_1 },
+};
+
+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;
+
+ Square_process.init((struct _DOLProcess_struct*)&Square_process);
+ while(Square_process.wptr->active) {
+ shm.states[index] = ++state;
+ Square_process.fire((struct _DOLProcess_struct*)&Square_process);
+ }
+
+ shm.states[index] = -1;
+ while(1);
+}
+
--- /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;
+#define DEBUG0(X) { shm.states[14] = (uint32_t)(X); }
+#define DEBUG1(X) { shm.states[15] = (uint32_t)(X); }
+
+void delay()
+{
+ for(volatile long a = 0; a < 25; a++)
+ for(volatile long b = 0; b < 2000000; b++)
+ ;
+}
+
+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;
+
+DEBUG1(level_shm(hwbuf)); delay();
+
+ 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
+/* 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
+
+typedef struct {
+ volatile uint32_t rp;
+ volatile uint32_t wp;
+ volatile uint32_t size;
+ char buf[];
+} PACKED hwbuf_t;
+
+typedef struct {
+ uint32_t rp;
+ uint32_t wp;
+ uint32_t size;
+ char buf[8];
+} PACKED buf0_t;
+
+typedef struct {
+ uint32_t rp;
+ uint32_t wp;
+ uint32_t size;
+ char buf[32];
+} PACKED buf1_t;
+
+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_ */