00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdio.h>
00031 #include <malloc.h>
00032 #ifdef MAIL
00033 #include <libspe.h>
00034 #include <sched.h>
00035 #else
00036 #include <libspe2.h>
00037 #endif
00038 #include <sys/wait.h>
00039 #include <sys/types.h>
00040 #include <errno.h>
00041 #include "DynProgr_SPE.h"
00042 #include <string.h>
00043 #include <stdbool.h>
00044 #include <ctype.h>
00045 #include <limits.h>
00046 #include <time.h>
00047 #include <math.h>
00048 #include <float.h>
00049 #include <assert.h>
00050
00051 #include "debug.h"
00052 #include "swps3.h"
00053 #include "matrix.h"
00054 #include "DynProgr_scalar.h"
00055 #include "DynProgr_PPU.h"
00056
00057 #define MAX(a,b) (a>b?a:b)
00058 #define MIN(a,b) (a<b?a:b)
00059
00060 extern spe_program_handle_t spe_dynprogr_handle;
00061
00062 #ifdef MAIL
00063 static spe_gid_t getSpeGid(){
00064 static spe_gid_t gid = 0;
00065 if (gid == 0){
00066 gid = spe_create_group(SCHED_RR, 1, 1);
00067 if (gid <= 0)
00068 error("PPU:Creating new group failed");
00069 }
00070 return gid;
00071 }
00073 static speid_t getSpeId(){
00074 static speid_t id = 0;
00075 if (!id)
00076 id = spe_create_thread(getSpeGid(), &spe_dynprogr_handle, NULL, NULL, -1, 0);
00077 return id;
00078 }
00079
00081 static void writeMailBox( ppu_addr_t addr ){
00082 speid_t spe_id = getSpeId();
00083 spe_write_in_mbox( spe_id, (uint32_t)addr );
00084 spe_write_in_mbox( spe_id, (uint32_t)(addr>>32) );
00085 }
00086
00088 static int readMailBox(){
00089 struct spe_event e = {
00090 .events = SPE_EVENT_MAILBOX,
00091 .gid = getSpeGid(),
00092 };
00093 if( !spe_get_event(&e, 1, -1) || e.revents != SPE_EVENT_MAILBOX ) error("PPU:Waiting for MailBox signal");
00094 return e.data;
00095 }
00096 #else
00097 static spe_context_ptr_t spe_context = NULL;
00098 #endif
00099
00105 static int submitSPECommand(SPECommand* command) {
00106 #ifdef MAIL
00107
00108 writeMailBox( (ppu_addr_t)command );
00109 return readMailBox();
00110 #else
00111 if( !spe_context ){
00112 spe_context = spe_context_create( 0, NULL );
00113 spe_program_load( spe_context, &spe_dynprogr_handle );
00114 }
00115
00116 unsigned int entry = SPE_DEFAULT_ENTRY;
00117 return spe_context_run( spe_context, &entry, 0, command, NULL, NULL );
00118
00119 #endif
00120 }
00121
00132 static int SPEInit(int dataType, int maxDbLen, Options *options) {
00133 SPECommand command __ALIGNED__;
00134
00135 command.command = SPE_CMD_INIT;
00136 command.data.INIT.dbMaxLen = maxDbLen;
00137 command.data.INIT.datatype = dataType;
00138 command.data.INIT.fixedDel = options->gapOpen;
00139 command.data.INIT.incDel = options->gapExt;
00140
00141 return submitSPECommand(&command);
00142 }
00143
00157 static int SPECreateProfile(const char* query, int queryLen, const void* matrix, double min, double max) {
00158 SPECommand command __ALIGNED__;
00159 assert(((ppu_addr_t)query & 0xf) == 0 && "query not aligned to 16 bytes");
00160 assert(((ppu_addr_t)matrix & 0xf) == 0 && "matrix not aligned to 16 bytes");
00161
00162 command.command = SPE_CMD_CREATE_PROFILE;
00163 command.data.CREATE_PROFILE.query.addr = (ppu_addr_t)query;
00164 command.data.CREATE_PROFILE.query.len = queryLen;
00165 command.data.CREATE_PROFILE.matrix.addr = (ppu_addr_t)matrix;
00166 command.data.CREATE_PROFILE.matrix.min = min;
00167 command.data.CREATE_PROFILE.matrix.max = max;
00168
00169 return submitSPECommand(&command);
00170 }
00171
00172 static int SPEGetProfile(const SPEProfile *profile) {
00173 SPECommand command __ALIGNED__;
00174 command.command = SPE_CMD_GET_PROFILE;
00175
00176 assert(((ppu_addr_t)profile->addr & 0xf) == 0 && "profile not aligned to 16 bytes");
00177 memcpy(&command.data.GET_PROFILE.profile, profile, sizeof(*profile));
00178
00179 return submitSPECommand(&command);
00180 }
00181
00182 static int SPEPutProfile(void *profile, int *blockSize) {
00183 int ret;
00184 SPECommand command __ALIGNED__;
00185 assert(((ppu_addr_t)profile & 0xf) == 0 && "profile not aligned to 16 byte");
00186
00187 command.command = SPE_CMD_PUT_PROFILE;
00188 command.data.PUT_PROFILE.blockSize = 0;
00189 command.data.PUT_PROFILE.addr = (ppu_addr_t)profile;
00190
00191 ret = submitSPECommand(&command);
00192
00193
00194 *blockSize = command.data.PUT_PROFILE.blockSize;
00195
00196 return ret;
00197 }
00198
00199 static int SPEAlign(const char *db, int dbLen, double *result) {
00200 int ret;
00201 SPECommand command __ALIGNED__;
00202 assert(((ppu_addr_t)db & 0xf) == 0 && "db sequence not aligned to 16 byte");
00203
00204 command.command = SPE_CMD_ALIGN;
00205 command.data.ALIGN.result = -1;
00206 command.data.ALIGN.db.len = dbLen;
00207 command.data.ALIGN.db.addr = (ppu_addr_t)db;
00208
00209 ret = submitSPECommand(&command);
00210
00211
00212 *result = command.data.ALIGN.result;
00213
00214 return ret;
00215 }
00216
00217 EXPORT double swps3_alignmentByteSPE( const SBMatrix matrix, const char * query, int queryLen, const char * db, int dbLen, Options * options ) {
00218 int i, ret;
00219 double min, max, maxScore;
00220
00221 ret = SPEInit(SPE_DATA_INT8, dbLen, options);
00222 if(ret != 0) error("error in SPEInit");
00223
00224
00225 max = MAX(options->gapExt,options->gapOpen);
00226 min = MIN(options->gapExt,options->gapOpen);
00227 for(i=0; i<MATRIX_DIM*MATRIX_DIM; i++) {
00228 if(max < matrix[i]) max = matrix[i];
00229 if(min > matrix[i]) min = matrix[i];
00230 }
00231 ret = SPECreateProfile(query, queryLen, matrix, min, max);
00232 if(ret != 0) error("error in SPECreateProfile");
00233
00234 ret = SPEAlign(db, dbLen, &maxScore);
00235 if(ret != 0) error("error in SPEAlign");
00236
00237
00238 if( ret != 0 || maxScore == -1 ){
00239 double dmatrix[MATRIX_DIM*MATRIX_DIM];
00240 warning( "sequence too long for SPE program, using PPU fallback\n" );
00241 for(i=0; i<MATRIX_DIM*MATRIX_DIM; ++i) dmatrix[i] = matrix[i];
00242 maxScore = swps3_alignScalar( dmatrix, query, queryLen, db, dbLen, options );
00243 }
00244 return maxScore;
00245 }
00246
00247 EXPORT double swps3_alignmentShortSPE( const SBMatrix matrix, const char * query, int queryLen, const char * db, int dbLen, Options * options ) {
00248 int i, ret;
00249 double max, min, maxScore;
00250 int16_t simi[MATRIX_DIM*MATRIX_DIM] __ALIGNED__;
00251
00252 ret = SPEInit(SPE_DATA_INT16, dbLen, options);
00253 if(ret != 0) error("error in SPEInit");
00254
00255
00256 max = MAX(options->gapExt,options->gapOpen);
00257 min = MIN(options->gapExt,options->gapOpen);
00258 for(i=0; i<MATRIX_DIM*MATRIX_DIM; i++) {
00259 if(max < matrix[i]) max = matrix[i];
00260 if(min > matrix[i]) min = matrix[i];
00261 simi[i] = matrix[i];
00262 }
00263 ret = SPECreateProfile(query, queryLen, simi, min, max);
00264 if(ret != 0) error("error in SPECreateProfile");
00265
00266 ret = SPEAlign(db, dbLen, &maxScore);
00267 if(ret != 0) error("error in SPEAlign");
00268
00269
00270 if( ret != 0 || maxScore == -1 ){
00271 double dmatrix[MATRIX_DIM*MATRIX_DIM];
00272 warning( "sequence too long for SPE program, using PPU fallback\n" );
00273 for(i=0; i<MATRIX_DIM*MATRIX_DIM; ++i) dmatrix[i] = matrix[i];
00274 maxScore = swps3_alignScalar( dmatrix, query, queryLen, db, dbLen, options );
00275 }
00276 return maxScore;
00277 }
00278
00279 EXPORT double swps3_alignmentFloatSPE( const SBMatrix matrix, const char * query, int queryLen, const char * db, int dbLen, Options * options ) {
00280 int i, ret;
00281 double max, min, maxScore;
00282 float simi[MATRIX_DIM*MATRIX_DIM] __ALIGNED__;
00283
00284 ret = SPEInit(SPE_DATA_FLOAT, dbLen, options);
00285 if(ret != 0) error("error in SPEInit");
00286
00287
00288 max = MAX(options->gapExt,options->gapOpen);
00289 min = MIN(options->gapExt,options->gapOpen);
00290 for(i=0; i<MATRIX_DIM*MATRIX_DIM; i++) {
00291 if(max < matrix[i]) max = matrix[i];
00292 if(min > matrix[i]) min = matrix[i];
00293 simi[i] = (float)matrix[i];
00294 }
00295 ret = SPECreateProfile(query, queryLen, simi, min, max);
00296 if(ret != 0) error("error in SPECreateProfile");
00297
00298 ret = SPEAlign(db, dbLen, &maxScore);
00299 if(ret != 0) error("error in SPEAlign");
00300
00301
00302 if( ret != 0 || maxScore == -1 ){
00303 double dmatrix[MATRIX_DIM*MATRIX_DIM];
00304 warning( "sequence too long for SPE program, using PPU fallback\n" );
00305 for(i=0; i<MATRIX_DIM*MATRIX_DIM; ++i) dmatrix[i] = matrix[i];
00306 maxScore = swps3_alignScalar( dmatrix, query, queryLen, db, dbLen, options );
00307 }
00308 return maxScore;
00309 }
00310
00314 EXPORT double swps3_alignmentProfileSPE( const char * db, int dbLen )
00315 {
00316 double maxScore;
00317 int ret;
00318
00319 ret = SPEAlign(db, dbLen, &maxScore);
00320 if(ret != 0) maxScore = -1;
00321
00322 return maxScore;
00323 }
00324
00325 EXPORT void swps3_loadProfileByte(SPEProfile *profile, int maxDbLen, Options *options)
00326 {
00327 int ret;
00328
00329 ret = SPEInit(SPE_DATA_INT8, maxDbLen, options);
00330 if(ret != 0) error("error in SPEInit");
00331
00332 ret = SPEGetProfile(profile);
00333 if(ret != 0) error("error in SPEGetProfile");
00334 }
00335
00336 EXPORT void swps3_loadProfileShort(SPEProfile *profile, int maxDbLen, Options *options)
00337 {
00338 int ret;
00339
00340 ret = SPEInit(SPE_DATA_INT16, maxDbLen, options);
00341 if(ret != 0) error("error in SPEInit");
00342
00343 ret = SPEGetProfile(profile);
00344 if(ret != 0) error("error in SPEGetProfile");
00345 }
00346
00347 EXPORT void swps3_loadProfileFloat(SPEProfile *profile, int maxDbLen, Options *options)
00348 {
00349 int ret;
00350
00351 ret = SPEInit(SPE_DATA_FLOAT, maxDbLen, options);
00352 if(ret != 0) error("error in SPEInit");
00353
00354 ret = SPEGetProfile(profile);
00355 if(ret != 0) error("error in SPEGetProfile");
00356 }
00357
00358 #define T int8_t
00359 EXPORT SPEProfile * swps3_createProfileBytePPU( const char * query, int queryLen, const SBMatrix matrix, int maxDbLen )
00360 {
00361 #include "DynProgr_PPU_profile.inc"
00362 }
00363 #undef T
00364
00365 #define T int16_t
00366 EXPORT SPEProfile * swps3_createProfileShortPPU( const char * query, int queryLen, const SBMatrix matrix, int maxDbLen )
00367 {
00368 #include "DynProgr_PPU_profile.inc"
00369 }
00370 #undef T
00371
00372 #define T float
00373 EXPORT SPEProfile * swps3_createProfileFloatPPU( const char * query, int queryLen, const SBMatrix matrix, int maxDbLen )
00374 {
00375 #include "DynProgr_PPU_profile.inc"
00376 }
00377 #undef T
00378
00379 EXPORT void swps3_freeProfilePPU(SPEProfile *profile) {
00380 free((void*)profile->addr);
00381 free(profile);
00382 }
00383