/************************************************************************************/ /*! \file commTest.c \brief Contains the communications test structure. The communications test routine is for testing out the speed & accuracy of MDSP->SDSP communications. */ #include /* must be included 1st */ #include #include #include #include "resources.h" #include "comRegDfns.h" #include "simulation.h" #include "commRegs.h" #include "commTest.h" #pragma CODE_SECTION(sdspCommTest, "xcode"); #if (!defined(COMM_TEST)) //Include a stub fxn in SDRAM: int32 sdspCommTest(void *ptr) {return SUCCESS; } #else //The communications test: #if (defined(COMMENTED)) /* These #includes were included in utilities.c to test the effect of the placement of the destination MDSP memory on the communications speed. */ #if (defined(COMM_TEST)) #include "commTest.h" //For the communications test routine: #pragma DATA_SECTION(sdspRegsC, "idata"); #pragma DATA_SECTION(sdspRegsD, "xpdata"); SdspRegTest sdspRegsB[N_SDSP], sdspRegsC[N_SDSP], sdspRegsD[N_SDSP]; #endif #endif #define DAS_BLINKEN_LICHT #pragma CODE_SECTION(sdspCommTest_i1, "icode"); #pragma CODE_SECTION(sdspCommTest_i2, "icode"); #pragma CODE_SECTION(sdspCommTest_i3, "icode"); #pragma CODE_SECTION(sdspCommTest_i4, "icode"); #pragma CODE_SECTION(sdspCommTest_i5, "icode"); #pragma CODE_SECTION(sdspCommTest_i6, "icode"); #pragma CODE_SECTION(sdspCommTest_i7, "icode"); #pragma CODE_SECTION(sdspCommTest_x1, "xcode"); #pragma CODE_SECTION(sdspCommTest_x2, "xcode"); #pragma CODE_SECTION(sdspCommTest_x3, "xcode"); #pragma CODE_SECTION(sdspCommTest_x4, "xcode"); #pragma CODE_SECTION(sdspCommTest_x5, "xcode"); #pragma CODE_SECTION(sdspCommTest_x6, "xcode"); #pragma CODE_SECTION(sdspCommTest_x7, "xcode"); extern char genStr[]; extern TIMER_Handle timer1; /* general purpose timer, started in main() */ // B: simple extern access. // C: extern access to idata section, D: extern access to external memory extern SdspRegTest sdspRegsB[N_SDSP]; extern far SdspRegTest sdspRegsC[N_SDSP], sdspRegsD[N_SDSP]; //Local structures: SdspRegTest sdspRegsA[N_SDSP]; int32 sdspCommTest_i1(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_i2(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_i3(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_i4(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_i5(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_i6(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_i7(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_x1(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_x2(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_x3(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_x4(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_x5(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_x6(void *ptr, void *sdspRegs, uint32 ntimes); int32 sdspCommTest_x7(void *ptr, void *sdspRegs, uint32 ntimes); /************************************************************************************ * sdspCommTest: * * synopsis: Tests the communications between the MDSP and SDSPs. The test is * primarily for speed of communications- testing the effects of code * and data placement & access on the speed of the communications. It is used * to optimize MDSP routines where code size & speed must be balanced. Generally * the access is to & from the communications registers; any valid SDSP address * can be used though.The speed is reported at the end, and is visible on the * oscilloscope if the LEDs are compiled in. * * There are 4 buffers in the MDSP that can gather the SDSP's information: * A => a local structure to this file, * B => a structure declared extern * C & D => structures declared extern far, with DATA_SECTION pragmas * placing them in idata (C) & in xpdata (D). * * There are 7 different comunication algorithms: * 1-4: gather the SDSP data by looping over the #words, using functions * which use HPIA/HPID to get the data. * 5-7: gather all the data at once using HPIA/HPID_I terminating with HPID. * * 1 => normal function calls to getSdspReg. * 2 => the getSdspReg function (only) is inlined. * 3 => the getSdspReg & its internal functions are inlined. * 4 => a monolithic inlined function is used (within which there are no * other function calls or inlined functions. * 5 => normal function calls to readSdspBlock. * 6 => the readSdspBlock function and its internal functions are inlined. * 7 => uses a monolithic inlined readSdspBlock function. * * Each of the 7 different algorithms has 2 routines running from internal * and external memory. * * Some results from a Rev. F Rod running SCT code: * * MDSP section placement: made no difference except for structure D (SDRAM), * which was ~10-12% slower (only). * MDSP code placement: external code runs ~2x slower. * * Algorithm: Reading 3 words per SDSP, each of the single word functions * are still significantly slower than the block functions: * 1: ~36.8 us, 2: 36.8 us, 3: 26.5 us, 4: 24.7 us, * 5: 21.5 us, 6: 17.4 us, 7: 16.1 us. (internal code & MDSP loc.) * * For 15 words per SDSP, the difference was (fxn 1, 4, 5 & 7): * 1: 166 us, 4: 106 us, 5: 54 us, 7: 45 us. * * author: Douglas Ferguson ************************************************************************************/ int32 sdspCommTest(void *ptr) { int32 returnCode= SUCCESS, status; uint32 t0, dt, i, nTimes[2]; CommTest *commTest= ptr; SdspRegTest *sdspRegs; int32 (*testFxn)(void *ptr, void *sRegs, uint32 nTimes)= NULL; if (commTest->sdspSect == 0) sdspRegs= &sdspRegsA[0]; //local. else if (commTest->sdspSect == 1) sdspRegs= &sdspRegsB[0]; //extern else if (commTest->sdspSect == 2) sdspRegs= &sdspRegsC[0]; //extern idata else if (commTest->sdspSect == 3) sdspRegs= &sdspRegsD[0]; //extern xpdata if (commTest->nWords >= N_COMM_TEST_REGS) { newError(&returnCode, PARAM_ERROR, FATAL_ERR, "sdspCommTest", "Too many SDSP registers.", __FILE__, __LINE__); return returnCode; } if (commTest->codePos == 0) { if (commTest->codeType == 1) testFxn= sdspCommTest_i1; else if (commTest->codeType == 2) testFxn= sdspCommTest_i2; else if (commTest->codeType == 3) testFxn= sdspCommTest_i3; else if (commTest->codeType == 4) testFxn= sdspCommTest_i4; else if (commTest->codeType == 5) testFxn= sdspCommTest_i5; else if (commTest->codeType == 6) testFxn= sdspCommTest_i6; else if (commTest->codeType == 7) testFxn= sdspCommTest_i7; } else if (commTest->codePos == 1) { if (commTest->codeType == 1) testFxn= sdspCommTest_x1; else if (commTest->codeType == 2) testFxn= sdspCommTest_x2; else if (commTest->codeType == 3) testFxn= sdspCommTest_x3; else if (commTest->codeType == 4) testFxn= sdspCommTest_x4; else if (commTest->codeType == 5) testFxn= sdspCommTest_x5; else if (commTest->codeType == 6) testFxn= sdspCommTest_x6; else if (commTest->codeType == 7) testFxn= sdspCommTest_x7; } if (testFxn == NULL) { newError(&returnCode, PARAM_ERROR, FATAL_ERR, "sdspCommTest", "Function does not exist.", __FILE__, __LINE__); return returnCode; } //The SDSP address is not tested for errors since if it's a bad input the FPGA //code will simply ignore it. //Note: sdspRegs is a pointer, so &sdspRegs => the *pointer's* address... setMem((uint32 *) sdspRegs, N_SDSP*SIZEOF(SdspRegTest), 0); //Clear the buffer. if (commTest->intLoop) {nTimes[0]= 1; nTimes[1]= commTest->nTimes; } //int. loop else {nTimes[1]= 1; nTimes[0]= commTest->nTimes; } //ext. loop t0= TIMER_getCount(timer1); for (i=0; islvBits & (1<sdspAddr, i=0; inWords; ++i, addr+=4) { sdspRegs[sdsp]->reg[i]= getSdspReg(sdsp, addr); } } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_x1(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<sdspAddr, i=0; inWords; ++i, addr+=4) { sdspRegs[sdsp]->reg[i]= getSdspReg(sdsp, addr); } } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_i2(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<sdspAddr, i=0; inWords; ++i, addr+=4) { sdspRegs[sdsp]->reg[i]= getSdspRegI(sdsp, addr); } } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_x2(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<sdspAddr, i=0; inWords; ++i, addr+=4) { sdspRegs[sdsp]->reg[i]= getSdspRegI(sdsp, addr); } } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_i3(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<sdspAddr, i=0; inWords; ++i, addr+=4) { sdspRegs[sdsp]->reg[i]= getSdspRegI2(sdsp, addr); } } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_x3(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<sdspAddr, i=0; inWords; ++i, addr+=4) { sdspRegs[sdsp]->reg[i]= getSdspRegI2(sdsp, addr); } } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_i4(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<sdspAddr, i=0; inWords; ++i, addr+=4) { sdspRegs[sdsp]->reg[i]= getSdspRegI3(sdsp, addr); } } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_x4(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<sdspAddr, i=0; inWords; ++i, addr+=4) { sdspRegs[sdsp]->reg[i]= getSdspRegI3(sdsp, addr); } } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_i5(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr, *mdspPtr, *sdspPtr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<reg[0]; sdspPtr= (uint32 *) commTest->sdspAddr; readSlvBlock(sdsp, sdspPtr, mdspPtr, commTest->nWords); } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_x5(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr, *mdspPtr, *sdspPtr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<reg[0]; sdspPtr= (uint32 *) commTest->sdspAddr; readSlvBlock(sdsp, sdspPtr, mdspPtr, commTest->nWords); } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_i6(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr, *mdspPtr, *sdspPtr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<reg[0]; sdspPtr= (uint32 *) commTest->sdspAddr; readSdspBlockI(sdsp, sdspPtr, mdspPtr, commTest->nWords); } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_x6(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr, *mdspPtr, *sdspPtr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<reg[0]; sdspPtr= (uint32 *) commTest->sdspAddr; readSdspBlockI(sdsp, sdspPtr, mdspPtr, commTest->nWords); } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_i7(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr, *mdspPtr, *sdspPtr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<reg[0]; sdspPtr= (uint32 *) commTest->sdspAddr; readSdspBlockI2(sdsp, sdspPtr, mdspPtr, commTest->nWords); } } //Fxn. body loop return status; } /************************************************************************************/ int32 sdspCommTest_x7(void *ptr, void *sRegs, uint32 nTimes) { int32 status= SUCCESS; uint32 sdsp, i, loop, addr, *mdspPtr, *sdspPtr; CommTest *commTest= ptr; SdspRegTest *sdspRegs[4]; //The internal vs. external loops measure function calling overhead. for (loop=0; loopslvBits & (1<reg[0]; sdspPtr= (uint32 *) commTest->sdspAddr; readSdspBlockI2(sdsp, sdspPtr, mdspPtr, commTest->nWords); } } //Fxn. body loop return status; } #endif //Communications test enabled.