#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)); } }