1 /****************************************************************
\r
3 * Creator: lschor, 2008-11-21
\r
4 * Description: Includes the main loop function for the ppu_main function
\r
7 * - 2008-11-21: Created
\r
12 // Buffer to an address for sending to to the PPE
\r
13 volatile char *dataToWriteP __attribute__ ((aligned(128)));
\r
15 // Number of corrent working process
\r
18 // General variables that have been used in the main workloop
\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
35 if (!spe_out_mbox_status(data[processNr].spe_ctx)) continue;
\r
38 spe_out_mbox_read(data[processNr].spe_ctx, &message, 1);
\r
40 request = message >> 28;
\r
41 len = (0xffff & message);
\r
42 queue = (message >> 16) & 0xfff;
\r
44 // What type of request are the data?
\r
45 if (request == SPE_WRITE_DEMAND) // Want an address to write
\r
48 // If there is not enough space in the queue
\r
49 if (MAXELEMENT - locBufCount[queue] < len)
\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
55 // There is enough space in the queue
\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
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
65 // Create the memory for the element
\r
66 dataToWriteP = (char *)malloc(roundDMA(len));
\r
68 // Create the address to send
\r
70 ea = (uint64_t)dataToWriteP;
\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
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
86 /***************************************************************************************************************/
\r
87 else if (request == SPE_READ_DEMAND) // Want an address to read
\r
89 // If no element is in the fifo queue
\r
90 if (locBufCount[queue] <= 0)
\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
96 // Has some elements in the fifo queue
\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
104 pthread_mutex_lock( &(mutex[queue]) );
\r
106 len = len > locBufCount[queue] ? locBufCount[queue] : len;
\r
108 // Can only send special sizes over the DMA
\r
109 // 1, 2, 4, 8, 16, ..., 16*x
\r
112 len = len - (len % 16);
\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
125 char *buf = (char *)_malloc_align(sizeof(char) * len, 4);
\r
127 // Can directly read all elements from the end of the buffer
\r
128 if (locBufStart[queue] + len < MAXELEMENT)
\r
130 memcpy(buf, &(locBuf[queue][locBufStart[queue]]), len);
\r
133 // Has to write from the end and from the beginning of the buffer
\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
140 locBufCount[queue] -= len;
\r
141 locBufStart[queue] = (locBufStart[queue] + len) % MAXELEMENT;
\r
143 pthread_mutex_unlock( & (mutex[queue]) );
\r
145 // Create the address to send
\r
147 ea = (uint64_t)buf;
\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
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
162 /***************************************************************************************************************/
\r
163 else if (request == SPE_WRITE_SUC) // Has finished writing
\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
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
174 pthread_mutex_lock( &(mutex[queueW]) );
\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
179 memcpy(&(locBuf[queueW][(locBufStart[queueW] + locBufCount[queueW]) % MAXELEMENT]), bufferW, lenW);
\r
182 // Otherwise something at the end and something at the beginning
\r
185 // At the end of the buffer
\r
186 memcpy(&(locBuf[queueW][(locBufStart[queueW] + locBufCount[queueW])]), bufferW, MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]);
\r
188 // At the beginning
\r
189 memcpy(locBuf[queueW], &(bufferW[MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]]), lenW - (MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]));
\r
192 locBufCount[queueW]+=lenW;
\r
194 pthread_mutex_unlock( & (mutex[queueW]) );
\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
203 /***************************************************************************************************************/
\r
204 else if (request == SPE_READ_SUC) // Has finished reading
\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
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
216 /***************************************************************************************************************/
\r
217 else if (request == SPE_DETACH) // A process has finished
\r
219 pthread_mutex_lock( &(mutexProcessNr) );
\r
221 pthread_mutex_unlock( &(mutexProcessNr) );
\r
224 /***************************************************************************************************************/
\r
225 else // Did nothing
\r
227 nanosleep(&t, NULL);
\r
231 // Check if we can stop the execution
\r
232 if (processFinished >= NUM_PROCS) break;
\r