From 68bdebd8cae39c30acc384664faa136aeaa9bb84 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sat, 5 Nov 2022 16:59:17 -0700 Subject: Add initial uarch model --- uarch/core.cpp | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 uarch/core.cpp (limited to 'uarch/core.cpp') diff --git a/uarch/core.cpp b/uarch/core.cpp new file mode 100644 index 0000000..34f422a --- /dev/null +++ b/uarch/core.cpp @@ -0,0 +1,140 @@ +#include +#include + +#include "uarch/core.h" + +fetch_stage::fetch_stage(core &c) + : c(c) + , pc(c.checker.pc) +{ } + +decode_stage::decode_stage(core &c) + : c(c) + , acc(c.checker.acc) + , link(c.checker.link) + , mq(c.checker.mq) + , pc(c.checker.pc) + , ctlregs(c.checker.ctlregs) + , icount(c.checker.icount) +{ } + +void fetch_stage::clock() { + if (c.fetch_restarto.has_value()) { + auto &r = *c.fetch_restarto; + pte(r.tr, "!"); + gen = r.new_gen; + pc = r.new_pc; + didrestart = true; + c.fetch_restarto.reset(); + } + + if (c.fetch_bundlep.can_write()) { + fetch_bundle b; + b.tr = infra::pt::toplevel(); + b.gen = gen; + b.pc = pc; + b.word = c.mem.fetch(pc); + if (didrestart) + infra::pt::event(b.tr, ">", now-1, ""); + pte(b.tr, "F"); + c.fetch_bundlep.write(std::move(b)); + pc = (pc & 070000) | ((pc + 1) & 007777); + didrestart = false; + } +} + +void decode_stage::clock() { + bool progress = ctlregs[HALTED]; + + if (!ctlregs[HALTED] && c.fetch_bundlep.can_read()) { + auto b = c.fetch_bundlep.read(); + + if (b.gen != gen) + goto bail_out; + + if (b.pc != pc) { + pte(b.tr, "~"); + fetch_restart r; + r.tr = b.tr; + r.new_gen = ++gen; + r.new_pc = pc; + c.fetch_restarto = std::move(r); + goto bail_out; + } + + progress = true; + + pte(b.tr, "E"); + + inst = decode(ctlregs[FLAGS], + pc, + c.mem.fetch(pc), + interrupt); + auto next_pc = inst.next_pc; + + if (inst.need_indirect_load) { + auto addr = c.mem.fetch(inst.init_address.value()); + if (inst.need_autoinc_store) { + addr = (addr + 1) & 07777; + c.mem.store(*inst.init_address, addr); + } + auto df = (ctlregs[FLAGS] & FLAG_DF) >> FLAG_DF_SHIFT; + inst.final_address = (df << 12) | addr; + } else { + assert(!inst.need_autoinc_store); + } + + pte(b.tr, "", inst.disasm()); + + if (inst.need_exec_load) + inst.data = c.mem.fetch(inst.final_address.value()); + + if (inst.need_read_acc) + inst.acc = acc; + if (inst.need_read_link) + inst.link = link; + if (inst.need_read_mq) + inst.mq = mq; + if (inst.read_ctlreg.has_value()) + inst.ctlval = ctlregs[*inst.read_ctlreg]; + + inst.execute(); + + if (inst.need_write_acc) + acc = inst.acc.value(); + if (inst.need_write_link) + link = inst.link.value(); + if (inst.need_write_mq) + mq = inst.mq.value(); + if (inst.write_ctlreg.has_value()) + ctlregs[*inst.write_ctlreg] = inst.ctlval.value(); + + if (inst.need_exec_store) + c.mem.store(inst.final_address.value(), inst.data.value()); + + assert(inst.next_pc == next_pc || inst.possibly_redirects); + pc = inst.next_pc; + } +bail_out: + + if (progress) + interrupt = c.system.interact(icount++, ctlregs); + + if (c.checker.icount != icount) { + assert(c.checker.icount + 1 == icount); + + c.checker.execute(); + assert(c.checker.icount == icount); + std::cerr << fmt::format("icount={:} pc={:05o} checkerpc={:05o}\n", icount, pc, c.checker.pc); + assert(pc == c.checker.pc); + assert(acc == c.checker.acc); + assert(link == c.checker.link); + assert(mq == c.checker.mq); + assert(ctlregs == c.checker.ctlregs); + if (inst.init_address.has_value()) + assert(c.mem.fetch(*inst.init_address) == c.checker.mem.fetch(*inst.init_address)); + if (inst.final_address.has_value()) + assert(c.mem.fetch(*inst.final_address) == c.checker.mem.fetch(*inst.final_address)); + assert(c.mem.fetch(pc) == c.checker.mem.fetch(pc)); + } +} -- cgit v1.2.3