Skip to content

§ 4.5.4. Execute

RV32IBaselineExecuteStage uses the operands captured in ID/EX. It has no register-file access, forwarding path, or internal sequential state.

Component Description Structural Behavioral
RV32IBaselineExecuteStage Shared-ALU computation, target resolution, EX/MEM packet Yes Yes

IO pins

Pin Direction Width Description
IN_VALID Input 1 ID/EX validity
IN_PC, IN_INSTRUCTION, IN_FETCH_STATUS Input 32 each Instruction identity and fetch status
IN_RS1_VALUE, IN_RS2_VALUE, IN_IMMEDIATE Input 32 each Captured operands and immediate
IN_CONTROL, IN_REGISTER_ADDRESSES Input 32 each Decoded control and register addresses
OUT_VALID Output 1 Forwarded validity
OUT_PC, OUT_INSTRUCTION, OUT_FETCH_STATUS, OUT_CONTROL, OUT_REGISTER_ADDRESSES Output 32 each Forwarded packet fields
OUT_ALU_RESULT, OUT_STORE_DATA Output 32 each ALU result and captured RS2
OUT_PC_PLUS_4, OUT_NEXT_PC Output 32 each Link/fallthrough value and resolved next PC
OUT_EXECUTION_STATUS Output 32 Bit 0: selected target misaligned; other bits zero
TERMINAL, CONTROL_FLOW Output 1 each Valid terminal instruction; valid branch/jump awaiting resolution

Behavior

Operand selectors and ALU_OP follow the single-cycle Execute datapath. Arithmetic, logic, shifts, comparisons, and address calculations use the same ALU32. Branch comparisons use its comparison outputs. A separate PC+immediate adder works concurrently with branch comparison; JAL and JALR instead reuse the main ALU for their target addition. JALR clears target bit 0.

NEXT_PC is the selected target for a jump or taken branch, otherwise PC+4. Only a selected misaligned target sets EXECUTION_STATUS. An untaken branch with a numerically misaligned candidate target does not trap.

This packet contract does not carry PC+4 in ID/EX, so Execute recomputes it with one incrementer. It is not a second ALU. STORE_DATA always equals the old captured RS2, never a newly written register value.

TERMINAL combines incoming terminal reasons with selected-target misalignment, qualified by IN_VALID. CONTROL_FLOW is asserted for every valid branch/jump, including untaken branches. The controller resumes Fetch only after this resolution cycle.

C++ example

The shared Packet type carries instruction fields. early_terminal checks validity, the defined fetch/execution status bits, legality, halt, and trap. The arithmetic helper includes ALU32's reserved-opcode zero result.

inline uint32_t alu(unsigned op,uint32_t a,uint32_t b) {
    const unsigned sh=b&31;
    switch(op) {
        case ALU32Op::ADD:return a+b; case ALU32Op::SUB:return a-b;
        case ALU32Op::AND:return a&b; case ALU32Op::OR:return a|b; case ALU32Op::XOR:return a^b;
        case ALU32Op::SLL:return a<<sh; case ALU32Op::SRL:return a>>sh;
        case ALU32Op::SRA:return sh&&(a&0x80000000u)?(a>>sh)|(~uint32_t{0}<<(32-sh)):a>>sh;
        case ALU32Op::SLT:return int32_t(a)<int32_t(b); case ALU32Op::SLTU:return a<b;
        case ALU32Op::PASS_A:return a; case ALU32Op::PASS_B:return b; default:return 0;
    }
}
inline StageResult execute(Packet p) {
    const auto as=bits(p.control,27,3),bs=bits(p.control,29,3);
    const auto op=bits(p.control,22,31),branch=bits(p.control,13,7),jump=bits(p.control,16,3);
    const uint32_t a=as==0?p.rs1_value:as==1?p.pc:0;
    const uint32_t b=bs==0?p.rs2_value:bs==1?p.immediate:0;
    p.alu_result=alu(op,a,b); p.store_data=p.rs2_value; p.pc_plus_4=p.pc+4;
    const bool compare=op==ALU32Op::SUB||op==ALU32Op::SLT||op==ALU32Op::SLTU;
    const bool eq=compare&&a==b,lt=compare&&int32_t(a)<int32_t(b),ltu=compare&&a<b;
    const bool conditions[]{false,eq,!eq,lt,!lt,ltu,!ltu,false};
    const bool taken=jump||conditions[branch];
    const auto target=jump==0?p.pc+p.immediate:jump==1?p.alu_result:jump==2?p.alu_result&~1u:0;
    p.next_pc=taken?target:p.pc_plus_4;
    p.execution_status=taken&&bool(target&3);
    return {p,early_terminal(p),p.valid&&(branch||jump)};
}

Implementation

Structural implementation

