int PspSpeedTests::threadFunc(SceSize args, void *argp) { PSP_INFO_PRINT("thread %x created.\n", sceKernelGetThreadId()); _sem.take(); PSP_INFO_PRINT("grabbed semaphore. Quitting thread\n"); return 0; }
void printBuffer(byte *ptr, uint32 len) { uint32 printLen = len <= 10 ? len : 10; for (int i = 0; i < printLen; i++) { PSP_INFO_PRINT("%x ", ptr[i]); } if (len > 10) { PSP_INFO_PRINT("... "); for (int i = len - 10; i < len; i++) PSP_INFO_PRINT("%x ", ptr[i]); } PSP_INFO_PRINT("\n"); }
int main(void) { //change clock rate to 333mhz scePowerSetClockFrequency(333, 333, 166); PowerManager::instance(); // Setup power manager SetupCallbacks(); static const char *argv[] = { "scummvm", NULL }; static int argc = sizeof(argv) / sizeof(char *) - 1; g_system = new OSystem_PSP(); assert(g_system); #ifdef DYNAMIC_MODULES PluginManager::instance().addPluginProvider(new PSPPluginProvider()); #endif /* unit/speed tests */ #if defined (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS) PSP_INFO_PRINT("running tests\n"); psp_tests(); sceKernelSleepThread(); // that's it. That's all we're doing #endif int res = scummvm_main(argc, argv); g_system->quit(); // TODO: Consider removing / replacing this! PowerManager::destroy(); // get rid of PowerManager sceKernelSleepThread(); return res; }
void PspSpeedTests::fastCopySpecificSize(byte *dst, byte *src, uint32 bytes) { uint32 time1, time2; uint32 fastcopyTime, memcpyTime; const int iterations = 2000; int intc; intc = pspSdkDisableInterrupts(); time1 = PspRtc::instance().getMicros(); for (int i=0; i<iterations; i++) { PspMemory::fastCopy(dst, src, bytes); } time2 = PspRtc::instance().getMicros(); pspSdkEnableInterrupts(intc); fastcopyTime = time2-time1; intc = pspSdkDisableInterrupts(); time1 = PspRtc::instance().getMicros(); for (int i=0; i<iterations; i++) { memcpy(dst, src, bytes); } time2 = PspRtc::instance().getMicros(); pspSdkEnableInterrupts(intc); memcpyTime = time2-time1; PSP_INFO_PRINT("%d bytes. memcpy[%d], fastcopy[%d]\n", bytes, memcpyTime, fastcopyTime); }
// 222: 9-10us void PspSpeedTests::changePrioritySpeed(int id, int priority) { uint32 time1 = PspRtc::instance().getMicros(); sceKernelChangeThreadPriority(id, priority); uint32 time2 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("Changing thread priority to %d for id %d took %dus\n", priority, id, time2-time1); }
// 222: 4-5us void PspSpeedTests::getPrioritySpeed() { uint32 time1 = PspRtc::instance().getMicros(); int priority = sceKernelGetThreadCurrentPriority(); uint32 time2 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("Getting thread priority %d took %dus\n", priority, time2-time1); }
void psp_tests() { PSP_INFO_PRINT("in tests\n"); #ifdef PSP_ENABLE_SPEED_TESTS // Speed tests PspSpeedTests speedTests; speedTests.tickSpeed(); speedTests.getMicrosSpeed(); speedTests.msReadSpeed(); speedTests.seekSpeed(); speedTests.msReadSpeed(); speedTests.threadFunctionsSpeed(); speedTests.semaphoreSpeed(); speedTests.semaphoreManyThreadSpeed(); speedTests.fastCopySpeed(); #endif #ifdef PSP_ENABLE_UNIT_TESTS // Unit tests PspUnitTests unitTests; //unitTests.testFastCopy(); unitTests.testFileSystem(); #endif }
void PspSpeedTests::readAndTime(uint32 bytes, char *buffer, FILE *file) { uint32 time1 = PspRtc::instance().getMicros(); // test minimal read fread(buffer, bytes, 1, file); uint32 time2 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("Reading %d byte takes %dus\n", bytes, time2-time1); }
void PspSpeedTests::seekAndTime(int bytes, int origin, FILE *file) { char buffer[1000]; uint32 time1 = PspRtc::instance().getMicros(); // test minimal read fseek(file, bytes, origin); uint32 time2 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("Seeking %d byte from %d took %dus\n", bytes, origin, time2-time1); time1 = PspRtc::instance().getMicros(); // test minimal read fread(buffer, 1000, 1, file); time2 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("Reading 1000 bytes took %dus\n", time2-time1); }
void PspSpeedTests::semaphoreSpeed() { PspSemaphore sem(1); uint32 time1 = PspRtc::instance().getMicros(); sem.take(); uint32 time2 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("taking semaphore took %d us\n", time2-time1); // 10us uint32 time3 = PspRtc::instance().getMicros(); sem.give(); uint32 time4 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("releasing semaphore took %d us\n", time4-time3); //10us-55us }
// 222: 5-7us int PspSpeedTests::getThreadIdSpeed() { uint32 time1 = PspRtc::instance().getMicros(); int threadId = sceKernelGetThreadId(); uint32 time2 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("Getting thread ID %d took %dus\n", threadId, time2-time1); return threadId; }
void PspSpeedTests::getMicrosSpeed() { uint32 time1, time2, time3, time4; time1 = PspRtc::instance().getMicros(); time2 = PspRtc::instance().getMicros(); time3 = PspRtc::instance().getMicros(); time4 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("getMicros() times: %d, %d, %d\n", time4-time3, time3-time2, time2-time1); }
void PspSpeedTests::semaphoreManyThreadSpeed() { // create 4 threads for (int i=0; i<4; i++) { int thid = sceKernelCreateThread("my_thread", PspSpeedTests::threadFunc, 0x18, 0x10000, THREAD_ATTR_USER, NULL); sceKernelStartThread(thid, 0, 0); } PSP_INFO_PRINT("main thread. created threads\n"); uint32 threads = _sem.numOfWaitingThreads(); while (threads < 4) { threads = _sem.numOfWaitingThreads(); PSP_INFO_PRINT("main thread: waiting threads[%d]\n", threads); } PSP_INFO_PRINT("main: semaphore value[%d]\n", _sem.getValue()); PSP_INFO_PRINT("main thread: waiting threads[%d]\n", _sem.numOfWaitingThreads()); _sem.give(4); }
void PspUnitTests::testFastCopy() { PSP_INFO_PRINT("running fastcopy unit test ***********\n"); PSP_INFO_PRINT("this test requires the test flag to be on in fastCopy\n\n"); uint32 *bufferSrc32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE); uint32 *bufferDst32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE); // fill buffer 1 for (int i=0; i<MEMCPY_BUFFER_SIZE/4; i++) bufferSrc32[i] = i | (((MEMCPY_BUFFER_SIZE/4)-i)<<16); // print buffer for (int i=0; i<50; i++) PSP_INFO_PRINT("%x ", bufferSrc32[i]); PSP_INFO_PRINT("\n"); byte *bufferSrc = ((byte *)bufferSrc32); byte *bufferDst = ((byte *)bufferDst32); fastCopyDifferentSizes(bufferDst, bufferSrc, true); fastCopyDifferentSizes(bufferDst+1, bufferSrc+1); fastCopyDifferentSizes(bufferDst+2, bufferSrc+2, true); fastCopyDifferentSizes(bufferDst+3, bufferSrc+3); fastCopyDifferentSizes(bufferDst, bufferSrc+1); fastCopyDifferentSizes(bufferDst, bufferSrc+2, true); fastCopyDifferentSizes(bufferDst+2, bufferSrc, true); fastCopyDifferentSizes(bufferDst, bufferSrc+3); fastCopyDifferentSizes(bufferDst+1, bufferSrc+2); fastCopyDifferentSizes(bufferDst+1, bufferSrc+3); fastCopyDifferentSizes(bufferDst+2, bufferSrc+1); fastCopyDifferentSizes(bufferDst+2, bufferSrc+3); fastCopyDifferentSizes(bufferDst+3, bufferSrc+1); fastCopyDifferentSizes(bufferDst+3, bufferSrc+2); free(bufferSrc32); free(bufferDst32); }
int Mp3PspStream::readBuffer(int16 *buffer, const int numSamples) { DEBUG_ENTER_FUNC(); int samples = 0; #ifdef PRINT_BUFFERS int16 *debugBuffer = buffer; #endif // Keep going as long as we have input available while (samples < numSamples && _state != MP3_STATE_EOS) { const int len = MIN(numSamples, samples + (int)(_pcmLength - _posInFrame) * MAD_NCHANNELS(&_header)); while (samples < len) { *buffer++ = _pcmSamples[_posInFrame << 1]; samples++; if (MAD_NCHANNELS(&_header) == 2) { *buffer++ = _pcmSamples[(_posInFrame << 1) + 1]; samples++; } _posInFrame++; // always skip an extra sample since ME always outputs stereo } if (_posInFrame >= _pcmLength) { // We used up all PCM data in the current frame -- read & decode more decodeMP3Data(); } } #ifdef PRINT_BUFFERS PSP_INFO_PRINT("buffer:\n"); for (int i = 0; i<numSamples; i++) PSP_INFO_PRINT("%d ", debugBuffer[i]); PSP_INFO_PRINT("\n\n"); #endif return samples; }
void PspSpeedTests::fastCopySpeed() { PSP_INFO_PRINT("running fastCopy speed test\n"); uint32 *bufferSrc32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE); uint32 *bufferDst32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE); // fill buffer 1 for (int i=0; i<MEMCPY_BUFFER_SIZE/4; i++) bufferSrc32[i] = i | (((MEMCPY_BUFFER_SIZE/4)-i)<<16); // print buffer for (int i=0; i<50; i++) PSP_INFO_PRINT("%x ", bufferSrc32[i]); PSP_INFO_PRINT("\n"); byte *bufferSrc = ((byte *)bufferSrc32); byte *bufferDst = ((byte *)bufferDst32); PSP_INFO_PRINT("\n\ndst and src cached: -----------------\n"); fastCopyDifferentSizes(bufferDst, bufferSrc); fastCopyDifferentSizes(bufferDst+1, bufferSrc+1); fastCopyDifferentSizes(bufferDst, bufferSrc+1); fastCopyDifferentSizes(bufferDst+1, bufferSrc); PSP_INFO_PRINT("\n\ndst cached, src uncached: -----------------\n"); bufferSrc = UNCACHED(bufferSrc); fastCopyDifferentSizes(bufferDst, bufferSrc); fastCopyDifferentSizes(bufferDst+1, bufferSrc+1); fastCopyDifferentSizes(bufferDst, bufferSrc+1); fastCopyDifferentSizes(bufferDst+1, bufferSrc); PSP_INFO_PRINT("\n\ndst uncached, src uncached: --------------\n"); bufferDst = UNCACHED(bufferDst); fastCopyDifferentSizes(bufferDst, bufferSrc); fastCopyDifferentSizes(bufferDst+1, bufferSrc+1); fastCopyDifferentSizes(bufferDst, bufferSrc+1); fastCopyDifferentSizes(bufferDst+1, bufferSrc); PSP_INFO_PRINT("\n\ndst uncached, src cached: -------------------\n"); bufferSrc = CACHED(bufferSrc); fastCopyDifferentSizes(bufferDst, bufferSrc); fastCopyDifferentSizes(bufferDst+1, bufferSrc+1); fastCopyDifferentSizes(bufferDst, bufferSrc+1); fastCopyDifferentSizes(bufferDst+1, bufferSrc); free(bufferSrc32); free(bufferDst32); }
void PspSpeedTests::fastCopyDifferentSizes(byte *dst, byte *src) { PSP_INFO_PRINT("\nsrc[%p], dst[%p]\n", src, dst); fastCopySpecificSize(dst, src, 1); fastCopySpecificSize(dst, src, 2); fastCopySpecificSize(dst, src, 3); fastCopySpecificSize(dst, src, 4); fastCopySpecificSize(dst, src, 5); fastCopySpecificSize(dst, src, 8); fastCopySpecificSize(dst, src, 10); fastCopySpecificSize(dst, src, 16); fastCopySpecificSize(dst, src, 32); fastCopySpecificSize(dst, src, 50); fastCopySpecificSize(dst, src, 100); fastCopySpecificSize(dst, src, 500); fastCopySpecificSize(dst, src, 1024); fastCopySpecificSize(dst, src, 2048); }
void PspSpeedTests::threadFunctionsSpeed() { // very unscientific -- just ballpark int id; id = getThreadIdSpeed(); getThreadIdSpeed(); getPrioritySpeed(); getPrioritySpeed(); changePrioritySpeed(id, 30); changePrioritySpeed(id, 35); changePrioritySpeed(id, 25); // test context switch time for (int i=0; i<10; i++) { uint time1 = PspRtc::instance().getMicros(); PspThread::delayMicros(0); uint time2 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("poll %d. context switch Time = %dus\n", i, time2-time1); // 10-15us } }
inline void MasterGuRenderer::guPostRender() { DEBUG_ENTER_FUNC(); sceGuFinish(); #ifdef USE_DISPLAY_CALLBACK if (_callbackId < 0) PSP_ERROR("bad callbackId[%d]\n", _callbackId); else sceKernelNotifyCallback(_callbackId, 0); // notify the callback. Nothing extra to pass #else sceGuSync(0, 0); #ifdef ENABLE_RENDER_MEASURE uint32 now = g_system->getMillis(); PSP_INFO_PRINT("Render took %d milliseconds\n", now - _lastRenderTime); #endif /* ENABLE_RENDER_MEASURE */ sceDisplayWaitVblankStart(); sceGuSwapBuffers(); _renderFinished = true; #endif /* !USE_DISPLAY_CALLBACK */ }
void PspMemory::testCopy(const byte *debugDst, const byte *debugSrc, uint32 debugBytes) { bool mismatch = false; PSP_INFO_PRINT("testing fastCopy..."); for (uint32 i = 0; i < debugBytes; i++) { if (debugDst[i] != debugSrc[i]) { if (!mismatch) { PSP_INFO_PRINT("**** mismatch in copy! ****\n"); PSP_INFO_PRINT("dst[%p], src[%p], bytes[%u]\n", debugDst, debugSrc, debugBytes); mismatch = true; } PSP_INFO_PRINT("[%d]%x!=%x ", i, debugSrc[i], debugDst[i]); } } if (mismatch) { PSP_INFO_PRINT("\n"); } else { PSP_INFO_PRINT("ok\n"); } }
void PspMemorySwap::testSwap(const uint16 *debugDst, const uint16 *debugSrc, uint32 debugBytes, PSPPixelFormat &format) { bool mismatch = false; PSP_INFO_PRINT("testing fastSwap..."); uint32 shorts = debugBytes >> 1; for (uint32 i = 0; i < shorts; i++) { if (debugDst[i] != format.swapRedBlue16(debugSrc[i])) { if (!mismatch) { PSP_INFO_PRINT("**** mismatch in swap! ****\n"); PSP_INFO_PRINT("dst[%p], src[%p], bytes[%u]\n", debugDst, debugSrc, debugBytes); mismatch = true; } PSP_INFO_PRINT("[%d]%x!=%x ", i<<1, format.swapRedBlue16(debugSrc[i]), debugDst[i]); } } if (mismatch) { PSP_INFO_PRINT("\n"); } else { PSP_INFO_PRINT("ok\n"); } }
void PspSpeedTests::tickSpeed() { uint32 ticksPerSecond = sceRtcGetTickResolution(); PSP_INFO_PRINT("ticksPerSecond[%d]\n", ticksPerSecond); uint32 currentTicks1[2]; uint32 currentTicks2[2]; sceRtcGetCurrentTick((u64 *)currentTicks1); sceRtcGetCurrentTick((u64 *)currentTicks2); PSP_INFO_PRINT("current tick[%x %x][%u %u]\n", currentTicks1[0], currentTicks1[1], currentTicks1[0], currentTicks1[1]); PSP_INFO_PRINT("current tick[%x %x][%u %u]\n", currentTicks2[0], currentTicks2[1], currentTicks2[0], currentTicks2[1]); pspTime time; sceRtcSetTick(&time, (u64 *)currentTicks2); PSP_INFO_PRINT("current tick in time, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time.year, time.month, time.day, time.hour, time.minutes, time.seconds, time.microseconds); pspTime time1; pspTime time2; sceRtcGetCurrentClockLocalTime(&time1); sceRtcGetCurrentClockLocalTime(&time2); PSP_INFO_PRINT("time1, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time1.year, time1.month, time1.day, time1.hour, time1.minutes, time1.seconds, time1.microseconds); PSP_INFO_PRINT("time2, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time2.year, time2.month, time2.day, time2.hour, time2.minutes, time2.seconds, time2.microseconds); }
void Mp3PspStream::decodeMP3Data() { DEBUG_ENTER_FUNC(); do { if (_state == MP3_STATE_INIT) { initStream(); initStreamME(); } if (_state == MP3_STATE_EOS) return; findValidHeader(); // seach for next valid header while (_state == MP3_STATE_READY) { // not a real 'while'. Just for easy flow _stream.error = MAD_ERROR_NONE; uint32 frame_size = _stream.next_frame - _stream.this_frame; updatePcmLength(); // Retrieve the number of PCM samples. // We seem to change this, so it needs to be dynamic PSP_DEBUG_PRINT("MP3 frame size[%d]. pcmLength[%d]\n", frame_size, _pcmLength); memcpy(_codecInBuffer, _stream.this_frame, frame_size); // we need it aligned // set up parameters for ME _codecParams[6] = (unsigned long)_codecInBuffer; _codecParams[8] = (unsigned long)_pcmSamples; _codecParams[7] = frame_size; _codecParams[9] = _pcmLength * 2; // x2 for stereo, though this one's not so important // debug #ifdef PRINT_BUFFERS PSP_DEBUG_PRINT("mp3 frame:\n"); for (int i=0; i < (int)frame_size; i++) { PSP_DEBUG_PRINT_SAMELN("%x ", _codecInBuffer[i]); } PSP_DEBUG_PRINT("\n"); #endif // Decode the next frame // This function blocks. We'll want to put it in a thread int ret = sceAudiocodecDecode(_codecParams, 0x1002); if (ret < 0) { PSP_INFO_PRINT("failed to decode MP3 data in ME. sceAudiocodecDecode returned 0x%x\n", ret); } #ifdef PRINT_BUFFERS PSP_DEBUG_PRINT("PCM frame:\n"); for (int i=0; i < (int)_codecParams[9]; i+=2) { // changed from i+=2 PSP_DEBUG_PRINT_SAMELN("%d ", (int16)_pcmSamples[i]); } PSP_DEBUG_PRINT("\n"); #endif _posInFrame = 0; break; } } while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN); if (_stream.error != MAD_ERROR_NONE) // catch EOS _state = MP3_STATE_EOS; }
// This function leaks. For now I don't care bool PspUnitTests::testFileSystem() { // create memory const uint32 BufSize = 32 * 1024; char* buffer = new char[BufSize]; int i; Common::WriteStream *wrStream; Common::SeekableReadStream *rdStream; PSP_INFO_PRINT("testing fileSystem...\n"); // fill buffer for (i=0; i<(int)BufSize; i += 4) { buffer[i] = 'A'; buffer[i + 1] = 'B'; buffer[i + 2] = 'C'; buffer[i + 3] = 'D'; } // create a file const char *path = "./file.test"; Common::FSNode file(path); PSP_INFO_PRINT("creating write stream...\n"); wrStream = file.createWriteStream(); if (!wrStream) { PSP_ERROR("%s couldn't be created.\n", path); return false; } // write contents char* index = buffer; int32 totalLength = BufSize; int32 curLength = 50; PSP_INFO_PRINT("writing...\n"); while(totalLength - curLength > 0) { if ((int)wrStream->write(index, curLength) != curLength) { PSP_ERROR("couldn't write %d bytes\n", curLength); return false; } totalLength -= curLength; index += curLength; //curLength *= 2; //PSP_INFO_PRINT("write\n"); } // write the rest if ((int)wrStream->write(index, totalLength) != totalLength) { PSP_ERROR("couldn't write %d bytes\n", curLength); return false; } delete wrStream; PSP_INFO_PRINT("reading...\n"); rdStream = file.createReadStream(); if (!rdStream) { PSP_ERROR("%s couldn't be created.\n", path); return false; } // seek to beginning if (!rdStream->seek(0, SEEK_SET)) { PSP_ERROR("couldn't seek to the beginning after writing the file\n"); return false; } // read the contents char *readBuffer = new char[BufSize + 4]; memset(readBuffer, 0, (BufSize + 4)); index = readBuffer; while (rdStream->read(index, 100) == 100) { index += 100; } if (!rdStream->eos()) { PSP_ERROR("didn't find EOS at end of stream\n"); return false; } // compare for (i=0; i<(int)BufSize; i++) if (buffer[i] != readBuffer[i]) { PSP_ERROR("reading/writing mistake at %x. Got %x instead of %x\n", i, readBuffer[i], buffer[i]); return false; } // Check for exceeding limit for (i=0; i<4; i++) { if (readBuffer[BufSize + i]) { PSP_ERROR("read exceeded limits. %d = %x\n", BufSize + i, readBuffer[BufSize + i]); } } delete rdStream; PSP_INFO_PRINT("writing...\n"); wrStream = file.createWriteStream(); if (!wrStream) { PSP_ERROR("%s couldn't be created.\n", path); return false; } const char *phrase = "Jello is really fabulous"; uint32 phraseLen = strlen(phrase); int ret; if ((ret = wrStream->write(phrase, phraseLen)) != (int)phraseLen) { PSP_ERROR("couldn't write phrase. Got %d instead of %d\n", ret, phraseLen); return false; } PSP_INFO_PRINT("reading...\n"); delete wrStream; rdStream = file.createReadStream(); if (!rdStream) { PSP_ERROR("%s couldn't be created.\n", path); return false; } char *readPhrase = new char[phraseLen + 2]; memset(readPhrase, 0, phraseLen + 2); if ((ret = rdStream->read(readPhrase, phraseLen) != phraseLen)) { PSP_ERROR("read error on phrase. Got %d instead of %d\n", ret, phraseLen); return false; } for (i=0; i<(int)phraseLen; i++) { if (readPhrase[i] != phrase[i]) { PSP_ERROR("bad read/write in phrase. At %d, %x != %x\n", i, readPhrase[i], phrase[i]); return false; } } // check for exceeding if (readPhrase[i] != 0) { PSP_ERROR("found excessive copy in phrase. %c at %d\n", readPhrase[i], i); return false; } PSP_INFO_PRINT("trying to read end...\n"); // seek to end if (!rdStream->seek(0, SEEK_END)) { PSP_ERROR("couldn't seek to end for append\n"); return false; }; // try to read if (rdStream->read(readPhrase, 2) || !rdStream->eos()) { PSP_ERROR("was able to read at end of file\n"); return false; } PSP_INFO_PRINT("ok\n"); return true; }