Implement load-forwarding in register file
MODIFY
src/processors/RISC-V/rv5s/rv5s.h
src/processors/RISC-V/rv5s/rv5s.h
@@ -89,8 +89,8 @@ public:
// -----------------------------------------------------------------------
// Branch
idex_reg->br_op_out >> branch->comp_op;
- idex_reg->r1_out >> branch->op1;
- idex_reg->r2_out >> branch->op2;
+ reg1_fw_src->out >> branch->op1;
+ reg2_fw_src->out >> branch->op2;
branch->res >> *br_and->in[0];
idex_reg->do_br_out >> *br_and->in[1];
@@ -246,7 +246,7 @@ public:
}
// Design subcomponents
- SUBCOMPONENT(registerFile, RegisterFile);
+ SUBCOMPONENT(registerFile, RegisterFile<true>);
SUBCOMPONENT(alu, ALU);
SUBCOMPONENT(control, Control);
SUBCOMPONENT(immediate, Immediate);

MODIFY
src/processors/RISC-V/rv5swof/rv5swof.h
src/processors/RISC-V/rv5swof/rv5swof.h
@@ -199,7 +199,7 @@ public:
}
// Design subcomponents
- SUBCOMPONENT(registerFile, RegisterFile);
+ SUBCOMPONENT(registerFile, RegisterFile<true>);
SUBCOMPONENT(alu, ALU);
SUBCOMPONENT(control, Control);
SUBCOMPONENT(immediate, Immediate);

MODIFY
src/processors/RISC-V/rv_registerfile.h
src/processors/RISC-V/rv_registerfile.h
@@ -10,6 +10,7 @@ namespace vsrtl {
namespace core {
using namespace Ripes;
+template <bool readBypass>
class RegisterFile : public Component {
public:
SetGraphicsType(ClockedComponent);
@@ -28,9 +29,43 @@ public:
// Reads
r1_addr >> _rd1_mem->addr;
r2_addr >> _rd2_mem->addr;
+
+ /** If read bypassing is enabled, we may read the next-state register value in the current state.
+ * Also note that, given that the RegisterFile is of type Component, all inputs must be propagated before
+ * outputs are propagated. Thus, we are sure to have received the next-state write address when we clock the
+ * output ports. This would >not< be the case if the RegisterFile was a clocked component.
+ */
+ if constexpr (readBypass) {
+ r1_out << [=] {
+ const int rd_idx = r1_addr.uValue();
+ if (rd_idx == 0)
+ return static_cast<unsigned>(0);
+
+ const int wr_idx = wr_addr.uValue();
+ if (wr_en.uValue() && wr_idx == r1_addr.uValue()) {
+ return data_in.uValue();
+ } else {
+ return _rd1_mem->data_out.uValue();
+ }
+ };
+
+ r2_out << [=] {
+ const int rd_idx = r2_addr.uValue();
+ if (rd_idx == 0)
+ return static_cast<unsigned>(0);
+
+ const int wr_idx = wr_addr.uValue();
+ if (wr_en.uValue() && wr_idx == r2_addr.uValue()) {
+ return data_in.uValue();
+ } else {
+ return _rd2_mem->data_out.uValue();
+ }
+ };
+ } else {
_rd1_mem->data_out >> r1_out;
_rd2_mem->data_out >> r2_out;
}
+ }
SUBCOMPONENT(_wr_mem, TYPE(WrMemory<RV_REGS_BITS, RV_REG_WIDTH, false>));
SUBCOMPONENT(_rd1_mem, TYPE(RdMemory<RV_REGS_BITS, RV_REG_WIDTH, false>));

MODIFY
src/processors/RISC-V/rvss/rvss.h
src/processors/RISC-V/rvss/rvss.h
@@ -113,7 +113,7 @@ public:
}
// Design subcomponents
- SUBCOMPONENT(registerFile, RegisterFile);
+ SUBCOMPONENT(registerFile, RegisterFile<false>);
SUBCOMPONENT(alu, ALU);
SUBCOMPONENT(control, Control);
SUBCOMPONENT(immediate, Immediate);

Implement load-forwarding in register file