dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cbe / lib / ProcessFifo.h
1 /**************************************************************** \r
2  *      FIFO Functions\r
3  *      Creator: lschor, 2008-10-30\r
4  *      Description: Defines Main functions for a FIFO in the Local Store of a SPE\r
5  *      \r
6  *      Revision: \r
7  *      - 2008-11-08: Created\r
8  *      - 2008-11-15: Added Performance Estimation methods\r
9  */\r
10 \r
11 #ifndef _PROCESS_FIFO_H_\r
12 #define _PROCESS_FIFO_H_\r
13 \r
14 // Maximum data allowed in the FIFO\r
15 static const int MAXELEMENT = 1024; \r
16 \r
17 // Varialbes to store a fifo-read process\r
18 uint32_t tag_id_read = 99;\r
19 uint32_t lenRead = 0; \r
20 uint32_t queueRead = 0; \r
21 char * resultRead; \r
22 \r
23 char *locBuf[NUM_FIFO];\r
24 int locBufCount[NUM_FIFO]; \r
25 int locBufStart[NUM_FIFO]; \r
26 \r
27 // How many is free in a fifo\r
28 uint32_t freespaceQueue(int queue)\r
29 {\r
30         return MAXELEMENT - locBufCount[queue]; \r
31 }\r
32 \r
33 \r
34 // Init all fifos\r
35 void initQueues()\r
36 {\r
37         int j; \r
38         for (j = 0; j < NUM_FIFO; j++)\r
39         {\r
40                 locBuf[j] = NULL;\r
41                 locBufCount[j] = 0;\r
42                 locBufStart[j] = 0;\r
43         }\r
44 }\r
45 \r
46 // Init a special queue\r
47 void initLocBuf(int queue)\r
48 {\r
49         locBuf[queue] = NULL;\r
50         locBufCount[queue] = 0;\r
51         locBufStart[queue] = 0;\r
52 }\r
53 \r
54 // Gives the memory of the buffers free\r
55 void deinitLocBuf()\r
56 {\r
57         int j; \r
58         for (j = 0; j < NUM_FIFO; j++)\r
59         {\r
60                 if (locBuf[j] != NULL)\r
61                 {\r
62                         free(locBuf[j]);\r
63                 }\r
64         }\r
65 }\r
66 \r
67 void updateLocBuf(int queue)\r
68 {\r
69         // If the buffer is used the first time, allocate him\r
70         if (locBuf[queue]== NULL)\r
71         {\r
72                 locBuf[queue] = (char *)malloc(MAXELEMENT * sizeof(char));\r
73         }\r
74 #ifdef MEASURE_DOL_READ_START_DMA\r
75         double t_dol_read_start_dma = spu_read_decrementer();\r
76 #endif\r
77 \r
78         // Double-Buffering --> Try to close the old read-process\r
79         if (tag_id_read != 99)\r
80         {\r
81                 waittag(tag_id_read); \r
82                 // Write the data you read into the queue; \r
83                 int i;  \r
84 \r
85                 #ifdef MEASURE_DOL_READ_DOUBLEBUF\r
86                         double t_dol_read_doublebuf = spu_read_decrementer();\r
87                 #endif\r
88 \r
89                 // Has to write all elements at the beginning or write all elements at the end of the buffer\r
90                 if (locBufStart[queueRead] + locBufCount[queueRead] > MAXELEMENT || locBufStart[queueRead] + locBufCount[queueRead] + lenRead < MAXELEMENT)\r
91                 {\r
92                         memcpy(&(locBuf[queueRead][(locBufStart[queueRead] + locBufCount[queueRead]) % MAXELEMENT]), resultRead, lenRead);\r
93                 }\r
94                 \r
95                 // Otherwise something at the end and something at the beginning\r
96                 else\r
97                 {\r
98                         // At the end of the buffer\r
99                         memcpy(&(locBuf[queueRead][(locBufStart[queueRead] + locBufCount[queueRead])]), resultRead, MAXELEMENT - locBufStart[queueRead] - locBufCount[queueRead]);\r
100                         \r
101                         // At the beginning\r
102                         memcpy(locBuf[queueRead], &(resultRead[MAXELEMENT - locBufStart[queueRead] - locBufCount[queueRead]]), lenRead - (MAXELEMENT - locBufStart[queueRead] - locBufCount[queueRead]));\r
103                 }\r
104 \r
105                 locBufCount[queueRead]+=lenRead;\r
106 \r
107                 #ifdef MEASURE_DOL_READ_DOUBLEBUF\r
108                         t_dol_read_doublebuf -= spu_read_decrementer();\r
109                         printf("DOL_READ_DOUBLEBUF_DMA;%f\n",t_dol_read_doublebuf * 1 / MEASURE_CPU);\r
110                 #endif\r
111 \r
112                 mfc_tag_release(tag_id_read); // release tag ID before exiting\r
113                 _free_align(resultRead);\r
114 \r
115                 // Send a okey about the data to the PPE\r
116                 spu_write_out_mbox((uint32_t)(SPE_READ_SUC << 28)); // stalls mailbox is full.\r
117                 tag_id_read = 99; \r
118         }\r
119         \r
120         uint32_t message = (SPE_READ_DEMAND << 28) | (queue << 16) | (freespaceQueue(queue));\r
121 \r
122 #ifdef MEASURE_DOL_READ_HANDSHAKE\r
123         double t_dol_read_handshake = spu_read_decrementer();\r
124 #endif\r
125 \r
126         spu_write_out_mbox((uint32_t)(message)); \r
127                         \r
128         message = spu_read_in_mbox(); \r
129         uint32_t request = message >> 28; \r
130         lenRead = (0xffff & message);\r
131 \r
132         if (request != (uint32_t) 1)\r
133         {\r
134                 return; \r
135         }\r
136         \r
137         if((tag_id_read=mfc_tag_reserve())==MFC_TAG_INVALID){\r
138                 printf("SPE: ERROR - can't reserve a tag ID\n"); return;\r
139         }\r
140         \r
141         // Wait for the response of the PPE --> The address where to read\r
142         uint32_t ea_mfc_h, ea_mfc_l;\r
143         uint64_t ea_mfc;\r
144                         \r
145         ea_mfc_h  = spu_read_in_mbox(); \r
146         ea_mfc_l  = spu_read_in_mbox();\r
147         ea_mfc = mfc_hl2ea(ea_mfc_h, ea_mfc_l); \r
148 \r
149 #ifdef MEASURE_DOL_READ_HANDSHAKE\r
150         t_dol_read_handshake -= spu_read_decrementer();\r
151         printf("DOL_READ_HANDSHAKE;%f\n",t_dol_read_handshake * 1 / MEASURE_CPU);\r
152 #endif\r
153 \r
154 #ifdef MEASURE_DOL_READ_START_DMA\r
155         t_dol_read_start_dma -= spu_read_decrementer();\r
156         printf("DOL_READ_START_DMA;%f\n",t_dol_read_start_dma * 1 / MEASURE_CPU);\r
157 #endif\r
158 \r
159         resultRead = (char *)_malloc_align(lenRead, 4); \r
160 \r
161 #ifdef MEASURE_DOL_READ_DMA\r
162         double t_dol_read_dma = spu_read_decrementer();\r
163 #endif\r
164         \r
165         // Read the data from the address we got from the PPE\r
166         mfc_get(&(resultRead[0]), ea_mfc, lenRead, tag_id_read, 0, 0); \r
167 #ifdef MEASURE_DOL_READ_DMA\r
168         t_dol_read_dma -= spu_read_decrementer();\r
169         printf("DOL_READ_DMA;%f\n",t_dol_read_dma * 1 / MEASURE_CPU);\r
170 #endif\r
171 \r
172         queueRead = queue; \r
173 }\r
174 \r
175 // Read from the local buffer\r
176 void readLocBuf(int queue, void *destination, int len)\r
177 {\r
178 #ifdef MEASURE_DOL_READ_LOCBUF\r
179         double t_dol_read_locbuf = spu_read_decrementer();\r
180 #endif\r
181         int count = 0;\r
182         int newLen = 0;\r
183         char* buffer = (char*) destination;\r
184         int i; \r
185 \r
186         while (count < len)\r
187         {\r
188                 newLen = (len - count) > MAXELEMENT? MAXELEMENT : len - count;\r
189                 \r
190                 while (locBufCount[queue] < newLen)\r
191                 {\r
192                         updateLocBuf(queue); \r
193                 }\r
194 \r
195                 // Can directly read all elements from the end of the buffer\r
196                 if (locBufStart[queue] + newLen < MAXELEMENT)\r
197                 {\r
198                         memcpy(buffer,  &(locBuf[queue][locBufStart[queue]]), newLen);\r
199                 }\r
200 \r
201                 // Has to write from the end and from the beginning of the buffer\r
202                 else\r
203                 {\r
204                         memcpy(&(buffer[count]), &(locBuf[queue][locBufStart[queue]]), MAXELEMENT - locBufStart[queue]);\r
205                         memcpy(&(buffer[count + MAXELEMENT - locBufStart[queue]]), locBuf[queue], newLen - MAXELEMENT + locBufStart[queue]);\r
206                 }\r
207 \r
208                 locBufCount[queue] -= newLen;\r
209                 locBufStart[queue] = (locBufStart[queue] + newLen) % MAXELEMENT;                \r
210                 count += newLen;\r
211         }\r
212 #ifdef MEASURE_DOL_READ_LOCBUF\r
213         t_dol_read_locbuf -= spu_read_decrementer();\r
214         printf("DOL_READ_LOCBUF;%f\n",t_dol_read_locbuf * 1 / MEASURE_CPU);\r
215 #endif\r
216 }\r
217 \r
218 \r
219 #endif // _PROCESS_FIFO_H_ \r