From eb3fd68203fee7c63245c702914c2acd3332d65a Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Thu, 22 Sep 2022 11:29:07 -0700 Subject: Initial commit. --- backend/regfile.h | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 backend/regfile.h (limited to 'backend/regfile.h') diff --git a/backend/regfile.h b/backend/regfile.h new file mode 100644 index 0000000..276504c --- /dev/null +++ b/backend/regfile.h @@ -0,0 +1,132 @@ +#pragma once + +#include + +#include "frontend/decode.h" +#include "infra/port.h" +#include "inst.h" +#include "memory/dram.h" + +namespace backend { + struct regfile : public infra::sim { + infra::port *decode_restartp = nullptr; + + infra::port instp; + infra::port *execp = nullptr; + infra::port writebackp; + infra::port *storep = nullptr; + + unsigned int generation_up = 0; + unsigned int generation_down = 0; + + std::array regs; + std::array hazards; + std::uint64_t pc = 0; + + regfile() { + regs.fill(0); + hazards.fill(false); + } + + void clock() { + if (writebackp.can_read() && storep->can_write()) { + auto i = writebackp.read(); + if (i.generation == generation_down) { + pte(i.transaction, "W", fmt::format("writeback gen={} pc={:x}", generation_down, pc)); + auto old_pc = pc; + pc = i.linear_next_pc; + switch (i.field[OPCODE]) { + case OP_JUMP_ABS_IF_ZERO: + case OP_JUMP_ABS_IF_NONZERO: + pte(i.transaction, "", fmt::format("jump to {:x}", i.result.value())); + pc = i.result.value(); + break; + case OP_EMIT: + pte(i.transaction, "*", fmt::format("emit {}", i.result.value())); + break; + case OP_STORE: + { + memory::dram::command c; + c.transaction = i.transaction; + c.line_address = i.field[SRC1] >> memory::LINE_BYTES_LOG2; + c.write = true; + c.mask.fill(false); + auto offset = i.field[SRC1] & memory::LINE_BYTE_OFFSET_MASK; + pte(i.transaction, "", fmt::format("store [{:x}]={:x} offset={:x}", i.field[SRC1], i.field[SRC2], offset)); + for (unsigned int j = 0; j < sizeof(i.field[SRC2]); ++j) { + c.mask[offset + j] = true; + c.data[offset + j] = (i.field[SRC2] >> (8 * j)) & 0xff; + } + storep->write(std::move(c)); + } + break; + default: + pte(i.transaction, "", fmt::format("wb r{}={:x}", i.field[FLAGS_DST] % regs.size(), i.result.value())); + regs[i.field[FLAGS_DST] % regs.size()] = i.result.value(); + hazards[i.field[FLAGS_DST] % regs.size()] = false; + break; + } + if (!i.predicted_next_pc.has_value() || pc != i.predicted_next_pc.value()) { + pte(i.transaction, "", "restart due to pc misprediction"); + frontend::decode::restart dr; + dr.new_generation = ++generation_up; + dr.new_pc = pc; + dr.from_pc = old_pc; + decode_restartp->write(std::move(dr)); + hazards.fill(false); + ++generation_down; + } + } + } + + if (instp.can_read() && execp->can_write() && !writebackp.can_read()) { + auto i = instp.peek(); + if (i.generation == generation_up) { + bool hazard = false; + if (!(i.field[FLAGS_DST] & FLAG_IMM1)) + hazard |= hazards[i.field[SRC1] % regs.size()]; + if (!(i.field[FLAGS_DST] & FLAG_IMM2)) + hazard |= hazards[i.field[SRC2] % regs.size()]; + switch (i.field[OPCODE]) { + case OP_JUMP_ABS_IF_ZERO: + case OP_JUMP_ABS_IF_NONZERO: + case OP_EMIT: + case OP_STORE: + break; + default: + hazard |= hazards[i.field[FLAGS_DST] % regs.size()]; + break; + } + if (!hazard) { + auto i = instp.read(); + if (!(i.field[FLAGS_DST] & FLAG_IMM1)) { + auto x = regs[i.field[SRC1] % regs.size()]; + pte(i.transaction, "", fmt::format("rf1[{}]={:x}", i.field[SRC1] % regs.size(), x)); + i.field[SRC1] = x; + } + if (!(i.field[FLAGS_DST] & FLAG_IMM2)) { + auto x = regs[i.field[SRC2] % regs.size()]; + pte(i.transaction, "", fmt::format("rf2[{}]={:x}", i.field[SRC2] % regs.size(), x)); + i.field[SRC2] = x; + } + pte(i.transaction, "R", fmt::format("read gen={}", generation_up)); + i.generation = generation_down; + switch (i.field[OPCODE]) { + case OP_JUMP_ABS_IF_ZERO: + case OP_JUMP_ABS_IF_NONZERO: + case OP_EMIT: + case OP_STORE: + break; + default: + hazards[i.field[FLAGS_DST] % regs.size()] = true; + break; + } + execp->write(std::move(i)); + } + } else { + instp.discard(); + } + } + } + }; +} -- cgit v1.2.3