Skip to content

Commit

Permalink
Make ROM speed testing work
Browse files Browse the repository at this point in the history
  • Loading branch information
Bim Overbohm committed May 11, 2022
1 parent adf4a0f commit 9212bd1
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 47 deletions.
Binary file modified 112.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified 336.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified MemTestGBA.gba
Binary file not shown.
Binary file modified MemTestGBA.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions src/cmake/CompilerFlagsGBA.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ set(COMPILERFLAGS "-save-temps -Wall -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--warn -x assembler-with-cpp ${ARCH}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARCH} ${COMPILERFLAGS} -std=c11")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -Og -g")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH} ${COMPILERFLAGS} -std=c++17 -fconserve-space -fno-threadsafe-statics -fno-rtti -fno-exceptions")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH} ${COMPILERFLAGS} -std=c++17 -fno-threadsafe-statics -fno-rtti -fno-exceptions")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -Og -g")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O3")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${ARCH}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS} -s")
Expand Down
89 changes: 54 additions & 35 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct alignas(4) TestConfig
struct alignas(4) SpeedResult
{
int32_t romTime = 0;
uint32_t bytesPerRomTest = 0;
int32_t readTime = 0;
int32_t writeTime = 0;
int32_t setTime = 0;
Expand All @@ -30,26 +31,33 @@ struct alignas(4) SpeedResult
int32_t copyFromTime = 0;
int32_t copyToDMATime = 0;
int32_t copyFromDMATime = 0;
uint32_t bytesPerTest = 0;
uint32_t bytesPerRamTest = 0;
};

// define all functions here, so we can put them into IWRAM
#define NOINLINE __attribute__((noinline))

void printSpeed(int32_t time, uint32_t bytes, uint16_t x, uint16_t y, TUI::Color backColor, TUI::Color textColor) IWRAM_CODE;
template <typename F>
void runBlockwise(F func, const TestConfig &config) IWRAM_CODE;
void readBlock(void *source, uint32_t value, uint32_t nrOfWords) IWRAM_CODE;
void readBlock(const void *source, uint32_t value, uint32_t nrOfWords) IWRAM_CODE;
void writeBlock(void *destination, uint32_t value, uint32_t nrOfWords) IWRAM_CODE;
template <typename F>
int32_t runFunctionBlockwise(F func, const TestConfig &config, uint32_t nrOfCycles) IWRAM_CODE;
template <typename F>
int32_t runFunction(F func, const TestConfig &config, uint32_t nrOfCycles) IWRAM_CODE;
int32_t runFunctionOnSrc(F func, const TestConfig &config, uint32_t nrOfCycles) IWRAM_CODE;
template <typename F>
int32_t runFunctionOnDest(F func, const TestConfig &config, uint32_t nrOfCycles) IWRAM_CODE;
SpeedResult runSpeedTest(const TestConfig &config, uint32_t nrOfCycles) IWRAM_CODE;
uint32_t testPattern(uint32_t index) IWRAM_CODE;
uint32_t runErrorTest(const TestConfig &config, uint32_t nrOfCycles, uint32_t pattern) IWRAM_CODE;
int32_t getTime() IWRAM_CODE;
void updateTime() IWRAM_CODE;
int32_t getTime() NOINLINE IWRAM_CODE;
void updateTime() NOINLINE IWRAM_CODE;
void updateBlinkState() IWRAM_CODE;
void updateInput() IWRAM_CODE;
void printTestState() IWRAM_CODE;
void printRamTimings() IWRAM_CODE;
void printRomWaitStates() IWRAM_CODE;
int main() IWRAM_CODE;

// ------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -85,7 +93,7 @@ void runBlockwise(F func, const TestConfig &config)
}
}

