Skip to main content

Module soft_core_model

Module soft_core_model 

Source
Expand description

The cycle-accurate Rust model of benchmarks/silicon/soft_core.v — the executable spec of the LOGOS universal interpreter in silicon. Fetch/decode/execute over a chip-word program ([opcode:8][dst:8][a:8][b:8]; wide/float/heap ops per the doc on run_soft_core_typed), returning the Show sequence. This is the differential ORACLE the whole spatial-interpreter campaign checks against: compile_to_full_words -> run_soft_core_typed must equal compile::vm_outcome for every program, and the iverilog testbenches agree with it. Lifted here (from rtl.rs’s test module) so both the in-crate RTL tests and the logicaffeine_tests integration locks share ONE oracle.

Structs§

SoftCoreRun
A run of the core: everything it showed, and how it failed if it did.

Enums§

ChipFailure
How the core stopped with a FAILURE (a trap-halt rather than a clean Halt).
RegVal
A VALUE integer register cell — the chip’s exact mirror of the VM’s Int/BigInt tower. The common case is a machine word (Small, the FAST path that keeps the 32-bit oracle byte-identical and the model fast over the 5e8-cycle budget); an integer that overflows the datapath promotes to an exact Big (unbounded BigInt), EXACTLY as crate::vm::value::Value / RuntimeValue::Int promotes to RuntimeValue::BigInt. INVARIANT (mirrors RuntimeValue::from_bigint): a Big never holds a value that fits i64 — every arithmetic result normalizes back to Small when it fits — so a value has one canonical representation and the printed decimal is unique. Pointers, list lengths, map tags, iterator cursors, and register indices stay Small (they are addresses, never over-i64), so the structural heap/pointer machinery reads them through RegVal::sm with no BigInt on the hot structural path.
ShowVal
One Show output of the soft-core, tagged by the datapath that produced it: an integer Show (opcode 89, the 32-bit ALU/heap result) or a FLOAT Show (opcode 212 ShowF, an f64 from the FPU float bank). The chip is dynamically typed at the VM level, but the encoder statically lowers each Show to the one whose operand type it proved — so the model carries the same distinction and ShowVal::fmt renders each exactly as the VM does (ints bare, floats via fmt_f64).

Functions§

run_soft_core
The integer-differential view of run_soft_core_typed: the Show sequence as raw i64 values. The pure integer programs (the hand-assembled ≡VM differential, the testbench emitter, the silicon demo) never emit a float Show, so at the 32-bit width this stays value-identical to the pre-FPU model (a 32-bit result carried in the low bits of an i64). A float program uses run_soft_core_typed + ShowVal::fmt instead (panics loudly here if one leaks a float).
run_soft_core_outcome
Run imem and report the failure contract the RTL’s failed/reasoned ports carry: a reasoned trap’s last Text record IS its reason (so it leaves shows); a trap without text is Trap.
run_soft_core_typed
run_soft_core_typed_preloaded
Run with preload seeded into the heap as heap[0..preload.len()] — the model twin of the SoC’s weight DATA phase. With preload = [len, w0, w1, …] that is a Seq of Int at pointer 0, so the compiled loaded() (pointer 0) makes item i of loaded() read heap[i]. The bump allocator continues after it.
run_soft_core_typed_w
The WIDTH-PARAMETRIC form of run_soft_core_typed — the real fetch/decode/execute loop. Every integer VALUE is an auto-promoting RegVal (fast Small(i64) + exact Big(BigInt) on overflow), so the datapath’s Int is UNBOUNDED exactly like the VM’s — the chip differs NOWHERE from the VM on integers at ANY width. This is a REFRAME of the old width toggle: width no longer masks value arithmetic (a product that overflows i32/i64 PROMOTES, matching the VM, rather than wrapping), so width == 32 and width == 64 both equal vm_outcome on the ShowVal output. width survives as a perf/area knob and the datapath-width parameter for the raw-i64 OUTPUT VIEW (run_soft_core_w, which masks each value to width bits to model a fixed-width hardware output register). Addresses/iterators stay usize; the float bank stays f64 (width-independent).
run_soft_core_w
The WIDTH-PARAMETRIC integer-differential view of run_soft_core_typed_w: the Show sequence as raw i64 values MASKED to the datapath width — the fixed-width tape-out core’s OUTPUT REGISTER view (width == 32 truncates each value to i32, width == 64 is the full i64 pattern). This is DISTINCT from run_soft_core_typed_w, whose ShowVal carries the UNBOUNDED value (VM-exact via BigInt): the typed path is the chip that “differs nowhere from the VM”; this raw view models what a width-bit hardware output register would show if you read the low bits, so the 32-bit tape-out core’s wrap is still observable here. A value that overflowed to Big contributes its low-64-bit two’s-complement pattern, then sign-extended to width. (Float/Text/Word32 Shows panic — the pure-integer callers never emit them.)
sign_extend_to_width
Sign-extend the low width bits of a value to a full i64 — a fixed-width datapath’s result register. width >= 64 is the identity; width == 32 reproduces the 32-bit core’s as i32 truncation exactly. The SAME logic yields a 32-, 64-, or any-power-of-two-width core — the toggle.
soft_core_alu
The Rust model of alu.v (32-bit), mirroring emit_alu_datapath_verilog exactly (wrapping / signed). Div / ExactDiv / Mod / FloorDiv are NOT here — they route to soft_core_divider (mirroring the soft-core’s shared_divider). DivPow2 stays (a cheap arithmetic shift).
soft_core_alu_w
Width-parametric model of alu.v — computes in i64 and sign-extends to width bits. soft_core_alu is the width == 32 case (proven equal by alu_width_toggle_is_32bit_faithful_and_64bit_wide). Div/Mod/ FloorDiv route to soft_core_divider_w, mirroring the shared divider.
soft_core_divider
The Rust model of the soft-core’s shared_divider unit (truncated signed division): Div / ExactDiv → quotient, Mod → remainder (dividend’s sign), FloorDiv → floor-adjusted quotient; b==0 → 0. run_soft_core issues opcodes 12/13/14/15 here instead of the combinational ALU, mirroring the RTL (the divider is proven == this by iverilog tb_shared_divider).
soft_core_divider_w
Width-parametric model of the shared divider (truncated signed division), sign-extended to width. soft_core_divider is the width == 32 case.