dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cbe / lib / ppu_main_workloop.h
1 /**************************************************************** \r
2  *      Main Loop function\r
3  *      Creator: lschor, 2008-11-21\r
4  *      Description: Includes the main loop function for the ppu_main function\r
5  *      \r
6  *      Revision: \r
7  *      - 2008-11-21: Created\r
8  */\r
9 \r
10 void workloop()\r
11 {\r
12         // Buffer to an address for sending to to the PPE\r
13         volatile char *dataToWriteP __attribute__ ((aligned(128))); \r
14 \r
15         // Number of corrent working process\r
16         int processNr; \r
17 \r
18         // General variables that have been used in the main workloop\r
19         uint32_t message;\r
20         uint32_t request;\r
21         uint32_t len;\r
22         uint32_t queue;\r
23 \r
24         struct timespec t;\r
25         t.tv_sec = 0;\r
26         t.tv_nsec = 5;\r
27 \r
28         while (1)\r
29         {\r
30                 // Goes through all nodes and check if they like to send some data\r
31                 // - Which node has some information\r
32                 // - Run through all nodes and if one has some work, do that\r
33                 for (processNr = 0; processNr < NUM_SPES; processNr++)\r
34                 {\r
35                         if (!spe_out_mbox_status(data[processNr].spe_ctx)) continue; \r
36         \r
37                         // Get the data\r
38                         spe_out_mbox_read(data[processNr].spe_ctx, &message, 1);\r
39                         \r
40                         request = message >> 28;\r
41                         len = (0xffff & message);\r
42                         queue = (message >> 16) & 0xfff;\r
43                         \r
44                         // What type of request are the data? \r
45                         if (request == SPE_WRITE_DEMAND)        // Want an address to write\r
46                         {\r
47 \r
48                                 // If there is not enough space in the queue\r
49                                 if (MAXELEMENT - locBufCount[queue] < len)\r
50                                 {\r
51                                         int message = (0 << 28) | (queue << 16) | locBufCount[queue];\r
52                                         spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
53                                 }\r
54 \r
55                                 // There is enough space in the queue\r
56                                 else\r
57                                 {\r
58                                 #ifdef MEASURE_SPE_WRITE_DEMAND\r
59                                         struct timeval t_ppe_write_demand_start, t_ppe_write_demand_end;\r
60                                         gettimeofday(&t_ppe_write_demand_start,NULL);\r
61                                 #endif\r
62                                         int message = (1 << 28) | (queue << 16) | len;\r
63                                         spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
64 \r
65                                         // Create the memory for the element\r
66                                         dataToWriteP = (char *)malloc(roundDMA(len));\r
67                                         \r
68                                         // Create the address to send\r
69                                         uint64_t ea;\r
70                                         ea = (uint64_t)dataToWriteP;\r
71                                         \r
72                                         // Enter the information into the temporary Buffer\r
73                                         tmpFifoEntryWrite[processNr].ea = ea;\r
74                                         tmpFifoEntryWrite[processNr].length=len;\r
75                                         tmpFifoEntryWrite[processNr].queue = queue;\r
76                                         \r
77                                         // Send the address\r
78                                         spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&ea, 2,SPE_MBOX_ANY_NONBLOCKING);\r
79                                 #ifdef MEASURE_SPE_WRITE_DEMAND\r
80                                         gettimeofday(&t_ppe_write_demand_end, NULL);\r
81                                         printf("PPE_WRITE_DEMAND;%f\n",(t_ppe_write_demand_end.tv_sec - t_ppe_write_demand_start.tv_sec) + 0.000001 * (t_ppe_write_demand_end.tv_usec - t_ppe_write_demand_start.tv_usec));\r
82                                 #endif\r
83                                 }\r
84                         }\r
85 \r
86                         /***************************************************************************************************************/\r
87                         else if (request == SPE_READ_DEMAND)    // Want an address to read\r
88                         {\r
89                                 // If no element is in the fifo queue\r
90                                 if (locBufCount[queue] <= 0)\r
91                                 {\r
92                                         int message = (0 << 28) | (queue << 16) | locBufCount[queue];\r
93                                         spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
94                                 }\r
95 \r
96                                 // Has some elements in the fifo queue\r
97                                 else\r
98                                 {\r
99                                 #ifdef MEASURE_SPE_READ_DEMAND\r
100                                         struct timeval t_ppe_read_demand_start, t_ppe_read_demand_end;\r
101                                         gettimeofday(&t_ppe_read_demand_start,NULL);\r
102                                 #endif\r
103 \r
104                                         pthread_mutex_lock( &(mutex[queue]) );\r
105                                         \r
106                                         len = len > locBufCount[queue] ? locBufCount[queue] : len;\r
107 \r
108                                         // Can only send special sizes over the DMA\r
109                                         // 1, 2, 4, 8, 16, ..., 16*x\r
110 \r
111                                         if (len >= 16)\r
112                                                 len = len - (len % 16);\r
113                                         else if (len >= 8)\r
114                                                 len = 8;\r
115                                         else if (len >= 4)\r
116                                                 len = 4;\r
117                                         else if (len >= 2)\r
118                                                 len = 2;\r
119                                         else\r
120                                                 len = 1;\r
121 \r
122                                         int message = (1 << 28) | (queue << 16) | len;\r
123                                         spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
124 \r
125                                         char *buf = (char *)_malloc_align(sizeof(char) * len, 4);\r
126 \r
127                                         // Can directly read all elements from the end of the buffer\r
128                                         if (locBufStart[queue] + len < MAXELEMENT)\r
129                                         {\r
130                                                 memcpy(buf, &(locBuf[queue][locBufStart[queue]]), len);\r
131                                         }\r
132 \r
133                                         // Has to write from the end and from the beginning of the buffer\r
134                                         else\r
135                                         {\r
136                                                 memcpy(&(buf[0]), &(locBuf[queue][locBufStart[queue]]), MAXELEMENT - locBufStart[queue]);\r
137                                                 memcpy(&(buf[MAXELEMENT - locBufStart[queue]]), locBuf[queue], len - MAXELEMENT + locBufStart[queue]);\r
138                                         }\r
139 \r
140                                         locBufCount[queue] -= len;\r
141                                         locBufStart[queue] = (locBufStart[queue] + len) % MAXELEMENT;\r
142 \r
143                                         pthread_mutex_unlock( & (mutex[queue]) );\r
144 \r
145                                         // Create the address to send\r
146                                         uint64_t ea;\r
147                                         ea = (uint64_t)buf;\r
148 \r
149                                         // Enter the information into the temporary Buffer\r
150                                         tmpFifoEntryRead[processNr].ea = ea;\r
151                                         tmpFifoEntryRead[processNr].length = len;\r
152                                         tmpFifoEntryRead[processNr].queue = queue; \r
153 \r
154                                         spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&(tmpFifoEntryRead[processNr].ea), 2,SPE_MBOX_ANY_NONBLOCKING);\r
155                                 #ifdef MEASURE_SPE_READ_DEMAND\r
156                                         gettimeofday(&t_ppe_read_demand_end, NULL);\r
157                                         printf("PPE;%f\n",(t_ppe_read_demand_end.tv_sec - t_ppe_read_demand_start.tv_sec) + 0.000001 * (t_ppe_read_demand_end.tv_usec - t_ppe_read_demand_start.tv_usec));\r
158                                 #endif\r
159                                 }\r
160                         }\r
161 \r
162                         /***************************************************************************************************************/\r
163                         else if (request == SPE_WRITE_SUC)      // Has finished writing\r
164                         {\r
165                         #ifdef MEASURE_SPE_WRITE_SUC\r
166                                 struct timeval t_ppe_write_suc_start, t_ppe_write_suc_end;\r
167                                 gettimeofday(&t_ppe_write_suc_start,NULL);\r
168                         #endif\r
169                                 // Enter the data into the FIFO\r
170                                 int queueW = tmpFifoEntryWrite[processNr].queue;\r
171                                 int lenW = tmpFifoEntryWrite[processNr].length; \r
172                                 char *bufferW = (char *)(tmpFifoEntryWrite[processNr].ea); \r
173                                 \r
174                                 pthread_mutex_lock( &(mutex[queueW]) );\r
175 \r
176                                 // Has to write all elements at the beginning or write all elements at the end of the buffer\r
177                                 if (locBufStart[queueW] + locBufCount[queueW] > MAXELEMENT || locBufStart[queueW] + locBufCount[queueW] + lenW < MAXELEMENT)\r
178                                 {\r
179                                         memcpy(&(locBuf[queueW][(locBufStart[queueW] + locBufCount[queueW]) % MAXELEMENT]), bufferW, lenW);\r
180                                 }\r
181 \r
182                                 // Otherwise something at the end and something at the beginning\r
183                                 else\r
184                                 {\r
185                                         // At the end of the buffer\r
186                                         memcpy(&(locBuf[queueW][(locBufStart[queueW] + locBufCount[queueW])]), bufferW, MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]);\r
187 \r
188                                         // At the beginning\r
189                                         memcpy(locBuf[queueW], &(bufferW[MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]]), lenW - (MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]));\r
190                                 }\r
191 \r
192                                 locBufCount[queueW]+=lenW;\r
193 \r
194                                 pthread_mutex_unlock( & (mutex[queueW]) );\r
195 \r
196                                 // Set the temporary entry to null\r
197                         #ifdef MEASURE_SPE_WRITE_SUC\r
198                                 gettimeofday(&t_ppe_write_suc_end, NULL);\r
199                                 printf("PPE;%f\n",(t_ppe_write_suc_end.tv_sec - t_ppe_write_suc_start.tv_sec) + 0.000001 * (t_ppe_write_suc_end.tv_usec - t_ppe_write_suc_start.tv_usec));\r
200                         #endif\r
201                         }\r
202 \r
203                         /***************************************************************************************************************/\r
204                         else if (request == SPE_READ_SUC)       // Has finished reading\r
205                         {\r
206                         #ifdef MEASURE_SPE_READ_SUC\r
207                                 struct timeval t_ppe_read_suc_start, t_ppe_read_suc_end;\r
208                                 gettimeofday(&t_ppe_read_suc_start,NULL);\r
209                         #endif\r
210                         #ifdef MEASURE_SPE_READ_SUC\r
211                                 gettimeofday(&t_ppe_read_suc_end, NULL);\r
212                                 printf("PPE;%f\n",(t_ppe_read_suc_end.tv_sec - t_ppe_read_suc_start.tv_sec) + 0.000001 * (t_ppe_read_suc_end.tv_usec - t_ppe_read_suc_start.tv_usec));\r
213                         #endif\r
214                         }\r
215 \r
216                         /***************************************************************************************************************/\r
217                         else if (request == SPE_DETACH) // A process has finished\r
218                         {\r
219                                 pthread_mutex_lock( &(mutexProcessNr) );\r
220                                 processFinished++;\r
221                                 pthread_mutex_unlock( &(mutexProcessNr) );\r
222                         }\r
223 \r
224                         /***************************************************************************************************************/\r
225                         else    // Did nothing\r
226                         {\r
227                                 nanosleep(&t, NULL);\r
228                         }\r
229                 }\r
230 \r
231                 // Check if we can stop the execution\r
232                 if (processFinished >= NUM_PROCS) break; \r
233         }\r
234 }\r
235 \r