swps3
DynProgr_SPE_main.c
Go to the documentation of this file.
1 
5 /*
6  * Copyright (c) 2007-2008 ETH Zürich, Institute of Computational Science
7  *
8  * Permission is hereby granted, free of charge, to any person
9  * obtaining a copy of this software and associated documentation
10  * files (the "Software"), to deal in the Software without
11  * restriction, including without limitation the rights to use,
12  * copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following
15  * conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27  * OTHER DEALINGS IN THE SOFTWARE.
28  */
29 
30 #include <spu_mfcio.h>
31 #include "DynProgr_SPE.h"
32 #include "DynProgr_SPE_functions.h"
33 #include <stdio.h>
34 #include "matrix.h"
35 
36 
37 #define min(a,b) (((a)<(b))?(a):(b))
38 #define max(a,b) (((a)>(b))?(a):(b))
39 
40 static int8_t mainMemory[ TOTAL_MEMORY ] __attribute__((__aligned__(16)));
41 static int allocated = 0;
42 static int datatype = -1;
43 void * alloc( int size ){
44  void * result = mainMemory + allocated;
45  allocated += ALIGN16(size);
46  if(allocated>TOTAL_MEMORY) return (void*)-1;
47  return result;
48 }
50  return TOTAL_MEMORY-allocated;
51 }
52 void reset(){
53  allocated = 0;
54  datatype = -1;
55 }
56 
57 int handleCommand( ppu_addr_t program_data_ea ){
59  int i;
60  /* Load the type */
61  mfc_get(&cmd, program_data_ea, sizeof(cmd), 0, 0, 0);
62  mfc_write_tag_mask(1<<0);
63  mfc_read_tag_status_all();
64 
65  switch(cmd.command) {
66  case SPE_CMD_INIT: /* resets stored data */
67  reset();
68  datatype = cmd.data.INIT.datatype;
69  if(datatype < 0 || datatype > 4) {
70  datatype = -1;
71  return -1;
72  }
73  fixedDel = cmd.data.INIT.fixedDel;
74  incDel = cmd.data.INIT.incDel;
75  maxDbLen = cmd.data.INIT.dbMaxLen;
76 
77  /* reset some variables */
78  profile = NULL;
79  remote_profile = 0;
80  blockStart = 0;
81  blockSize = 0;
82  s1 = NULL;
83  ls1 = 0;
84  simi = NULL;
85 
86  /* allocate memory for database string and inter-block
87  * buffers */
88  s2 = (char *)alloc( maxDbLen*sizeof(char) );
89  maxS = alloc( maxDbLen*dataSize[datatype] );
90  delS = alloc( maxDbLen*dataSize[datatype] );
91  break;
92 
93  case SPE_CMD_CREATE_PROFILE: /* downloads query sequence and scoring matrix and initializes the profile */
94  if(profile != NULL || datatype == -1) return -1;
95 
96  mn = min(cmd.data.CREATE_PROFILE.matrix.min,min(fixedDel,incDel));
97  mx = max(cmd.data.CREATE_PROFILE.matrix.max,max(fixedDel,incDel));
98  ls1 = cmd.data.CREATE_PROFILE.query.len;
99 
100  /* allocate and load query sequence */
101  s1 = alloc( ls1*sizeof(char) );
102  for( i=0; i<ls1; i+=MAX_TRANSFER )
103  mfc_get( s1+i, cmd.data.CREATE_PROFILE.query.addr+i, ALIGN16(min(ls1-i, MAX_TRANSFER)*sizeof(char)), 0, 0, 0 );
104 
105  /* allocate and load matrix */
106  simi = alloc( MATRIX_DIM*MATRIX_DIM*dataSize[datatype] );
107  mfc_get( simi, cmd.data.CREATE_PROFILE.matrix.addr, ALIGN16(MATRIX_DIM*MATRIX_DIM*dataSize[datatype]), 1, 0, 0 );
108 
109  /* wait for DMA to finish */
110  mfc_write_tag_mask((1<<0)|(1<<1));
111  mfc_read_tag_status_all();
112 
113  /* compute block size and allocate memory */
114  if(memRemaining() <= 0) return -1;
115  blockSize=(memRemaining() / ((MATRIX_DIM+3)*dataSize[datatype])) & -16;
116  if (blockSize < 50) return -1;
117  blockSize = ALIGN16(min(blockSize,ls1));
118 
119  /* allocate memory and initialize profile */
120  profile = alloc( blockSize * MATRIX_DIM * dataSize[datatype] );
121  loadOpt = alloc( blockSize * dataSize[datatype] );
122  storeOpt = alloc( blockSize * dataSize[datatype] );
123  rD = alloc( blockSize * dataSize[datatype] );
124 
125  blockStart = 0;
126 #ifdef DEBUG_FETCH
127  printf(">>>> creating profile\n");
128 #endif
130  break;
131 
132  case SPE_CMD_PUT_PROFILE: /* upload profile to main memory */
133  if(profile == NULL || s1 == NULL) return -1;
134 
135  /* normally we would expect the first block of the profile is
136  * already present in memory. If not generate it */
137  if(blockStart != 0) {
138  blockStart = 0;
140  }
141  cmd.data.PUT_PROFILE.blockSize = blockSize;
142 
143  /* create profile blockwise and upload it to main memory */
145  int64_t bs;
146  int currentBlockSize = ALIGN16(min(ls1-blockStart,blockSize));
147  if(blockStart != 0) createProfile[datatype]();
148 
149  for( bs=0; bs<currentBlockSize * MATRIX_DIM * dataSize[datatype]; bs+=MAX_TRANSFER ) {
150  mfc_put( ((char*)profile)+bs, cmd.data.PUT_PROFILE.addr+blockStart*MATRIX_DIM*dataSize[datatype]+bs, ALIGN16(min(currentBlockSize*MATRIX_DIM*dataSize[datatype]-bs, (int64_t)MAX_TRANSFER)), 0, 0, 0 );
151 
152  /* wait for DMA to finish */
153  mfc_write_tag_mask(1<<0);
154  mfc_read_tag_status_all();
155  }
156  }
157 
158  /* Write back the data */
159  mfc_put(&cmd, program_data_ea, sizeof(cmd), 0, 0, 0);
160  mfc_write_tag_mask(1<<0);
161  mfc_read_tag_status_all();
162  break;
163 
164  case SPE_CMD_GET_PROFILE: /* download profile from main memory */
165  if(datatype == -1 || profile != NULL) return -1;
166  remote_profile = cmd.data.GET_PROFILE.profile.addr;
167 
168  mn = min(cmd.data.GET_PROFILE.profile.min,min(fixedDel,incDel));
169  mx = max(cmd.data.GET_PROFILE.profile.max,max(fixedDel,incDel));
170  ls1 = cmd.data.GET_PROFILE.profile.len;
171  blockSize = cmd.data.GET_PROFILE.profile.blockSize;
172 
173  profile = alloc( blockSize * MATRIX_DIM * dataSize[datatype] );
174  loadOpt = alloc( blockSize * dataSize[datatype] );
175  storeOpt = alloc( blockSize * dataSize[datatype] );
176  rD = alloc( blockSize * dataSize[datatype] );
177  if(memRemaining() < 0) return -1;
178 
179  blockStart = 0;
180 #ifdef DEBUG_FETCH
181  printf(">>>> fetching profile (%d bytes)\n",ALIGN16(blockSize * MATRIX_DIM * dataSize[datatype]));
182 #endif
183  for( i=0; i<ALIGN16(blockSize * MATRIX_DIM * dataSize[datatype]); i+=MAX_TRANSFER ) {
184  mfc_get( ((char*)profile)+i, remote_profile+i, ALIGN16(min(blockSize*MATRIX_DIM*dataSize[datatype]-i, (int64_t)MAX_TRANSFER)), 0, 0, 0 );
185 
186  /* wait for DMA to finish */
187  mfc_write_tag_mask(1<<0);
188  mfc_read_tag_status_all();
189  }
190  break;
191 
192  case SPE_CMD_ALIGN: /* perform a local alignment */
193  if(profile == NULL) return -1;
194 
195  ls2 = cmd.data.ALIGN.db.len;
196 
197  /* download database sequence */
198  for( i=0; i<ls2; i+=MAX_TRANSFER )
199  mfc_get( s2+i, cmd.data.ALIGN.db.addr+i, ALIGN16(min(ls2-i, MAX_TRANSFER)*sizeof(char)), 0, 0, 0 );
200  mfc_write_tag_mask(1<<0);
201  mfc_read_tag_status_all();
202 
203  /* initialize the profile if it has not been initialized yet */
204  if(blockStart != 0) {
205  if(remote_profile == 0) {
206  blockStart = 0;
207 #ifdef DEBUG_FETCH
208  printf(">>>> creating profile\n");
209 #endif
211  } else {
212  blockStart = 0;
213 #ifdef DEBUG_FETCH
214  printf(">>>> fetching profile (%d bytes)\n",ALIGN16(blockSize * MATRIX_DIM * dataSize[datatype]));
215 #endif
216  for( i=0; i<ALIGN16(blockSize * MATRIX_DIM * dataSize[datatype]); i+=MAX_TRANSFER ) {
217  mfc_get( ((char*)profile)+i, remote_profile+i, ALIGN16(min(blockSize*MATRIX_DIM*dataSize[datatype]-i, (int64_t)MAX_TRANSFER)), 0, 0, 0 );
218 
219  /* wait for DMA to finish */
220  mfc_write_tag_mask(1<<0);
221  mfc_read_tag_status_all();
222  }
223  }
224  }
225 
226  cmd.data.ALIGN.result = dynProgLocal[datatype]();
227 
228  /* Write back the data */
229  mfc_put(&cmd, program_data_ea, sizeof(cmd), 0, 0, 0);
230  mfc_write_tag_mask(1<<0);
231  mfc_read_tag_status_all();
232  break;
233 
234  default:
235  return -1;
236  }
237  return 0;
238 }
239 #ifdef MAIL
240 int main() {
241  while (1){
242  int res;
243  ppu_addr_t program_data_ea = spu_read_in_mbox();
244  program_data_ea += ((ppu_addr_t)spu_read_in_mbox())<<32;
245  res = handleCommand( program_data_ea );
246 // spu_write_out_mbox( res );
247  spu_write_out_intr_mbox( res );
248  }
249  return 0;
250 }
251 
252 #else
253 int main(uint64_t spe_id, ppu_addr_t program_data_ea, ppu_addr_t env) {
254  (void)spe_id;
255  (void)env;
256  return handleCommand( program_data_ea );
257 }
258 #endif