summaryrefslogtreecommitdiff
path: root/Source/UnitTests/Core/DSP/DSPAcceleratorTest.cpp
diff options
context:
space:
mode:
authorLéo Lam <leo@innovatetechnologi.es>2017-09-19 21:12:06 +0200
committerLéo Lam <leo@innovatetechnologi.es>2017-09-24 20:48:29 +0200
commit5dae20ea9d2dfefcc507b3c6da41a31371803340 (patch)
tree0498312b28a760ce80c9d1385bc82c5e30a64f91 /Source/UnitTests/Core/DSP/DSPAcceleratorTest.cpp
parentde6e80736445110aa3f1e896fbfd75ac1cadc090 (diff)
UnitTests: Add DSP accelerator tests
Includes DSP accelerator tests for basic behaviour, and everything that was fixed by the PR.
Diffstat (limited to 'Source/UnitTests/Core/DSP/DSPAcceleratorTest.cpp')
-rw-r--r--Source/UnitTests/Core/DSP/DSPAcceleratorTest.cpp187
1 files changed, 187 insertions, 0 deletions
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 <array>
+
+#include <gtest/gtest.h>
+
+#include "Common/CommonTypes.h"
+#include "Core/DSP/DSPAccelerator.h"
+
+// Simulated DSP accelerator.
+class TestAccelerator : public DSP::Accelerator
+{
+public:
+ // For convenience.
+ u16 TestRead()
+ {
+ std::array<s16, 16> 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);
+}