First Commit
This commit is contained in:
12
externals/teakra/tests/CMakeLists.txt
vendored
Normal file
12
externals/teakra/tests/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
add_executable(teakra_tests
|
||||
dma.cpp
|
||||
btdmp.cpp
|
||||
interpreter.cpp
|
||||
main.cpp
|
||||
timer.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(teakra_tests PRIVATE teakra catch)
|
||||
target_compile_options(teakra_tests PRIVATE ${TEAKRA_CXX_FLAGS})
|
||||
|
||||
add_test(teakra_tests teakra_tests)
|
||||
193
externals/teakra/tests/btdmp.cpp
vendored
Normal file
193
externals/teakra/tests/btdmp.cpp
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
#include <catch.hpp>
|
||||
#include <queue>
|
||||
#include "../src/btdmp.h"
|
||||
|
||||
struct BtdmpTestEnvironment {
|
||||
Teakra::CoreTiming core_timing;
|
||||
Teakra::Btdmp btdmp{core_timing};
|
||||
int interrupt_counter = 0;
|
||||
std::queue<std::array<std::int16_t, 2>> sample_queue;
|
||||
BtdmpTestEnvironment() {
|
||||
btdmp.SetInterruptHandler([&]() { interrupt_counter++; });
|
||||
btdmp.SetAudioCallback(
|
||||
[&](std::array<std::int16_t, 2> samples) { sample_queue.push(samples); });
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("Btdmp queueing", "[btdmp]") {
|
||||
BtdmpTestEnvironment env;
|
||||
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
env.btdmp.SetTransmitEnable(1);
|
||||
env.btdmp.SetTransmitPeriod(1000);
|
||||
|
||||
REQUIRE(env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.btdmp.Skip(3050);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
REQUIRE(env.sample_queue.size() == 3);
|
||||
REQUIRE(env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
auto samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{0, 0}});
|
||||
}
|
||||
|
||||
env.btdmp.Skip(949);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
REQUIRE(env.sample_queue.size() == 0);
|
||||
REQUIRE(env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
|
||||
env.btdmp.Tick();
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
REQUIRE(env.sample_queue.size() == 1);
|
||||
REQUIRE(env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
auto samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{0, 0}});
|
||||
|
||||
env.btdmp.Skip(999);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
REQUIRE(env.sample_queue.size() == 0);
|
||||
REQUIRE(env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
|
||||
env.btdmp.Skip(1);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
REQUIRE(env.sample_queue.size() == 1);
|
||||
REQUIRE(env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{0, 0}});
|
||||
|
||||
env.btdmp.Skip(100);
|
||||
env.btdmp.Send(0x1234);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == 899);
|
||||
REQUIRE(env.sample_queue.size() == 0);
|
||||
REQUIRE(!env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
|
||||
env.btdmp.Skip(899);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == 0);
|
||||
REQUIRE(env.sample_queue.size() == 0);
|
||||
REQUIRE(!env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
|
||||
env.btdmp.Tick();
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
REQUIRE(env.sample_queue.size() == 1);
|
||||
REQUIRE(env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{0x1234, 0}});
|
||||
|
||||
env.btdmp.Skip(100);
|
||||
env.btdmp.Send(11);
|
||||
env.btdmp.Send(22);
|
||||
env.btdmp.Send(33);
|
||||
env.btdmp.Send(44);
|
||||
env.btdmp.Send(55);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == 900 + 1000 + 1000 - 1);
|
||||
REQUIRE(env.sample_queue.size() == 0);
|
||||
REQUIRE(!env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
|
||||
env.btdmp.Skip(1500);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == 900 + 1000 + 1000 - 1 - 1500);
|
||||
REQUIRE(env.sample_queue.size() == 1);
|
||||
REQUIRE(!env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{11, 22}});
|
||||
|
||||
for (int i = 0; i < 13; ++i) {
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
env.btdmp.Send(i);
|
||||
}
|
||||
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == 1000 * 8 - 600 - 1);
|
||||
REQUIRE(env.sample_queue.size() == 0);
|
||||
REQUIRE(!env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(env.btdmp.GetTransmitFull());
|
||||
|
||||
for (int i = 0; i < 4567; ++i) {
|
||||
env.btdmp.Tick();
|
||||
}
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == 1000 * 8 - 600 - 1 - 4567);
|
||||
REQUIRE(env.sample_queue.size() == 5);
|
||||
REQUIRE(!env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
|
||||
env.btdmp.Skip(1000 * 7 - 600 - 1 - 4567);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == 1000);
|
||||
REQUIRE(env.sample_queue.size() == 6);
|
||||
REQUIRE(!env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
|
||||
env.btdmp.Tick();
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == 999);
|
||||
REQUIRE(env.sample_queue.size() == 7);
|
||||
REQUIRE(!env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{33, 44}});
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{55, 0}});
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{1, 2}});
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{3, 4}});
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{5, 6}});
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{7, 8}});
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{9, 10}});
|
||||
|
||||
env.btdmp.Skip(999);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == 0);
|
||||
REQUIRE(env.sample_queue.size() == 0);
|
||||
REQUIRE(!env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
|
||||
env.btdmp.Tick();
|
||||
REQUIRE(env.interrupt_counter == 2);
|
||||
REQUIRE(env.btdmp.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
REQUIRE(env.sample_queue.size() == 1);
|
||||
REQUIRE(env.btdmp.GetTransmitEmpty());
|
||||
REQUIRE(!env.btdmp.GetTransmitFull());
|
||||
samples = env.sample_queue.front();
|
||||
env.sample_queue.pop();
|
||||
REQUIRE(samples == std::array<std::int16_t, 2>{{11, 12}});
|
||||
}
|
||||
726
externals/teakra/tests/dma.cpp
vendored
Normal file
726
externals/teakra/tests/dma.cpp
vendored
Normal file
@@ -0,0 +1,726 @@
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <catch.hpp>
|
||||
#include "../src/ahbm.h"
|
||||
#include "../src/dma.h"
|
||||
#include "../src/shared_memory.h"
|
||||
|
||||
TEST_CASE("DMA + AHBM test", "[dma]") {
|
||||
Teakra::SharedMemory shared_memory;
|
||||
Teakra::Ahbm ahbm;
|
||||
Teakra::Dma dma(shared_memory, ahbm);
|
||||
std::vector<u8> fcram(0x80);
|
||||
dma.SetInterruptHandler([] {});
|
||||
ahbm.SetDmaChannel(0, 1);
|
||||
ahbm.SetExternalMemoryCallback(
|
||||
[&fcram](u32 address) -> u8 {
|
||||
REQUIRE(address >= 0x20000000);
|
||||
return fcram[address - 0x20000000];
|
||||
},
|
||||
[&fcram](u32 address, u8 v) {
|
||||
REQUIRE(address >= 0x20000000);
|
||||
fcram[address - 0x20000000] = v;
|
||||
},
|
||||
[&fcram](u32 address) -> u16 {
|
||||
REQUIRE(address >= 0x20000000);
|
||||
return fcram[address - 0x20000000] | ((u16)fcram[address - 0x20000000 + 1] << 8);
|
||||
},
|
||||
[&fcram](u32 address, u16 v) {
|
||||
REQUIRE(address >= 0x20000000);
|
||||
fcram[address - 0x20000000 + 0] = (u8)v;
|
||||
fcram[address - 0x20000000 + 1] = v >> 8;
|
||||
},
|
||||
[&fcram](u32 address) -> u32 {
|
||||
REQUIRE(address >= 0x20000000);
|
||||
return fcram[address - 0x20000000] | ((u32)fcram[address - 0x20000000 + 1] << 8)
|
||||
| ((u32)fcram[address - 0x20000000 + 2] << 16) | ((u32)fcram[address - 0x20000000 + 3] << 24);
|
||||
},
|
||||
[&fcram](u32 address, u32 v) {
|
||||
REQUIRE(address >= 0x20000000);
|
||||
fcram[address - 0x20000000 + 0] = (u8)v;
|
||||
fcram[address - 0x20000000 + 1] = (u8)(v >> 8);
|
||||
fcram[address - 0x20000000 + 2] = (u8)(v >> 16);
|
||||
fcram[address - 0x20000000 + 3] = (u8)(v >> 24);
|
||||
});
|
||||
|
||||
for (u8 i = 0; i < 0x80; ++i) {
|
||||
shared_memory.raw[0x40000 + i] = i;
|
||||
fcram[i] = i + 0x80;
|
||||
}
|
||||
|
||||
auto GetDspTestArea = [&shared_memory]() {
|
||||
return std::vector<u8>(shared_memory.raw.begin() + 0x40000,
|
||||
shared_memory.raw.begin() + 0x40000 + 0x80);
|
||||
};
|
||||
|
||||
auto GenerateExpected = [](const std::string& str, u8 base = 0) {
|
||||
auto stri = str.begin();
|
||||
std::vector<u8> result;
|
||||
for (u8 i = 0; i < 0x80; ++i) {
|
||||
if (stri == str.end()) {
|
||||
result.push_back(i + base);
|
||||
} else {
|
||||
if (*stri == '-') {
|
||||
result.push_back(i + base);
|
||||
stri += 2;
|
||||
continue;
|
||||
}
|
||||
u8 v = (u8)std::stoi(std::string(stri, stri + 2), 0, 16);
|
||||
result.push_back(v);
|
||||
stri += 2;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// Configurations and results below are from hwtest
|
||||
|
||||
SECTION("Read from AHBM") {
|
||||
dma.SetAddrSrcHigh(0x2000);
|
||||
dma.SetAddrDstHigh(0x0000);
|
||||
dma.SetSize0(4);
|
||||
dma.SetSize1(1);
|
||||
dma.SetSize2(1);
|
||||
dma.SetSrcSpace(7);
|
||||
dma.SetDstSpace(0);
|
||||
ahbm.SetDirection(0, 0);
|
||||
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8000000082000000"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081000082830000"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081828380818283"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(1);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8283808182838485"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(2);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081828384858687"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(3);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8283848586878485"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("00810000"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8000000000810000"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(1);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("0081000082000000"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(2);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8200000000830000"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081000080810000"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(1);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081000082830000"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081828380818283"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(1);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081828380818283"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(2);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081828380818283"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(3);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081828384858687"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 2);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081828384858687"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("88898A8B8C8D8E8F"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("9091929394959697"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("98999A9B9C9D9E9F"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081828384858687"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 2);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081868788898E8F"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("9091969798999E9F"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081868788898E8F"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 2);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081000084850000"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("888900008C8D0000"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081000084850000"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 2);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081828384858687"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("88898A8B8C8D8E8F"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8081828384858687"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(1);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 2);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("0000828300008687"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("00008A8B00008E8F"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("0000828300008687"));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 2);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8000000000810000"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8200000000830000"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8400000000850000"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8600000000870000"));
|
||||
dma.DoDma(0);
|
||||
REQUIRE(GetDspTestArea() == GenerateExpected("8000000000810000"));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Write to AHBM") {
|
||||
dma.SetAddrSrcHigh(0x0000);
|
||||
dma.SetAddrDstHigh(0x2000);
|
||||
dma.SetSize0(4);
|
||||
dma.SetSize1(1);
|
||||
dma.SetSize2(1);
|
||||
dma.SetSrcSpace(0);
|
||||
dma.SetDstSpace(7);
|
||||
ahbm.SetDirection(0, 1);
|
||||
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("2021222324252627", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20--22--24--26--", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20232427", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(3);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20----23----24----27", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(4);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20------22------24------26", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x11);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("22252629", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(1);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("--21222526", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20232427", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(1);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("--2122252627", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(1);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("--21--23--25--27", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(3);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("2021--23----2425--27", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(3);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20210000----0000--270000", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(4);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20210000222300002425000026270000", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("2021000024250000", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20230000", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(5);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20210000--230000----0000------00", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(1);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(0);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("--21000026270000", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(1);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("2023", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("2027", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20--24", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(3);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20----27", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x11);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(3);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20----27", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x12);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(3);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 0);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("24----2B", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(3);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("2021--27", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(2);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20212425", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(1);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("2027", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(4);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 1);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("2021----2425", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSize0(8);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(4);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("202122232425262728292A2B2C2D2E2F", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSize0(8);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(5);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 0);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("20212223--270000----2A2B------00", 0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSize0(16);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(4);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 1);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("202122232425262728292A2B2C2D2E2F"
|
||||
"303132333435363738393A3B3C3D3E3F",
|
||||
0x80));
|
||||
}
|
||||
SECTION("") {
|
||||
dma.SetAddrSrcLow(0x10);
|
||||
dma.SetAddrDstLow(0);
|
||||
dma.SetSize0(16);
|
||||
dma.SetSrcStep0(2);
|
||||
dma.SetDstStep0(8);
|
||||
dma.SetDwordMode(1);
|
||||
ahbm.SetUnitSize(0, 2);
|
||||
ahbm.SetBurstSize(0, 1);
|
||||
dma.DoDma(0);
|
||||
REQUIRE(fcram == GenerateExpected("202122232425262728292A2B2C2D2E2F"
|
||||
"--------------------------------"
|
||||
"303132333435363738393A3B3C3D3E3F",
|
||||
0x80));
|
||||
}
|
||||
}
|
||||
}
|
||||
156
externals/teakra/tests/interpreter.cpp
vendored
Normal file
156
externals/teakra/tests/interpreter.cpp
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
#include <memory>
|
||||
#include <catch.hpp>
|
||||
#include "../src/core_timing.h"
|
||||
#include "../src/interpreter.h"
|
||||
#include "../src/memory_interface.h"
|
||||
#include "../src/shared_memory.h"
|
||||
|
||||
TEST_CASE("Cycle accuracy", "[interpreter]") {
|
||||
Teakra::CoreTiming core_timing;
|
||||
Teakra::SharedMemory shared_memory;
|
||||
Teakra::MemoryInterfaceUnit miu;
|
||||
Teakra::MemoryInterface memory_interface{shared_memory, miu};
|
||||
Teakra::RegisterState regs;
|
||||
Teakra::Interpreter interpreter(core_timing, regs, memory_interface);
|
||||
|
||||
regs.pc = 0;
|
||||
regs.a[0] = 0;
|
||||
regs.a[1] = 0;
|
||||
regs.ie = 1;
|
||||
regs.im[0] = 1;
|
||||
|
||||
memory_interface.ProgramWrite(0x0000, 0x4180); // br (RESET vector)
|
||||
|
||||
memory_interface.ProgramWrite(0x0006, 0x4180); // br (INT0 vector)
|
||||
memory_interface.ProgramWrite(0x0007, 0x2000); // br 0x2000
|
||||
|
||||
for (u32 i = 0; i < 16; ++i) {
|
||||
memory_interface.ProgramWrite(0x1000 + i, 0x67D0); // inc a0
|
||||
memory_interface.ProgramWrite(0x2000 + i, 0x77D0); // inc a1
|
||||
}
|
||||
|
||||
memory_interface.ProgramWrite(0x1010, 0x57F0); // brr -1
|
||||
|
||||
class InterruptGenerator : public Teakra::CoreTiming::Callbacks {
|
||||
Teakra::Interpreter& interpreter;
|
||||
u64 counter = 0;
|
||||
|
||||
public:
|
||||
InterruptGenerator(Teakra::Interpreter& interpreter) : interpreter(interpreter) {}
|
||||
|
||||
void SetCounter(u64 new_counter) {
|
||||
counter = new_counter;
|
||||
}
|
||||
|
||||
void Tick() override {
|
||||
if (counter != 0) {
|
||||
--counter;
|
||||
if (counter == 0) {
|
||||
interpreter.SignalInterrupt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u64 GetMaxSkip() const override {
|
||||
if (counter != 0) {
|
||||
return counter - 1;
|
||||
} else {
|
||||
return Infinity;
|
||||
}
|
||||
}
|
||||
|
||||
void Skip(u64 ticks) override {
|
||||
if (counter != 0) {
|
||||
counter -= ticks;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
InterruptGenerator interrupt_generator(interpreter);
|
||||
interrupt_generator.SetCounter(7);
|
||||
core_timing.RegisterCallbacks(&interrupt_generator);
|
||||
|
||||
SECTION("Simple counting") {
|
||||
memory_interface.ProgramWrite(0x0001, 0x1000);
|
||||
interpreter.Run(1 + 5);
|
||||
REQUIRE(regs.a[0] == 5);
|
||||
REQUIRE(regs.a[1] == 0);
|
||||
}
|
||||
|
||||
SECTION("Counting with interrupt") {
|
||||
memory_interface.ProgramWrite(0x0001, 0x1000);
|
||||
interpreter.Run(1 + 7 + 1 + 3);
|
||||
REQUIRE(regs.a[0] == 7);
|
||||
REQUIRE(regs.a[1] == 3);
|
||||
}
|
||||
|
||||
SECTION("Counting with idle and interrupt") {
|
||||
memory_interface.ProgramWrite(0x0001, 0x100D);
|
||||
interpreter.Run(1 + 6);
|
||||
REQUIRE(regs.a[0] == 3);
|
||||
REQUIRE(regs.a[1] == 0);
|
||||
|
||||
interpreter.Run(3);
|
||||
REQUIRE(regs.a[0] == 3);
|
||||
REQUIRE(regs.a[1] == 1);
|
||||
}
|
||||
|
||||
SECTION("Counting with idle and interrupt 2") {
|
||||
memory_interface.ProgramWrite(0x0001, 0x100D);
|
||||
interpreter.Run(1 + 7);
|
||||
REQUIRE(regs.a[0] == 3);
|
||||
REQUIRE(regs.a[1] == 0);
|
||||
|
||||
interpreter.Run(3);
|
||||
REQUIRE(regs.a[0] == 3);
|
||||
REQUIRE(regs.a[1] == 2);
|
||||
}
|
||||
|
||||
SECTION("Counting with idle and interrupt 3") {
|
||||
memory_interface.ProgramWrite(0x0001, 0x100D);
|
||||
interpreter.Run(1 + 7 + 1 + 2);
|
||||
REQUIRE(regs.a[0] == 3);
|
||||
REQUIRE(regs.a[1] == 2);
|
||||
}
|
||||
|
||||
SECTION("Idle with interrupt 1") {
|
||||
memory_interface.ProgramWrite(0x0001, 0x1010);
|
||||
interpreter.Run(1 + 7 + 1 + 2);
|
||||
REQUIRE(regs.a[0] == 0);
|
||||
REQUIRE(regs.a[1] == 2);
|
||||
}
|
||||
|
||||
SECTION("Idle with interrupt 2") {
|
||||
memory_interface.ProgramWrite(0x0001, 0x1010);
|
||||
interpreter.Run(1 + 7);
|
||||
REQUIRE(regs.a[0] == 0);
|
||||
REQUIRE(regs.a[1] == 0);
|
||||
|
||||
interpreter.Run(1 + 2);
|
||||
REQUIRE(regs.a[0] == 0);
|
||||
REQUIRE(regs.a[1] == 2);
|
||||
}
|
||||
|
||||
SECTION("Idle with interrupt 3") {
|
||||
memory_interface.ProgramWrite(0x0001, 0x1010);
|
||||
interpreter.Run(1 + 6);
|
||||
REQUIRE(regs.a[0] == 0);
|
||||
REQUIRE(regs.a[1] == 0);
|
||||
|
||||
SECTION("Single step on the interrupt") {
|
||||
interpreter.Run(1);
|
||||
REQUIRE(regs.a[0] == 0);
|
||||
REQUIRE(regs.a[1] == 0);
|
||||
|
||||
interpreter.Run(1 + 2);
|
||||
REQUIRE(regs.a[0] == 0);
|
||||
REQUIRE(regs.a[1] == 2);
|
||||
}
|
||||
|
||||
SECTION("Run over the interrupt") {
|
||||
interpreter.Run(1 + 1 + 2);
|
||||
REQUIRE(regs.a[0] == 0);
|
||||
REQUIRE(regs.a[1] == 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
externals/teakra/tests/main.cpp
vendored
Normal file
2
externals/teakra/tests/main.cpp
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch.hpp>
|
||||
224
externals/teakra/tests/timer.cpp
vendored
Normal file
224
externals/teakra/tests/timer.cpp
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
#include <catch.hpp>
|
||||
#include "../src/timer.h"
|
||||
|
||||
struct TimerTestEnvironment {
|
||||
Teakra::CoreTiming core_timing;
|
||||
Teakra::Timer timer{core_timing};
|
||||
int interrupt_counter = 0;
|
||||
TimerTestEnvironment() {
|
||||
timer.SetInterruptHandler([&]() { interrupt_counter++; });
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("Single mode", "[timer]") {
|
||||
TimerTestEnvironment env;
|
||||
env.timer.count_mode = Teakra::Timer::CountMode::Single;
|
||||
env.timer.update_mmio = 1;
|
||||
env.timer.start_low = 5;
|
||||
env.timer.start_high = 0;
|
||||
env.timer.Restart();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 5);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 4);
|
||||
|
||||
env.timer.Tick();
|
||||
env.timer.Tick();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 3);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 2);
|
||||
|
||||
env.timer.Skip(2);
|
||||
REQUIRE(env.timer.counter_low == 1);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0);
|
||||
|
||||
env.timer.pause = 1;
|
||||
env.timer.Tick();
|
||||
REQUIRE(env.timer.counter_low == 1);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.timer.pause = 0;
|
||||
env.timer.Tick();
|
||||
REQUIRE(env.timer.counter_low == 0);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.timer.Tick();
|
||||
REQUIRE(env.timer.counter_low == 0);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
}
|
||||
|
||||
TEST_CASE("Auto restart mode", "[timer]") {
|
||||
TimerTestEnvironment env;
|
||||
env.timer.count_mode = Teakra::Timer::CountMode::AutoRestart;
|
||||
env.timer.update_mmio = 1;
|
||||
env.timer.start_low = 5;
|
||||
env.timer.start_high = 0x1234;
|
||||
env.timer.Restart();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 5);
|
||||
REQUIRE(env.timer.counter_high == 0x1234);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0x12340004);
|
||||
|
||||
env.timer.Tick();
|
||||
env.timer.Tick();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 3);
|
||||
REQUIRE(env.timer.counter_high == 0x1234);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0x12340002);
|
||||
|
||||
env.timer.Skip(0x12340002);
|
||||
REQUIRE(env.timer.counter_low == 1);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0);
|
||||
|
||||
env.timer.pause = 1;
|
||||
env.timer.Tick();
|
||||
REQUIRE(env.timer.counter_low == 1);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.timer.pause = 0;
|
||||
env.timer.Tick();
|
||||
REQUIRE(env.timer.counter_low == 0);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0x12340005);
|
||||
|
||||
env.timer.Tick();
|
||||
REQUIRE(env.timer.counter_low == 5);
|
||||
REQUIRE(env.timer.counter_high == 0x1234);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0x12340004);
|
||||
}
|
||||
|
||||
TEST_CASE("Free running mode", "[timer]") {
|
||||
TimerTestEnvironment env;
|
||||
// Set to Single most first to reset counter
|
||||
env.timer.count_mode = Teakra::Timer::CountMode::Single;
|
||||
env.timer.update_mmio = 1;
|
||||
env.timer.start_low = 5;
|
||||
env.timer.start_high = 0x1234;
|
||||
env.timer.Restart();
|
||||
env.timer.count_mode = Teakra::Timer::CountMode::FreeRunning;
|
||||
|
||||
REQUIRE(env.timer.counter_low == 5);
|
||||
REQUIRE(env.timer.counter_high == 0x1234);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0x12340004);
|
||||
|
||||
env.timer.Restart();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 5);
|
||||
REQUIRE(env.timer.counter_high == 0x1234);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0x12340004);
|
||||
|
||||
env.timer.Tick();
|
||||
env.timer.Tick();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 3);
|
||||
REQUIRE(env.timer.counter_high == 0x1234);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0x12340002);
|
||||
|
||||
env.timer.Skip(0x12340002);
|
||||
REQUIRE(env.timer.counter_low == 1);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0);
|
||||
|
||||
env.timer.pause = 1;
|
||||
env.timer.Tick();
|
||||
REQUIRE(env.timer.counter_low == 1);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.timer.pause = 0;
|
||||
env.timer.Tick();
|
||||
REQUIRE(env.timer.counter_low == 0);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0xFFFFFFFF);
|
||||
|
||||
env.timer.Tick();
|
||||
REQUIRE(env.timer.counter_low == 0xFFFF);
|
||||
REQUIRE(env.timer.counter_high == 0xFFFF);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.timer.GetMaxSkip() == 0xFFFFFFFE);
|
||||
}
|
||||
|
||||
TEST_CASE("Event counting restart mode", "[timer]") {
|
||||
TimerTestEnvironment env;
|
||||
env.timer.count_mode = Teakra::Timer::CountMode::EventCount;
|
||||
env.timer.update_mmio = 1;
|
||||
env.timer.start_low = 5;
|
||||
env.timer.start_high = 0;
|
||||
env.timer.Restart();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 5);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.timer.Tick();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 5);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.timer.TickEvent();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 4);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.timer.pause = 1;
|
||||
env.timer.TickEvent();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 4);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.timer.pause = 0;
|
||||
env.timer.TickEvent();
|
||||
env.timer.TickEvent();
|
||||
env.timer.TickEvent();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 1);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 0);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.timer.TickEvent();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 0);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
|
||||
env.timer.TickEvent();
|
||||
|
||||
REQUIRE(env.timer.counter_low == 0);
|
||||
REQUIRE(env.timer.counter_high == 0);
|
||||
REQUIRE(env.interrupt_counter == 1);
|
||||
REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
|
||||
}
|
||||
Reference in New Issue
Block a user