backend-infra-engineer: Release v0.3.0 snapshot
This commit is contained in:
134
test/emu/audio/apu_test.cc
Normal file
134
test/emu/audio/apu_test.cc
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "app/emu/audio/apu.h"
|
||||
#include "app/emu/memory/memory.h"
|
||||
|
||||
#include <gmock/gmock-nice-strict.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace yaze {
|
||||
namespace test {
|
||||
|
||||
using testing::_;
|
||||
using testing::Return;
|
||||
using yaze::emu::Apu;
|
||||
using yaze::emu::MemoryImpl;
|
||||
|
||||
class ApuTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
memory_ = std::make_unique<MemoryImpl>();
|
||||
apu_ = std::make_unique<Apu>(*memory_);
|
||||
apu_->Init();
|
||||
}
|
||||
|
||||
std::unique_ptr<MemoryImpl> memory_;
|
||||
std::unique_ptr<Apu> apu_;
|
||||
};
|
||||
|
||||
// Test the IPL ROM handshake sequence timing
|
||||
TEST_F(ApuTest, IplRomHandshakeTiming) {
|
||||
// 1. Initial state check
|
||||
EXPECT_EQ(apu_->Read(0x00) & 0x80, 0); // Ready bit should be clear
|
||||
|
||||
// 2. Start handshake
|
||||
apu_->Write(0x00, 0x80); // Set control register bit 7
|
||||
|
||||
// 3. Wait for APU ready signal with cycle counting
|
||||
int cycles = 0;
|
||||
const int max_cycles = 1000; // Maximum expected cycles for handshake
|
||||
while (!(apu_->Read(0x00) & 0x80) && cycles < max_cycles) {
|
||||
apu_->RunCycles(1);
|
||||
cycles++;
|
||||
}
|
||||
|
||||
// 4. Verify timing constraints
|
||||
EXPECT_LT(cycles, max_cycles); // Should complete within max cycles
|
||||
EXPECT_GT(cycles, 0); // Should take some cycles
|
||||
EXPECT_TRUE(apu_->Read(0x00) & 0x80); // Ready bit should be set
|
||||
|
||||
// 5. Verify handshake completion
|
||||
EXPECT_EQ(apu_->GetStatus() & 0x80, 0x80); // Ready bit in status register
|
||||
}
|
||||
|
||||
// Test APU initialization sequence
|
||||
TEST_F(ApuTest, ApuInitialization) {
|
||||
// 1. Check initial state
|
||||
EXPECT_EQ(apu_->GetStatus(), 0x00);
|
||||
EXPECT_EQ(apu_->GetControl(), 0x00);
|
||||
|
||||
// 2. Initialize APU
|
||||
apu_->Init();
|
||||
|
||||
// 3. Verify initialization
|
||||
EXPECT_EQ(apu_->GetStatus(), 0x00);
|
||||
EXPECT_EQ(apu_->GetControl(), 0x00);
|
||||
|
||||
// 4. Check DSP registers are initialized
|
||||
for (int i = 0; i < 128; i++) {
|
||||
EXPECT_EQ(apu_->Read(0x00 + i), 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
// Test sample generation and timing
|
||||
TEST_F(ApuTest, SampleGenerationTiming) {
|
||||
// 1. Generate samples
|
||||
const int sample_count = 1024;
|
||||
std::vector<int16_t> samples(sample_count);
|
||||
|
||||
// 2. Measure timing
|
||||
uint64_t start_cycles = apu_->GetCycles();
|
||||
apu_->GetSamples(samples.data(), sample_count, false);
|
||||
uint64_t end_cycles = apu_->GetCycles();
|
||||
|
||||
// 3. Verify timing
|
||||
EXPECT_GT(end_cycles - start_cycles, 0);
|
||||
|
||||
// 4. Verify samples
|
||||
bool has_non_zero = false;
|
||||
for (int i = 0; i < sample_count; ++i) {
|
||||
if (samples[i] != 0) {
|
||||
has_non_zero = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(has_non_zero);
|
||||
}
|
||||
|
||||
// Test DSP register access timing
|
||||
TEST_F(ApuTest, DspRegisterAccessTiming) {
|
||||
// 1. Write to DSP registers
|
||||
const uint8_t test_value = 0x42;
|
||||
uint64_t start_cycles = apu_->GetCycles();
|
||||
|
||||
apu_->Write(0x00, 0x80); // Set control register
|
||||
apu_->Write(0x01, test_value); // Write to DSP address
|
||||
|
||||
uint64_t end_cycles = apu_->GetCycles();
|
||||
|
||||
// 2. Verify timing
|
||||
EXPECT_GT(end_cycles - start_cycles, 0);
|
||||
|
||||
// 3. Verify register access
|
||||
EXPECT_EQ(apu_->Read(0x01), test_value);
|
||||
}
|
||||
|
||||
// Test DMA transfer timing
|
||||
TEST_F(ApuTest, DmaTransferTiming) {
|
||||
// 1. Prepare DMA data
|
||||
const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
|
||||
|
||||
// 2. Measure DMA timing
|
||||
uint64_t start_cycles = apu_->GetCycles();
|
||||
apu_->WriteDma(0x00, data, sizeof(data));
|
||||
uint64_t end_cycles = apu_->GetCycles();
|
||||
|
||||
// 3. Verify timing
|
||||
EXPECT_GT(end_cycles - start_cycles, 0);
|
||||
|
||||
// 4. Verify DMA transfer
|
||||
EXPECT_EQ(apu_->Read(0x00), 0x01);
|
||||
EXPECT_EQ(apu_->Read(0x01), 0x02);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace yaze
|
||||
122
test/emu/audio/ipl_handshake_test.cc
Normal file
122
test/emu/audio/ipl_handshake_test.cc
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "app/emu/audio/apu.h"
|
||||
#include "app/emu/memory/memory.h"
|
||||
|
||||
#include <gmock/gmock-nice-strict.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace yaze {
|
||||
namespace test {
|
||||
|
||||
using testing::_;
|
||||
using testing::Return;
|
||||
using yaze::emu::Apu;
|
||||
using yaze::emu::MemoryImpl;
|
||||
|
||||
class IplHandshakeTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
memory_ = std::make_unique<MemoryImpl>();
|
||||
apu_ = std::make_unique<Apu>(*memory_);
|
||||
apu_->Init();
|
||||
}
|
||||
|
||||
std::unique_ptr<MemoryImpl> memory_;
|
||||
std::unique_ptr<Apu> apu_;
|
||||
};
|
||||
|
||||
// Test IPL ROM handshake timing with exact cycle counts
|
||||
TEST_F(IplHandshakeTest, ExactCycleTiming) {
|
||||
// 1. Initial state
|
||||
EXPECT_EQ(apu_->Read(0x00) & 0x80, 0); // Ready bit should be clear
|
||||
|
||||
// 2. Start handshake
|
||||
apu_->Write(0x00, 0x80); // Set control register bit 7
|
||||
|
||||
// 3. Run exact number of cycles for handshake
|
||||
const int expected_cycles = 64; // Expected cycle count for handshake
|
||||
apu_->RunCycles(expected_cycles);
|
||||
|
||||
// 4. Verify handshake completed
|
||||
EXPECT_TRUE(apu_->Read(0x00) & 0x80); // Ready bit should be set
|
||||
EXPECT_EQ(apu_->GetStatus() & 0x80, 0x80); // Ready bit in status register
|
||||
}
|
||||
|
||||
// Test IPL ROM handshake timing with cycle range
|
||||
TEST_F(IplHandshakeTest, CycleRange) {
|
||||
// 1. Initial state
|
||||
EXPECT_EQ(apu_->Read(0x00) & 0x80, 0); // Ready bit should be clear
|
||||
|
||||
// 2. Start handshake
|
||||
apu_->Write(0x00, 0x80); // Set control register bit 7
|
||||
|
||||
// 3. Wait for handshake with cycle counting
|
||||
int cycles = 0;
|
||||
const int min_cycles = 32; // Minimum expected cycles
|
||||
const int max_cycles = 96; // Maximum expected cycles
|
||||
|
||||
while (!(apu_->Read(0x00) & 0x80) && cycles < max_cycles) {
|
||||
apu_->RunCycles(1);
|
||||
cycles++;
|
||||
}
|
||||
|
||||
// 4. Verify timing constraints
|
||||
EXPECT_GE(cycles, min_cycles); // Should take at least min_cycles
|
||||
EXPECT_LE(cycles, max_cycles); // Should complete within max_cycles
|
||||
EXPECT_TRUE(apu_->Read(0x00) & 0x80); // Ready bit should be set
|
||||
}
|
||||
|
||||
// Test IPL ROM handshake with multiple attempts
|
||||
TEST_F(IplHandshakeTest, MultipleAttempts) {
|
||||
const int num_attempts = 10;
|
||||
std::vector<int> cycle_counts;
|
||||
|
||||
for (int i = 0; i < num_attempts; i++) {
|
||||
// Reset APU
|
||||
apu_->Init();
|
||||
|
||||
// Start handshake
|
||||
apu_->Write(0x00, 0x80);
|
||||
|
||||
// Count cycles until ready
|
||||
int cycles = 0;
|
||||
while (!(apu_->Read(0x00) & 0x80) && cycles < 1000) {
|
||||
apu_->RunCycles(1);
|
||||
cycles++;
|
||||
}
|
||||
|
||||
// Record cycle count
|
||||
cycle_counts.push_back(cycles);
|
||||
|
||||
// Verify handshake completed
|
||||
EXPECT_TRUE(apu_->Read(0x00) & 0x80);
|
||||
}
|
||||
|
||||
// Verify cycle count consistency
|
||||
int min_cycles = *std::min_element(cycle_counts.begin(), cycle_counts.end());
|
||||
int max_cycles = *std::max_element(cycle_counts.begin(), cycle_counts.end());
|
||||
EXPECT_LE(max_cycles - min_cycles, 2); // Cycle count should be consistent
|
||||
}
|
||||
|
||||
// Test IPL ROM handshake with interrupts
|
||||
TEST_F(IplHandshakeTest, WithInterrupts) {
|
||||
// 1. Initial state
|
||||
EXPECT_EQ(apu_->Read(0x00) & 0x80, 0);
|
||||
|
||||
// 2. Enable interrupts
|
||||
apu_->Write(0x00, 0x80 | 0x40); // Set control register bits 7 and 6
|
||||
|
||||
// 3. Run cycles with interrupts
|
||||
int cycles = 0;
|
||||
while (!(apu_->Read(0x00) & 0x80) && cycles < 1000) {
|
||||
apu_->RunCycles(1);
|
||||
cycles++;
|
||||
}
|
||||
|
||||
// 4. Verify handshake completed
|
||||
EXPECT_TRUE(apu_->Read(0x00) & 0x80);
|
||||
EXPECT_EQ(apu_->GetStatus() & 0x80, 0x80);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace yaze
|
||||
Reference in New Issue
Block a user