+/**************************************************************** \r
+ * Main Loop function\r
+ * Creator: lschor, 2008-11-21\r
+ * Description: Includes the main loop function for the ppu_main function\r
+ * \r
+ * Revision: \r
+ * - 2008-11-21: Created\r
+ */\r
+\r
+void workloop()\r
+{\r
+ // Buffer to an address for sending to to the PPE\r
+ volatile char *dataToWriteP __attribute__ ((aligned(128))); \r
+\r
+ // Number of corrent working process\r
+ int processNr; \r
+\r
+ // General variables that have been used in the main workloop\r
+ uint32_t message;\r
+ uint32_t request;\r
+ uint32_t len;\r
+ uint32_t queue;\r
+\r
+ struct timespec t;\r
+ t.tv_sec = 0;\r
+ t.tv_nsec = 5;\r
+\r
+ while (1)\r
+ {\r
+ // Goes through all nodes and check if they like to send some data\r
+ // - Which node has some information\r
+ // - Run through all nodes and if one has some work, do that\r
+ for (processNr = 0; processNr < NUM_SPES; processNr++)\r
+ {\r
+ if (!spe_out_mbox_status(data[processNr].spe_ctx)) continue; \r
+ \r
+ // Get the data\r
+ spe_out_mbox_read(data[processNr].spe_ctx, &message, 1);\r
+ \r
+ request = message >> 28;\r
+ len = (0xffff & message);\r
+ queue = (message >> 16) & 0xfff;\r
+ \r
+ // What type of request are the data? \r
+ if (request == SPE_WRITE_DEMAND) // Want an address to write\r
+ {\r
+\r
+ // If there is not enough space in the queue\r
+ if (MAXELEMENT - locBufCount[queue] < len)\r
+ {\r
+ int message = (0 << 28) | (queue << 16) | locBufCount[queue];\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
+ }\r
+\r
+ // There is enough space in the queue\r
+ else\r
+ {\r
+ #ifdef MEASURE_SPE_WRITE_DEMAND\r
+ struct timeval t_ppe_write_demand_start, t_ppe_write_demand_end;\r
+ gettimeofday(&t_ppe_write_demand_start,NULL);\r
+ #endif\r
+ int message = (1 << 28) | (queue << 16) | len;\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
+\r
+ // Create the memory for the element\r
+ dataToWriteP = (char *)malloc(roundDMA(len));\r
+ \r
+ // Create the address to send\r
+ uint64_t ea;\r
+ ea = (uint64_t)dataToWriteP;\r
+ \r
+ // Enter the information into the temporary Buffer\r
+ tmpFifoEntryWrite[processNr].ea = ea;\r
+ tmpFifoEntryWrite[processNr].length=len;\r
+ tmpFifoEntryWrite[processNr].queue = queue;\r
+ \r
+ // Send the address\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&ea, 2,SPE_MBOX_ANY_NONBLOCKING);\r
+ #ifdef MEASURE_SPE_WRITE_DEMAND\r
+ gettimeofday(&t_ppe_write_demand_end, NULL);\r
+ 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
+ #endif\r
+ }\r
+ }\r
+\r
+ /***************************************************************************************************************/\r
+ else if (request == SPE_READ_DEMAND) // Want an address to read\r
+ {\r
+ // If no element is in the fifo queue\r
+ if (locBufCount[queue] <= 0)\r
+ {\r
+ int message = (0 << 28) | (queue << 16) | locBufCount[queue];\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
+ }\r
+\r
+ // Has some elements in the fifo queue\r
+ else\r
+ {\r
+ #ifdef MEASURE_SPE_READ_DEMAND\r
+ struct timeval t_ppe_read_demand_start, t_ppe_read_demand_end;\r
+ gettimeofday(&t_ppe_read_demand_start,NULL);\r
+ #endif\r
+\r
+ pthread_mutex_lock( &(mutex[queue]) );\r
+ \r
+ len = len > locBufCount[queue] ? locBufCount[queue] : len;\r
+\r
+ // Can only send special sizes over the DMA\r
+ // 1, 2, 4, 8, 16, ..., 16*x\r
+\r
+ if (len >= 16)\r
+ len = len - (len % 16);\r
+ else if (len >= 8)\r
+ len = 8;\r
+ else if (len >= 4)\r
+ len = 4;\r
+ else if (len >= 2)\r
+ len = 2;\r
+ else\r
+ len = 1;\r
+\r
+ int message = (1 << 28) | (queue << 16) | len;\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
+\r
+ char *buf = (char *)_malloc_align(sizeof(char) * len, 4);\r
+\r
+ // Can directly read all elements from the end of the buffer\r
+ if (locBufStart[queue] + len < MAXELEMENT)\r
+ {\r
+ memcpy(buf, &(locBuf[queue][locBufStart[queue]]), len);\r
+ }\r
+\r
+ // Has to write from the end and from the beginning of the buffer\r
+ else\r
+ {\r
+ memcpy(&(buf[0]), &(locBuf[queue][locBufStart[queue]]), MAXELEMENT - locBufStart[queue]);\r
+ memcpy(&(buf[MAXELEMENT - locBufStart[queue]]), locBuf[queue], len - MAXELEMENT + locBufStart[queue]);\r
+ }\r
+\r
+ locBufCount[queue] -= len;\r
+ locBufStart[queue] = (locBufStart[queue] + len) % MAXELEMENT;\r
+\r
+ pthread_mutex_unlock( & (mutex[queue]) );\r
+\r
+ // Create the address to send\r
+ uint64_t ea;\r
+ ea = (uint64_t)buf;\r
+\r
+ // Enter the information into the temporary Buffer\r
+ tmpFifoEntryRead[processNr].ea = ea;\r
+ tmpFifoEntryRead[processNr].length = len;\r
+ tmpFifoEntryRead[processNr].queue = queue; \r
+\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&(tmpFifoEntryRead[processNr].ea), 2,SPE_MBOX_ANY_NONBLOCKING);\r
+ #ifdef MEASURE_SPE_READ_DEMAND\r
+ gettimeofday(&t_ppe_read_demand_end, NULL);\r
+ 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
+ #endif\r
+ }\r
+ }\r
+\r
+ /***************************************************************************************************************/\r
+ else if (request == SPE_WRITE_SUC) // Has finished writing\r
+ {\r
+ #ifdef MEASURE_SPE_WRITE_SUC\r
+ struct timeval t_ppe_write_suc_start, t_ppe_write_suc_end;\r
+ gettimeofday(&t_ppe_write_suc_start,NULL);\r
+ #endif\r
+ // Enter the data into the FIFO\r
+ int queueW = tmpFifoEntryWrite[processNr].queue;\r
+ int lenW = tmpFifoEntryWrite[processNr].length; \r
+ char *bufferW = (char *)(tmpFifoEntryWrite[processNr].ea); \r
+ \r
+ pthread_mutex_lock( &(mutex[queueW]) );\r
+\r
+ // Has to write all elements at the beginning or write all elements at the end of the buffer\r
+ if (locBufStart[queueW] + locBufCount[queueW] > MAXELEMENT || locBufStart[queueW] + locBufCount[queueW] + lenW < MAXELEMENT)\r
+ {\r
+ memcpy(&(locBuf[queueW][(locBufStart[queueW] + locBufCount[queueW]) % MAXELEMENT]), bufferW, lenW);\r
+ }\r
+\r
+ // Otherwise something at the end and something at the beginning\r
+ else\r
+ {\r
+ // At the end of the buffer\r
+ memcpy(&(locBuf[queueW][(locBufStart[queueW] + locBufCount[queueW])]), bufferW, MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]);\r
+\r
+ // At the beginning\r
+ memcpy(locBuf[queueW], &(bufferW[MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]]), lenW - (MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]));\r
+ }\r
+\r
+ locBufCount[queueW]+=lenW;\r
+\r
+ pthread_mutex_unlock( & (mutex[queueW]) );\r
+\r
+ // Set the temporary entry to null\r
+ #ifdef MEASURE_SPE_WRITE_SUC\r
+ gettimeofday(&t_ppe_write_suc_end, NULL);\r
+ 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
+ #endif\r
+ }\r
+\r
+ /***************************************************************************************************************/\r
+ else if (request == SPE_READ_SUC) // Has finished reading\r
+ {\r
+ #ifdef MEASURE_SPE_READ_SUC\r
+ struct timeval t_ppe_read_suc_start, t_ppe_read_suc_end;\r
+ gettimeofday(&t_ppe_read_suc_start,NULL);\r
+ #endif\r
+ #ifdef MEASURE_SPE_READ_SUC\r
+ gettimeofday(&t_ppe_read_suc_end, NULL);\r
+ 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
+ #endif\r
+ }\r
+\r
+ /***************************************************************************************************************/\r
+ else if (request == SPE_DETACH) // A process has finished\r
+ {\r
+ pthread_mutex_lock( &(mutexProcessNr) );\r
+ processFinished++;\r
+ pthread_mutex_unlock( &(mutexProcessNr) );\r
+ }\r
+\r
+ /***************************************************************************************************************/\r
+ else // Did nothing\r
+ {\r
+ nanosleep(&t, NULL);\r
+ }\r
+ }\r
+\r
+ // Check if we can stop the execution\r
+ if (processFinished >= NUM_PROCS) break; \r
+ }\r
+}\r
+\r