--- /dev/null
+/**************************************************************** \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