1 /****************************************************************
\r
2 * Process Wrapper Functions
\r
3 * Creator: lschor, 2008-10-30
\r
4 * Description: General process wrapper file, includes DOL_read and DOL_write as main functions
\r
7 * - 2008-10-30: Created
\r
8 * - 2008-11-08: Update to Double Buffering
\r
9 * - 2008-11-15: Added Performance Estimation methods
\r
12 #ifndef __PROCESS_WRAPPER_H__
\r
13 #define __PROCESS_WRAPPER_H__
\r
15 #include <spu_intrinsics.h>
\r
16 #include <spu_mfcio.h>
\r
19 #include <stdarg.h> // Used for va_list
\r
21 #include "lib/malloc_align.h" // Malloc for DMA
\r
22 #include "lib/free_align.h" // Free for DMA
\r
25 #include "estimation.h"
\r
28 #define waittag(tag_id) mfc_write_tag_mask(1<<tag_id); mfc_read_tag_status_all();
\r
31 #define GETINDEX(dimension) \
\r
32 ((ProcessWrapper*)(p->wptr))->index[dimension]
\r
34 #define CREATEPORTVAR(name) \
\r
37 #define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \
\r
38 createPort(&port, base, number_of_indices, index_range_pairs)
\r
40 // Include the FIFO Functions
\r
41 #include "lib/ProcessFifo.h"
\r
43 // Include some help functions
\r
44 #include "lib/ProcessWrapperHelp.h"
\r
46 // Struct for a process
\r
47 typedef struct _process_wrapper {
\r
50 uint32_t is_detached;
\r
52 uint32_t* port_queue_id;
\r
53 uint32_t number_of_ports;
\r
56 // Tag address for the write process
\r
57 uint32_t tag_id_write = 99;
\r
59 // Pointer to the current data buffer
\r
60 char * resultWrite;
\r
63 * Finish a DOL_write process
\r
65 void finish_DOL_write()
\r
67 if (tag_id_write != 99)
\r
69 #ifdef MEASURE_DOL_WRITE_FINISH
\r
70 double t_dol_write_finish = spu_read_decrementer();
\r
73 // Wait until the write process is finished
\r
74 waittag(tag_id_write);
\r
75 mfc_tag_release(tag_id_write); // release tag ID before exiting
\r
76 _free_align(resultWrite);
\r
77 // Send a okey about the data to the PPE
\r
78 spu_write_out_mbox((uint32_t)(SPE_WRITE_SUC << 28)); // stalls mailbox is full.
\r
82 #ifdef MEASURE_DOL_WRITE_FINISH
\r
83 t_dol_write_finish -= spu_read_decrementer();
\r
84 printf("DOL_WRITE_FINISH;%f\n",t_dol_write_finish * 1 / MEASURE_CPU);
\r
91 * Read from the FIFO
\r
93 void DOL_read(void *port, void *buf, int len, DOLProcess *process)
\r
95 #ifdef MEASURE_DOL_READ
\r
96 double t_dol_read = spu_read_decrementer();
\r
99 ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;
\r
102 for (i = 0; i < process_wrapper->number_of_ports; i++)
\r
104 if (process_wrapper->port_id[i] == (int)port)
\r
106 int queue = process_wrapper->port_queue_id[i];
\r
108 finish_DOL_write();
\r
110 // Try to get new data into the local Buffer
\r
111 updateLocBuf(queue);
\r
113 // Read from the Buffer
\r
114 readLocBuf(queue, buf, len);
\r
119 #ifdef MEASURE_DOL_READ
\r
120 t_dol_read -= spu_read_decrementer();
\r
121 printf("DOL_READ;%f\n",t_dol_read * 1 / MEASURE_CPU);
\r
128 * Write data into the FIFO
\r
130 void DOL_write(void *port, void *buf, int len, DOLProcess *process)
\r
132 #ifdef MEASURE_DOL_WRITE
\r
133 double t_dol_write = spu_read_decrementer();
\r
136 ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;
\r
139 for (i = 0; i < process_wrapper->number_of_ports; i++)
\r
141 if (process_wrapper->port_id[i] == (int)port)
\r
143 // This is our queue
\r
144 int queue = process_wrapper->port_queue_id[i];
\r
146 #ifdef MEASURE_DOL_WRITE_START_DMA
\r
147 double t_dol_write_start_dma = spu_read_decrementer();
\r
150 // There has been a writing process. Is it already finished?
\r
151 finish_DOL_write();
\r
153 // Create the new write process
\r
155 // reserve DMA tag ID
\r
156 if((tag_id_write=mfc_tag_reserve())==MFC_TAG_INVALID){
\r
157 printf("SPE: ERROR - can't reserve a tag ID\n"); return;
\r
160 // Create the message we like to send, format:
\r
161 // 4 bit: code (total 16 possibilities)
\r
162 // 12 bit: queue (total 4096 possibilities)
\r
163 // 16 bit: len (total maximal size of 512 KB which could be send)
\r
164 uint32_t message = (SPE_WRITE_DEMAND << 28) | (queue << 16) | (len);
\r
166 #ifdef MEASURE_DOL_WRITE_HANDSHAKE
\r
167 double t_dol_write_handshake = spu_read_decrementer();
\r
169 // Demand the PPE for an address
\r
170 spu_write_out_mbox(message);
\r
172 // Copy the data into the right data-alignment
\r
173 resultWrite = (char *)_malloc_align(roundDMA(len), 4);
\r
174 memcpy(resultWrite, buf, len);
\r
176 // Is there enough free space to write into the queues?
\r
177 uint32_t messageIn = spu_read_in_mbox();
\r
178 uint32_t request = messageIn >> 28;
\r
180 while (request != (uint32_t) 1)
\r
182 spu_write_out_mbox(message);
\r
183 messageIn = spu_read_in_mbox();
\r
184 request = messageIn >> 28;
\r
187 // Wait for the response of the PPE, i.e. the address for the FIFO element
\r
188 uint32_t ea_mfc_h, ea_mfc_l;
\r
190 ea_mfc_h = spu_read_in_mbox();
\r
191 ea_mfc_l = spu_read_in_mbox();
\r
192 ea_mfc = mfc_hl2ea(ea_mfc_h, ea_mfc_l);
\r
194 #ifdef MEASURE_DOL_WRITE_HANDSHAKE
\r
195 t_dol_write_handshake -= spu_read_decrementer();
\r
196 printf("DOL_WRITE_HANDSHAKE;%f\n",t_dol_write_handshake * 1 / MEASURE_CPU);
\r
200 #ifdef MEASURE_DOL_WRITE_START_DMA
\r
201 t_dol_write_start_dma -= spu_read_decrementer();
\r
202 printf("DOL_WRITE_START_DMA;%f\n",t_dol_write_start_dma * 1 / MEASURE_CPU);
\r
205 #ifdef MEASURE_DOL_WRITE_DMA
\r
206 double t_dol_write_dma = spu_read_decrementer();
\r
209 // Write the data to the address we got from the PPE
\r
210 mfc_put((void *)&(resultWrite[0]), ea_mfc, roundDMA(len), tag_id_write, 0, 0);
\r
212 #ifdef MEASURE_DOL_WRITE_DMA
\r
213 t_dol_write_dma -= spu_read_decrementer();
\r
214 printf("DOL_WRITE_DMA;%f\n",t_dol_write_dma * 1 / MEASURE_CPU);
\r
221 #ifdef MEASURE_DOL_WRITE
\r
222 t_dol_write -= spu_read_decrementer();
\r
223 printf("DOL_WRITE;%f\n",t_dol_write * 1 / MEASURE_CPU);
\r
228 * Detach the DOL Process
\r
230 void DOL_detach(DOLProcess *process) {
\r
231 //printf("[%s] DOL_detach.\n", (char*)(((ProcessWrapper*)process->wptr)->name));
\r
233 // Check if all write processes are finished
\r
234 if (tag_id_write != 99)
\r
236 waittag(tag_id_write);
\r
237 mfc_tag_release(tag_id_write); // release tag ID before exiting
\r
238 _free_align(resultWrite);
\r
239 spu_write_out_mbox((uint32_t)(2 << 28)); // stalls mailbox is full.
\r
242 uint32_t message = (SPE_DETACH << 28);
\r
243 spu_write_out_mbox(message);
\r
245 ((ProcessWrapper*)process->wptr)->is_detached = 1;
\r