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). --- isa/fib/fib.h | 288 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 isa/fib/fib.h (limited to 'isa/fib') diff --git a/isa/fib/fib.h b/isa/fib/fib.h new file mode 100644 index 0000000..13801c8 --- /dev/null +++ b/isa/fib/fib.h @@ -0,0 +1,288 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "aisa/aisa.h" + +namespace isa::fib { + + namespace Reg { + enum { + ENV_TOP, + ENV_FIB, + + AREG, + ATMP, + + PC, + + A, + B, + Q, + }; + + const char *disasm(aisa::regnum_t x) + { + switch (x) { + case ENV_TOP: return "ENV_TOP"; + case ENV_FIB: return "ENV_FIB"; + case AREG: return "AREG"; + case ATMP: return "ATMP"; + case PC: return "PC"; + case A: return "A"; + case B: return "B"; + case Q: return "Q"; + default: return "???"; + } + } + } + + struct StepAdd : public aisa::Step { + StepAdd(aisa::regnum_t q, aisa::regnum_t a, aisa::regnum_t b) + { + source_regs.resize(2); + source_regs[0] = a; + source_regs[1] = b; + + destination_regs.resize(1); + destination_regs[0] = q; + } + + std::string disasm(const aisa::Wires *w) const override + { + if (w) + return fmt::format("{}({}) <- {}({}) + {}({})", Reg::disasm(destination_regs[0]), w->destination_vals[0], Reg::disasm(source_regs[0]), w->source_vals[0], Reg::disasm(source_regs[1]), w->source_vals[1]); + return fmt::format("{} <- {} + {}", Reg::disasm(destination_regs[0]), Reg::disasm(source_regs[0]), Reg::disasm(source_regs[1])); + } + + void evaluate(aisa::Wires &w) const override + { + w.destination_vals.resize(1); + w.destination_vals[0] = w.source_vals[0] + w.source_vals[1]; + } + }; + + struct StepAddImmediate : public aisa::Step { + aisa::regval_t x; + + StepAddImmediate(aisa::regnum_t q, aisa::regnum_t a, aisa::regval_t x) + :x(x) + { + source_regs.resize(1); + source_regs[0] = a; + + destination_regs.resize(1); + destination_regs[0] = q; + } + + std::string disasm(const aisa::Wires *w) const override + { + if (w) + return fmt::format("{}({}) <- {}({}) + {}", Reg::disasm(destination_regs[0]), w->destination_vals[0], Reg::disasm(source_regs[0]), w->source_vals[0], x); + return fmt::format("{} <- {} + {}", Reg::disasm(destination_regs[0]), Reg::disasm(source_regs[0]), x); + } + + void evaluate(aisa::Wires &w) const override + { + w.destination_vals.resize(1); + w.destination_vals[0] = w.source_vals[0] + x; + } + }; + + template struct StepLoad : public aisa::Step { + StepLoad(aisa::regnum_t q, aisa::regnum_t a) + { + source_regs.resize(1); + source_regs[0] = a; + + destination_regs.resize(1); + destination_regs[0] = q; + + mop = aisa::MOp::LOAD; + } + + std::string disasm(const aisa::Wires *w) const override + { + if (w) + return fmt::format("{}({}) <- [{}({})]", Reg::disasm(destination_regs[0]), w->destination_vals[0], Reg::disasm(source_regs[0]), w->source_vals[0]); + return fmt::format("{} <- [{}]", Reg::disasm(destination_regs[0]), Reg::disasm(source_regs[0])); + } + + aisa::MemInfo meminfo(const aisa::Wires &w) const override + { + aisa::MemInfo mi; + mi.physical_addr = w.source_vals[0] * WORD; + mi.size = WORD; + return mi; + } + + void evaluate(aisa::Wires &w) const override + { + w.destination_vals.resize(1); + auto &q = w.destination_vals[0]; + q = 0; + for (unsigned int i = 0; i < WORD; ++i) + q |= static_cast(w.memory_val[i]) << (8 * i); + } + }; + + struct StepMove : public aisa::Step { + StepMove(aisa::regnum_t q, aisa::regnum_t a) + { + source_regs.resize(1); + source_regs[0] = a; + + destination_regs.resize(1); + destination_regs[0] = q; + } + + std::string disasm(const aisa::Wires *w) const override + { + if (w) + return fmt::format("{}({}) <- {}({})", Reg::disasm(destination_regs[0]), w->destination_vals[0], Reg::disasm(source_regs[0]), w->source_vals[0]); + return fmt::format("{} <- {}", Reg::disasm(destination_regs[0]), Reg::disasm(source_regs[0])); + } + + void evaluate(aisa::Wires &w) const override + { + w.destination_vals = w.source_vals; + } + }; + + struct StepMoveImmediate : public aisa::Step { + aisa::regval_t x; + + StepMoveImmediate(aisa::regnum_t q, aisa::regval_t x) + : x(x) + { + destination_regs.resize(1); + destination_regs[0] = q; + } + + std::string disasm(const aisa::Wires *w) const override + { + if (w) + return fmt::format("{}({}) <- {}", Reg::disasm(destination_regs[0]), w->destination_vals[0], x); + return fmt::format("{} <- {}", Reg::disasm(destination_regs[0]), x); + } + + void evaluate(aisa::Wires &w) const override + { + w.destination_vals.resize(1); + w.destination_vals[0] = x; + } + }; + + template struct StepSpawn : public aisa::Step { + void evaluate(aisa::Wires &w) const override + { + w.new_task = {std::make_unique(), 0}; + } + + std::string disasm(const aisa::Wires *w) const override + { + return fmt::format("spawn"); + } + }; + + template struct StepStore : public aisa::Step { + StepStore(aisa::regnum_t a, aisa::regnum_t d) + { + source_regs.resize(2); + source_regs[0] = a; + source_regs[1] = d; + + mop = aisa::MOp::STORE; + } + + std::string disasm(const aisa::Wires *w) const override + { + if (w) + return fmt::format("[{}({})] <- {}({})", Reg::disasm(source_regs[0]), w->source_vals[0], Reg::disasm(source_regs[1]), w->source_vals[1]); + return fmt::format("[{}] <- {}", Reg::disasm(source_regs[0]), Reg::disasm(source_regs[1])); + } + + aisa::MemInfo meminfo(const aisa::Wires &w) const override + { + aisa::MemInfo mi; + mi.physical_addr = w.source_vals[0] * WORD; + mi.size = WORD; + return mi; + } + + void evaluate(aisa::Wires &w) const override + { + w.memory_val.resize(WORD); + for (unsigned int i = 0; i < WORD; ++i) + w.memory_val[i] = w.source_vals[1] >> (8 * i); + } + }; + + template struct TaskFib : public aisa::Task { + TaskFib() + { + environment = Reg::ENV_FIB; + } + + std::string disasm() const override + { + return "fib"; + } + + std::optional, aisa::regval_t>> step(aisa::regval_t env) const override + { + switch (env) { + case 0: return {{std::make_unique>(Reg::A, Reg::PC), env+1}}; + case 1: return {{std::make_unique(Reg::PC, Reg::PC, 1), env+1}}; + case 2: return {{std::make_unique>(Reg::B, Reg::PC), env+1}}; + case 3: return {{std::make_unique(Reg::AREG, Reg::PC, 1), env+1}}; + case 4: return {{std::make_unique(Reg::Q, Reg::A, Reg::B), env+1}}; + case 5: return {{std::make_unique>(Reg::AREG, Reg::Q), env+1}}; + } + + return {}; + } + }; + + template struct TaskTop : public aisa::Task { + TaskTop() + { + environment = Reg::ENV_TOP; + } + + std::string disasm() const override + { + return "top"; + } + + std::optional, aisa::regval_t>> step(aisa::regval_t env) const override + { + switch (env) { + case 0: return {{std::make_unique(Reg::PC, 0), env+1}}; + case 1: return {{std::make_unique(Reg::AREG, 0), env+1}}; + case 2: return {{std::make_unique(Reg::ATMP, 0), env+1}}; + case 3: return {{std::make_unique>(Reg::AREG, Reg::ATMP), env+1}}; + case 4: return {{std::make_unique(Reg::AREG, 1), env+1}}; + case 5: return {{std::make_unique(Reg::ATMP, 1), env+1}}; + case 6: return {{std::make_unique>(Reg::AREG, Reg::ATMP), env+1}}; + case 7: return {{std::make_unique>>(), env}}; + } + + return {}; + } + }; + + template struct Fib : public aisa::ISA { + std::pair, aisa::regval_t> initial_task() const override + { + auto t = std::make_unique>(); + return {std::move(t), 0}; + } + }; + +} -- cgit v1.2.3