Flow Control
Ziren enforces MIPS32r2 control flow verification via dedicated Branch and Jump chips, ensuring precise execution of program control instructions.
Branch Chip
MIPS branch instructions execute conditional jumps through register comparisons (BEQ/BNE for equality, BGTZ/BLEZ etc. for sign checks). They calculate targets using 16-bit offsets shifted left twice (enabling ±128KB jumps) and feature a mandatory branch delay slot that always executes the next instruction—simplifying pipelining by allowing compiler-controlled optimizations.
Structure Description
Branch chip uses columns to record the following information.
- Control Flow Management
- Tracks current and future program counter states across sequential and branching execution paths (
pc, next_pc,target_pc,next_next_pc
). - Implements 32-bit address validation through dedicated range-checking components(
next_pc_range_checker, target_pc_range_checker, next_next_pc_range_checker
).
- Tracks current and future program counter states across sequential and branching execution paths (
- Operand Handling System
- Stores three register/immediate values following MIPS three-operand convention (
op_a_value, op_b_value, op_c_value
).
- Stores three register/immediate values following MIPS three-operand convention (
- Instruction Semantics Encoding
- Embeds five mutually exclusive flags corresponding to MIPS branch opcodes (
is_beq, is_bltz, is_blez, is_bgtz, is_bgez
).
- Embeds five mutually exclusive flags corresponding to MIPS branch opcodes (
- Execution State Tracking
- Maintains dual execution path indicators for taken/not-taken branch conditions(
is_branching, not_branching
).
- Maintains dual execution path indicators for taken/not-taken branch conditions(
- Comparison Logic Core
- Evaluates signed integer relationships between primary operands, generating equality, greater-than, and less-than condition flags (
a_eq_b, a_gt_b, a_lt_b
).
- Evaluates signed integer relationships between primary operands, generating equality, greater-than, and less-than condition flags (
Major Constraints
We use the following key constraints to validate the branch chip:
-
Program Counter Validation
- Range check for all PC values (
pc
,next_pc
,target_pc
,next_next_pc
, etc.). - Branching case:
next_pc
must equaltarget_pc
. - Non-branching case:
next_next_pc
must equalnext_pc + 4
. is_branching
andnot_branching
are mutually exclusive and exhaustive for real instructions.
- Range check for all PC values (
-
Instruction Validity
- Exactly one branch instruction flag must be active per row (
1 = is_beq + ... + is_bgtz
). - Instruction flags are strictly boolean values (0/1).
- Opcode validity is enforced through linear combination verification.
- Exactly one branch instruction flag must be active per row (
-
Branch Condition Logic
is_branching
andnot_branching
consistent whti condition flags.
Jump Chip
MIPS jump instructions force unconditional PC changes via absolute or register-based targets.They calculate 256MB-range addresses by combining PC's upper bits with 26-bit immediates or use full 32-bit register values. All jumps enforce a mandatory delay slot executing the next instruction—enabling compiler-driven pipeline optimizations without speculative execution.
Structure Description
Jump chip uses columns to record the following information:
-
Control Flow Management
- Tracks current program counter and jump targets (
pc, next_pc, target_pc
). - Implements 32-bit address validation via dedicated range checkers (
next_pc_range_checker, target_pc_range_checker, op_a_range_checker
).
- Tracks current program counter and jump targets (
-
Operand System
- Stores three operands for jump address calculation (
op_a_value, op_b_value, op_c_value
).
- Stores three operands for jump address calculation (
-
Instruction Semantics
- Embeds three mutually exclusive jump-type flags (
is_jump, is_jumpi, is_jumpdirect
).
- Embeds three mutually exclusive jump-type flags (
Major Constraints
We use the following key constraints to validate the jump chip:
- Instruction Validity
-
Exactly one jump instruction flag must be active per row:
#![allow(unused)] fn main() { 1 = is_jump + is_jumpi + is_jumpdirect }
-
Instruction flags are strictly boolean (0/1).
-
Opcode validity enforced through linear combination verification:
#![allow(unused)] fn main() { opcode = is_jump*JUMP + is_jumpi*JUMPI + is_jumpdirect*JUMPDIRECT }
-
- Return Address Handling
- Return address is saved in op_a_value:
op_a_value is saved into op_a register only when 'op_a_0 = 0'(checked in CpuChip)#![allow(unused)] fn main() { op_a_value = next_pc + 4 }
- Return address is saved in op_a_value:
- Range Checking
- All critical values (
op_a_value, next_pc, target_pc
) are range-checked, ensuring values are valid 32-bit words.
- All critical values (
- PC Transition Logic
- Target_pc calculation via ALU operation:
#![allow(unused)] fn main() { send_alu( Opcode::ADD, target_pc = next_pc + op_b_value, is_jumpdirect ) }
- Direct jumps (
is_jumpdirect
) use immediate operand addition.
- Target_pc calculation via ALU operation: