§ 4.5.3. Decode and Register Read¶
RV32IBaselineDecodeStage decodes IF/ID and reads the architectural register file. Writes come from the older instruction in Writeback, not from the instruction currently being decoded.
| Component | Description | Structural | Behavioral |
|---|---|---|---|
RV32IBaselineDecodeStage |
Instruction decoding, two register reads, independent WB write port | Yes | Yes |
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
CLK, RST |
Input | 1 each | Register-file clock and asynchronous reset |
IN_VALID |
Input | 1 | IF/ID validity |
IN_PC, IN_INSTRUCTION, IN_FETCH_STATUS |
Input | 32 each | IF/ID payload |
REGISTER_WRITE, WB_RD, WB_VALUE |
Input | 1, 5, 32 | Authorized WB write, its destination, its value |
OUT_VALID |
Output | 1 | Incoming validity |
OUT_PC, OUT_INSTRUCTION, OUT_FETCH_STATUS |
Output | 32 each | Forwarded packet fields |
OUT_RS1_VALUE, OUT_RS2_VALUE, OUT_IMMEDIATE |
Output | 32 each | Current source values and sign-extended immediate |
OUT_CONTROL, OUT_REGISTER_ADDRESSES |
Output | 32 each | Packed control and register addresses |
TERMINAL, CONTROL_FLOW |
Output | 1 each | Valid packet needs precise stopping; valid branch/JAL/JALR |
Behavior¶
The decoder uses the instruction decoding rules. The register file resets to zero, writes a nonzero WB_RD on an enabled rising edge, and ignores writes to x0. Both source reads are combinational.
There is no writeback bypass. Before a writeback edge the old register value remains on the read port. A consumer therefore stays in IF/ID until its producer has passed Writeback. ID/EX captures source operands only when control releases the dependency stall.
TERMINAL is IN_VALID && (fetch fault || PC misalignment || illegal instruction || halt request || trap request). CONTROL_FLOW is IN_VALID && (nonzero branch type || nonzero jump type). These are requests to pipeline control, not immediate architectural state changes. All ordinary decoder outputs are still computed for an invalid packet.
C++ example¶
The instruction decoder and control encoder below are the same reusable, non-simulator functions documented in 4.3. Packet fields and packed encodings are defined in 4.5.1. The register update uses WB_RD independently of the decoded RD.
struct Decode {
std::array<uint32_t,32> registers{};
bool previous_clock=false;
StageResult evaluate(Packet p, bool clk, bool reset, bool register_write,
unsigned wb_rd, uint32_t wb_value) {
if(reset) registers.fill(0);
else if(!previous_clock && clk && register_write && (wb_rd&31))
registers[wb_rd&31]=wb_value;
previous_clock=clk;
const auto d=rv32i::RV32IDecoder::decode(p.instruction);
const auto c=rv32i::RV32IControl::fromDecoded(d);
p.control=packControl(c); p.addresses=packAddresses(d.rs1,d.rs2,d.rd);
p.immediate=uint32_t(d.immediate);
p.rs1_value=d.rs1?registers[d.rs1]:0;
p.rs2_value=d.rs2?registers[d.rs2]:0;
const bool terminal=p.valid&&((p.fetch_status&3)||!c.legal||c.halt||c.trap);
return {p,terminal,p.valid&&(unsigned(c.branch)||unsigned(c.jump))};
}
};
Implementation¶
Structural implementation¶
CONTROL is RV32IDecodeControlUnit and REGISTER_FILE is the FF-backed RegisterFile32x32. Rewire components form CONTROL, REGISTER_ADDRESSES, and forwarded packet fields. PACKET_STATUS groups the shared terminal/control-flow gates; Decode supplies zero execution status because target calculation has not occurred yet. No forwarding selector or WB_BYPASS component is instantiated.
Behavioral implementation¶
BehavioralDecode uses the shared BehavioralStage implementation to store the 32 registers and their history, update the WB destination on a known rising edge, then decode and read sources. Both forms expose architectural register-state access for core snapshots and program verification, and share rv32i.baseline.decode. Reset precedes binary equivalence checks.
Examples¶
The scenario writes x1 while decoding an instruction whose destination is x7, checks old-value reads before the edge, checks x0, and exercises branch/terminal qualification.
All 16 recorded rows of RV32IBaselineDecodeStageTest, in checkpoint order. Outputs are test expectations verified against the simulation. Time is the absolute settled checkpoint time in simulator units, not milliseconds or CPU cycles.
Default scenario profile: baseline-structural-stages / structural (f72af366c5dca6eb). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | CLKInput · 1 bit |
IN_FETCH_STATUSInput · 32 bit |
IN_INSTRUCTIONInput · 32 bit |
IN_PCInput · 32 bit |
IN_VALIDInput · 1 bit |
REGISTER_WRITEInput · 1 bit |
RSTInput · 1 bit |
WB_RDInput · 5 bit |
WB_VALUEInput · 32 bit |
CONTROL_FLOWExpected output · 1 bit |
OUT_CONTROLExpected output · 32 bit |
OUT_FETCH_STATUSExpected output · 32 bit |
OUT_IMMEDIATEExpected output · 32 bit |
OUT_INSTRUCTIONExpected output · 32 bit |
OUT_PCExpected output · 32 bit |
OUT_REGISTER_ADDRESSESExpected output · 32 bit |
OUT_RS1_VALUEExpected output · 32 bit |
OUT_RS2_VALUEExpected output · 32 bit |
OUT_VALIDExpected output · 1 bit |
TERMINALExpected output · 1 bit |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
#0initial-inputs | 16 | 0 |
0x00000000 |
0x00000000 |
0x00000000 |
0 |
0 |
1 |
0x00 |
0x00000000 |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked |
#1reset | 17 | 0 |
0x00000000 |
0x00000000 |
0x00000000 |
0 |
0 |
1 |
0x00 |
0x00000000 |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked |
#2independent-write-destination | 36 | 0 |
0x00000000 |
0x002083B3 |
0x00000000 |
1 |
1 |
0 |
0x01 |
0x00000007 |
not checked | not checked | not checked | not checked | not checked | not checked | 0x00001C41 |
0x00000000 |
not checked | not checked | 0 |
#3write-x1-not-decoded-x7 | 52 | 1 |
0x00000000 |
0x002083B3 |
0x00000000 |
1 |
1 |
0 |
0x01 |
0x00000007 |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | 0x00000007 |
0x00000000 |
not checked | not checked |
#4no-high-clock-rewrite | 68 | 1 |
0x00000000 |
0x002083B3 |
0x00000000 |
1 |
1 |
0 |
0x01 |
0x00000009 |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | 0x00000007 |
not checked | not checked | not checked |
#5x2-setup | 69 | 0 |
0x00000000 |
0x002083B3 |
0x00000000 |
1 |
1 |
0 |
0x02 |
0x0000000B |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked |
#6write-x2 | 85 | 1 |
0x00000000 |
0x002083B3 |
0x00000000 |
1 |
1 |
0 |
0x02 |
0x0000000B |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | 0x0000000B |
not checked | not checked |
#7x0-setup | 101 | 0 |
0x00000000 |
0x00000013 |
0x00000000 |
1 |
1 |
0 |
0x00 |
0x0000000B |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked |
#8x0 | 117 | 1 |
0x00000000 |
0x00000013 |
0x00000000 |
1 |
1 |
0 |
0x00 |
0x0000000B |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | 0x00000000 |
not checked | not checked | not checked |
#9control-flow-99 | 135 | 1 |
0x00000000 |
0x00000063 |
0x00000000 |
1 |
0 |
0 |
0x00 |
0x0000000B |
1 |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | 0 |
#10control-flow-8388847 | 152 | 1 |
0x00000000 |
0x008000EF |
0x00000000 |
1 |
0 |
0 |
0x00 |
0x0000000B |
1 |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | 0 |
#11control-flow-32871 | 169 | 1 |
0x00000000 |
0x00008067 |
0x00000000 |
1 |
0 |
0 |
0x00 |
0x0000000B |
1 |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | 0 |
#12halt | 185 | 1 |
0x00000000 |
0x00100073 |
0x00000000 |
1 |
0 |
0 |
0x00 |
0x0000000B |
0 |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | 1 |
#13invalid-slot | 187 | 1 |
0x00000000 |
0x00100073 |
0x00000000 |
0 |
0 |
0 |
0x00 |
0x0000000B |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | 0 |
#14fetch-fault | 203 | 1 |
0x00000002 |
0x00000013 |
0x00000000 |
1 |
0 |
0 |
0x00 |
0x0000000B |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | 1 |
#15reserved-status-ignored | 208 | 1 |
0x80000000 |
0x00000013 |
0x00000000 |
1 |
0 |
0 |
0x00 |
0x0000000B |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | 0 |
Scroll within the table for all rows and pins. Buses use hexadecimal; values containing X/Z use MSB-first binary. Inputs show the declared values in effect at each checkpoint, including retained inputs. Sequential tests also replay preparation changes between checkpoints, such as lowering the clock. Use the matching checkpoint label in the simulation below.
Tests¶
RV32IBaselineDecodeStageTest compares both implementations. Program tests check the architectural register file at every retirement. Sources: RV32IBaselinePipeline.cpp, RV32IBaselinePipelineBehavioral.cpp.