dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cbe / lib / ProcessWrapper.h
diff --git a/dol/src/dol/visitor/cbe/lib/ProcessWrapper.h b/dol/src/dol/visitor/cbe/lib/ProcessWrapper.h
new file mode 100644 (file)
index 0000000..c06075d
--- /dev/null
@@ -0,0 +1,248 @@
+/**************************************************************** \r
+ *     Process Wrapper Functions\r
+ *     Creator: lschor, 2008-10-30\r
+ *     Description: General process wrapper file, includes DOL_read and DOL_write as main functions\r
+ *     \r
+ *     Revision: \r
+ *     - 2008-10-30: Created\r
+ *     - 2008-11-08: Update to Double Buffering\r
+ *     - 2008-11-15: Added Performance Estimation methods\r
+ */\r
+\r
+#ifndef __PROCESS_WRAPPER_H__\r
+#define __PROCESS_WRAPPER_H__\r
+\r
+#include <spu_intrinsics.h>\r
+#include <spu_mfcio.h>\r
+#include <string.h>\r
+#include <stdio.h>\r
+#include <stdarg.h>            // Used for va_list\r
+#include <stdlib.h>\r
+#include "lib/malloc_align.h"   // Malloc for DMA\r
+#include "lib/free_align.h"     // Free for DMA\r
+#include "dol.h"\r
+#include "common.h"\r
+#include "estimation.h"\r
+\r
+//Cell Macros\r
+#define waittag(tag_id) mfc_write_tag_mask(1<<tag_id); mfc_read_tag_status_all();\r
+\r
+//DOL macros\r
+#define GETINDEX(dimension) \\r
+    ((ProcessWrapper*)(p->wptr))->index[dimension]\r
+\r
+#define CREATEPORTVAR(name) \\r
+    int name\r
+\r
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \\r
+    createPort(&port, base, number_of_indices, index_range_pairs)\r
+\r
+// Include the FIFO Functions\r
+#include "lib/ProcessFifo.h"\r
+\r
+// Include some help functions\r
+#include "lib/ProcessWrapperHelp.h"\r
+\r
+// Struct for a process\r
+typedef struct _process_wrapper {\r
+       char*           name;\r
+       uint32_t*       index;\r
+       uint32_t        is_detached;\r
+       uint32_t*       port_id;\r
+       uint32_t*       port_queue_id;\r
+       uint32_t        number_of_ports;\r
+} ProcessWrapper;\r
+\r
+// Tag address for the write process\r
+uint32_t tag_id_write = 99; \r
+\r
+// Pointer to the current data buffer\r
+char * resultWrite; \r
+\r
+/**\r
+ * Finish a DOL_write process\r
+ */\r
+void finish_DOL_write()\r
+{\r
+       if (tag_id_write != 99)\r
+       {\r
+               #ifdef MEASURE_DOL_WRITE_FINISH\r
+                       double t_dol_write_finish = spu_read_decrementer();\r
+               #endif\r
+\r
+               // Wait until the write process is finished\r
+               waittag(tag_id_write);\r
+               mfc_tag_release(tag_id_write); // release tag ID before exiting\r
+               _free_align(resultWrite);\r
+               // Send a okey about the data to the PPE\r
+               spu_write_out_mbox((uint32_t)(SPE_WRITE_SUC << 28)); // stalls mailbox is full.\r
+               tag_id_write = 99; \r
+               //queueWrite = -1;\r
+\r
+               #ifdef MEASURE_DOL_WRITE_FINISH\r
+                       t_dol_write_finish -= spu_read_decrementer();\r
+                       printf("DOL_WRITE_FINISH;%f\n",t_dol_write_finish * 1 / MEASURE_CPU);\r
+               #endif\r
+\r
+       }\r
+}\r
+\r
+/**\r
+ * Read from the FIFO\r
+ */\r
+void DOL_read(void *port, void *buf, int len, DOLProcess *process)\r
+{\r
+#ifdef MEASURE_DOL_READ\r
+       double t_dol_read = spu_read_decrementer();\r
+#endif\r
+\r
+       ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;\r
+       int i; \r
+\r
+       for (i = 0; i < process_wrapper->number_of_ports; i++) \r
+       {\r
+               if (process_wrapper->port_id[i] == (int)port) \r
+               {\r
+                       int queue = process_wrapper->port_queue_id[i];\r
+\r
+                       finish_DOL_write(); \r
+                       \r
+                       // Try to get new data into the local Buffer\r
+                       updateLocBuf(queue); \r
+                       \r
+                       // Read from the Buffer\r
+                       readLocBuf(queue, buf, len); \r
+                       \r
+                       break; \r
+               }\r
+       }\r
+#ifdef MEASURE_DOL_READ\r
+       t_dol_read -= spu_read_decrementer();\r
+       printf("DOL_READ;%f\n",t_dol_read * 1 / MEASURE_CPU);\r
+#endif\r
+\r
+}\r
+\r
+\r
+/**\r
+ * Write data into the FIFO\r
+ */\r
+void DOL_write(void *port, void *buf, int len, DOLProcess *process)\r
+{\r
+#ifdef MEASURE_DOL_WRITE\r
+       double t_dol_write = spu_read_decrementer();\r
+#endif\r
+\r
+       ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;\r
+       int i; \r
+       \r
+       for (i = 0; i < process_wrapper->number_of_ports; i++) \r
+       {\r
+               if (process_wrapper->port_id[i] == (int)port) \r
+               {\r
+                       // This is our queue\r
+                       int queue = process_wrapper->port_queue_id[i];\r
+                       \r
+               #ifdef MEASURE_DOL_WRITE_START_DMA\r
+                       double t_dol_write_start_dma = spu_read_decrementer();\r
+               #endif\r
+\r
+                       // There has been a writing process. Is it already finished? \r
+                       finish_DOL_write(); \r
+\r
+                       // Create the new write process\r
+                       \r
+                       // reserve DMA tag ID\r
+                       if((tag_id_write=mfc_tag_reserve())==MFC_TAG_INVALID){\r
+                               printf("SPE: ERROR - can't reserve a tag ID\n"); return;\r
+                       }\r
+\r
+                       // Create the message we like to send, format: \r
+                       // 4 bit:  code (total 16 possibilities)\r
+                       // 12 bit: queue (total 4096 possibilities)\r
+                       // 16 bit: len  (total maximal size of 512 KB which could be send)\r
+                       uint32_t message = (SPE_WRITE_DEMAND << 28) | (queue << 16) | (len); \r
+\r
+               #ifdef MEASURE_DOL_WRITE_HANDSHAKE\r
+                       double t_dol_write_handshake = spu_read_decrementer();\r
+               #endif\r
+                       // Demand the PPE for an address\r
+                       spu_write_out_mbox(message); \r
+\r
+                       // Copy the data into the right data-alignment\r
+                       resultWrite = (char *)_malloc_align(roundDMA(len), 4); \r
+                       memcpy(resultWrite, buf, len); \r
+                       \r
+                       // Is there enough free space to write into the queues? \r
+                       uint32_t messageIn = spu_read_in_mbox(); \r
+                       uint32_t request = messageIn >> 28; \r
+                       \r
+                       while (request != (uint32_t) 1)\r
+                       {\r
+                               spu_write_out_mbox(message); \r
+                               messageIn = spu_read_in_mbox(); \r
+                               request = messageIn >> 28; \r
+                       }\r
+\r
+                       // Wait for the response of the PPE, i.e. the address for the FIFO element\r
+                       uint32_t ea_mfc_h, ea_mfc_l;\r
+                       uint64_t ea_mfc;\r
+                       ea_mfc_h  = spu_read_in_mbox();\r
+                       ea_mfc_l  = spu_read_in_mbox();\r
+                       ea_mfc = mfc_hl2ea(ea_mfc_h, ea_mfc_l);\r
+\r
+               #ifdef MEASURE_DOL_WRITE_HANDSHAKE\r
+                       t_dol_write_handshake -= spu_read_decrementer();\r
+                       printf("DOL_WRITE_HANDSHAKE;%f\n",t_dol_write_handshake * 1 / MEASURE_CPU);\r
+               #endif\r
+\r
+\r
+               #ifdef MEASURE_DOL_WRITE_START_DMA\r
+                       t_dol_write_start_dma -= spu_read_decrementer();\r
+                       printf("DOL_WRITE_START_DMA;%f\n",t_dol_write_start_dma * 1 / MEASURE_CPU);\r
+               #endif\r
+\r
+               #ifdef MEASURE_DOL_WRITE_DMA\r
+                       double t_dol_write_dma = spu_read_decrementer();\r
+               #endif\r
+               \r
+                       // Write the data to the address we got from the PPE\r
+                       mfc_put((void *)&(resultWrite[0]), ea_mfc, roundDMA(len), tag_id_write, 0, 0); \r
+\r
+               #ifdef MEASURE_DOL_WRITE_DMA\r
+                       t_dol_write_dma -= spu_read_decrementer();\r
+                       printf("DOL_WRITE_DMA;%f\n",t_dol_write_dma * 1 / MEASURE_CPU);\r
+               #endif\r
+\r
+\r
+                       break;\r
+               }\r
+       }\r
+#ifdef MEASURE_DOL_WRITE\r
+       t_dol_write -= spu_read_decrementer();\r
+       printf("DOL_WRITE;%f\n",t_dol_write * 1 / MEASURE_CPU);\r
+#endif\r
+}\r
+\r
+/**\r
+ * Detach the DOL Process\r
+ */\r
+void DOL_detach(DOLProcess *process) {\r
+       //printf("[%s] DOL_detach.\n", (char*)(((ProcessWrapper*)process->wptr)->name));\r
+\r
+       // Check if all write processes are finished\r
+       if (tag_id_write != 99)\r
+       {\r
+               waittag(tag_id_write);\r
+               mfc_tag_release(tag_id_write); // release tag ID before exiting\r
+               _free_align(resultWrite); \r
+               spu_write_out_mbox((uint32_t)(2 << 28)); // stalls mailbox is full.\r
+       }\r
+\r
+       uint32_t message = (SPE_DETACH << 28); \r
+       spu_write_out_mbox(message); \r
+       deinitLocBuf();\r
+    ((ProcessWrapper*)process->wptr)->is_detached = 1;\r
+}\r
+\r
+#endif\r