More infrastructure.
authorethereal <ethereal@ethv.net>
Mon, 8 Jun 2015 03:21:31 +0000 (03:21 +0000)
committerethereal <ethereal@ethv.net>
Mon, 8 Jun 2015 03:21:31 +0000 (03:21 +0000)
.gitignore
Makefile
src/CMakeLists.txt
src/ecommon.h [new file with mode: 0644]
src/ecore/ecore.c
src/ecore/ecore.h [new file with mode: 0644]
src/ecore/render.c [new file with mode: 0644]
src/ecore/render.h [new file with mode: 0644]
src/ecore/rreq.c [new file with mode: 0644]
src/ecore/rreq.h [new file with mode: 0644]
src/ewrap/main.c

index a680c7e..68a8b6a 100644 (file)
@@ -3,3 +3,5 @@
 /ewrap
 
 *.swp
+.ycm_*
+.vimrc
index c92961c..b753ee8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,9 +4,7 @@ all:
 
 .PHONY: redep
 redep:
-       mkdir -p build/
-       cd build/
-       cmake ..
+       mkdir -p build/ ; cd build/ ; cmake ..
 
 .PHONY: clean
 clean:
index 25f4e04..d411a1d 100644 (file)
@@ -9,7 +9,9 @@ if(${build_ecore})
     #add_custom_command(OUTPUT ecore.srec DEPENDS ecore.elf COMMAND e-objcopy --srec-forceS3 --output-target srec ecore.elf ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ecore.srec)
     #add_custom_target(ecore ALL DEPENDS ecore.srec)
 
-    add_custom_command(OUTPUT ecore.elf DEPENDS ecore/ecore.c COMMAND e-gcc -Wall -Wextra ${CMAKE_CURRENT_LIST_DIR}/ecore/ecore.c -o ecore.elf -le-lib -T$ENV{EPIPHANY_HOME}/bsps/current/internal.ldf)
+    aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/ecore/ sources)
+
+    add_custom_command(OUTPUT ecore.elf DEPENDS ${sources} COMMAND e-gcc -Wall -Wextra -std=c99 ${sources} -o ecore.elf -le-lib -T$ENV{EPIPHANY_HOME}/bsps/current/internal.ldf -ffreestanding)
     add_custom_command(OUTPUT ecore.srec DEPENDS ecore.elf COMMAND e-objcopy --srec-forceS3 --output-target srec ecore.elf ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ecore.srec)
     add_custom_target(ecore ALL DEPENDS ecore.srec)
 endif(${build_ecore})
diff --git a/src/ecommon.h b/src/ecommon.h
new file mode 100644 (file)
index 0000000..2e9daec
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef ECOMMON_H
+#define ECOMMON_H
+
+#include <stdint.h>
+
+typedef struct __attribute__((packed)) {
+    
+} shm_mat_t;
+
+typedef struct __attribute__((packed)) {
+    float x, y, z;
+    uint32_t mat;
+} shm_sph_t;
+
+typedef struct __attribute__((packed)) {
+    float x, y, z;
+    float dx, dy, dz, dw;
+    float fov;
+} shm_cam_t;
+
+typedef struct __attribute__((packed)) {
+    uint32_t width, height;
+    uint32_t fb_off;
+
+    uint32_t mat_off;
+    uint32_t mat_count;
+
+    uint32_t sph_off;
+    uint32_t sph_count;
+
+    uint32_t data_end;
+
+    uint32_t generation;
+    uint32_t finished;
+
+    shm_cam_t cam;
+} shm_region_t;
+
+#endif
index b77926b..bd1029b 100644 (file)
@@ -1,27 +1,31 @@
-#include <stdint.h>
+#include "ecore.h"
 
-#include "e_lib.h"
+#include "rreq.h"
+#include "render.h"
+
+e_memseg_t shared_mem;
+shm_region_t *shm_region;
 
 int main() {
-    e_coreid_t id = e_get_coreid();
+    e_shm_attach(&shared_mem, "raytrace_shm");
 
-    unsigned x, y;
-    e_coords_from_coreid(id, &x, &y);
-    
-    int iid = y*e_group_config.group_rows + x;
+    shm_region = (void *)(shared_mem.ephy_base);
 
-    e_memseg_t mem;
+    setup_range_request();
 
-    e_shm_attach(&mem, "message_shm");
+    e_coreid_t eid = e_get_coreid();
+    unsigned x, y;
+    e_coords_from_coreid(eid, &x, &y);
 
-    unsigned char buf = 1;
-    *((uint8_t *)mem.ephy_base + iid) = 1;
-    //e_write(&mem, &buf, e_group_config.core_row, e_group_config.core_col, (void *)14, 1);
-    //e_write(&e_emem_config, &buf, e_group_config.core_row, e_group_config.core_col, (void *)0, 1);
-    //uint8_t *ext = (uint8_t*)e_emem_config.base + 0x01000000;
+    e_irq_global_mask(E_FALSE);
+    e_irq_mask(E_USER_INT, E_FALSE);
 
-    //ext[0] = 1;
+    int id = y*e_group_config.group_rows + x;
+    while(1) {
+        request_new_range(id);
+        // do rendering
+        render_finished();
+    }
 
-    while(1) {}
     return 0;
 }
