mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-09-01 00:28:55 +00:00
Refactor to share JSON implementation details.
Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
8b7607f5e9
commit
17b71aafc3
@ -161,9 +161,11 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="array_t.cpp" />
|
||||
<ClCompile Include="byte_t.cpp" />
|
||||
<ClCompile Include="cycles_t.cpp" />
|
||||
<ClCompile Include="cycle_t.cpp" />
|
||||
<ClCompile Include="element_t.cpp" />
|
||||
<ClCompile Include="opcode_test_suite_t.cpp" />
|
||||
<ClCompile Include="ram_t.cpp" />
|
||||
<ClCompile Include="simdjson\simdjson.cpp">
|
||||
@ -184,9 +186,11 @@
|
||||
<ClCompile Include="test_t.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="array_t.h" />
|
||||
<ClInclude Include="byte_t.h" />
|
||||
<ClInclude Include="cycles_t.h" />
|
||||
<ClInclude Include="cycle_t.h" />
|
||||
<ClInclude Include="element_t.h" />
|
||||
<ClInclude Include="opcode_test_suite_t.h" />
|
||||
<ClInclude Include="ram_t.h" />
|
||||
<ClInclude Include="simdjson\simdjson.h" />
|
||||
|
@ -47,6 +47,12 @@
|
||||
<ClCompile Include="byte_t.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="array_t.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="element_t.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@ -79,5 +85,11 @@
|
||||
<ClInclude Include="byte_t.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="array_t.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="element_t.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -26,12 +26,8 @@ void TestRunner::lowerPOWER() {
|
||||
EightBit::Bus::lowerPOWER();
|
||||
}
|
||||
|
||||
void TestRunner::addActualCycle(const cycle_t& value) {
|
||||
m_actualCycles.add(value);
|
||||
}
|
||||
|
||||
void TestRunner::addActualCycle(uint16_t address, uint8_t value, std::string action) {
|
||||
addActualCycle({ address, value, action });
|
||||
m_actualCycles.push_back({ address, value, action });
|
||||
}
|
||||
|
||||
void TestRunner::addActualCycle(EightBit::register16_t address, uint8_t value, std::string action) {
|
||||
@ -46,23 +42,41 @@ void TestRunner::addActualWriteCycle(EightBit::register16_t address, uint8_t val
|
||||
addActualCycle(address, value, "write");
|
||||
}
|
||||
|
||||
void TestRunner::dumpCycles(std::string which, const cycles_t& events) {
|
||||
void TestRunner::dumpCycle(uint16_t address, uint8_t value, std::string action) {
|
||||
os()
|
||||
<< std::setfill('0') << std::hex
|
||||
<< "Address: " << std::setw(4) << (int)address
|
||||
<< ", value: " << std::setw(2) << (int)value
|
||||
<< ", action: " << action;
|
||||
pushCurrentMessage();
|
||||
}
|
||||
|
||||
void TestRunner::dumpCycles(std::string which, const actual_cycles_t& events) {
|
||||
m_messages.push_back(which);
|
||||
dumpCycles(events);
|
||||
}
|
||||
|
||||
void TestRunner::dumpCycles(const cycles_t& cycles) {
|
||||
void TestRunner::dumpCycles(const actual_cycles_t& cycles) {
|
||||
for (const auto& cycle: cycles)
|
||||
dumpCycle(cycle);
|
||||
}
|
||||
|
||||
void TestRunner::dumpCycle(const cycle_t& cycle) {
|
||||
os()
|
||||
<< std::setfill('0') << std::hex
|
||||
<< "Address: " << std::setw(4) << cycle.address()
|
||||
<< ", value: " << std::setw(2) << (int)cycle.value()
|
||||
<< ", action: " << cycle.action();
|
||||
pushCurrentMessage();
|
||||
void TestRunner::dumpCycle(const actual_cycle_t& cycle) {
|
||||
dumpCycle(std::get<0>(cycle), std::get<1>(cycle), std::get<2>(cycle));
|
||||
}
|
||||
|
||||
void TestRunner::dumpCycles(std::string which, cycles_t events) {
|
||||
m_messages.push_back(which);
|
||||
dumpCycles(events);
|
||||
}
|
||||
|
||||
void TestRunner::dumpCycles(cycles_t cycles) {
|
||||
for (auto cycle: cycles)
|
||||
dumpCycle(cycle_t(cycle));
|
||||
}
|
||||
|
||||
void TestRunner::dumpCycle(cycle_t cycle) {
|
||||
dumpCycle(cycle.address(), cycle.value(), cycle.action());
|
||||
}
|
||||
|
||||
void TestRunner::initialise() {
|
||||
@ -144,12 +158,13 @@ bool TestRunner::checkState() {
|
||||
if (m_cycle_count_mismatch)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < expected_cycles.size(); ++i) {
|
||||
const auto& expected = expected_cycles[i];
|
||||
const auto& actual = actual_cycles[i]; // actual could be less than expected
|
||||
check("Cycle address", expected.address(), actual.address());
|
||||
check("Cycle value", expected.value(), actual.value());
|
||||
check("Cycle action", expected.action(), actual.action());
|
||||
size_t actual_idx = 0;
|
||||
for (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::get<2>(actual));
|
||||
}
|
||||
|
||||
const auto final = test().final();
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <Symbols.h>
|
||||
|
||||
#include "test_t.h"
|
||||
#include "cycle_t.h"
|
||||
|
||||
class TestRunner final : public EightBit::Bus {
|
||||
private:
|
||||
@ -29,7 +30,9 @@ private:
|
||||
std::ostringstream m_os;
|
||||
std::vector<std::string> m_messages;
|
||||
|
||||
cycles_t m_actualCycles;
|
||||
typedef std::tuple<uint16_t, uint8_t, std::string> actual_cycle_t;
|
||||
typedef std::vector<actual_cycle_t> actual_cycles_t;
|
||||
actual_cycles_t m_actualCycles;
|
||||
bool m_cycle_count_mismatch = false;
|
||||
|
||||
int m_cycles = 0;
|
||||
@ -56,7 +59,7 @@ private:
|
||||
|
||||
bool check(std::string what, uint16_t address, uint8_t expected, uint8_t actual);
|
||||
|
||||
void addActualCycle(const cycle_t& value);
|
||||
void addActualCycle(const actual_cycle_t& value);
|
||||
void addActualCycle(uint16_t address, uint8_t value, std::string action);
|
||||
void addActualCycle(EightBit::register16_t address, uint8_t value, std::string action);
|
||||
|
||||
@ -65,9 +68,15 @@ private:
|
||||
|
||||
void disassemble(uint16_t address);
|
||||
|
||||
void dumpCycles(std::string which, const cycles_t& cycles);
|
||||
void dumpCycles(const cycles_t& cycles);
|
||||
void dumpCycle(const cycle_t& cycle);
|
||||
void dumpCycle(uint16_t address, uint8_t value, std::string action);
|
||||
|
||||
void dumpCycles(std::string which, cycles_t cycles);
|
||||
void dumpCycles(cycles_t cycles);
|
||||
void dumpCycle(cycle_t cycle);
|
||||
|
||||
void dumpCycles(std::string which, const actual_cycles_t& cycles);
|
||||
void dumpCycles(const actual_cycles_t& cycles);
|
||||
void dumpCycle(const actual_cycle_t& cycle);
|
||||
|
||||
[[nodiscard]] auto& os() { return m_os; }
|
||||
|
||||
|
5
M6502/HarteTest_6502/array_t.cpp
Normal file
5
M6502/HarteTest_6502/array_t.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "array_t.h"
|
||||
|
||||
array_t::array_t(simdjson::dom::array input) noexcept
|
||||
: m_raw(input) {}
|
26
M6502/HarteTest_6502/array_t.h
Normal file
26
M6502/HarteTest_6502/array_t.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "simdjson/simdjson.h"
|
||||
|
||||
class array_t {
|
||||
private:
|
||||
const simdjson::dom::array m_raw;
|
||||
|
||||
protected:
|
||||
array_t(simdjson::dom::array input) noexcept;
|
||||
|
||||
auto raw() const noexcept { return m_raw; }
|
||||
|
||||
[[nodiscard]] auto at(size_t idx) const noexcept { return raw().at(idx); }
|
||||
[[nodiscard]] auto integer_at(size_t idx) const noexcept { return (int64_t)at(idx); }
|
||||
[[nodiscard]] auto address_at(size_t idx) const noexcept { return (uint16_t)integer_at(idx); }
|
||||
[[nodiscard]] auto byte_at(size_t idx) const noexcept { return (uint8_t)integer_at(idx); }
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto begin() const noexcept { return m_raw.begin(); }
|
||||
[[nodiscard]] auto end() const noexcept { return m_raw.end(); }
|
||||
[[nodiscard]] auto size() const noexcept { return m_raw.size(); }
|
||||
[[nodiscard]] auto operator[](size_t idx) const noexcept { return m_raw.at(idx); }
|
||||
};
|
@ -2,4 +2,4 @@
|
||||
#include "byte_t.h"
|
||||
|
||||
byte_t::byte_t(simdjson::dom::array input) noexcept
|
||||
: m_raw(input) {}
|
||||
: array_t(input) {}
|
||||
|
@ -1,18 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "simdjson/simdjson.h"
|
||||
|
||||
class byte_t final {
|
||||
private:
|
||||
const simdjson::dom::array m_raw;
|
||||
|
||||
[[nodiscard]] auto at(size_t idx) const noexcept { return m_raw.at(idx); }
|
||||
[[nodiscard]] auto integer_at(size_t idx) const noexcept { return (int64_t)at(idx); }
|
||||
[[nodiscard]] auto address_at(size_t idx) const noexcept { return (uint16_t)integer_at(idx); }
|
||||
[[nodiscard]] auto byte_at(size_t idx) const noexcept { return (uint8_t)integer_at(idx); }
|
||||
#include "array_t.h"
|
||||
|
||||
class byte_t : public array_t {
|
||||
public:
|
||||
byte_t(simdjson::dom::array input) noexcept;
|
||||
|
||||
|
@ -1,15 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "cycle_t.h"
|
||||
|
||||
cycle_t::cycle_t(uint16_t address, uint8_t value, std::string action) noexcept
|
||||
: m_address(address),
|
||||
m_value(value),
|
||||
m_action(action) {}
|
||||
|
||||
cycle_t::cycle_t(simdjson::dom::element input) noexcept
|
||||
: cycle_t(input.get_array()) {}
|
||||
|
||||
cycle_t::cycle_t(simdjson::dom::array input) noexcept
|
||||
: m_address((uint16_t)(int64_t)input.at(0)),
|
||||
m_value((uint8_t)(int64_t)input.at(1)),
|
||||
m_action((std::string)input.at(2)) {}
|
||||
: byte_t(input) {}
|
||||
|
@ -1,23 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "simdjson/simdjson.h"
|
||||
|
||||
class cycle_t final {
|
||||
private:
|
||||
const uint16_t m_address = 0xffff;
|
||||
const uint8_t m_value = 0xff;
|
||||
const std::string m_action;
|
||||
#include "byte_t.h"
|
||||
|
||||
class cycle_t final : public byte_t {
|
||||
public:
|
||||
cycle_t(uint16_t address, uint8_t value, std::string action) noexcept;
|
||||
|
||||
cycle_t(simdjson::dom::element input) noexcept;
|
||||
cycle_t(simdjson::dom::array input) noexcept;
|
||||
|
||||
[[nodiscard]] constexpr auto address() const noexcept { return m_address; }
|
||||
[[nodiscard]] constexpr auto value() const noexcept { return m_value; }
|
||||
[[nodiscard]] auto action() const noexcept { return m_action; }
|
||||
[[nodiscard]] auto action() const noexcept { return (std::string)at(2); }
|
||||
};
|
||||
|
@ -1,18 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "cycles_t.h"
|
||||
|
||||
cycles_t::cycles_t(size_t reserved) {
|
||||
m_cycles.reserve(reserved);
|
||||
}
|
||||
|
||||
void cycles_t::add(const cycle_t& cycle) {
|
||||
assert(m_cycles.capacity() >= (m_cycles.size() + 1));
|
||||
m_cycles.push_back(cycle);
|
||||
}
|
||||
|
||||
cycles_t::cycles_t(simdjson::dom::array input) {
|
||||
assert(m_cycles.empty());
|
||||
m_cycles.reserve(input.size());
|
||||
for (auto entry : input)
|
||||
add(entry);
|
||||
}
|
||||
cycles_t::cycles_t(simdjson::dom::array input) noexcept
|
||||
: array_t(input) {}
|
||||
|
@ -1,25 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "simdjson/simdjson.h"
|
||||
|
||||
#include "cycle_t.h"
|
||||
|
||||
class cycles_t final {
|
||||
private:
|
||||
std::vector<cycle_t> m_cycles;
|
||||
#include "array_t.h"
|
||||
|
||||
class cycles_t final : public array_t {
|
||||
public:
|
||||
cycles_t(size_t reserved = 10);
|
||||
cycles_t(simdjson::dom::array input);
|
||||
|
||||
void add(const cycle_t& cycle);
|
||||
|
||||
[[nodiscard]] auto begin() const noexcept { return m_cycles.begin(); }
|
||||
[[nodiscard]] auto end() const noexcept { return m_cycles.end(); }
|
||||
|
||||
[[nodiscard]] auto size() const noexcept { return m_cycles.size(); }
|
||||
|
||||
[[nodiscard]] const auto& operator[](size_t idx) const noexcept { return m_cycles[idx]; }
|
||||
cycles_t(simdjson::dom::array input) noexcept;
|
||||
};
|
||||
|
5
M6502/HarteTest_6502/element_t.cpp
Normal file
5
M6502/HarteTest_6502/element_t.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "element_t.h"
|
||||
|
||||
element_t::element_t(const simdjson::dom::element input) noexcept
|
||||
: m_raw(input) {}
|
20
M6502/HarteTest_6502/element_t.h
Normal file
20
M6502/HarteTest_6502/element_t.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "simdjson/simdjson.h"
|
||||
|
||||
class element_t {
|
||||
private:
|
||||
simdjson::dom::element m_raw;
|
||||
|
||||
protected:
|
||||
element_t(simdjson::dom::element input) noexcept;
|
||||
|
||||
auto raw() const noexcept { return m_raw; }
|
||||
|
||||
[[nodiscard]] auto at(std::string key) const noexcept { return raw()[key]; }
|
||||
[[nodiscard]] auto array_at(std::string key) const noexcept { return at(key).get_array(); }
|
||||
[[nodiscard]] auto integer_at(std::string key) const noexcept { return (int64_t)at(key); }
|
||||
};
|
@ -2,4 +2,4 @@
|
||||
#include "ram_t.h"
|
||||
|
||||
ram_t::ram_t(simdjson::dom::array input) noexcept
|
||||
: m_raw(input) {}
|
||||
: array_t(input) {}
|
||||
|
@ -2,15 +2,9 @@
|
||||
|
||||
#include "simdjson/simdjson.h"
|
||||
|
||||
#include "byte_t.h"
|
||||
|
||||
class ram_t final {
|
||||
private:
|
||||
simdjson::dom::array m_raw;;
|
||||
#include "array_t.h"
|
||||
|
||||
class ram_t final : public array_t {
|
||||
public:
|
||||
ram_t(simdjson::dom::array input) noexcept;
|
||||
|
||||
[[nodiscard]] auto begin() const noexcept { return m_raw.begin(); }
|
||||
[[nodiscard]] auto end() const noexcept { return m_raw.end(); }
|
||||
};
|
||||
|
@ -2,4 +2,4 @@
|
||||
#include "state_t.h"
|
||||
|
||||
state_t::state_t(const simdjson::dom::element input) noexcept
|
||||
: m_raw(input) {}
|
||||
: element_t(input) {}
|
||||
|
@ -1,20 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "simdjson/simdjson.h"
|
||||
|
||||
#include "element_t.h"
|
||||
#include "ram_t.h"
|
||||
|
||||
class state_t final {
|
||||
class state_t final : public element_t {
|
||||
private:
|
||||
const simdjson::dom::element m_raw;
|
||||
|
||||
[[nodiscard]] auto at(std::string key) const noexcept { return m_raw[key]; }
|
||||
[[nodiscard]] auto integer_at(std::string key) const noexcept { return (int64_t)at(key); }
|
||||
[[nodiscard]] auto address_at(std::string key) const noexcept { return (uint16_t)integer_at(key); }
|
||||
[[nodiscard]] auto byte_at(std::string key) const noexcept { return (uint8_t)integer_at(key); }
|
||||
[[nodiscard]] auto array_at(std::string key) const noexcept { return at(key).get_array(); }
|
||||
|
||||
public:
|
||||
state_t(simdjson::dom::element input) noexcept;
|
||||
|
@ -2,4 +2,4 @@
|
||||
#include "test_t.h"
|
||||
|
||||
test_t::test_t(const simdjson::dom::element input) noexcept
|
||||
: m_raw(input) {}
|
||||
: element_t(input) {}
|
||||
|
@ -1,19 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "simdjson/simdjson.h"
|
||||
|
||||
#include "element_t.h"
|
||||
#include "cycles_t.h"
|
||||
#include "state_t.h"
|
||||
|
||||
class test_t final {
|
||||
private:
|
||||
simdjson::dom::element m_raw;
|
||||
|
||||
[[nodiscard]] auto at(std::string key) const noexcept { return m_raw[key]; }
|
||||
[[nodiscard]] auto array_at(std::string key) const noexcept { return at(key).get_array(); }
|
||||
|
||||
class test_t final : public element_t {
|
||||
public:
|
||||
test_t(simdjson::dom::element input) noexcept;
|
||||
|
||||
|
@ -26,41 +26,25 @@ int main() {
|
||||
opcode_test_suite_t opcode(path.string());
|
||||
opcode.load();
|
||||
|
||||
bool opcode_undocumented = false;
|
||||
bool opcode_unimplemented = false;
|
||||
bool opcode_invalid = false;
|
||||
|
||||
for (auto opcode_test_element : opcode) {
|
||||
|
||||
const auto opcode_test = test_t(opcode_test_element);
|
||||
|
||||
TestRunner runner(opcode_test);
|
||||
runner.check();
|
||||
|
||||
auto undocumented = runner.undocumented();
|
||||
auto unimplemented = runner.unimplemented();
|
||||
auto implemented = runner.implemented();
|
||||
auto invalid = runner.invalid();
|
||||
|
||||
if (invalid) {
|
||||
opcode_invalid = true;
|
||||
if (unimplemented)
|
||||
opcode_unimplemented = true;
|
||||
if (undocumented)
|
||||
opcode_undocumented = true;
|
||||
++invalid_opcode_count;
|
||||
if (runner.unimplemented())
|
||||
++unimplemented_opcode_count;
|
||||
if (runner.undocumented())
|
||||
++undocumented_opcode_count;
|
||||
std::cout << "** Failed: " << opcode_test.name() << "\n";
|
||||
for (const auto& message : runner.messages())
|
||||
std::cout << "**** " << message << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode_undocumented)
|
||||
++undocumented_opcode_count;
|
||||
if (opcode_unimplemented)
|
||||
++unimplemented_opcode_count;
|
||||
if (opcode_invalid)
|
||||
++invalid_opcode_count;
|
||||
}
|
||||
|
||||
const auto finish_time = std::chrono::steady_clock::now();
|
||||
|
Loading…
Reference in New Issue
Block a user