From c72951a36d6cb9775dc1ecd9bc26bc13e796f10c Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sat, 2 Jul 2022 13:45:09 -0700 Subject: Dropping the async interface, and adding some real uarch. --- aisa/aisa.cpp | 6 ++ aisa/aisa.h | 20 +---- aisa/async.h | 225 ------------------------------------------------- aisa/coroutine.h | 119 -------------------------- aisa/simple-models.cpp | 49 +++++++++++ aisa/simple-models.h | 39 ++------- 6 files changed, 63 insertions(+), 395 deletions(-) delete mode 100644 aisa/async.h delete mode 100644 aisa/coroutine.h create mode 100644 aisa/simple-models.cpp (limited to 'aisa') diff --git a/aisa/aisa.cpp b/aisa/aisa.cpp index 811c882..8c8cd1e 100644 --- a/aisa/aisa.cpp +++ b/aisa/aisa.cpp @@ -6,6 +6,12 @@ namespace aisa { + ISA::~ISA() { } + + Task::~Task() { } + + Step::~Step() { } + std::optional, regval_t>> Task::step(regval_t environment_val) const { return {}; } MemInfo Step::meminfo(const Wires &wires) const { return {}; } diff --git a/aisa/aisa.h b/aisa/aisa.h index e4e1074..a986cd7 100644 --- a/aisa/aisa.h +++ b/aisa/aisa.h @@ -17,7 +17,7 @@ namespace aisa { struct Task; struct ISA { - virtual ~ISA() { } + virtual ~ISA(); virtual std::pair, regval_t> initial_task() const = 0; }; @@ -27,7 +27,7 @@ namespace aisa { struct Task { regnum_t environment; - virtual ~Task() { } + virtual ~Task(); virtual std::string disasm() const = 0; @@ -58,24 +58,10 @@ namespace aisa { std::vector source_regs; std::vector destination_regs; - virtual ~Step() { } + virtual ~Step(); virtual std::string disasm(const Wires *w = nullptr) const = 0; - std::optional predicate_reg() const - { - if (predicate.has_value()) - return predicate->first; - return {}; - } - - std::optional expected_predicate_val() const - { - if (predicate.has_value()) - return predicate->second; - return {}; - } - MOp mop = MOp::NONE; virtual MemInfo meminfo(const Wires &wires) const; diff --git a/aisa/async.h b/aisa/async.h deleted file mode 100644 index 42e99e7..0000000 --- a/aisa/async.h +++ /dev/null @@ -1,225 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "aisa/aisa.h" -#include "aisa/coroutine.h" // IWYU pragma: export - -namespace aisa { - - template struct AsyncEval { - CRTP & crtp() noexcept { return static_cast(*this); } - - task async_load_reg(regnum_t rn) - { - while (true) { - if (auto rv = crtp().load_reg(rn); rv.has_value()) - co_return *rv; - co_await std::suspend_always{}; - } - } - - task async_store_reg(regnum_t rn, regval_t rv) - { - while (true) { - if (crtp().store_reg(rn, rv)) - co_return; - co_await std::suspend_always{}; - } - } - - task async_fetch_mem(byte_t *bytes, addr_t physical_addr, addr_t size) - { - while (true) { - if (crtp().fetch_mem(bytes, physical_addr, size)) - co_return; - co_await std::suspend_always{}; - } - } - - task async_store_mem(addr_t physical_addr, const byte_t *bytes, addr_t size) - { - while (true) { - if (crtp().store_mem(physical_addr, bytes, size)) - co_return; - co_await std::suspend_always{}; - } - } - - task async_predicate(const Step &step) - { - if (step.predicate.has_value()) { - regval_t pval = co_await crtp().async_load_reg(step.predicate->first); - co_return pval == step.predicate->second; - } - co_return true; - } - - task async_load_source_registers(const Step &step, Wires &w) - { - w.source_vals.resize(step.source_regs.size()); - for (unsigned int i = 0; i < step.source_regs.size(); ++i) - w.source_vals[i] = co_await crtp().async_load_reg(step.source_regs[i]); - } - - task async_load_source_memory(const Step &step, const MemInfo &mi, Wires &w) - { - w.memory_val.resize(mi.size); - co_await crtp().async_fetch_mem(w.memory_val.data(), mi.physical_addr, mi.size); - } - - task async_load_sources(const Step &step, Wires &w) - { - co_await crtp().async_load_source_registers(step, w); - - if (step.mop == MOp::LOAD) { - auto mi = step.meminfo(w); - co_await crtp().async_load_source_memory(step, mi, w); - } - } - - task async_write_destination_registers(const Step &step, const Wires &w) - { - for (unsigned int i = 0; i < step.destination_regs.size(); ++i) - co_await crtp().async_store_reg(step.destination_regs[i], w.destination_vals[i]); - } - - task async_write_destination_memory(const Step &step, const MemInfo &mi, const Wires &w) - { - co_await crtp().async_store_mem(mi.physical_addr, w.memory_val.data(), mi.size); - } - - task async_write_destinations(const Step &step, const Wires &w) - { - if (w.aborted) - co_return; - - co_await crtp().async_write_destination_registers(step, w); - - if (step.mop == MOp::STORE) { - auto mi = step.meminfo(w); - co_await crtp().async_write_destination_memory(step, mi, w); - } - } - - task async_push_task(std::unique_ptr &&task) - { - while (true) { - if (crtp().push_task(std::move(task))) - co_return; - co_await std::suspend_always{}; - } - } - - task async_new_task(std::unique_ptr &&task, regval_t environment_val) - { - auto rn = task->environment; - co_await crtp().async_push_task(std::move(task)); - co_await crtp().async_store_reg(rn, environment_val); - } - - task async_run_step(const Step &step) - { - Wires w; - - if (!co_await crtp().async_predicate(step)) - co_return std::move(w); - - co_await crtp().async_load_sources(step, w); - - step.evaluate(w); - - co_await crtp().async_write_destinations(step, w); - - if (w.new_task.has_value()) - co_await crtp().async_new_task(std::move(w.new_task->first), w.new_task->second); - - co_return std::move(w); - } - - task async_top_task() - { - while (true) { - if (auto rv = crtp().top_task(); rv.has_value()) - co_return &**rv; - co_await std::suspend_always{}; - } - } - - task async_pop_task() - { - while (true) { - if (crtp().pop_task()) - co_return; - co_await std::suspend_always{}; - } - } - - task>> async_fetch_step() - { - auto task = co_await crtp().async_top_task(); - - auto rn = task->environment; - auto rv = co_await crtp().async_load_reg(rn); - - auto step = task->step(rv); - if (step.has_value()) { - co_await crtp().async_store_reg(rn, step->second); - co_return std::move(step->first); - } else { - co_await crtp().async_pop_task(); - co_return {}; - } - } - - task, Wires>> async_fetch_and_run_step() - { - while (true) { - if (auto step = co_await crtp().async_fetch_step(); step.has_value()) { - auto wires = co_await crtp().async_run_step(**step); - co_return {std::move(*step), std::move(wires)}; - } - } - } - - task async_run_subtree() - { - while (true) { - if (auto step = co_await crtp().async_fetch_step(); step.has_value()) - co_await crtp().async_run_step_and_subtree(**step); - else - break; - } - } - - task async_run_step_and_subtree(const Step &step) - { - auto w = co_await crtp().async_run_step(step); - - if (w.new_task.has_value()) - co_await crtp().async_run_subtree(); - - co_return std::move(w); - } - - task async_setup_initial_task(const ISA &isa) - { - auto task = isa.initial_task(); - - co_await crtp().async_new_task(std::move(task.first), task.second); - } - - task async_run(const ISA &isa) - { - co_await crtp().async_setup_initial_task(isa); - - co_await crtp().async_run_subtree(); - } - - }; - -} diff --git a/aisa/coroutine.h b/aisa/coroutine.h deleted file mode 100644 index 1b55362..0000000 --- a/aisa/coroutine.h +++ /dev/null @@ -1,119 +0,0 @@ -#pragma once - -#include -#include - -namespace aisa { - - template struct task_promise; - - template struct task : public std::coroutine_handle> { - using handle = std::coroutine_handle>; - using promise_type = task_promise; - bool await_ready() const noexcept { return handle::done(); } - result_t await_resume() const noexcept; - template void await_suspend(std::coroutine_handle> h) const noexcept; - std::optional operator()() noexcept; - }; - - template<> struct task : public std::coroutine_handle> { - using handle = std::coroutine_handle>; - using promise_type = task_promise; - bool await_ready() const noexcept { return handle::done(); } - void await_resume() const noexcept; - template void await_suspend(std::coroutine_handle> h) const noexcept; - bool operator()() noexcept; - }; - - template struct task_promise { - std::coroutine_handle<> precursor; - std::optional result; - task_promise() = default; - task_promise(const task_promise &) = delete; - task get_return_object() noexcept { return task{std::coroutine_handle>::from_promise(*this)}; } - std::suspend_never initial_suspend() const noexcept { return {}; } - std::suspend_always final_suspend() const noexcept { return {}; } - void unhandled_exception() { } - void return_value(result_t x) noexcept { result = std::move(x); } - }; - - template<> struct task_promise { - std::coroutine_handle<> precursor; - task_promise() = default; - task_promise(const task_promise &) = delete; - task get_return_object() noexcept { return task{std::coroutine_handle>::from_promise(*this)}; } - std::suspend_never initial_suspend() const noexcept { return {}; } - std::suspend_always final_suspend() const noexcept { return {}; } - void unhandled_exception() { } - void return_void() noexcept { } - }; - - template result_t task::await_resume() const noexcept - { - auto x = std::move(handle::promise().result.value()); - handle::destroy(); - return x; - } - - template template void task::await_suspend(std::coroutine_handle> h) const noexcept - { - h.promise().precursor = *this; - } - - template std::optional task::operator()() noexcept - { - if (!handle::operator bool()) - return {}; - if (!handle::done()) { - auto &precursor = handle::promise().precursor; - if (precursor) { - if (!precursor.done()) - precursor.resume(); - if (precursor.done()) - precursor = nullptr; - } - if (!precursor) - handle::resume(); - } - if (handle::done()) { - auto x = await_resume(); - handle::operator=(nullptr); - return x; - } - return {}; - } - - inline void task::await_resume() const noexcept - { - handle::destroy(); - } - - template void task::await_suspend(std::coroutine_handle> h) const noexcept - { - h.promise().precursor = *this; - } - - inline bool task::operator()() noexcept - { - if (!handle::operator bool()) - return true; - if (!handle::done()) { - auto &precursor = handle::promise().precursor; - if (precursor) { - if (!precursor.done()) - precursor.resume(); - if (precursor.done()) - precursor = nullptr; - } - if (!precursor) - handle::resume(); - } - if (handle::done()) { - await_resume(); - handle::operator=(nullptr); - return true; - } - return false; - } - -} diff --git a/aisa/simple-models.cpp b/aisa/simple-models.cpp new file mode 100644 index 0000000..b69dcb7 --- /dev/null +++ b/aisa/simple-models.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include + +#include "aisa/aisa.h" +#include "aisa/simple-models.h" + +namespace aisa { + + bool TaskStack::pop_task() + { + if (tasks.empty()) + return false; + tasks.pop_back(); + return true; + } + + bool TaskStack::push_task(std::unique_ptr &&task) + { + tasks.emplace_back(std::move(task)); + return true; + } + + std::optional TaskStack::top_task() + { + if (tasks.empty()) + return {}; + return tasks.back().get(); + } + + std::optional VectorRF::load_reg(regnum_t rn) const + { + if (rf.size() <= rn) + return {}; + return rf[rn]; + } + + bool VectorRF::store_reg(regnum_t rn, regval_t rv) + { + if (rf.size() <= rn) + rf.resize(rn + 1); + rf[rn] = rv; + return true; + } + +} diff --git a/aisa/simple-models.h b/aisa/simple-models.h index 62b5388..a94f010 100644 --- a/aisa/simple-models.h +++ b/aisa/simple-models.h @@ -7,7 +7,6 @@ #include #include #include -#include #include #include "aisa/aisa.h" @@ -51,45 +50,17 @@ namespace aisa { struct TaskStack { std::deque> tasks; - bool pop_task() - { - if (tasks.empty()) - return false; - tasks.pop_back(); - return true; - } - - bool push_task(std::unique_ptr &&task) - { - tasks.emplace_back(std::move(task)); - return true; - } + bool pop_task(); + bool push_task(std::unique_ptr &&task); - std::optional top_task() - { - if (tasks.empty()) - return {}; - return tasks.back().get(); - } + std::optional top_task(); }; struct VectorRF { std::vector> rf; - std::optional load_reg(regnum_t rn) const - { - if (rf.size() <= rn) - return {}; - return rf[rn]; - } - - bool store_reg(regnum_t rn, regval_t rv) - { - if (rf.size() <= rn) - rf.resize(rn + 1); - rf[rn] = rv; - return true; - } + std::optional load_reg(regnum_t rn) const; + bool store_reg(regnum_t rn, regval_t rv); }; } -- cgit v1.2.3