diff --git a/src/ecore/ecore.h b/src/ecore/ecore.h
new file mode 100644 (file)
index 0000000..8b9ead6
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef ECORE_H
+#define ECORE_H
+
+#define NCORES 16
+
+#include <stdint.h>
+#include <e_lib.h>
+
+#include "../ecommon.h"
+
+extern e_memseg_t shared_mem;
+
+extern shm_region_t *shm_region;
+
+#endif
diff --git a/src/ecore/render.c b/src/ecore/render.c
new file mode 100644 (file)
index 0000000..a1a1b6c
--- /dev/null
@@ -0,0 +1,19 @@
+#include "ecore.h"
+
+#include "render.h"
+
+uint32_t render_start, render_end;
+uint8_t __attribute__((section(".data_bank2"))) in_buffer[0x2000];
+void *in_buffer_ptr;
+uint32_t __attribute__((section(".data_bank3"))) out_buffer[NUM_OUT_ELEMENTS];
+
+void render_finished() {
+    // use DMA channel 1 to transfer results back
+    e_dma_desc_t desc;
+    e_dma_set_desc(E_DMA_1, E_DMA_ENABLE | E_DMA_WORD | E_DMA_MASTER, NULL,
+        4, 4, NUM_OUT_ELEMENTS, 1, 0, 0, out_buffer,
+        (uint8_t *)shared_mem.ephy_base + shm_region->fb_off + render_start,
+        &desc);
+    e_dma_start(&desc, E_DMA_1);
+    e_dma_wait(E_DMA_1);
+}
diff --git a/src/ecore/render.h b/src/ecore/render.h
new file mode 100644 (file)
index 0000000..141f63f
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef RENDER_H
+#define RENDER_H
+
+#define NUM_OUT_ELEMENTS 0x800/4
+
+void render_finished();
+
+extern uint32_t render_start, render_end;
+extern void *in_buffer_ptr;
+
+#endif
diff --git a/src/ecore/rreq.c b/src/ecore/rreq.c
new file mode 100644 (file)
index 0000000..3d6b81e
--- /dev/null
@@ -0,0 +1,114 @@
+#include "ecore.h"
+#include "render.h"
+
+uint8_t range_requests[NCORES];
+uint8_t idle_core_count;
+uint32_t range_start, range_end;
+uint32_t current_generation;
+
+uint8_t message_intr;
+
+e_dma_desc_t __attribute__((aligned(8))) dma_desc;
+
+
+void handle_range_request(int id) {
+    if(range_start >= range_end) {
+        // set core to be marked as idle
+        idle_core_count ++;
+        return;
+    }
+
+    uint8_t target_r = id%e_group_config.group_rows;
+    uint8_t target_c = id/e_group_config.group_rows;
+
+    // assign target core a rendering range
+    uint32_t len = range_end - range_start;
+    if(len > NUM_OUT_ELEMENTS) len = NUM_OUT_ELEMENTS;
+    uint32_t target_range_start = range_start;
+    uint32_t target_range_end = range_start + len;
+
+    e_write(&e_group_config, &target_range_start, target_r, target_c,
+        &render_start, 4);
+    e_write(&e_group_config, &target_range_end, target_r, target_c,
+        &render_end, 4);
+
+    // do cross-core read of current generation to check if it's up to date
+    uint32_t target_generation;
+    e_read(&e_group_config, &target_generation, target_r, target_c,
+        &current_generation, 4);
+
+    if(target_generation != shm_region->generation) {
+        // first update generation ID
+        e_write(&e_group_config, &current_generation, target_r, target_c,
+            &current_generation, 4);
+
+        // need to DMA in render data, using target core's DMA engine
+        e_dma_desc_t desc;
+        desc.config = E_DMA_ENABLE | E_DMA_WORD | E_DMA_MASTER | E_DMA_MSGMODE;
+        desc.inner_stride = 4 << 16 | 4;
+        desc.outer_stride = 0;
+        desc.src_addr = shm_region;
+        desc.dst_addr = in_buffer_ptr;
+        desc.count = 1 << 16 | shm_region->data_end/4;
+        e_write(&e_group_config, &desc, target_r, target_c, &dma_desc,
+            sizeof(desc));
+        // initiate DMA
+        uint32_t value = 0x08 | ((uint32_t)&dma_desc & 0xffff << 16);
+        e_write(&e_group_config, &value, target_r, target_c, (void *)0xf0520,
+            4);
+    }
+    else {
+        // render data already present, so just send a message IRQ
+        e_irq_set(target_r, target_c, E_MESSAGE_INT);
+    }
+}
+
+void __attribute((interrupt)) range_request_handler(
+    int __attribute__((unused)) irq) {
+
+    // clear ILAT entry to accept other pending requests
+    e_reg_write(E_REG_ILATCL, 1<<9);
+
+    for(int i = 0; i < NCORES; i ++) {
+        if(range_requests[i]) {
+            range_requests[i] = 0;
+            handle_range_request(i);
+        }
+    }
+
+    // are all cores idle?
+    if(idle_core_count == NCORES) {
+        shm_region->finished = 1;
+        // if so, wait for next generation to be set up
+        while(shm_region->generation == current_generation) {}
+        // mark all cores as non-idle
+        idle_core_count = 0;
+        shm_region->finished = 0;
+        // set up rendering range appropriately
+        range_start = 0, range_end = shm_region->height*shm_region->width;
+        // trigger handler again
+        e_reg_write(E_REG_ILATCL, 1<<9);
+    }
+}
+
+void __attribute((interrupt)) message_handler() {
+    message_intr = 1;
+}
+
+void setup_range_request() {
+    for(int i = 0; i < NCORES; i ++) range_requests[i] = 0;
+    current_generation = 0;
+
+    e_irq_attach(E_USER_INT, range_request_handler);
+    e_irq_set(E_USER_INT, 0, 0);
+}
+
+void request_new_range(int id) {
+    uint8_t one = 1;
+    e_write(&e_group_config, &one, 0, 0, range_requests + id, 1);
+
+    message_intr = 0;
+    e_irq_set(0, 0, E_USER_INT);
+
+    while(!message_intr) {}
+}
diff --git a/src/ecore/rreq.h b/src/ecore/rreq.h
new file mode 100644 (file)
index 0000000..bbe30db
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef RREQ_H
+#define RREQ_H
+
+void setup_range_request();
+void request_new_range(int id);
+
+#endif
index e9595b7..465497d 100644 (file)
@@ -4,6 +4,10 @@
 #include "e-hal.h"
 #include "e-loader.h"
 
