mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-12-22 09:30:32 +00:00
Refactor the code to isolate the cycles parsing. Interesting speed up!
Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
50cea1b81a
commit
79f3e3ac6c
@ -161,6 +161,8 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="cycles_t.cpp" />
|
||||
<ClCompile Include="cycle_t.cpp" />
|
||||
<ClCompile Include="opcode_test_suite_t.cpp" />
|
||||
<ClCompile Include="simdjson\simdjson.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
@ -180,6 +182,8 @@
|
||||
<ClCompile Include="test_t.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="cycles_t.h" />
|
||||
<ClInclude Include="cycle_t.h" />
|
||||
<ClInclude Include="nlohmann\json.hpp" />
|
||||
<ClInclude Include="opcode_test_suite_t.h" />
|
||||
<ClInclude Include="simdjson\simdjson.h" />
|
||||
|
@ -38,6 +38,12 @@
|
||||
<ClCompile Include="simdjson\simdjson.cpp">
|
||||
<Filter>Header Files\simdjson</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cycle_t.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cycles_t.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@ -61,6 +67,12 @@
|
||||
<ClInclude Include="simdjson\simdjson.h">
|
||||
<Filter>Header Files\simdjson</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cycle_t.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cycles_t.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
@ -25,27 +25,42 @@ void TestRunner::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::addActualCycle(const cycle_t& value) {
|
||||
m_actualCycles.add(value);
|
||||
}
|
||||
|
||||
void TestRunner::dumpEvents(std::string which, const test_t::events_t& events) {
|
||||
void TestRunner::addActualCycle(uint16_t address, uint8_t value, cycle_t::action_t action) {
|
||||
addActualCycle({ address, value, action });
|
||||
}
|
||||
|
||||
void TestRunner::addActualCycle(EightBit::register16_t address, uint8_t value, cycle_t::action_t action) {
|
||||
addActualCycle(address.word, value, action);
|
||||
}
|
||||
|
||||
void TestRunner::addActualReadCycle(EightBit::register16_t address, uint8_t value) {
|
||||
addActualCycle(address, value, cycle_t::action_t::read);
|
||||
}
|
||||
|
||||
void TestRunner::addActualWriteCycle(EightBit::register16_t address, uint8_t value) {
|
||||
addActualCycle(address, value, cycle_t::action_t::write);
|
||||
}
|
||||
|
||||
void TestRunner::dumpCycles(std::string which, const cycles_t& events) {
|
||||
m_messages.push_back(which);
|
||||
dumpEvents(events);
|
||||
dumpCycles(events);
|
||||
}
|
||||
|
||||
void TestRunner::dumpEvents(const test_t::events_t& events) {
|
||||
void TestRunner::dumpCycles(const cycles_t& cycles) {
|
||||
os() << std::hex << std::uppercase << std::setfill('0');
|
||||
for (const auto& event: events)
|
||||
dumpEvent(event);
|
||||
for (const auto& cycle: cycles)
|
||||
dumpCycle(cycle);
|
||||
}
|
||||
|
||||
void TestRunner::dumpEvent(const test_t::event_t& event) {
|
||||
const auto [address, contents, action] = event;
|
||||
void TestRunner::dumpCycle(const cycle_t& cycle) {
|
||||
os()
|
||||
<< "Address: " << std::setw(4) << address
|
||||
<< ", contents: " << std::setw(2) << (int)contents
|
||||
<< ", action: " << test_t::to_string(action);
|
||||
<< "Address: " << std::setw(4) << cycle.address()
|
||||
<< ", value: " << std::setw(2) << (int)cycle.value()
|
||||
<< ", action: " << cycle_t::to_string(cycle.action());
|
||||
m_messages.push_back(os().str());
|
||||
os().str("");
|
||||
}
|
||||
@ -53,11 +68,11 @@ void TestRunner::dumpEvent(const test_t::event_t& event) {
|
||||
void TestRunner::initialise() {
|
||||
|
||||
ReadByte.connect([this](EightBit::EventArgs&) {
|
||||
addActualEvent(test_t::action::read, ADDRESS().word, DATA());
|
||||
addActualReadCycle(ADDRESS(), DATA());
|
||||
});
|
||||
|
||||
WrittenByte.connect([this](EightBit::EventArgs&) {
|
||||
addActualEvent(test_t::action::write, ADDRESS().word, DATA());
|
||||
addActualWriteCycle(ADDRESS(), DATA());
|
||||
});
|
||||
|
||||
os() << std::hex << std::uppercase << std::setfill('0');
|
||||
@ -85,11 +100,11 @@ void TestRunner::raise(std::string what, uint8_t expected, uint8_t actual) {
|
||||
os().str("");
|
||||
}
|
||||
|
||||
void TestRunner::raise(std::string what, test_t::action expected, test_t::action actual) {
|
||||
void TestRunner::raise(std::string what, cycle_t::action_t expected, cycle_t::action_t actual) {
|
||||
os()
|
||||
<< what
|
||||
<< ": expected: " << test_t::to_string(expected)
|
||||
<< ", actual: " << test_t::to_string(actual);
|
||||
<< ": expected: " << cycle_t::to_string(expected)
|
||||
<< ", actual: " << cycle_t::to_string(actual);
|
||||
m_messages.push_back(os().str());
|
||||
os().str("");
|
||||
}
|
||||
@ -120,27 +135,25 @@ void TestRunner::initialiseState() {
|
||||
RAM().poke(address, value);
|
||||
}
|
||||
|
||||
m_actualEvents.clear();
|
||||
m_actualCycles.clear();
|
||||
}
|
||||
|
||||
bool TestRunner::checkState() {
|
||||
|
||||
const auto& finished = test().final_state();
|
||||
|
||||
const auto& expected_events = test().cycles();
|
||||
const auto& actual_events = m_actualEvents;
|
||||
m_event_count_mismatch = expected_events.size() != actual_events.size();
|
||||
if (m_event_count_mismatch)
|
||||
const auto& expected_cycles = test().cycles();
|
||||
const auto& actual_cycles = m_actualCycles;
|
||||
m_cycle_count_mismatch = expected_cycles.size() != actual_cycles.size();
|
||||
if (m_cycle_count_mismatch)
|
||||
return false;
|
||||
|
||||
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);
|
||||
for (int i = 0; i < expected_cycles.size(); ++i) {
|
||||
const auto& expected = expected_cycles.at(i);
|
||||
const auto& actual = actual_cycles.at(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());
|
||||
}
|
||||
|
||||
const auto pc_good = check("PC", finished.pc(), CPU().PC().word);
|
||||
@ -168,7 +181,7 @@ bool TestRunner::check() {
|
||||
initialiseState();
|
||||
const int cycles = CPU().step();
|
||||
const auto valid = checkState();
|
||||
if (m_event_count_mismatch) {
|
||||
if (m_cycle_count_mismatch) {
|
||||
if (cycles == 1) {
|
||||
m_messages.push_back("Unimplemented");
|
||||
} else {
|
||||
@ -177,12 +190,12 @@ bool TestRunner::check() {
|
||||
<< std::dec << std::setfill(' ')
|
||||
<< "Stepped cycles: " << cycles
|
||||
<< ", expected events: " << test().cycles().size()
|
||||
<< ", actual events: " << m_actualEvents.size();
|
||||
<< ", actual events: " << m_actualCycles.size();
|
||||
m_messages.push_back(os().str());
|
||||
os().str("");
|
||||
|
||||
dumpEvents("-- Expected cycles", test().cycles());
|
||||
dumpEvents("-- Actual cycles", m_actualEvents);
|
||||
dumpCycles("-- Expected cycles", test().cycles());
|
||||
dumpCycles("-- Actual cycles", m_actualCycles);
|
||||
}
|
||||
}
|
||||
lowerPOWER();
|
||||
|
@ -20,15 +20,15 @@ private:
|
||||
std::ostringstream m_os;
|
||||
std::vector<std::string> m_messages;
|
||||
|
||||
test_t::events_t m_actualEvents;
|
||||
bool m_event_count_mismatch = false;
|
||||
cycles_t m_actualCycles;
|
||||
bool m_cycle_count_mismatch = false;
|
||||
|
||||
void initialiseState();
|
||||
[[nodiscard]] bool checkState();
|
||||
|
||||
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);
|
||||
void raise(std::string what, cycle_t::action_t expected, cycle_t::action_t actual);
|
||||
|
||||
template<class T>
|
||||
bool check(std::string what, T expected, T actual) {
|
||||
@ -40,11 +40,16 @@ private:
|
||||
|
||||
bool check(std::string what, uint16_t address, uint8_t expected, uint8_t actual);
|
||||
|
||||
void addActualEvent(test_t::action action, uint16_t address, uint8_t value);
|
||||
void addActualCycle(const cycle_t& value);
|
||||
void addActualCycle(uint16_t address, uint8_t value, cycle_t::action_t action);
|
||||
void addActualCycle(EightBit::register16_t address, uint8_t value, cycle_t::action_t action);
|
||||
|
||||
void dumpEvents(std::string which, const test_t::events_t& events);
|
||||
void dumpEvents(const test_t::events_t& events);
|
||||
void dumpEvent(const test_t::event_t& event);
|
||||
void addActualReadCycle(EightBit::register16_t address, uint8_t value);
|
||||
void addActualWriteCycle(EightBit::register16_t address, uint8_t value);
|
||||
|
||||
void dumpCycles(std::string which, const cycles_t& cycles);
|
||||
void dumpCycles(const cycles_t& cycles);
|
||||
void dumpCycle(const cycle_t& cycle);
|
||||
|
||||
[[nodiscard]] auto& os() { return m_os; }
|
||||
|
||||
|
91
M6502/HarteTest_6502/cycle_t.cpp
Normal file
91
M6502/HarteTest_6502/cycle_t.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "stdafx.h"
|
||||
#include "cycle_t.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
cycle_t::action_t cycle_t::to_action(std::string value) {
|
||||
if (value == "read")
|
||||
return action_t::read;
|
||||
if (value == "write")
|
||||
return action_t::write;
|
||||
throw new std::out_of_range("Unknown action");
|
||||
}
|
||||
|
||||
std::string cycle_t::to_string(action_t value) {
|
||||
if (value == action_t::read)
|
||||
return "read";
|
||||
if (value == action_t::write)
|
||||
return "write";
|
||||
throw new std::out_of_range("Unknown action");
|
||||
}
|
||||
|
||||
cycle_t::cycle_t(uint16_t address, uint8_t value, action_t action)
|
||||
: m_address(address),
|
||||
m_value(value),
|
||||
m_action(action) {}
|
||||
|
||||
cycle_t::cycle_t(uint16_t address, uint8_t value, std::string action)
|
||||
: m_address(address),
|
||||
m_value(value),
|
||||
m_action(to_action(action)) {}
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
|
||||
cycle_t::cycle_t(simdjson::dom::element input)
|
||||
: cycle_t(input.get_array()) {}
|
||||
|
||||
cycle_t::cycle_t(simdjson::dom::array input)
|
||||
: m_address((uint16_t)(uint64_t)input.at(0)),
|
||||
m_value((uint8_t)(uint64_t)input.at(1)),
|
||||
m_action(to_action((std::string)input.at(2))) {
|
||||
assert(input.size() == 3);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
|
||||
cycle_t::cycle_t(const boost::json::value& input)
|
||||
: cycle_t(input.as_array()) {}
|
||||
|
||||
cycle_t::cycle_t(const boost::json::array& input)
|
||||
: m_address((uint16_t)input.at(0).as_int64()),
|
||||
m_value((uint8_t)input.at(1).as_int64()),
|
||||
m_action(to_action((std::string)input.at(2).as_string())) {
|
||||
assert(input.size() == 3);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
|
||||
cycle_t::cycle_t(const nlohmann::json& input)
|
||||
: m_address(input[0].get<uint16_t>()),
|
||||
m_value(input[1].get<uint8_t>()),
|
||||
m_action(to_action(input[2].get<std::string>())) {
|
||||
assert(input.size() == 3);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
//cycle_t(const Json::Value& input);
|
||||
|
||||
cycle_t::cycle_t(const Json::Value& input)
|
||||
: m_address(input[0].asUInt()),
|
||||
m_value(input[1].asUInt()),
|
||||
m_action(to_action(input[2].asString())) {
|
||||
assert(input.size() == 3);
|
||||
}
|
||||
|
||||
|
||||
//for (const auto& cycles_entry : cycles_array) {
|
||||
// assert(cycles_entry.size() == 3);
|
||||
// const auto address = cycles_entry[0].asUInt();
|
||||
// const auto contents = cycles_entry[1].asUInt();
|
||||
// const auto action = to_action(cycles_entry[2].asString());
|
||||
// m_cycles.push_back({ address, contents, action });
|
||||
//}
|
||||
|
||||
#endif
|
61
M6502/HarteTest_6502/cycle_t.h
Normal file
61
M6502/HarteTest_6502/cycle_t.h
Normal file
@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
# include "simdjson/simdjson.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
# include <boost/json.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
# include "nlohmann/json.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
# include <json/json.h>
|
||||
#endif
|
||||
|
||||
class cycle_t final {
|
||||
public:
|
||||
enum class action_t { read, write, unknown };
|
||||
|
||||
private:
|
||||
uint16_t m_address = 0xffff;
|
||||
uint8_t m_value = 0xff;
|
||||
action_t m_action = action_t::unknown;
|
||||
|
||||
public:
|
||||
[[nodiscard]] static action_t to_action(std::string value);
|
||||
[[nodiscard]] static std::string to_string(action_t value);
|
||||
|
||||
cycle_t() {}
|
||||
cycle_t(uint16_t address, uint8_t value, action_t action);
|
||||
cycle_t(uint16_t address, uint8_t value, std::string action);
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
cycle_t(simdjson::dom::element input);
|
||||
cycle_t(simdjson::dom::array input);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
cycle_t(const boost::json::value& input);
|
||||
cycle_t(const boost::json::array& input);
|
||||
#endif
|
||||
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
cycle_t(const nlohmann::json& input);
|
||||
#endif
|
||||
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
cycle_t(const Json::Value& input);
|
||||
#endif
|
||||
|
||||
|
||||
[[nodiscard]] constexpr auto address() const noexcept { return m_address; }
|
||||
[[nodiscard]] constexpr auto value() const noexcept { return m_value; }
|
||||
[[nodiscard]] constexpr auto action() const noexcept { return m_action; }
|
||||
};
|
53
M6502/HarteTest_6502/cycles_t.cpp
Normal file
53
M6502/HarteTest_6502/cycles_t.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#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) {
|
||||
m_cycles.push_back(cycle);
|
||||
}
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
|
||||
cycles_t::cycles_t(simdjson::dom::array input) {
|
||||
m_cycles.reserve(input.size());
|
||||
for (const auto& entry : input)
|
||||
add(entry);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
|
||||
cycles_t::cycles_t(const boost::json::value& input)
|
||||
: cycles_t(input.as_array()) {}
|
||||
|
||||
cycles_t::cycles_t(const boost::json::array& input) {
|
||||
m_cycles.reserve(input.size());
|
||||
for (const auto& entry : input)
|
||||
add(entry);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
|
||||
cycles_t::cycles_t(const nlohmann::json& input) {
|
||||
m_cycles.reserve(input.size());
|
||||
for (const auto& entry : input)
|
||||
add(entry);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
|
||||
cycles_t::cycles_t(const Json::Value& input) {
|
||||
m_cycles.reserve(input.size());
|
||||
for (const auto& entry : input)
|
||||
add(entry);
|
||||
}
|
||||
|
||||
#endif
|
58
M6502/HarteTest_6502/cycles_t.h
Normal file
58
M6502/HarteTest_6502/cycles_t.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
# include "simdjson/simdjson.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
# include <boost/json.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
# include "nlohmann/json.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
# include <json/json.h>
|
||||
#endif
|
||||
|
||||
#include "cycle_t.h"
|
||||
|
||||
class cycles_t final {
|
||||
private:
|
||||
std::vector<cycle_t> m_cycles;
|
||||
|
||||
public:
|
||||
cycles_t(size_t reserved = 10);
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
cycles_t(simdjson::dom::array input);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
cycles_t(const boost::json::value& input);
|
||||
cycles_t(const boost::json::array& input);
|
||||
#endif
|
||||
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
cycles_t(const nlohmann::json& input);
|
||||
#endif
|
||||
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
cycles_t(const Json::Value& input);
|
||||
#endif
|
||||
|
||||
void add(const cycle_t& cycle);
|
||||
|
||||
[[nodiscard]] auto begin() const { return m_cycles.begin(); }
|
||||
[[nodiscard]] auto end() const { return m_cycles.end(); }
|
||||
|
||||
[[nodiscard]] auto size() const noexcept { return m_cycles.size(); }
|
||||
|
||||
void clear() { m_cycles.clear(); }
|
||||
|
||||
[[nodiscard]] auto& at(size_t idx) { return m_cycles.at(idx); }
|
||||
[[nodiscard]] const auto& at(size_t idx) const { return m_cycles.at(idx); }
|
||||
};
|
@ -4,61 +4,65 @@
|
||||
|
||||
state_t::state_t() {}
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
|
||||
state_t::state_t(const simdjson::dom::element serialised)
|
||||
: m_pc((uint16_t)(uint64_t)serialised["pc"]),
|
||||
m_s((uint8_t)(uint64_t)serialised["s"]),
|
||||
m_a((uint8_t)(uint64_t)serialised["a"]),
|
||||
m_x((uint8_t)(uint64_t)serialised["x"]),
|
||||
m_y((uint8_t)(uint64_t)serialised["y"]),
|
||||
m_p((uint8_t)(uint64_t)serialised["p"]) {
|
||||
|
||||
const auto ram_entries = serialised["ram"].get_array();
|
||||
m_ram.reserve(ram_entries.size());
|
||||
for (const auto ram_entry : ram_entries) {
|
||||
assert(ram_entry.is_array());
|
||||
const auto ram_entry_array = ram_entry.get_array();
|
||||
assert(ram_entry_array.size() == 2);
|
||||
const auto address = (uint16_t)(uint64_t)ram_entry_array.at(0);
|
||||
const auto value = (uint8_t)(uint64_t)ram_entry_array.at(1);
|
||||
m_ram.push_back({ address, value });
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
|
||||
state_t::state_t(const boost::json::object& serialised) {
|
||||
initialise(serialised);
|
||||
assert(initialised());
|
||||
}
|
||||
|
||||
state_t::state_t(const boost::json::value& serialised) {
|
||||
initialise(serialised.as_object());
|
||||
assert(initialised());
|
||||
}
|
||||
|
||||
void state_t::initialise(const boost::json::object& serialised) {
|
||||
|
||||
assert(!initialised());
|
||||
|
||||
m_pc = (uint16_t)serialised.at("pc").as_int64();
|
||||
m_s = (uint8_t)serialised.at("s").as_int64();
|
||||
m_a = (uint8_t)serialised.at("a").as_int64();
|
||||
m_x = (uint8_t)serialised.at("x").as_int64();
|
||||
m_y = (uint8_t)serialised.at("y").as_int64();
|
||||
m_p = (uint8_t)serialised.at("p").as_int64();
|
||||
state_t::state_t(const boost::json::object& serialised)
|
||||
: m_pc((uint16_t)serialised.at("pc").as_int64()),
|
||||
m_s((uint8_t)serialised.at("s").as_int64()),
|
||||
m_a((uint8_t)serialised.at("a").as_int64()),
|
||||
m_x((uint8_t)serialised.at("x").as_int64()),
|
||||
m_y((uint8_t)serialised.at("y").as_int64()),
|
||||
m_p((uint8_t)serialised.at("p").as_int64()) {
|
||||
|
||||
const auto& ram_entries = serialised.at("ram").as_array();
|
||||
m_ram.reserve(ram_entries.size());
|
||||
for (const auto& ram_entry : ram_entries) {
|
||||
const auto& ram_entry_array = ram_entry.as_array();
|
||||
assert(ram_entry_array.size() == 2);
|
||||
const auto address = (uint16_t)ram_entry_array.at(0).as_int64();
|
||||
const auto value = (uint8_t)ram_entry_array.at(0).as_int64();
|
||||
m_ram[address] = value;
|
||||
const auto value = (uint8_t)ram_entry_array.at(1).as_int64();
|
||||
m_ram.push_back({ address, value });
|
||||
}
|
||||
|
||||
m_initialised = true;
|
||||
}
|
||||
|
||||
state_t::state_t(const boost::json::value& serialised)
|
||||
: state_t(serialised.as_object()) {}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
|
||||
state_t::state_t(const nlohmann::json& serialised) {
|
||||
assert(serialised.is_object());
|
||||
initialise(serialised);
|
||||
assert(initialised());
|
||||
}
|
||||
|
||||
void state_t::initialise(const nlohmann::json& serialised) {
|
||||
|
||||
assert(!initialised());
|
||||
|
||||
m_pc = serialised["pc"].get<uint16_t>();
|
||||
m_s = serialised["s"].get<uint8_t>();
|
||||
m_a = serialised["a"].get<uint8_t>();
|
||||
m_x = serialised["x"].get<uint8_t>();
|
||||
m_y = serialised["y"].get<uint8_t>();
|
||||
m_p = serialised["p"].get<uint8_t>();
|
||||
state_t::state_t(const nlohmann::json& serialised)
|
||||
: m_pc(serialised["pc"].get<uint16_t>()),
|
||||
m_s(serialised["s"].get<uint8_t>()),
|
||||
m_a(serialised["a"].get<uint8_t>()),
|
||||
m_x(serialised["x"].get<uint8_t>()),
|
||||
m_y(serialised["y"].get<uint8_t>()),
|
||||
m_p(serialised["p"].get<uint8_t>()) {
|
||||
|
||||
const auto& ram_entries = serialised["ram"];
|
||||
assert(ram_entries.is_array());
|
||||
@ -67,32 +71,21 @@ void state_t::initialise(const nlohmann::json& serialised) {
|
||||
assert(ram_entry.size() == 2);
|
||||
const auto address = ram_entry[0].get<uint16_t>();
|
||||
const auto value = ram_entry[1].get<uint8_t>();
|
||||
m_ram[address] = value;
|
||||
m_ram.push_back({ address, value });
|
||||
}
|
||||
|
||||
m_initialised = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
|
||||
state_t::state_t(const Json::Value& serialised) {
|
||||
assert(serialised.isObject());
|
||||
initialise(serialised);
|
||||
assert(initialised());
|
||||
}
|
||||
|
||||
void state_t::initialise(const Json::Value& serialised) {
|
||||
|
||||
assert(!initialised());
|
||||
|
||||
m_pc = serialised["pc"].asUInt();
|
||||
m_s = serialised["s"].asUInt();
|
||||
m_a = serialised["a"].asUInt();
|
||||
m_x = serialised["x"].asUInt();
|
||||
m_y = serialised["y"].asUInt();
|
||||
m_p = serialised["p"].asUInt();
|
||||
state_t::state_t(const Json::Value& serialised)
|
||||
: m_pc(serialised["pc"].asUInt()),
|
||||
m_s(serialised["s"].asUInt()),
|
||||
m_a(serialised["a"].asUInt()),
|
||||
m_x(serialised["x"].asUInt()),
|
||||
m_y(serialised["y"].asUInt()),
|
||||
m_p(serialised["p"].asUInt()) {
|
||||
|
||||
const auto& ram_entries = serialised["ram"];
|
||||
assert(ram_entries.isArray());
|
||||
@ -101,45 +94,8 @@ void state_t::initialise(const Json::Value& serialised) {
|
||||
assert(ram_entry.size() == 2);
|
||||
const auto address = ram_entry[0].asUInt();
|
||||
const auto value = ram_entry[1].asUInt();
|
||||
m_ram[address] = value;
|
||||
m_ram.push_back({ address, value });
|
||||
}
|
||||
|
||||
m_initialised = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
|
||||
state_t::state_t(const simdjson::dom::element serialised) {
|
||||
assert(serialised.is_object());
|
||||
initialise(serialised);
|
||||
assert(initialised());
|
||||
}
|
||||
|
||||
void state_t::initialise(const simdjson::dom::element serialised) {
|
||||
|
||||
assert(!initialised());
|
||||
|
||||
m_pc = (uint16_t)(uint64_t)serialised["pc"];
|
||||
m_s = (uint8_t)(uint64_t)serialised["s"];
|
||||
m_a = (uint8_t)(uint64_t)serialised["a"];
|
||||
m_x = (uint8_t)(uint64_t)serialised["x"];
|
||||
m_y = (uint8_t)(uint64_t)serialised["y"];
|
||||
m_p = (uint8_t)(uint64_t)serialised["p"];
|
||||
|
||||
const auto ram_entries = serialised["ram"];
|
||||
assert(ram_entries.is_array());
|
||||
for (const auto ram_entry : ram_entries) {
|
||||
assert(ram_entry.is_array());
|
||||
const auto ram_entry_array = ram_entry.get_array();
|
||||
assert(ram_entry_array.size() == 2);
|
||||
const auto address = (uint64_t)ram_entry_array.at(0);
|
||||
const auto value = (uint64_t)ram_entry_array.at(1);
|
||||
m_ram[(uint16_t)address] = (uint8_t)value;
|
||||
}
|
||||
|
||||
m_initialised = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
# include "simdjson/simdjson.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
# include <boost/json.hpp>
|
||||
@ -15,43 +20,27 @@
|
||||
# include <json/json.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
# include "simdjson/simdjson.h"
|
||||
#endif
|
||||
|
||||
class state_t final {
|
||||
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::map<uint16_t, uint8_t> m_ram;
|
||||
|
||||
[[nodiscard]] constexpr auto initialised() const noexcept { return m_initialised; }
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
void initialise(const boost::json::object& serialised);
|
||||
#endif
|
||||
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
void initialise(const nlohmann::json& serialised);
|
||||
#endif
|
||||
std::vector<std::pair<uint16_t, uint8_t>> m_ram;
|
||||
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
void initialise(const Json::Value& serialised);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
void initialise(simdjson::dom::element serialised);
|
||||
#endif
|
||||
|
||||
public:
|
||||
state_t();
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
state_t(simdjson::dom::element serialised);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
state_t(const boost::json::object& serialised);
|
||||
state_t(const boost::json::value& serialised);
|
||||
@ -65,10 +54,6 @@ public:
|
||||
state_t(const Json::Value& serialised);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
state_t(simdjson::dom::element serialised);
|
||||
#endif
|
||||
|
||||
[[nodiscard]] constexpr auto pc() const noexcept { return m_pc; }
|
||||
[[nodiscard]] constexpr auto s() const noexcept { return m_s; }
|
||||
[[nodiscard]] constexpr auto a() const noexcept { return m_a; }
|
||||
|
@ -11,12 +11,18 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
//#define TEST_JSON_PERFORMANCE
|
||||
#define TEST_JSON_PERFORMANCE
|
||||
|
||||
#define USE_SIMDJSON_JSON // 16 seconds
|
||||
//#define USE_SIMDJSON_JSON // 14 seconds
|
||||
//#define USE_BOOST_JSON // 28 seconds
|
||||
//#define USE_NLOHMANN_JSON // 73 seconds
|
||||
//#define USE_JSONCPP_JSON // 105 seconds
|
||||
//#define USE_NLOHMANN_JSON // 56 seconds
|
||||
#define USE_JSONCPP_JSON // 105 seconds
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
# define JSON_PREFER_PASS_BY_VALUE
|
||||
# define JSON_PREFER_REUSE_OF_PARSER
|
||||
# include "simdjson/simdjson.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
# include <boost/json.hpp>
|
||||
@ -30,9 +36,3 @@
|
||||
# define JSON_PREFER_REUSE_OF_PARSER
|
||||
# include <json/json.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
# define JSON_PREFER_PASS_BY_VALUE
|
||||
# define JSON_PREFER_REUSE_OF_PARSER
|
||||
# include "simdjson/simdjson.h"
|
||||
#endif
|
||||
|
@ -1,133 +1,64 @@
|
||||
#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");
|
||||
}
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
|
||||
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");
|
||||
}
|
||||
test_t::test_t(const simdjson::dom::element serialised)
|
||||
: m_name(serialised["name"]),
|
||||
m_initial_state(serialised["initial"]),
|
||||
m_final_state(serialised["final"]),
|
||||
m_cycles(serialised["cycles"].get_array()) {}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
|
||||
test_t::test_t(const boost::json::object& serialised) {
|
||||
initialise(serialised);
|
||||
}
|
||||
test_t::test_t(const boost::json::object& serialised)
|
||||
: m_name(serialised.at("name").as_string()),
|
||||
m_initial_state(serialised.at("initial")),
|
||||
m_final_state(serialised.at("final")),
|
||||
m_cycles(serialised.at("cycles")) {}
|
||||
|
||||
test_t::test_t(const boost::json::value& serialised) {
|
||||
initialise(serialised.as_object());
|
||||
}
|
||||
|
||||
void test_t::initialise(const boost::json::object& serialised) {
|
||||
|
||||
m_name = serialised.at("name").as_string();
|
||||
m_initial_state = state_t(serialised.at("initial"));
|
||||
m_final_state = state_t(serialised.at("final"));
|
||||
|
||||
const auto& cycles_array = serialised.at("cycles").as_array();
|
||||
m_cycles.reserve(cycles_array.size());
|
||||
|
||||
for (const auto& cycles_entry : cycles_array) {
|
||||
const auto& cycle_array = cycles_entry.as_array();
|
||||
assert(cycle_array.size() == 3);
|
||||
const auto address = (uint16_t)cycle_array.at(0).as_int64();
|
||||
const auto contents = (uint8_t)cycle_array.at(1).as_int64();
|
||||
const auto action = to_action((std::string)cycle_array.at(2).as_string());
|
||||
m_cycles.push_back({ address, contents, action });
|
||||
}
|
||||
}
|
||||
test_t::test_t(const boost::json::value& serialised)
|
||||
: test_t(serialised.as_object()) {}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
|
||||
test_t::test_t(const nlohmann::json& serialised) {
|
||||
assert(serialised.is_object());
|
||||
initialise(serialised);
|
||||
}
|
||||
|
||||
void test_t::initialise(const nlohmann::json& serialised) {
|
||||
|
||||
m_name = serialised["name"].get<std::string>();
|
||||
m_initial_state = state_t(serialised["initial"]);
|
||||
m_final_state = state_t(serialised["final"]);
|
||||
|
||||
const auto& cycles_array = serialised["cycles"];
|
||||
m_cycles.reserve(cycles_array.size());
|
||||
|
||||
for (const auto& cycles_entry : cycles_array) {
|
||||
assert(cycles_entry.size() == 3);
|
||||
const auto address = cycles_entry[0].get<uint16_t>();
|
||||
const auto contents = cycles_entry[1].get<uint8_t>();
|
||||
const auto action = to_action(cycles_entry[2].get<std::string>());
|
||||
m_cycles.push_back({ address, contents, action });
|
||||
}
|
||||
}
|
||||
test_t::test_t(const nlohmann::json& serialised)
|
||||
: m_name(serialised["name"].get<std::string>()),
|
||||
m_initial_state(serialised["initial"]),
|
||||
m_final_state(serialised["final"]),
|
||||
m_cycles(serialised["cycles"]) {}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
|
||||
test_t::test_t(const Json::Value& serialised) {
|
||||
assert(serialised.isObject());
|
||||
initialise(serialised);
|
||||
}
|
||||
test_t::test_t(const Json::Value& serialised)
|
||||
: m_name(serialised["name"].asString()),
|
||||
m_initial_state(serialised["initial"]),
|
||||
m_final_state(serialised["final"]),
|
||||
m_cycles(serialised["cycles"]) {}
|
||||
|
||||
void test_t::initialise(const Json::Value& serialised) {
|
||||
|
||||
m_name = serialised["name"].asString();
|
||||
m_initial_state = state_t(serialised["initial"]);
|
||||
m_final_state = state_t(serialised["final"]);
|
||||
|
||||
const auto& cycles_array = serialised["cycles"];
|
||||
m_cycles.reserve(cycles_array.size());
|
||||
//m_name = serialised["name"].asString();
|
||||
//m_initial_state = state_t(serialised["initial"]);
|
||||
//m_final_state = state_t(serialised["final"]);
|
||||
|
||||
for (const auto& cycles_entry : cycles_array) {
|
||||
assert(cycles_entry.size() == 3);
|
||||
const auto address = cycles_entry[0].asUInt();
|
||||
const auto contents = cycles_entry[1].asUInt();
|
||||
const auto action = to_action(cycles_entry[2].asString());
|
||||
m_cycles.push_back({ address, contents, action });
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
|
||||
test_t::test_t(const simdjson::dom::element serialised) {
|
||||
assert(serialised.is_object());
|
||||
initialise(serialised);
|
||||
}
|
||||
|
||||
void test_t::initialise(const simdjson::dom::element serialised) {
|
||||
|
||||
m_name = serialised["name"];
|
||||
m_initial_state = state_t(serialised["initial"]);
|
||||
m_final_state = state_t(serialised["final"]);
|
||||
|
||||
const auto cycles_array = serialised["cycles"].get_array();
|
||||
m_cycles.reserve(cycles_array.size());
|
||||
|
||||
for (const auto cycles_entry : cycles_array) {
|
||||
const auto cycle_array = cycles_entry.get_array();
|
||||
assert(cycle_array.size() == 3);
|
||||
const auto address = (uint16_t)(uint64_t)cycle_array.at(0);
|
||||
const auto contents = (uint8_t)(uint64_t)cycle_array.at(1);
|
||||
const auto action = to_action((std::string)cycle_array.at(2));
|
||||
m_cycles.push_back({ address, contents, action });
|
||||
}
|
||||
}
|
||||
//const auto& cycles_array = serialised["cycles"];
|
||||
//m_cycles.reserve(cycles_array.size());
|
||||
|
||||
//for (const auto& cycles_entry : cycles_array) {
|
||||
// assert(cycles_entry.size() == 3);
|
||||
// const auto address = cycles_entry[0].asUInt();
|
||||
// const auto contents = cycles_entry[1].asUInt();
|
||||
// const auto action = to_action(cycles_entry[2].asString());
|
||||
// m_cycles.push_back({ address, contents, action });
|
||||
//}
|
||||
//}
|
||||
|
||||
#endif
|
||||
|
@ -5,6 +5,10 @@
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
# include "simdjson/simdjson.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
# include <boost/json.hpp>
|
||||
#endif
|
||||
@ -17,46 +21,26 @@
|
||||
# include <json/json.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
# include "simdjson/simdjson.h"
|
||||
#endif
|
||||
|
||||
#include "cycles_t.h"
|
||||
#include "state_t.h"
|
||||
|
||||
class test_t final {
|
||||
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;
|
||||
|
||||
[[nodiscard]] static action to_action(std::string value);
|
||||
[[nodiscard]] 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;
|
||||
cycles_t m_cycles;
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
void initialise(const boost::json::object& serialised);
|
||||
#endif
|
||||
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
void initialise(const nlohmann::json& serialised);
|
||||
#endif
|
||||
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
void initialise(const Json::Value& serialised);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
void initialise(simdjson::dom::element serialised);
|
||||
#endif
|
||||
//#ifdef USE_JSONCPP_JSON
|
||||
// void initialise(const Json::Value& serialised);
|
||||
//#endif
|
||||
|
||||
public:
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
test_t(simdjson::dom::element serialised);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOST_JSON
|
||||
test_t(const boost::json::object& serialised);
|
||||
test_t(const boost::json::value& serialised);
|
||||
@ -70,12 +54,8 @@ public:
|
||||
test_t(const Json::Value& serialised);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
test_t(simdjson::dom::element serialised);
|
||||
#endif
|
||||
|
||||
[[nodiscard]] constexpr const auto& name() const noexcept { return m_name; }
|
||||
[[nodiscard]] constexpr const auto& initial_state() const noexcept { return m_initial_state; }
|
||||
[[nodiscard]] constexpr const auto& final_state() const noexcept { return m_final_state; }
|
||||
[[nodiscard]] constexpr const auto& cycles() const noexcept { return m_cycles; }
|
||||
};
|
||||
};
|
||||
|
@ -23,20 +23,20 @@ int main() {
|
||||
opcode.load();
|
||||
opcode.parse();
|
||||
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
const auto opcode_test_array = opcode.raw().get_array();
|
||||
#endif
|
||||
#ifdef USE_BOOST_JSON
|
||||
const auto& opcode_test_array = opcode.raw().as_array();
|
||||
#endif
|
||||
#ifdef USE_NLOHMANN_JSON
|
||||
const auto& opcode_test_array = opcode.raw();
|
||||
assert(opcode_test_array).is_array());
|
||||
assert(opcode_test_array.is_array());
|
||||
#endif
|
||||
#ifdef USE_JSONCPP_JSON
|
||||
const auto& opcode_test_array = opcode.raw();
|
||||
assert(opcode_test_array.is_array());
|
||||
#endif
|
||||
#ifdef USE_SIMDJSON_JSON
|
||||
const auto opcode_test_array = opcode.raw().get_array();
|
||||
#endif
|
||||
|
||||
bool opcode_bad = false;
|
||||
for (const auto& opcode_test_element : opcode_test_array) {
|
||||
|
Loading…
Reference in New Issue
Block a user