dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cbe / lib / ppu_main_workloop.h
diff --git a/dol/src/dol/visitor/cbe/lib/ppu_main_workloop.h b/dol/src/dol/visitor/cbe/lib/ppu_main_workloop.h
new file mode 100644 (file)
index 0000000..874bf32
--- /dev/null
@@ -0,0 +1,235 @@
+/**************************************************************** \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