+#include "../ecommon.h"
+
+shm_region_t *shm_region;
+
 int main() {
     e_platform_t platform;
     e_epiphany_t dev;
@@ -15,47 +19,46 @@ int main() {
 
     e_set_host_verbosity(H_D0);
 
-    int r = e_shm_alloc(&mem, "message_shm", platform.rows * platform.cols);
-    if(r != E_OK) r = e_shm_attach(&mem, "message_shm");
+    int r = e_shm_alloc(&mem, "raytrace_shm", platform.rows * platform.cols);
+    if(r != E_OK) r = e_shm_attach(&mem, "raytrace_shm");
     if(r != E_OK) {
         printf("Failed to attach to shared memory!\n");
         return 1;
     }
+    shm_region = mem.base;
 
     e_open(&dev, 0, 0, platform.rows, platform.cols);
     printf("rows, cols: %i, %i\n", platform.rows, platform.cols);
 
-
     uint8_t finished[platform.rows * platform.cols];
     for(int i = 0; i < platform.rows * platform.cols; i ++) finished[i] = 0;
     r = e_write(&mem, 0,0, 0, finished, platform.rows * platform.cols);
     if(r == E_ERR) { printf("Failed to write\n"); }
 
-    e_load_group("ecore.srec", &dev, 0, 0, 4, 4, E_TRUE);
+    /* ensure that core (0,0) is loaded first; it needs to finish initialization
+        strictly before the others do.
 
-    sleep(1);
+        XXX: guarantee this?
+    */
+    e_load("ecore.srec", &dev, 0, 0, E_TRUE);
 
-    int cnt = 0;
-    while(1) {
-        uint8_t finished[platform.rows * platform.cols];
-        e_read(&mem, 0,0, 0, finished, 16);
-        if(r == E_ERR) { printf("Failed to read\n"); }
-
-        cnt = 0;
-        for(int i = 0; i < 16; i ++) {
-            if(finished[i] != 0) {
-                cnt ++;
-                printf("%i finished! (%i)\n", i, finished[i]);
-            }
+    for(int i = 0; i < platform.rows; i ++) {
+        for(int j = 0; j < platform.cols; j ++) {
+            if(i == 0 && j == 0) continue;
+            e_load("ecore.srec", &dev, i, j, E_TRUE);
         }
-        if(cnt != 0) break;
     }
 
-    if(cnt) printf("Received message from a core!\n");
+    // rendering loop
 
-    e_close(&dev);
+    // pseudo-code:
+    // - wait for shm_region->finished == 1
+    // 
+    while(shm_region->finished == 0) {}
+    printf("Finished!\n");
 
-    e_shm_release("message_shm");
+    e_close(&dev);
+    e_shm_release("raytrace_shm");
     e_finalize();
 
     return 0;