First stab at using the Harte randomised processor tests. Some failures detected in the M6502 run.

Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2021-10-10 21:26:30 +01:00
parent 6c3ef821bf
commit 6a59bfbcd8
15 changed files with 768 additions and 0 deletions

View File

@ -0,0 +1,189 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{894eb6ef-4c8d-4401-bbaa-aba05a021abb}</ProjectGuid>
<RootNamespace>HarteTest_6502</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>HarteTest_6502</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\inc;..\..\inc;C:\Libraries\boost_1_77_0;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\inc;..\..\inc;C:\Libraries\boost_1_77_0;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\inc;..\..\inc;C:\Libraries\boost_1_77_0;$(IncludePath)</IncludePath>
<LibraryPath>C:\Libraries\boost_1_77_0\lib64-msvc-14.2;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\inc;..\..\inc;C:\Libraries\boost_1_77_0;$(IncludePath)</IncludePath>
<LibraryPath>C:\Libraries\boost_1_77_0\lib64-msvc-14.2;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="json_t.cpp" />
<ClCompile Include="opcode_test_suite_t.cpp" />
<ClCompile Include="state_t.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="TestRunner.cpp" />
<ClCompile Include="tests.cpp" />
<ClCompile Include="test_t.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="json_t.h" />
<ClInclude Include="opcode_test_suite_t.h" />
<ClInclude Include="state_t.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="TestRunner.h" />
<ClInclude Include="test_t.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\EightBit.vcxproj">
<Project>{a9c24bd9-0cb4-4c84-b09b-46b815f9da47}</Project>
</ProjectReference>
<ProjectReference Include="..\src\M6502.vcxproj">
<Project>{d8726a1b-bbfe-47ef-9860-26b90140ba66}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="tests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="json_t.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="state_t.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test_t.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="opcode_test_suite_t.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TestRunner.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="json_t.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="state_t.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="test_t.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="opcode_test_suite_t.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TestRunner.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,138 @@
#include "stdafx.h"
#include "TestRunner.h"
#include <iostream>
#include <Disassembly.h>
TestRunner::TestRunner(const test_t& test)
: m_test(test) {}
EightBit::MemoryMapping TestRunner::mapping(uint16_t address) noexcept {
return { RAM(), 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
}
void TestRunner::raisePOWER() {
EightBit::Bus::raisePOWER();
CPU().raisePOWER();
CPU().raiseRESET();
CPU().raiseINT();
CPU().raiseNMI();
CPU().raiseSO();
CPU().raiseRDY();
}
void TestRunner::lowerPOWER() {
CPU().lowerPOWER();
EightBit::Bus::lowerPOWER();
}
void TestRunner::addActualEvent(test_t::action action, uint16_t address, uint8_t value) {
m_actualEvents.push_back( { address, value, action } );
}
void TestRunner::initialise() {
ReadByte.connect([this](EightBit::EventArgs&) {
addActualEvent(test_t::action::read, ADDRESS().word, DATA());
});
WrittenByte.connect([this](EightBit::EventArgs&) {
addActualEvent(test_t::action::write, ADDRESS().word, DATA());
});
}
void TestRunner::raise(std::string what, uint16_t expected, uint16_t actual) {
std::cout
<< "** Failure: " << what
<< ": expected: " << EightBit::Disassembly::dump_WordValue(expected)
<< ", actual: " << EightBit::Disassembly::dump_WordValue(actual)
<< "\n";
}
void TestRunner::raise(std::string what, uint8_t expected, uint8_t actual) {
std::cout
<< "** Failure: " << what
<< ": expected: " << EightBit::Disassembly::dump_ByteValue(expected)
<< "(" << EightBit::Disassembly::dump_Flags(expected) << ")"
<< ", actual: " << EightBit::Disassembly::dump_ByteValue(actual)
<< "(" << EightBit::Disassembly::dump_Flags(actual) << ")"
<< "\n";
}
void TestRunner::raise(std::string what, test_t::action expected, test_t::action actual) {
std::cout
<< "** Failure: " << what
<< ": expected: " << test_t::to_string(expected)
<< ", actual: " << test_t::to_string(actual)
<< "\n";
}
void TestRunner::initialiseState() {
const auto& starting = test().initial_state();
CPU().PC().word = starting.pc();
CPU().S() = starting.s();
CPU().A() = starting.a();
CPU().X() = starting.x();
CPU().Y() = starting.y();
CPU().P() = starting.p();
const auto& ram = starting.ram();
for (const auto& entry : ram) {
const auto [address, value] = entry;
RAM().poke(address, value);
}
m_actualEvents.clear();
}
void TestRunner::verifyState() {
const auto& finished = test().final_state();
const auto& expected_events = test().cycles();
const auto& actual_events = m_actualEvents;
if (expected_events.size() != actual_events.size()) {
//std::cout << "** event count mismatch" << "\n";
return;
}
for (int i = 0; i < expected_events.size(); ++i) {
const auto& expected = expected_events[i];
const auto [expectedAddress, expectedContents, expectedAction] = expected;
const auto& actual = actual_events.at(i); // actual could be less than expected
const auto [actualAddress, actualContents, actualAction] = actual;
check("Event action", expectedAction, actualAction);
check("Event address", expectedAddress, actualAddress);
check("Event contents", expectedContents, actualContents);
}
const auto pc_good = check("PC", finished.pc(), CPU().PC().word);
const auto s_good = check("S", finished.s(), CPU().S());
const auto a_good = check("A", finished.a(), CPU().A());
const auto x_good = check("X", finished.x(), CPU().X());
const auto y_good = check("Y", finished.y(), CPU().Y());
const auto p_good = check("P", finished.p(), CPU().P());
const auto& ram = finished.ram();
bool ram_problem = false;
for (const auto& entry : ram) {
const auto [address, value] = entry;
const auto ram_good = check("RAM: " + EightBit::Disassembly::dump_WordValue(address), value, RAM().peek(address));
if (!ram_good && !ram_problem)
ram_problem = true;
}
const auto good = pc_good && s_good && a_good && x_good && y_good && p_good && !ram_problem;
std::cout << (good ? "+" : "-");
}
void TestRunner::run() {
initialise();
raisePOWER();
initialiseState();
const int cycles = CPU().step();
verifyState();
lowerPOWER();
}

View File

@ -0,0 +1,50 @@
#pragma once
#include <Bus.h>
#include <Ram.h>
#include <mos6502.h>
#include "test_t.h"
class TestRunner final : public EightBit::Bus {
private:
EightBit::Ram m_ram = 0x10000;
EightBit::MOS6502 m_cpu = { *this };
const test_t& m_test;
test_t::events_t m_actualEvents;
void initialiseState();
void verifyState();
void raise(std::string what, uint16_t expected, uint16_t actual);
void raise(std::string what, uint8_t expected, uint8_t actual);
void raise(std::string what, test_t::action expected, test_t::action actual);
template<class T>
bool check(std::string what, T expected, T actual) {
const auto success = actual == expected;
if (!success)
raise(what, expected, actual);
return success;
}
void addActualEvent(test_t::action action, uint16_t address, uint8_t value);
protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
public:
TestRunner(const test_t& test);
virtual void raisePOWER() final;
virtual void lowerPOWER() final;
virtual void initialise() final;
constexpr auto& RAM() noexcept { return m_ram; }
constexpr auto& CPU() noexcept { return m_cpu; }
constexpr const auto& test() const noexcept { return m_test; }
void run();
};

View File

@ -0,0 +1,53 @@
#include "stdafx.h"
#include "json_t.h"
#include <cassert>
const boost::json::value& json_t::get_value(const boost::json::object& object, std::string key) {
auto* value = object.if_contains(key);
assert(value != nullptr);
return *value;
}
int64_t json_t::get_int64(const boost::json::value& value) {
assert(value.is_number());
assert(value.is_int64());
return value.get_int64();
}
uint16_t json_t::get_uint16(const boost::json::value& value) {
return static_cast<uint16_t>(get_int64(value));
}
uint8_t json_t::get_uint8(const boost::json::value& value) {
return static_cast<uint8_t>(get_int64(value));
}
int64_t json_t::get_int64(const boost::json::object& object, std::string key) {
return get_int64(get_value(object, key));
}
uint16_t json_t::get_uint16(const boost::json::object& object, std::string key) {
return static_cast<uint16_t>(get_int64(object, key));
}
uint8_t json_t::get_uint8(const boost::json::object& object, std::string key) {
return static_cast<uint8_t>(get_int64(object, key));
}
const boost::json::array& json_t::get_array(const boost::json::value& value) {
assert(value.is_array());
return value.get_array();
}
const boost::json::array& json_t::get_array(const boost::json::object& object, std::string key) {
return get_array(get_value(object, key));
}
const boost::json::string& json_t::get_string(const boost::json::value& value) {
assert(value.is_string());
return value.get_string();
}
const boost::json::string& json_t::get_string(const boost::json::object& object, std::string key) {
return get_string(get_value(object, key));
}

View File

@ -0,0 +1,24 @@
#pragma once
#include <string>
#include <boost/json.hpp>
class json_t {
protected:
static const boost::json::value& get_value(const boost::json::object& object, std::string key);
static int64_t get_int64(const boost::json::value& value);
static uint16_t get_uint16(const boost::json::value& value);
static uint8_t get_uint8(const boost::json::value& value);
static int64_t get_int64(const boost::json::object& object, std::string key);
static uint16_t get_uint16(const boost::json::object& object, std::string key);
static uint8_t get_uint8(const boost::json::object& object, std::string key);
static const boost::json::array& get_array(const boost::json::value& value);
static const boost::json::array& get_array(const boost::json::object& object, std::string key);
static const boost::json::string& get_string(const boost::json::value& value);
static const boost::json::string& get_string(const boost::json::object& object, std::string key);
};

View File

@ -0,0 +1,27 @@
#include "stdafx.h"
#include "opcode_test_suite_t.h"
#include <cassert>
#include <fstream>
#include <filesystem>
std::string opcode_test_suite_t::read(std::string path) {
std::ifstream file(path, std::ios::in | std::ios::binary);
const auto size = std::filesystem::file_size(path);
std::string result(size, '\0');
file.read(result.data(), size);
return result;
}
opcode_test_suite_t::opcode_test_suite_t(std::string path)
: m_path(path) {}
const boost::json::array& opcode_test_suite_t::get_array() const noexcept {
assert(raw().is_array());
return raw().get_array();
}
void opcode_test_suite_t::load() {
const auto contents = read(path());
m_raw = boost::json::parse(contents);
}

View File

@ -0,0 +1,21 @@
#pragma once
#include <string>
#include <boost/json.hpp>
class opcode_test_suite_t final {
private:
static std::string read(std::string path);
std::string m_path;
boost::json::value m_raw;
public:
opcode_test_suite_t(std::string path);
constexpr const auto& path() const noexcept { return m_path; }
constexpr const auto& raw() const noexcept { return m_raw; }
const boost::json::array& get_array() const noexcept;
void load();
};

View File

@ -0,0 +1,40 @@
#include "stdafx.h"
#include "state_t.h"
#include <cassert>
void state_t::initialise(const boost::json::object& serialised) {
assert(!initialised());
m_pc = get_uint16(serialised, "pc");
m_s = get_uint8(serialised, "s");
m_a = get_uint8(serialised, "a");
m_x = get_uint8(serialised, "x");
m_y = get_uint8(serialised, "y");
m_p = get_uint8(serialised, "p");
const auto& ram_entries = get_array(serialised, "ram");
for (const auto& ram_entry : ram_entries) {
assert(ram_entry.is_array());
const auto& ram_entry_array = ram_entry.as_array();
assert(ram_entry_array.size() == 2);
const auto address = get_uint16(ram_entry_array[0]);
const auto value = get_uint8(ram_entry_array[1]);
m_ram[address] = value;
}
m_initialised = true;
}
state_t::state_t() {}
state_t::state_t(const boost::json::object& serialised) {
initialise(serialised);
assert(initialised());
}
state_t::state_t(const boost::json::value& serialised) {
assert(serialised.is_object());
initialise(serialised.get_object());
assert(initialised());
}

View File

@ -0,0 +1,37 @@
#pragma once
#include <cstdint>
#include <unordered_map>
#include <boost/json.hpp>
#include "json_t.h"
class state_t final : public json_t {
private:
bool m_initialised = false;
uint16_t m_pc = 0xffff;
uint8_t m_s = 0xff;
uint8_t m_a = 0xff;
uint8_t m_x = 0xff;
uint8_t m_y = 0xff;
uint8_t m_p = 0xff;
std::unordered_map<uint16_t, uint8_t> m_ram;
constexpr auto initialised() const noexcept { return m_initialised; }
void initialise(const boost::json::object& serialised);
public:
state_t();
state_t(const boost::json::object& serialised);
state_t(const boost::json::value& serialised);
constexpr auto pc() const noexcept { return m_pc; }
constexpr auto s() const noexcept { return m_s; }
constexpr auto a() const noexcept { return m_a; }
constexpr auto x() const noexcept { return m_x; }
constexpr auto y() const noexcept { return m_y; }
constexpr auto p() const noexcept { return m_p; }
constexpr const auto& ram() const noexcept { return m_ram; }
};

View File

@ -0,0 +1 @@
#include "stdafx.h"

View File

@ -0,0 +1,14 @@
#pragma once
#include <cassert>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>
#include <boost/json.hpp>

View File

@ -0,0 +1,48 @@
#include "stdafx.h"
#include "test_t.h"
#include <cassert>
#include <stdexcept>
test_t::action test_t::to_action(std::string value) {
if (value == "read")
return action::read;
if (value == "write")
return action::write;
throw new std::out_of_range("Unknown action");
}
std::string test_t::to_string(action value) {
if (value == action::read)
return "read";
if (value == action::write)
return "write";
throw new std::out_of_range("Unknown action");
}
void test_t::initialise(const boost::json::object& serialised) {
m_name = get_string(serialised, "name");
m_initial_state = state_t(get_value(serialised, "initial"));
m_final_state = state_t(get_value(serialised, "final"));
const auto& cycles_array = get_array(serialised, "cycles");
m_cycles.reserve(cycles_array.size());
for (const auto& cycles_entry : cycles_array) {
const auto& cycle_array = get_array(cycles_entry);
assert(cycle_array.size() == 3);
const auto address = get_uint16(cycle_array[0]);
const auto contents = get_uint8(cycle_array[1]);
const auto action = to_action((std::string)get_string(cycle_array[2]));
m_cycles.push_back( { address, contents, action } );
}
}
test_t::test_t(const boost::json::object& serialised) {
initialise(serialised);
}
test_t::test_t(const boost::json::value& serialised) {
assert(serialised.is_object());
initialise(serialised.get_object());
}

View File

@ -0,0 +1,38 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <tuple>
#include <boost/json.hpp>
#include "state_t.h"
#include "json_t.h"
class test_t final : public json_t {
public:
enum class action { read, write };
typedef std::tuple<uint16_t, uint8_t, action> event_t; // address, contents, action
typedef std::vector<event_t> events_t;
static action to_action(std::string value);
static std::string to_string(action value);
private:
std::string m_name;
state_t m_initial_state;
state_t m_final_state;
events_t m_cycles;
void initialise(const boost::json::object& serialised);
public:
test_t(const boost::json::object& serialised);
test_t(const boost::json::value& serialised);
constexpr const auto& name() const noexcept { return m_name; }
constexpr const auto& initial_state() const noexcept { return m_initial_state; }
constexpr const auto& final_state() const noexcept { return m_final_state; }
constexpr const auto& cycles() const noexcept { return m_cycles; }
};

View File

@ -0,0 +1,32 @@
#include "stdafx.h"
#include <iostream>
#include <filesystem>
#include "TestRunner.h"
#include "test_t.h"
#include "opcode_test_suite_t.h"
int main() {
std::filesystem::path location = "C:\\github\\spectrum\\libraries\\EightBit\\modules\\ProcessorTests\\6502\\v1";
for (const auto& entry : std::filesystem::directory_iterator{ location }) {
const auto path = entry.path();
std::cout << "** path: " << path << std::endl;
opcode_test_suite_t opcode(path.string());
opcode.load();
const auto& opcode_test_array = opcode.get_array();
for (const auto& opcode_test_element : opcode_test_array) {
const auto opcode_test = test_t(opcode_test_element);
TestRunner runner(opcode_test);
runner.run();
}
std::cout << "\n";
}
}