From 5dae20ea9d2dfefcc507b3c6da41a31371803340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Tue, 19 Sep 2017 21:12:06 +0200 Subject: [PATCH] UnitTests: Add DSP accelerator tests Includes DSP accelerator tests for basic behaviour, and everything that was fixed by the PR. --- Source/UnitTests/Core/CMakeLists.txt | 3 +- .../UnitTests/Core/DSP/DSPAcceleratorTest.cpp | 187 ++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 Source/UnitTests/Core/DSP/DSPAcceleratorTest.cpp diff --git a/Source/UnitTests/Core/CMakeLists.txt b/Source/UnitTests/Core/CMakeLists.txt index 4df4ee52ff..ba8c228e88 100644 --- a/Source/UnitTests/Core/CMakeLists.txt +++ b/Source/UnitTests/Core/CMakeLists.txt @@ -2,11 +2,12 @@ add_dolphin_test(MMIOTest MMIOTest.cpp) add_dolphin_test(PageFaultTest PageFaultTest.cpp) add_dolphin_test(CoreTimingTest CoreTimingTest.cpp) +add_dolphin_test(DSPAcceleratorTest DSP/DSPAcceleratorTest.cpp) add_dolphin_test(DSPAssemblyTest DSP/DSPAssemblyTest.cpp DSP/DSPTestBinary.cpp DSP/DSPTestText.cpp DSP/HermesBinary.cpp -) +) add_dolphin_test(ESFormatsTest IOS/ES/FormatsTest.cpp IOS/ES/TestBinaryData.cpp) diff --git a/Source/UnitTests/Core/DSP/DSPAcceleratorTest.cpp b/Source/UnitTests/Core/DSP/DSPAcceleratorTest.cpp new file mode 100644 index 0000000000..5cebc103a8 --- /dev/null +++ b/Source/UnitTests/Core/DSP/DSPAcceleratorTest.cpp @@ -0,0 +1,187 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include + +#include + +#include "Common/CommonTypes.h" +#include "Core/DSP/DSPAccelerator.h" + +// Simulated DSP accelerator. +class TestAccelerator : public DSP::Accelerator +{ +public: + // For convenience. + u16 TestRead() + { + std::array coefs{}; + m_accov_raised = false; + return Read(coefs.data()); + } + + bool EndExceptionRaised() const { return m_accov_raised; } +protected: + void OnEndException() override + { + EXPECT_TRUE(m_reads_stopped); + m_accov_raised = true; + } + u8 ReadMemory(u32 address) override { return 0; } + void WriteMemory(u32 address, u8 value) override {} + bool m_accov_raised = false; +}; + +TEST(DSPAccelerator, Initialization) +{ + TestAccelerator accelerator; + accelerator.SetCurrentAddress(0x00000000); + accelerator.SetStartAddress(0x00000000); + accelerator.SetEndAddress(0x00001000); + EXPECT_EQ(accelerator.GetStartAddress(), 0x00000000u); + EXPECT_EQ(accelerator.GetCurrentAddress(), 0x00000000u); + EXPECT_EQ(accelerator.GetEndAddress(), 0x00001000u); +} + +TEST(DSPAccelerator, SimpleReads) +{ + TestAccelerator accelerator; + accelerator.SetCurrentAddress(0x00000000); + accelerator.SetStartAddress(0x00000000); + accelerator.SetEndAddress(0x00001000); + + for (size_t i = 1; i <= 0xf; ++i) + { + accelerator.TestRead(); + EXPECT_FALSE(accelerator.EndExceptionRaised()); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress() + i); + } +} + +TEST(DSPAccelerator, AddressMasking) +{ + TestAccelerator accelerator; + + accelerator.SetCurrentAddress(0x48000000); + accelerator.SetStartAddress(0x48000000); + accelerator.SetEndAddress(0x48001000); + EXPECT_EQ(accelerator.GetStartAddress(), 0x08000000u); + EXPECT_EQ(accelerator.GetCurrentAddress(), 0x08000000u); + EXPECT_EQ(accelerator.GetEndAddress(), 0x08001000u); + + accelerator.SetCurrentAddress(0xffffffff); + accelerator.SetStartAddress(0xffffffff); + accelerator.SetEndAddress(0xffffffff); + EXPECT_EQ(accelerator.GetStartAddress(), 0x3fffffffu); + EXPECT_EQ(accelerator.GetCurrentAddress(), 0xbfffffffu); + EXPECT_EQ(accelerator.GetEndAddress(), 0x3fffffffu); +} + +TEST(DSPAccelerator, PredScaleRegisterMasking) +{ + TestAccelerator accelerator; + + accelerator.SetPredScale(0xbbbb); + EXPECT_EQ(accelerator.GetPredScale(), 0x3bu); + accelerator.SetPredScale(0xcccc); + EXPECT_EQ(accelerator.GetPredScale(), 0x4cu); + accelerator.SetPredScale(0xffff); + EXPECT_EQ(accelerator.GetPredScale(), 0x7fu); +} + +TEST(DSPAccelerator, OverflowBehaviour) +{ + TestAccelerator accelerator; + accelerator.SetCurrentAddress(0x00000000); + accelerator.SetStartAddress(0x00000000); + accelerator.SetEndAddress(0x0000000f); + + for (size_t i = 1; i <= 0xf; ++i) + { + accelerator.TestRead(); + EXPECT_FALSE(accelerator.EndExceptionRaised()); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress() + i); + } + + accelerator.TestRead(); + EXPECT_TRUE(accelerator.EndExceptionRaised()); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress()); + + // Since an ACCOV has fired, reads are stopped (until the YN2 register is reset), + // so the current address shouldn't be updated for this read. + accelerator.TestRead(); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress()); + + // Simulate a write to YN2, which internally resets the "reads stopped" flag. + // After resetting it, reads should work once again. + accelerator.SetYn2(0); + for (size_t i = 1; i <= 0xf; ++i) + { + accelerator.TestRead(); + EXPECT_FALSE(accelerator.EndExceptionRaised()); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress() + i); + } +} + +TEST(DSPAccelerator, OverflowFor16ByteAlignedAddresses) +{ + TestAccelerator accelerator; + accelerator.SetCurrentAddress(0x00000000); + accelerator.SetStartAddress(0x00000000); + accelerator.SetEndAddress(0x00000010); + + for (size_t i = 1; i <= 0xf; ++i) + { + accelerator.TestRead(); + EXPECT_FALSE(accelerator.EndExceptionRaised()); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress() + i); + } + + accelerator.TestRead(); + EXPECT_FALSE(accelerator.EndExceptionRaised()); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress() + 1); + + accelerator.TestRead(); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress() + 2); +} + +TEST(DSPAccelerator, OverflowForXXXXXXX1Addresses) +{ + TestAccelerator accelerator; + accelerator.SetCurrentAddress(0x00000000); + accelerator.SetStartAddress(0x00000000); + accelerator.SetEndAddress(0x00000011); + + for (size_t i = 1; i <= 0xf; ++i) + { + accelerator.TestRead(); + EXPECT_FALSE(accelerator.EndExceptionRaised()); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress() + i); + } + + accelerator.TestRead(); + EXPECT_FALSE(accelerator.EndExceptionRaised()); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress()); + + accelerator.TestRead(); + EXPECT_EQ(accelerator.GetCurrentAddress(), accelerator.GetStartAddress() + 1); +} + +TEST(DSPAccelerator, CurrentAddressSkips) +{ + TestAccelerator accelerator; + accelerator.SetCurrentAddress(0x00000000); + accelerator.SetStartAddress(0x00000000); + accelerator.SetEndAddress(0x00001000); + + for (size_t j = 1; j <= 0xf; ++j) + accelerator.TestRead(); + EXPECT_EQ(accelerator.GetCurrentAddress(), 0x0000000fu); + + accelerator.TestRead(); + EXPECT_EQ(accelerator.GetCurrentAddress(), 0x00000012u); + + accelerator.TestRead(); + EXPECT_EQ(accelerator.GetCurrentAddress(), 0x00000013u); +}