From bbaf58c9fd0f485266d86868dc35f1d2be3589cd Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sun, 26 Jun 2022 16:24:13 -0700 Subject: Significant changes, and a working "ISA" that just computes fib(n). --- aisa/async.h | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 aisa/async.h (limited to 'aisa/async.h') diff --git a/aisa/async.h b/aisa/async.h new file mode 100644 index 0000000..42e99e7 --- /dev/null +++ b/aisa/async.h @@ -0,0 +1,225 @@ +#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(); + } + + }; + +} -- cgit v1.2.3