DATAPATH reuses RV32ISingleCycleExecuteStage; NEXT_PC reuses RV32ISingleCycleNextPCStage. A structural IncrementBy4, field/status rewiring, and the shared PACKET_STATUS group complete the stage. There is exactly one CPU-specific ALU32 datapath and no separate RS1+immediate target adder.

Behavioral implementation

executePacket evaluates the same binary ALU, branch conditions, targets, and status without a simulator-owned register. The registered family is rv32i.baseline.execute. A catalog-selected behavioral stage uses gate-derived per-path delays and, where available, a delay twin for the current values. Compare values after settling; the checked equivalence scope is binary inputs.

Examples

The rows cover arithmetic, both branch outcomes, selected-target alignment, JAL/JALR target reuse, signed/unsigned comparison, and invalid-slot qualification.

All 11 recorded rows of RV32IBaselineExecuteStageTest, 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 IN_CONTROLInput · 32 bit IN_FETCH_STATUSInput · 32 bit IN_IMMEDIATEInput · 32 bit IN_INSTRUCTIONInput · 32 bit IN_PCInput · 32 bit IN_REGISTER_ADDRESSESInput · 32 bit IN_RS1_VALUEInput · 32 bit IN_RS2_VALUEInput · 32 bit IN_VALIDInput · 1 bit CONTROL_FLOWExpected output · 1 bit OUT_ALU_RESULTExpected output · 32 bit OUT_CONTROLExpected output · 32 bit OUT_EXECUTION_STATUSExpected output · 32 bit OUT_FETCH_STATUSExpected output · 32 bit OUT_INSTRUCTIONExpected output · 32 bit OUT_NEXT_PCExpected output · 32 bit OUT_PCExpected output · 32 bit OUT_PC_PLUS_4Expected output · 32 bit OUT_REGISTER_ADDRESSESExpected output · 32 bit OUT_STORE_DATAExpected output · 32 bit OUT_VALIDExpected output · 1 bit TERMINALExpected output · 1 bit
#0initial-inputs33 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#1addi65 0x20001283 0x00000000 0x00000005 0x00000000 0x00000100 0x00000000 0x00000007 0xDEADBEEF 1 0 0x0000000C not checked not checked not checked not checked 0x00000104 not checked 0x00000104 not checked 0xDEADBEEF not checked 0
#2beq-not-taken103 0x00403181 0x00000000 0x00000008 0x00000000 0x00000100 0x00000000 0x00000007 0x00000008 1 1 not checked not checked 0x00000000 not checked not checked 0x00000104 not checked not checked not checked not checked not checked not checked
#3beq-taken145 0x00403181 0x00000000 0x00000008 0x00000000 0x00000100 0x00000000 0x00000007 0x00000007 1 not checked not checked not checked not checked not checked not checked 0x00000108 not checked not checked not checked not checked not checked not checked
#4taken-misaligned159 0x00403181 0x00000000 0x00000002 0x00000000 0x00000100 0x00000000 0x00000007 0x00000007 1 not checked not checked not checked 0x00000001 not checked not checked not checked not checked not checked not checked not checked not checked 1
#5untaken-misaligned-target-is-harmless195 0x00403181 0x00000000 0x00000002 0x00000000 0x00000100 0x00000000 0x00000007 0x00000008 1 not checked not checked not checked 0x00000000 not checked not checked not checked not checked not checked not checked not checked not checked 0
#6jal-shares-alu226 0x28011603 0x00000000 0x00000008 0x00000000 0x00000100 0x00000000 0x00000007 0x00000008 1 not checked 0x00000108 not checked not checked not checked not checked 0x00000108 not checked not checked not checked not checked not checked not checked
#7jalr-clears-bit-zero260 0x20021683 0x00000000 0x00000000 0x00000000 0x00000100 0x00000000 0x00000109 0x00000008 1 not checked 0x00000109 not checked not checked not checked not checked 0x00000108 not checked not checked not checked not checked not checked not checked
#8signed-branch294 0x00407181 0x00000000 0x00000008 0x00000000 0x00000100 0x00000000 0xFFFFFFFF 0x00000001 1 not checked not checked not checked not checked not checked not checked 0x00000108 not checked not checked not checked not checked not checked not checked
#9unsigned-branch303 0x0040B181 0x00000000 0x00000008 0x00000000 0x00000100 0x00000000 0xFFFFFFFF 0x00000001 1 not checked not checked not checked not checked not checked not checked 0x00000104 not checked not checked not checked not checked not checked not checked
#10invalid-slot308 0x0040B181 0x00000003 0x00000008 0x00000000 0x00000100 0x00000000 0xFFFFFFFF 0x00000001 0 0 not checked 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.

Open Execute stage

Tests

RV32IBaselineExecuteStageTest compares both implementations; program cases exercise the complete instruction set supported by the reference. Sources: RV32IBaselinePipeline.cpp, RV32IBaselinePipelineBehavioral.cpp.