fbefdd3d1cd290cbf22b3f198166dff21865b836
[sphoot.git] / src / ecore / rreq.c
1 #include "ecore.h"
2 #include "render.h"
3
4 uint8_t range_requests[NCORES];
5 uint32_t idle_cores;
6 uint32_t range_start, range_end;
7 uint32_t current_generation;
8
9 uint8_t message_intr;
10
11 e_dma_desc_t __attribute__((aligned(8))) dma_desc;
12
13
14 void handle_range_request(int id) {
15     shm_region->msg[id] = 6;
16     if(range_start >= range_end) {
17         // set core to be marked as idle
18         idle_cores |= (1<<id);
19         return;
20     }
21     shm_region->msg[id] = 7;
22     range_requests[id] = 0;
23
24     uint8_t target_r = id%e_group_config.group_rows;
25     uint8_t target_c = id/e_group_config.group_rows;
26
27     // assign target core a rendering range
28     uint32_t len = range_end - range_start;
29     if(len > NUM_OUT_ELEMENTS) len = NUM_OUT_ELEMENTS;
30     uint32_t target_range_start = range_start;
31     uint32_t target_range_end = range_start + len;
32
33     e_write(&e_group_config, &target_range_start, target_r, target_c,
34         &render_start, 4);
35     e_write(&e_group_config, &target_range_end, target_r, target_c,
36         &render_end, 4);
37
38     // do cross-core read of current generation to check if it's up to date
39     uint32_t target_generation;
40     e_read(&e_group_config, &target_generation, target_r, target_c,
41         &current_generation, 4);
42
43     shm_region->msg[id] = 8;
44     if(target_generation != shm_region->generation) {
45         shm_region->msg[id] = 16 + target_generation;
46         // first update generation ID
47         e_write(&e_group_config, &shm_region->generation, target_r, target_c,
48             &current_generation, 4);
49
50 #if 0
51         // need to DMA in render data, using target core's DMA engine
52         e_dma_desc_t desc;
53         desc.config = E_DMA_ENABLE | E_DMA_WORD | E_DMA_MASTER | E_DMA_MSGMODE;
54         desc.inner_stride = 4 << 16 | 4;
55         desc.outer_stride = 0;
56         desc.src_addr = shm_region;
57         desc.dst_addr = in_buffer_ptr;
58         desc.count = 1 << 16 | shm_region->data_end/4;
59         e_write(&e_group_config, &desc, target_r, target_c, &dma_desc,
60             sizeof(desc));
61         // initiate DMA
62         uint32_t value = E_DMA_STARTUP | ((uint32_t)&dma_desc & 0xffff) << 16;
63         e_write(&e_group_config, &value, target_r, target_c,
64             (void *)E_REG_DMA1CONFIG, 4);
65 #endif
66
67         // XXX: debug
68         e_irq_set(target_r, target_c, E_MESSAGE_INT);
69     }
70     else {
71         // render data already present, so just send a message IRQ
72         e_irq_set(target_r, target_c, E_MESSAGE_INT);
73     }
74 }
75
76 void __attribute((interrupt)) range_request_handler(
77     int __attribute__((unused)) irq) {
78
79     shm_region->interrupts_fired ++;
80
81     // clear ILAT entry to accept other pending requests
82     e_reg_write(E_REG_ILATCL, 1<<9);
83
84     for(int i = 0; i < NCORES; i ++) {
85         if(range_requests[i]) {
86             handle_range_request(i);
87         }
88     }
89
90     // are all cores idle?
91     if(idle_cores == (1<<NCORES)-1) {
92         shm_region->finished = 1;
93         // if so, wait for next generation to be set up
94         while(shm_region->generation == current_generation) {}
95         // mark all cores as non-idle
96         idle_cores = 0;
97         shm_region->finished = 0;
98         // set up rendering range appropriately
99         range_start = 0, range_end = shm_region->height*shm_region->width;
100         shm_region->range_end = range_end;
101         // trigger handler again
102         e_reg_write(E_REG_ILATST, 1<<9);
103     }
104 }
105
106 void __attribute((interrupt)) message_handler() {
107     message_intr = 1;
108     shm_region->messages_received ++;
109 }
110
111 void setup_range_request() {
112     for(int i = 0; i < NCORES; i ++) range_requests[i] = 0;
113     current_generation = 0;
114
115     e_irq_attach(E_USER_INT, range_request_handler);
116     e_irq_attach(E_MESSAGE_INT, message_handler);
117 }
118
119 void request_new_range(int id) {
120     uint8_t one = 1;
121     e_write(&e_group_config, &one, 0, 0, range_requests + id, 1);
122
123     message_intr = 0;
124     e_irq_set(0, 0, E_USER_INT);
125     shm_region->msg[id] = 5;
126     while(!message_intr) {}
127 }