Skip to content

4-State Simulation

Celox supports IEEE 1800-compliant 4-state simulation with X (unknown) propagation.

Representation Model

4-state values are represented as value/mask pairs. For each bit:

maskvalueMeaning
000
011
10Z (high-impedance)
11X (unknown)

Signals wider than 64 bits are split into chunks (i64 x N) and stored as a pair of value chunk arrays and mask chunk arrays (TransValue::FourState { values, masks }).

Z vs X Encoding

Both (v=0, m=1) (Z) and (v=1, m=1) (X) indicate uncertain bits. The distinction is preserved throughout the pipeline — no normalization is applied. Z literals like 8'hzz retain their Z encoding (v=0, m=1) through operations, and X literals retain (v=1, m=1).

The VCD writer distinguishes Z and X per-bit using the (mask, value) pair for correct waveform output.

X Propagation Rules

X (mask) propagation in each operation follows IEEE 1800 semantics.

Bitwise Operations

OperationMask computationNotes
a & b(ma | mb) & ~(~va & ~ma) & ~(~vb & ~mb)A known 0 cancels X
a | b(ma | mb) & ~(va & ~ma) & ~(vb & ~mb)A known 1 cancels X
a ^ bma | mbX if either operand is X

Shift Operations

ConditionMask computation
Shift amount is knownShift the mask by the shift amount
Shift amount contains XEntire result becomes all-X

Arithmetic and Comparison Operations

OperationMask computationNotes
+, -, *, /, %If either operand contains X, the entire result becomes all-XConservative propagation
==, !=, <, > etc.Same as above (1-bit result)

Mux (Ternary Operator)

ConditionBehavior
Selector is knownUse value/mask of the selected branch
Selector contains XConservative mask: OR of both branches' masks

Reduction Operations

OperationMask computation
& (reduction AND)If a known 0 exists, the result is a known 0; otherwise X
| (reduction OR)If a known 1 exists, the result is a known 1; otherwise X
^ (reduction XOR)If any bit is X, the result is X

SIR-Level Z Preservation

Two SIR instructions have dedicated 4-state handling to preserve Z (high-impedance) bits through the pipeline without converting them to X:

  • Mux(dst, cond, then_val, else_val): Selects the value/mask pair of the chosen branch. When cond has X/Z bits, the result is all-X. Unlike the previous AND/OR lowering pattern, this preserves exact Z bits of the selected branch.
  • Concat(dst, [msb..lsb]): Pure data movement concatenation. Preserves the value/mask of each part without modification, keeping Z bits intact.

These instructions replaced the earlier Shl+Or (for Concat) and Branch-based (for Mux) lowering patterns, which could convert Z to X through bitwise operations.

Boundary with 2-State Variables

When storing to a bit-type (2-state) variable, the mask is forcibly reset to 0 (post-store processing in memory.rs). This prevents unintended propagation of X through 2-state variables.

Test Coverage

4-state related tests are located in tests/four_state.rs. For detailed coverage status and plans for additional tests, see four_state_test_plan.md.