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