dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cbe / lib / ProcessWrapper.h
1 /**************************************************************** \r
2  *      Process Wrapper Functions\r
3  *      Creator: lschor, 2008-10-30\r
4  *      Description: General process wrapper file, includes DOL_read and DOL_write as main functions\r
5  *      \r
6  *      Revision: \r
7  *      - 2008-10-30: Created\r
8  *      - 2008-11-08: Update to Double Buffering\r
9  *      - 2008-11-15: Added Performance Estimation methods\r
10  */\r
11 \r
12 #ifndef __PROCESS_WRAPPER_H__\r
13 #define __PROCESS_WRAPPER_H__\r
14 \r
15 #include <spu_intrinsics.h>\r
16 #include <spu_mfcio.h>\r
17 #include <string.h>\r
18 #include <stdio.h>\r
19 #include <stdarg.h>             // Used for va_list\r
20 #include <stdlib.h>\r
21 #include "lib/malloc_align.h"   // Malloc for DMA\r
22 #include "lib/free_align.h"     // Free for DMA\r
23 #include "dol.h"\r
24 #include "common.h"\r
25 #include "estimation.h"\r
26 \r
27 //Cell Macros\r
28 #define waittag(tag_id) mfc_write_tag_mask(1<<tag_id);  mfc_read_tag_status_all();\r
29 \r
30 //DOL macros\r
31 #define GETINDEX(dimension) \\r
32     ((ProcessWrapper*)(p->wptr))->index[dimension]\r
33 \r
34 #define CREATEPORTVAR(name) \\r
35     int name\r
36 \r
37 #define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \\r
38     createPort(&port, base, number_of_indices, index_range_pairs)\r
39 \r
40 // Include the FIFO Functions\r
41 #include "lib/ProcessFifo.h"\r
42 \r
43 // Include some help functions\r
44 #include "lib/ProcessWrapperHelp.h"\r
45 \r
46 // Struct for a process\r
47 typedef struct _process_wrapper {\r
48         char*           name;\r
49         uint32_t*       index;\r
50         uint32_t        is_detached;\r
51         uint32_t*       port_id;\r
52         uint32_t*       port_queue_id;\r
53         uint32_t        number_of_ports;\r
54 } ProcessWrapper;\r
55 \r
56 // Tag address for the write process\r
57 uint32_t tag_id_write = 99; \r
58 \r
59 // Pointer to the current data buffer\r
60 char * resultWrite; \r
61 \r
62 /**\r
63  * Finish a DOL_write process\r
64  */\r
65 void finish_DOL_write()\r
66 {\r
67         if (tag_id_write != 99)\r
68         {\r
69                 #ifdef MEASURE_DOL_WRITE_FINISH\r
70                         double t_dol_write_finish = spu_read_decrementer();\r
71                 #endif\r
72 \r
73                 // Wait until the write process is finished\r
74                 waittag(tag_id_write);\r
75                 mfc_tag_release(tag_id_write); // release tag ID before exiting\r
76                 _free_align(resultWrite);\r
77                 // Send a okey about the data to the PPE\r
78                 spu_write_out_mbox((uint32_t)(SPE_WRITE_SUC << 28)); // stalls mailbox is full.\r
79                 tag_id_write = 99; \r
80                 //queueWrite = -1;\r
81 \r
82                 #ifdef MEASURE_DOL_WRITE_FINISH\r
83                         t_dol_write_finish -= spu_read_decrementer();\r
84                         printf("DOL_WRITE_FINISH;%f\n",t_dol_write_finish * 1 / MEASURE_CPU);\r
85                 #endif\r
86 \r
87         }\r
88 }\r
89 \r
90 /**\r
91  * Read from the FIFO\r
92  */\r
93 void DOL_read(void *port, void *buf, int len, DOLProcess *process)\r
94 {\r
95 #ifdef MEASURE_DOL_READ\r
96         double t_dol_read = spu_read_decrementer();\r
97 #endif\r
98 \r
99         ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;\r
100         int i; \r
101 \r
102         for (i = 0; i < process_wrapper->number_of_ports; i++) \r
103         {\r
104                 if (process_wrapper->port_id[i] == (int)port) \r
105                 {\r
106                         int queue = process_wrapper->port_queue_id[i];\r
107 \r
108                         finish_DOL_write(); \r
109                         \r
110                         // Try to get new data into the local Buffer\r
111                         updateLocBuf(queue); \r
112                         \r
113                         // Read from the Buffer\r
114                         readLocBuf(queue, buf, len); \r
115                         \r
116                         break; \r
117                 }\r
118         }\r
119 #ifdef MEASURE_DOL_READ\r
120         t_dol_read -= spu_read_decrementer();\r
121         printf("DOL_READ;%f\n",t_dol_read * 1 / MEASURE_CPU);\r
122 #endif\r
123 \r
124 }\r
125 \r
126 \r
127 /**\r
128  * Write data into the FIFO\r
129  */\r
130 void DOL_write(void *port, void *buf, int len, DOLProcess *process)\r
131 {\r
132 #ifdef MEASURE_DOL_WRITE\r
133         double t_dol_write = spu_read_decrementer();\r
134 #endif\r
135 \r
136         ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;\r
137         int i; \r
138         \r
139         for (i = 0; i < process_wrapper->number_of_ports; i++) \r
140         {\r
141                 if (process_wrapper->port_id[i] == (int)port) \r
142                 {\r
143                         // This is our queue\r
144                         int queue = process_wrapper->port_queue_id[i];\r
145                         \r
146                 #ifdef MEASURE_DOL_WRITE_START_DMA\r
147                         double t_dol_write_start_dma = spu_read_decrementer();\r
148                 #endif\r
149 \r
150                         // There has been a writing process. Is it already finished? \r
151                         finish_DOL_write(); \r
152 \r
153                         // Create the new write process\r
154                         \r
155                         // reserve DMA tag ID\r
156                         if((tag_id_write=mfc_tag_reserve())==MFC_TAG_INVALID){\r
157                                 printf("SPE: ERROR - can't reserve a tag ID\n"); return;\r
158                         }\r
159 \r
160                         // Create the message we like to send, format: \r
161                         // 4 bit:  code (total 16 possibilities)\r
162                         // 12 bit: queue (total 4096 possibilities)\r
163                         // 16 bit: len  (total maximal size of 512 KB which could be send)\r
164                         uint32_t message = (SPE_WRITE_DEMAND << 28) | (queue << 16) | (len); \r
165 \r
166                 #ifdef MEASURE_DOL_WRITE_HANDSHAKE\r
167                         double t_dol_write_handshake = spu_read_decrementer();\r
168                 #endif\r
169                         // Demand the PPE for an address\r
170                         spu_write_out_mbox(message); \r
171 \r
172                         // Copy the data into the right data-alignment\r
173                         resultWrite = (char *)_malloc_align(roundDMA(len), 4); \r
174                         memcpy(resultWrite, buf, len); \r
175                         \r
176                         // Is there enough free space to write into the queues? \r
177                         uint32_t messageIn = spu_read_in_mbox(); \r
178                         uint32_t request = messageIn >> 28; \r
179                         \r
180                         while (request != (uint32_t) 1)\r
181                         {\r
182                                 spu_write_out_mbox(message); \r
183                                 messageIn = spu_read_in_mbox(); \r
184                                 request = messageIn >> 28; \r
185                         }\r
186 \r
187                         // Wait for the response of the PPE, i.e. the address for the FIFO element\r
188                         uint32_t ea_mfc_h, ea_mfc_l;\r
189                         uint64_t ea_mfc;\r
190                         ea_mfc_h  = spu_read_in_mbox();\r
191                         ea_mfc_l  = spu_read_in_mbox();\r
192                         ea_mfc = mfc_hl2ea(ea_mfc_h, ea_mfc_l);\r
193 \r
194                 #ifdef MEASURE_DOL_WRITE_HANDSHAKE\r
195                         t_dol_write_handshake -= spu_read_decrementer();\r
196                         printf("DOL_WRITE_HANDSHAKE;%f\n",t_dol_write_handshake * 1 / MEASURE_CPU);\r
197                 #endif\r
198 \r
199 \r
200                 #ifdef MEASURE_DOL_WRITE_START_DMA\r
201                         t_dol_write_start_dma -= spu_read_decrementer();\r
202                         printf("DOL_WRITE_START_DMA;%f\n",t_dol_write_start_dma * 1 / MEASURE_CPU);\r
203                 #endif\r
204 \r
205                 #ifdef MEASURE_DOL_WRITE_DMA\r
206                         double t_dol_write_dma = spu_read_decrementer();\r
207                 #endif\r
208                 \r
209                         // Write the data to the address we got from the PPE\r
210                         mfc_put((void *)&(resultWrite[0]), ea_mfc, roundDMA(len), tag_id_write, 0, 0); \r
211 \r
212                 #ifdef MEASURE_DOL_WRITE_DMA\r
213                         t_dol_write_dma -= spu_read_decrementer();\r
214                         printf("DOL_WRITE_DMA;%f\n",t_dol_write_dma * 1 / MEASURE_CPU);\r
215                 #endif\r
216 \r
217 \r
218                         break;\r
219                 }\r
220         }\r
221 #ifdef MEASURE_DOL_WRITE\r
222         t_dol_write -= spu_read_decrementer();\r
223         printf("DOL_WRITE;%f\n",t_dol_write * 1 / MEASURE_CPU);\r
224 #endif\r
225 }\r
226 \r
227 /**\r
228  * Detach the DOL Process\r
229  */\r
230 void DOL_detach(DOLProcess *process) {\r
231         //printf("[%s] DOL_detach.\n", (char*)(((ProcessWrapper*)process->wptr)->name));\r
232 \r
233         // Check if all write processes are finished\r
234         if (tag_id_write != 99)\r
235         {\r
236                 waittag(tag_id_write);\r
237                 mfc_tag_release(tag_id_write); // release tag ID before exiting\r
238                 _free_align(resultWrite); \r
239                 spu_write_out_mbox((uint32_t)(2 << 28)); // stalls mailbox is full.\r
240         }\r
241 \r
242         uint32_t message = (SPE_DETACH << 28); \r
243         spu_write_out_mbox(message); \r
244         deinitLocBuf();\r
245     ((ProcessWrapper*)process->wptr)->is_detached = 1;\r
246 }\r
247 \r
248 #endif\r