mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-04-22 08:41:12 +00:00
Lots of C++20 and stability changes in 6502 HarteTest
This commit is contained in:
parent
19f8e20021
commit
3d5d4d889c
@ -12,22 +12,19 @@
|
||||
|
||||
class TestRunner final : public EightBit::Bus {
|
||||
private:
|
||||
static std::set<uint8_t> m_undocumented_opcodes;
|
||||
static bool m_undocumented_opcodes_initialised;
|
||||
|
||||
EightBit::Ram m_ram = 0x10000;
|
||||
EightBit::MOS6502 m_cpu = { *this };
|
||||
|
||||
protected:
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
|
||||
EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
|
||||
|
||||
public:
|
||||
TestRunner();
|
||||
|
||||
virtual void raisePOWER() final;
|
||||
virtual void lowerPOWER() final;
|
||||
void raisePOWER() final;
|
||||
void lowerPOWER() final;
|
||||
|
||||
virtual void initialise() final;
|
||||
void initialise() final;
|
||||
|
||||
[[nodiscard]] constexpr auto& RAM() noexcept { return m_ram; }
|
||||
[[nodiscard]] constexpr auto& CPU() noexcept { return m_cpu; }
|
||||
|
@ -106,7 +106,9 @@ void checker_t::initialiseState() {
|
||||
cpu.P() = initial.p();
|
||||
for (const auto entry : initial.ram()) {
|
||||
const byte_t byte(entry);
|
||||
ram.poke(byte.address(), byte.value());
|
||||
const auto address = byte.address();
|
||||
const auto value = byte.value();
|
||||
ram.poke(address, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,18 +136,28 @@ bool checker_t::checkState() {
|
||||
auto& ram = runner().RAM();
|
||||
|
||||
const auto expected_cycles = test().cycles();
|
||||
const auto actual_cycles = m_actualCycles;
|
||||
const auto& actual_cycles = m_actualCycles;
|
||||
m_cycle_count_mismatch = expected_cycles.size() != actual_cycles.size();
|
||||
if (m_cycle_count_mismatch)
|
||||
return false;
|
||||
|
||||
size_t actual_idx = 0;
|
||||
for (const auto expected_cycle : expected_cycles) {
|
||||
|
||||
const auto expected = cycle_t(expected_cycle);
|
||||
const auto actual = actual_cycles.at(actual_idx++); // actual could be less than expected
|
||||
check("Cycle address", expected.address(), std::get<0>(actual));
|
||||
check("Cycle value", expected.value(), std::get<1>(actual));
|
||||
check("Cycle action", expected.action(), std::string_view(std::get<2>(actual)));
|
||||
const auto& actual = actual_cycles.at(actual_idx++); // actual could be less than expected
|
||||
|
||||
const auto expected_address = expected.address();
|
||||
const auto actual_address = std::get<0>(actual);
|
||||
check("Cycle address", expected_address, actual_address);
|
||||
|
||||
const auto expected_value = expected.value();
|
||||
const auto actual_value = std::get<1>(actual);
|
||||
check("Cycle value", expected_value, actual_value);
|
||||
|
||||
const auto expected_action = expected.action();
|
||||
const auto& actual_action = std::get<2>(actual);
|
||||
check("Cycle action", expected_action, std::string_view(actual_action));
|
||||
}
|
||||
|
||||
const auto final = test().final();
|
||||
@ -159,7 +171,9 @@ bool checker_t::checkState() {
|
||||
bool ram_problem = false;
|
||||
for (const auto entry : final.ram()) {
|
||||
const byte_t byte(entry);
|
||||
const auto ram_good = check("RAM", byte.address(), byte.value(), ram.peek(byte.address()));
|
||||
const auto address = byte.address();
|
||||
const auto value = byte.value();
|
||||
const auto ram_good = check("RAM", address, value, ram.peek(address));
|
||||
if (!ram_good && !ram_problem)
|
||||
ram_problem = true;
|
||||
}
|
||||
@ -195,17 +209,19 @@ void checker_t::check(test_t current) {
|
||||
initialiseState();
|
||||
const auto pc = cpu.PC().word;
|
||||
const auto start_opcode = runner().peek(pc);
|
||||
|
||||
m_undocumented = m_undocumented_opcodes.contains(start_opcode);
|
||||
if (undocumented()) {
|
||||
m_valid = false;
|
||||
m_messages.push_back("Undocumented");
|
||||
return;
|
||||
}
|
||||
|
||||
m_cycles = cpu.step();
|
||||
runner().lowerPOWER();
|
||||
|
||||
m_valid = checkState();
|
||||
|
||||
m_undocumented = m_undocumented_opcodes.find(start_opcode) != m_undocumented_opcodes.end();
|
||||
if (undocumented()) {
|
||||
m_messages.push_back("Undocumented");
|
||||
return;
|
||||
}
|
||||
|
||||
if (unimplemented()) {
|
||||
m_messages.push_back("Unimplemented");
|
||||
return;
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "TestRunner.h"
|
||||
|
||||
class checker_t {
|
||||
public:
|
||||
private:
|
||||
static std::set<uint8_t> m_undocumented_opcodes;
|
||||
static bool m_undocumented_opcodes_initialised;
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_COROUTINES
|
||||
|
||||
#include <coroutine>
|
||||
#include <utility>
|
||||
|
||||
@ -55,3 +57,5 @@ private:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // USE_COROUTINES
|
@ -4,7 +4,9 @@
|
||||
opcode_test_suite_t::opcode_test_suite_t(const std::string path) noexcept
|
||||
: parser_t(path) {}
|
||||
|
||||
#ifdef USE_COROUTINES
|
||||
co_generator_t<test_t> opcode_test_suite_t::generator() {
|
||||
for (const auto element : *this)
|
||||
co_yield test_t(element);
|
||||
}
|
||||
#endif
|
@ -3,9 +3,12 @@
|
||||
#include <string>
|
||||
|
||||
#include "parser_t.h"
|
||||
#include "co_generator_t.h"
|
||||
#include "test_t.h"
|
||||
|
||||
#ifdef USE_COROUTINES
|
||||
#include "co_generator_t.h"
|
||||
#endif
|
||||
|
||||
class opcode_test_suite_t final : public parser_t {
|
||||
private:
|
||||
[[nodiscard]] auto array() const noexcept { return raw().get_array(); }
|
||||
@ -17,5 +20,7 @@ public:
|
||||
[[nodiscard]] auto begin() const noexcept { return array().begin(); }
|
||||
[[nodiscard]] auto end() const noexcept { return array().end(); }
|
||||
|
||||
#ifdef USE_COROUTINES
|
||||
co_generator_t<test_t> generator();
|
||||
#endif
|
||||
};
|
||||
|
@ -1,13 +1,18 @@
|
||||
#include "stdafx.h"
|
||||
#include "processor_test_suite_t.h"
|
||||
|
||||
#ifdef USE_COROUTINES
|
||||
#include <filesystem>
|
||||
#endif
|
||||
|
||||
processor_test_suite_t::processor_test_suite_t(std::string location) noexcept
|
||||
: m_location(location) {
|
||||
}
|
||||
|
||||
#ifdef USE_COROUTINES
|
||||
co_generator_t<opcode_test_suite_t> processor_test_suite_t::generator() {
|
||||
std::filesystem::path directory = location();
|
||||
for (const auto& entry : std::filesystem::directory_iterator{ directory })
|
||||
co_yield opcode_test_suite_t(entry.path().string());
|
||||
}
|
||||
#endif
|
||||
|
@ -3,7 +3,10 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#ifdef USE_COROUTINES
|
||||
#include "co_generator_t.h"
|
||||
#endif
|
||||
|
||||
#include "opcode_test_suite_t.h"
|
||||
|
||||
class processor_test_suite_t final {
|
||||
@ -15,5 +18,7 @@ public:
|
||||
|
||||
std::string_view location() const noexcept { return m_location; }
|
||||
|
||||
#ifdef USE_COROUTINES
|
||||
co_generator_t<opcode_test_suite_t> generator();
|
||||
#endif
|
||||
};
|
||||
|
@ -2,4 +2,4 @@
|
||||
|
||||
#include "array_t.h"
|
||||
|
||||
typedef array_t ram_t;
|
||||
typedef array_t ram_t; // Intended to indicate that ram_t is meant to hold byte_t objects
|
||||
|
@ -23,3 +23,5 @@
|
||||
#include <Symbols.h>
|
||||
|
||||
#include "simdjson/simdjson.h"
|
||||
|
||||
#define USE_COROUTINES
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include "opcode_test_suite_t.h"
|
||||
#include "processor_test_suite_t.h"
|
||||
|
||||
#define USE_COROUTINES
|
||||
|
||||
int main() {
|
||||
|
||||
auto directory = std::string("C:\\github\\spectrum\\libraries\\EightBit\\modules\\ProcessorTests\\6502\\v1");
|
||||
@ -66,7 +64,7 @@ int main() {
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator{ location }) {
|
||||
|
||||
const auto path = entry.path();
|
||||
const auto& path = entry.path();
|
||||
|
||||
std::cout << "Processing: " << path.filename() << "\n";
|
||||
opcode_test_suite_t opcode(path.string());
|
||||
|
Loading…
x
Reference in New Issue
Block a user