void readBlock(void *source, uint32_t value, uint32_t nrOfWords)
void readBlock(const void *source, uint32_t value, uint32_t nrOfWords)
{
uint32_t v = value;
auto src32 = reinterpret_cast<const uint32_t *>(source);
Expand Down Expand Up @@ -121,7 +129,18 @@ int32_t runFunctionBlockwise(F func, const TestConfig &config, uint32_t nrOfCycl
}

template <typename F>
int32_t runFunction(F func, const TestConfig &config, uint32_t nrOfCycles)
int32_t runFunctionOnSrc(F func, const TestConfig &config, uint32_t nrOfCycles)
{
auto startTime = getTime();
for (uint32_t cycle = 0; cycle < nrOfCycles; cycle++)
{
func(config.src, 0x12345678, config.srcSize >> 2);
}
return getTime() - startTime;
}

template <typename F>
int32_t runFunctionOnDest(F func, const TestConfig &config, uint32_t nrOfCycles)
{
auto startTime = getTime();
for (uint32_t cycle = 0; cycle < nrOfCycles; cycle++)
Expand All @@ -133,16 +152,16 @@ int32_t runFunction(F func, const TestConfig &config, uint32_t nrOfCycles)

SpeedResult runSpeedTest(const TestConfig &config, uint32_t nrOfCycles)
{
SpeedResult result = {0, 0, 0, 0, 0, 0, 0, 0, 0, config.destSize * nrOfCycles};
SpeedResult result = {0, ROM_DATA_SIZE * 4 * nrOfCycles, 0, 0, 0, 0, 0, 0, 0, 0, config.destSize * nrOfCycles};
auto rom = config;
rom.src = reinterpret_cast<const uint8_t *>(ROM_DATA);
rom.srcSize = ROM_DATA_SIZE * 4;
result.romTime = runFunction(readBlock, rom, nrOfCycles);
result.romTime = runFunctionOnSrc(readBlock, rom, nrOfCycles);
auto to = config;
result.readTime = runFunction(readBlock, to, nrOfCycles);
result.writeTime = runFunction(writeBlock, to, nrOfCycles);
result.setTime = runFunction(Memory::memset32, to, nrOfCycles);
result.setDMATime = runFunction(DMA::dma_fill32, to, nrOfCycles);
result.readTime = runFunctionOnDest(readBlock, to, nrOfCycles);
result.writeTime = runFunctionOnDest(writeBlock, to, nrOfCycles);
result.setTime = runFunctionOnDest(Memory::memset32, to, nrOfCycles);
result.setDMATime = runFunctionOnDest(DMA::dma_fill32, to, nrOfCycles);
TestConfig from = {const_cast<uint8_t *>(config.src), config.srcSize, config.dest, config.destSize};
result.copyFromTime = runFunctionBlockwise(Memory::memcpy32, from, nrOfCycles);
result.copyToTime = runFunctionBlockwise(Memory::memcpy32, to, nrOfCycles);
Expand Down Expand Up @@ -240,12 +259,6 @@ void updateTime()
TimerTicks += TimerIncrement;
}

void printTestState()
{
TUI::printString("Error test", 4, 16, TUI::Color::LightGray, !testSpeed && blinkState ? TUI::Color::Red : TUI::Color::Blue);
TUI::printString("Speed test", 20, 16, TUI::Color::LightGray, testSpeed && blinkState ? TUI::Color::Red : TUI::Color::Blue);
}

void updateBlinkState()
{
// blink UI elements
Expand All @@ -254,13 +267,19 @@ void updateBlinkState()
printTestState();
}

void updateRamTimings()
void printTestState()
{
TUI::printString("Error test", 4, 16, TUI::Color::LightGray, !testSpeed && blinkState ? TUI::Color::Red : TUI::Color::Blue);
TUI::printString("Speed test", 20, 16, TUI::Color::LightGray, testSpeed && blinkState ? TUI::Color::Red : TUI::Color::Blue);
}

void printRamTimings()
{
TUI::printString(RamWaitStateStrings[ramWaitStateIndex], 15, 3, TUI::Color::Blue, TUI::Color::White);
TUI::printString(RamWaitStateOptionStrings[ramWaitStateIndex], 0, 17, TUI::Color::LightGray, TUI::Color::Blue);
}

void updateRomWaitStates()
void printRomWaitStates()
{
TUI::printString(RomWaitStateStrings[romWaitStateIndex], 26, 3, TUI::Color::Blue, TUI::Color::White);
TUI::printString(RomWaitStateOptionStrings[romWaitStateIndex], 0, 18, TUI::Color::LightGray, TUI::Color::Blue);
Expand All @@ -283,7 +302,7 @@ void updateInput()
if (ramWaitStateIndex != ramWaitStateIndexBefore)
{
Memory::RegWaitEwram = RamWaitStates[ramWaitStateIndex];
updateRamTimings();
printRamTimings();
}
// check if need to change ROM wait states
auto romWaitStateIndexBefore = romWaitStateIndex;
Expand All @@ -298,7 +317,7 @@ void updateInput()
if (romWaitStateIndex != romWaitStateIndexBefore)
{
Memory::RegWaitCnt = RomWaitStates[romWaitStateIndex];
updateRomWaitStates();
printRomWaitStates();
}
// check if we need to change the test mode
auto testSpeedBefore = testSpeed;
Expand Down Expand Up @@ -350,11 +369,11 @@ int main()
TUI::printString(RamWaitStateOptionStrings[ramWaitStateIndex], 0, 17, TUI::Color::LightGray, TUI::Color::Blue);
TUI::printString(RomWaitStateOptionStrings[romWaitStateIndex], 0, 18, TUI::Color::LightGray, TUI::Color::Blue);
TUI::printString(" (START) Reboot ", 0, 19, TUI::Color::LightGray, TUI::Color::Blue);
updateRamTimings();
updateRomWaitStates();
printRamTimings();
printRomWaitStates();
// start wall clock
irqInit();
// set up time to increase time every ~5ms
// set up time to increase time every ~2.5ms
irqSet(irqMASKS::IRQ_TIMER3, updateTime);
irqEnable(irqMASKS::IRQ_TIMER3);
REG_TM3CNT_L = 65536 - TimerIncrement;
Expand All @@ -378,15 +397,15 @@ int main()
if (testSpeed)
{
auto result = runSpeedTest(testConfig, CyclesSpeed);
printSpeed(result.romTime, result.bytesPerTest, 15, 5, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.readTime, result.bytesPerTest, 15, 6, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.writeTime, result.bytesPerTest, 15, 7, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.setTime, result.bytesPerTest, 15, 8, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.setDMATime, result.bytesPerTest, 15, 9, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.copyFromTime, result.bytesPerTest, 15, 10, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.copyToTime, result.bytesPerTest, 15, 11, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.copyFromDMATime, result.bytesPerTest, 18, 12, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.copyToDMATime, result.bytesPerTest, 18, 13, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.romTime, result.bytesPerRomTest, 15, 5, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.readTime, result.bytesPerRamTest, 15, 6, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.writeTime, result.bytesPerRamTest, 15, 7, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.setTime, result.bytesPerRamTest, 15, 8, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.setDMATime, result.bytesPerRamTest, 15, 9, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.copyFromTime, result.bytesPerRamTest, 15, 10, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.copyToTime, result.bytesPerRamTest, 15, 11, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.copyFromDMATime, result.bytesPerRamTest, 18, 12, TUI::Color::Blue, TUI::Color::White);
printSpeed(result.copyToDMATime, result.bytesPerRamTest, 18, 13, TUI::Color::Blue, TUI::Color::White);
}
else
{
Expand Down
18 changes: 9 additions & 9 deletions src/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,24 @@ namespace Memory
extern uint8_t EWRAM_BLOCK[EWRAM_ALLOC_SIZE] EWRAM_DATA;

/// @brief Register for Game Pak SRAM and ROM wait states
constexpr reg_t<uint16_t, REG_BASE + 0x0204> RegWaitCnt;
constexpr reg_t<uint32_t, REG_BASE + 0x0204> RegWaitCnt;

/// @brief Minimum wait states possible for Game Pak ROM (2,1) and faster SRAM wait states (4)
/// @brief Minimum wait states possible for Game Pak ROM (2,1 / 2,1 / 2,1) and faster SRAM wait states (4)
/// See: http://problemkaputt.de/gbatek.htm#gbasystemcontrol
constexpr uint16_t WaitCntFast = 0x46D8;
constexpr uint32_t WaitCntFast = 0x46D8;

/// @brief Regular wait states possible for Game Pak ROM (3,1) and maximum SRAM wait states (8)
/// @brief Regular wait states possible for Game Pak ROM (3,1 / 3,1 / 3,1) and maximum SRAM wait states (8)
/// This is what most commercial carts use.
/// See: http://problemkaputt.de/gbatek.htm#gbasystemcontrol
constexpr uint16_t WaitCntNormal = 0x4317;
constexpr uint32_t WaitCntNormal = 0x45B7;

/// @brief Slower wait states possible for Game Pak ROM (4,2) and maximum SRAM wait states (8)
/// @brief Slower wait states possible for Game Pak ROM (4,2 / 4,4 / 4,8) and maximum SRAM wait states (8)
/// See: http://problemkaputt.de/gbatek.htm#gbasystemcontrol
constexpr uint16_t WaitCntSlow = 0x4303;
constexpr uint32_t WaitCntSlow = 0x4003;

/// @brief Maximum wait states possible for Game Pak ROM (8,2) and maximum SRAM wait states (8)
/// @brief Maximum wait states possible for Game Pak ROM (8,2 / 8,4 / 8,8) and maximum SRAM wait states (8)
/// See: http://problemkaputt.de/gbatek.htm#gbasystemcontrol
constexpr uint16_t WaitCntSlowest = 0x430F;
constexpr uint32_t WaitCntSlowest = 0x436F;

/// @brief Register for EWRAM wait states
constexpr reg_t<uint32_t, REG_BASE + 0x0800> RegWaitEwram;
Expand Down

0 comments on commit 9212bd1

Please sign in to comment.