|
|
@@ -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); |
|
|
} |