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. --- uarch/exec.cpp | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 uarch/exec.cpp (limited to 'uarch/exec.cpp') diff --git a/uarch/exec.cpp b/uarch/exec.cpp new file mode 100644 index 0000000..e40813b --- /dev/null +++ b/uarch/exec.cpp @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uarch/exec.h" +#include "util/assert.h" + +namespace uarch { + + ExecStage::ExecStage(sim::Scheduler &scheduler, sim::Queue &execq, sim::Queue &fillreqq, sim::Queue &fillq, sim::Queue &storeq) + : sim::Schedulable(scheduler) + , execq(execq) + , fillreqq(fillreqq) + , fillq(fillq) + , storeq(storeq) + { + execq.add_reader(this); + fillreqq.add_writer(this); + fillq.add_reader(this); + storeq.add_writer(this); + } + + void ExecStage::clock() + { + if (tasks.empty() && !step && execq.available()) { + auto uop = execq.read(); + std::cout << "exec accepts uop " << uop.top_task().value()->disasm() << "\n"; + aisa::TaskStack::operator=(std::move(uop)); + aisa::VectorRF::operator=(std::move(uop)); + } + + bool sent_store = false; + while (!sent_store) { + while (!step) { + auto t = top_task(); + if (!t) + goto no_work; + const auto &task = **t; + auto s = task.step(load_reg(task.environment).value()); + if (s.has_value()) { + step = std::move(s->first); + std::cout << "exec step " << step->disasm() << "\n"; + wires = {}; + outstanding_fill = false; + fill_complete = false; + ASSERT(store_reg(task.environment, s->second), "Could not write next environment value"); + } else { + pop_task(); + if (tasks.empty()) + std::cout << "exec completes uop\n"; + } + } + + if (step->predicate.has_value()) { + auto x = load_reg(step->predicate->first); + if (x.has_value()) { + if (*x != step->predicate->second) + goto nextstep; + } else { + std::cout << "exec stalls on predicate register"; + break; + } + } + + wires.source_vals.reserve(step->source_regs.size()); + for (unsigned int i = wires.source_vals.size(); i < step->source_regs.size(); ++i) { + auto x = load_reg(step->source_regs[i]); + if (!x.has_value()) { + std::cout << "exec stalls on source register"; + break; + } + wires.source_vals.emplace_back(*x); + } + + if (step->mop == aisa::MOp::LOAD && !fill_complete) { + auto mi = step->meminfo(wires); + if (outstanding_fill) { + for (unsigned int i = 0; i < fillq.available(); ++i) { + auto &fill = fillq.peek(i); + if (fill.physical_addr == mi.physical_addr) { + std::cout << "exec fills\n"; + wires.memory_val = std::move(fill.bytes); + outstanding_fill = false; + fill_complete = true; + } + } + if (!fill_complete) + break; + } else { + std::cout << "exec sends fill request\n"; + FillReq req; + req.fillq = &fillq; + req.physical_addr = mi.physical_addr; + req.size = mi.size; + fillreqq.write(std::move(req)); + outstanding_fill = true; + fill_complete = false; + break; + } + } + + step->evaluate(wires); + + for (unsigned int i = 0; i < step->destination_regs.size(); ++i) + ASSERT(store_reg(step->destination_regs[i], wires.destination_vals[i]), "Could not write destination register"); + + if (step->mop == aisa::MOp::STORE) { + std::cout << "exec sends store\n"; + auto mi = step->meminfo(wires); + Store store; + store.physical_addr = mi.physical_addr; + store.bytes = std::move(wires.memory_val); + storeq.write(std::move(store)); + //sent_store = true; + } + +nextstep: + step = nullptr; + wires = {}; + outstanding_fill = false; + fill_complete = false; + } + +no_work: + + while (fillq.available()) { + std::cout << "exec consumes fill\n"; + fillq.read(); + } + } + +} -- cgit v1.2.3