目录

include/AK/Plugin/PluginServices/PS3/MultiCoreServices.h

Go to the documentation of this file.
00001 
00002 //
00003 // MultiCoreServices.h
00004 //
00005 // PS3 implementation
00006 //
00007 // Copyright (c) 2006 Audiokinetic Inc. / All Rights Reserved
00008 //
00010 #ifndef MULTICORE_SERVICES_H_
00011 #define MULTICORE_SERVICES_H_
00012 
00013 #include <AK/SoundEngine/Common/AkTypes.h>
00014 
00015 #include <stdlib.h>
00016 #include <AK/Tools/Common/AkAssert.h>
00017 #include <string.h>
00018 
00019 #include <cell/spurs/job_chain.h>
00020 #include <cell/spurs/job_descriptor.h>
00021 #include <cell/spurs/job_commands.h>
00022 
00023 #if defined (__SPU__) && defined (_DEBUG)
00024 #include <spu_printf.h>
00025 #endif
00026 
00027 namespace AK
00028 {
00029 namespace MultiCoreServices
00030 {
00032     struct BinData
00033     {
00034         void*       pAddress;   
00035         AkUInt16    Size;       
00036     };
00037 
00038 #ifndef __SPU__
00039 
00040 
00041     static AkNoInline AkInt32 AddSpursJobDma(AkSpursJob& in_SpursJob, void *in_pSource, AkUInt32 uiLength)
00042     {
00043         // this must be __attribute__((aligned(16))) at least
00044         // __attribute__((aligned(128))) is recommended
00045         AKASSERT(((uintptr_t)in_pSource & 0x0000000F) == 0);
00046 
00047         // figure out how much we can take
00048         AkUInt16 MaxSize = sizeof(in_SpursJob.workArea.dmaList);
00049 
00050         // is there any space left ?
00051         if(in_SpursJob.header.sizeDmaList < MaxSize)
00052         {
00053             AkUInt32 NumDmas = 0;
00054             uintptr_t uiPointer = (uintptr_t) in_pSource;
00055             uint64_t uiSize = AK_ALIGN_SIZE_FOR_DMA(uiLength);
00056 
00057             AKASSERT(uiSize == uiLength);
00058 
00059             uint64_t uiSizeLeft = uiSize;
00060 
00061             // break the transfer in 16kB chunks if needed
00062             while(uiSizeLeft > 0)
00063             {
00064                 // still got some space left ?
00065                 if(in_SpursJob.header.sizeDmaList < MaxSize)
00066                 {
00067                     ++NumDmas;
00068 
00069                     // get 16kB at most
00070                     uint64_t uiChunkSize = (uiSizeLeft > 16384) ? 16384 : uiSizeLeft;
00071 
00072                     // build the dma list element
00073                     AkUInt64 DmaListElement = (0 & 1ULL) << 63 | (uiChunkSize & 0xffffULL) << 32 | ((uintptr_t) uiPointer  & 0xffffffffULL);
00074                     in_SpursJob.workArea.dmaList[in_SpursJob.header.sizeDmaList/8] = DmaListElement;
00075                     // update the dma list size
00076                     in_SpursJob.header.sizeDmaList += 8;
00077 
00078                     // keep track of what's goin on
00079                     uiSizeLeft -= uiChunkSize;
00080                     uiPointer += uiChunkSize;
00081                 }
00082                 else
00083                 {
00084                     // the whole transfer could not fit in the dma list
00085                     return -1;
00086                 }
00087             }
00088 
00089             // all is well the transfer fits in the dma list
00090             in_SpursJob.header.sizeInOrInOut += uiSize;
00091             return NumDmas;
00092         }
00093         // dma list is full
00094         return -1;
00095     }
00096 
00099     static AkForceInline void AddSpursJobSmallDma(AkSpursJob& in_SpursJob, const void *in_pSource, AkUInt32 uiLength)
00100     {
00101         // this must be __attribute__((aligned(16))) at least
00102         // __attribute__((aligned(128))) is recommended
00103         AKASSERT(uiLength <= (16*1024));
00104         AKASSERT(((uintptr_t)in_pSource & 0x0000000F) == 0);
00105         AKASSERT(uiLength== AK_ALIGN_SIZE_FOR_DMA(uiLength));
00106         AKASSERT( in_SpursJob.header.sizeDmaList < sizeof(in_SpursJob.workArea.dmaList) );
00107         AKASSERT( uiLength != 0 );
00108 
00109         AkUInt64 DmaListElement = (0 & 1ULL) << 63 | (uiLength & 0xffffULL) << 32 | ((uintptr_t) in_pSource  & 0xffffffffULL);
00110         in_SpursJob.workArea.dmaList[in_SpursJob.header.sizeDmaList/8] = DmaListElement;
00111         in_SpursJob.header.sizeDmaList += 8;
00112         in_SpursJob.header.sizeInOrInOut += uiLength;
00113     }
00114 #endif 
00115 
00116     struct DspProcess
00117     {
00118 #ifndef __SPU__
00119 
00120         inline void ResetDspProcess( 
00121             bool in_bIO     
00122             )
00123         {
00124             memset( &SpursJob, 0, sizeof( SpursJob ) ); // gets inlined into vector stores
00125             // should we use I/O buffers ?
00126             SpursJob.header.useInOutBuffer = in_bIO ? 1 : 0;
00127 #ifdef _DEBUG
00128             SpursJob.header.jobType =  CELL_SPURS_JOB_TYPE_MEMORY_CHECK;
00129 #endif
00130         }
00131 
00133         inline void SetOutputBufferSize( 
00134             AkUInt32 in_uSize   
00135             )
00136         {
00137             AKASSERT( !( in_uSize & 0xf ) ); // 16-byte aligned size
00138 
00139             SpursJob.header.sizeOut = in_uSize;
00140         }
00141 
00143         inline void SetScratchSize(
00144             AkUInt32 in_ScratchBytes    
00145             )
00146         {
00147             // convert to quads
00148             AkUInt16 ScratchSize = (in_ScratchBytes + 15) / 16;
00149             SpursJob.header.sizeScratch = ScratchSize;
00150         }
00151 
00154         inline void SetStackSize(
00155             AkUInt32 in_StackBytes  
00156             )
00157         {
00158             // convert to quads
00159             AkUInt16 StackSize = (in_StackBytes + 15) / 16;
00160             SpursJob.header.sizeStack = StackSize;
00161         }
00162 
00164         inline void SetDspProcess(BinData& in_BinData)
00165         {
00166             // this must be __attribute__((aligned(16)))
00167             AKASSERT(((uintptr_t)in_BinData.pAddress & 0x0000000F) == 0);
00168             // set the executable info
00169             SpursJob.header.eaBinary = (uintptr_t)in_BinData.pAddress;
00170             SpursJob.header.sizeBinary = in_BinData.Size;
00171         }
00172 
00174         inline int SetDspProcess( const void * in_jobbin2 )
00175         {
00176             return cellSpursJobHeaderSetJobbin2Param( &SpursJob.header, in_jobbin2 );
00177         }
00178 
00181         inline AkInt32 AddDspProcessDma(void *in_pSource, AkUInt32 uiLength)
00182         {
00183             return AddSpursJobDma(SpursJob,in_pSource,uiLength);
00184         }
00185 
00188         inline void AddDspProcessSmallDma(const void *in_pSource, AkUInt32 uiLength)
00189         {
00190             AddSpursJobSmallDma(SpursJob,in_pSource,uiLength);
00191         }
00192 
00197         inline void SetUserData( 
00198             AkUInt32 uIdx,      
00199             AkUInt64 uData      
00200             )
00201         {
00202             AKASSERT( uIdx*8 >= SpursJob.header.sizeDmaList );
00203             SpursJob.workArea.userData[ uIdx ] = uData;
00204         }
00205 
00207         inline AkUInt64 GetSpursJobCommand()
00208         {
00209             return CELL_SPURS_JOB_COMMAND_JOB(&SpursJob);
00210         }
00211 #endif
00212 
00213     private:
00214         AkSpursJob      SpursJob AK_ALIGN_FASTDMA;
00215     } AK_ALIGN_FASTDMA;
00216 
00217 #if defined(__SPU__) && defined(_DEBUG)
00218 
00219     AkForceInline void ShowContext(CellSpursJobContext2 *pContext,  CellSpursJob256 *pJob)
00220     {
00221         int NumIoBuffers = pContext->numIoBuffer;
00222         spu_printf("SPU =========> numIoBuffer      = %d\n",NumIoBuffers);
00223 
00224         // Get BufferList
00225         void *pBufferList[NumIoBuffers];
00226         int nGetBufferResult = cellSpursJobGetPointerList(pBufferList, &pJob->header, pContext);
00227 
00228         if ( nGetBufferResult == CELL_OK )
00229         {
00230             for(int Counter = 0 ; Counter < NumIoBuffers ; ++Counter)
00231             {
00232                 spu_printf("SPU =========> pBufferList[%2d] = 0x%8.8X\n",Counter, (unsigned int) pBufferList[Counter]);
00233             }
00234         }
00235         else
00236         {
00237             spu_printf("SPU =========> pBufferList : Error : Can't get buffer list. [%s%s]", nGetBufferResult == CELL_SPURS_JOB_ERROR_ALIGN ? "CELL_SPURS_JOB_ERROR_ALIGN" : "", nGetBufferResult == CELL_SPURS_JOB_ERROR_NULL_POINTER ? "CELL_SPURS_JOB_ERROR_NULL_POINTER" : "");
00238         }
00239         spu_printf("SPU =========> numCacheBuffer   = %d\n",pContext->numCacheBuffer);
00240         spu_printf("SPU =========> oBuffer          = 0x%8.8X\n",(unsigned int) pContext->oBuffer);
00241         spu_printf("SPU =========> sBuffer          = 0x%8.8X\n",(unsigned int) pContext->sBuffer);
00242         spu_printf("SPU =========> dmaTag           = %d\n",pContext->dmaTag);
00243         spu_printf("SPU =========> eaJobDescriptor  = 0x%llX\n",pContext->eaJobDescriptor);
00244     }
00245 
00247     AkForceInline void ShowJob(CellSpursJob256 *pJob)
00248     {
00249         spu_printf("SPU =========> eaBinary         = 0x%8.8X\n",(unsigned int) pJob->header.eaBinary);
00250         spu_printf("SPU =========> sizeBinary       = %d\n",pJob->header.sizeBinary);
00251         spu_printf("SPU =========> sizeDmaList      = %d\n",pJob->header.sizeDmaList);
00252         spu_printf("SPU =========> eaHighInput      = %d\n",pJob->header.eaHighInput);
00253         spu_printf("SPU =========> useInOutBuffer   = %d\n",pJob->header.useInOutBuffer);
00254         spu_printf("SPU =========> sizeInOrInOut    = %d\n",pJob->header.sizeInOrInOut);
00255         spu_printf("SPU =========> sizeOut          = %d\n",pJob->header.sizeOut);
00256         spu_printf("SPU =========> sizeStack        = %d\n",pJob->header.sizeStack);
00257         spu_printf("SPU =========> sizeScratch      = %d\n",pJob->header.sizeScratch);
00258         spu_printf("SPU =========> eaHighCache      = %d\n",pJob->header.eaHighCache);
00259         spu_printf("SPU =========> sizeCacheDmaList = %d\n",pJob->header.sizeCacheDmaList);
00260     //  CellSpursJobID idJob;
00261 
00262         uint64_t* pUserData = (uint64_t*)pJob->workArea.userData;
00263 
00264         for(int Counter = 0 ; Counter < 10 ; ++Counter)
00265         {
00266             uint64_t Data = *pUserData++;
00267             spu_printf("SPU =========> userData[%d]      = 0x%llX\n",Counter,Data);
00268         }
00269     }
00270     
00272     AkForceInline void PrintVectorHex(void* in_pVector)
00273     {
00274         spu_printf("SPU =========> 0x%8.8X 0x%8.8X 0x%8.8X 0x%8.8X\n",  *(unsigned int*)in_pVector,
00275                                                                         *((unsigned int*)in_pVector + 1),
00276                                                                         *((unsigned int*)in_pVector + 2),
00277                                                                         *((unsigned int*)in_pVector + 3));
00278     }
00279 
00281     AkForceInline void PrintVectorFloat(void* in_pVector)
00282     {
00283         spu_printf("SPU =========> %.3f %.3f %.3f %.3f\n",  *(float*)in_pVector,
00284                                                             *((float*)in_pVector + 1),
00285                                                             *((float*)in_pVector + 2),
00286                                                             *((float*)in_pVector + 3));
00287     }
00288 #endif // defined(__SPU__) && defined(_DEBUG)
00289 }
00290 }
00291 
00292 #endif // MULTICORE_SERVICES_H_