Skip to content

analog: bench.t27 -- ngspice wall time and a fixed-step backward-Euler reference for the M0/M1 circuits (Closes #10505) - #10517

Merged
gHashTag merged 2 commits into
masterfrom
claude/analog-bench-10505
Oct 18, 2026
Merged

gHashTag merged 2 commits into
masterfrom
claude/analog-bench-10505

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #10505

Part of #10486 (W7 and W10 of docs/analog/competitors.md).

specs/analog/bench.t27 records ngspice-47 wall time for five circuits, the board side where a receipt exists, the claim rule, and the tests that keep them honest. specs/analog/decks/ holds the netlists (plain SPICE data, no .control block): a fixed-step backward-Euler deck and a default-adaptive deck per circuit, and rc_pwl_naive.cir as the negative control.

Measurements

Apple M1, 8 GB, macOS 26.3.1 arm64, sandboxed session (Seatbelt), 2026-10-18, ngspice-47 from Homebrew (SPARSE 1.3). Command: ngspice -b -r <name>.raw specs/analog/decks/<name>.cir. Wall = whole process, median of 10 timed runs after one warm-up. Deviation columns are volts.

Circuit Unknowns Fixed: points Fixed: wall median Fixed: .tran Fixed vs f64 backward Euler Adaptive: points Adaptive: wall median Adaptive vs exact continuous
RC (M0 and M1 circuit 1) 1 220 14.228 ms 0.796 ms 1.0e-15 217 14.373 ms 2.4e-4
series RLC 3 220 14.813 ms 0.914 ms 2.7e-15 218 14.691 ms 3.4e-4
3-node RC ladder 3 220 14.607 ms 0.836 ms 9.4e-15 218 14.106 ms 2.4e-4
5-node RC ladder 5 220 14.659 ms 0.866 ms 7.8e-15 218 14.281 ms 2.4e-4
10-node RC ladder (not in linear.t27) 10 220 15.021 ms 0.983 ms 7.7e-15 218 15.336 ms 2.4e-4

Board (only M0 has a receipt): 1200 clocks at 100 MHz = 12 us compute, plus one 108-character line at 115200 baud = 9375 us, so 9387 us including readout (computed from the receipt, not a stopwatch reading). The RLC and the 5-node ladder are pending (M1b, #10496); the 3-node and 10-node ladders have no board top. The bitstream build time is in no receipt in this repository and was not measured: it is recorded as not measured and no break-even count is stated.

Reading: for every row ngspice's wall is 14 to 15 ms and more than 90 percent of it is start-up and file work (.tran is 0.8 to 1.0 ms); it is flat from 1 to 10 unknowns. On M0 the wall ratio is 14228 / 9387 = 1.52, a ratio of two fixed overheads (process start-up against a UART line), not of two simulators. The compute-only ratio (796 us over 12 us = 66) is a different quantity and is not a speed claim about a run, because the user of a run pays the readout. may_claim_speedup is true only with a measured board time and a ratio of at least 1, and the test over the table finds exactly one claimable row (M0), robust to the fastest of the 10 ngspice runs.

Fixed-step finding (W10): ngspice as an independent backward-Euler reference

ngspice reproduces backward Euler on the exact grid to float64 rounding. Target was 1e-9 V; achieved 1e-15 to 9.4e-15 V at every one of the 200 grid points, every node, for all five circuits, against an independent f64 LU recurrence; the 200 steps equal dt to 2.2e-14 relative.

  • method=gear maxord=1 is backward Euler. trtol=1e7 stops the truncation test from shrinking a step (without it the step collapses to 2.1e-13 s at the source edge; without maxord=1 the steps stay at 50 ns but the method is trapezoidal, 0.024 V from backward Euler on the RC).
  • A PWL source cannot do it. ngspice opens every .tran with a ramp of steps that double up to tmax and restarts the ramp after every breakpoint; a PWL corner or PULSE edge is a breakpoint. With the natural PWL source (rc_pwl_naive.cir) there are 217 internal points, 4 of them on the 50 ns grid, v(out) at 5 us is off the recurrence by 1.7e-5 V (0.992412 against 0.992396), at 10 us by 1.2e-4 V, and 0.016 V at the first grid point.
  • The recipe: a B source (declares no breakpoint) turned on at 8.5 steps, with the circuit at rest at 0 V before it, so the opening ramp cannot touch the state; from the first internal point after turn-on every step equals tmax. The raw file (-r) holds float64 values. The price is 20 extra internal points (220, not 201) and a source that is a function of time.

Not covered

  • The deviation numbers come from a throwaway float64 helper (numpy LU for backward Euler, matrix exponential for the continuous circuit) that is not committed; only the RC rows can be re-derived inside the spec (its tests check the recorded values against the closed recurrence 1 - (1/1.05)^100). A t27 tool that reads the raw file belongs to the SPICE reader (M2).
  • One machine, one day, a sandboxed session; the wall times include the sandbox's start-up cost.
  • No board number for any circuit but M0; no build time; no break-even count for any row. The issue's "at least 5 circuits with board wall, build time and break-even" cannot be met until M1b and a build measurement exist; the table has five rows with ngspice complete and the board columns marked pending or absent.
  • The table has four distinct netlists: M1's circuit 1 is M0's RC. The fifth row (10-node ladder) is not a circuit of linear.t27; it is there to read the ngspice time against size.

Gate

  • t27c test-report specs/analog/bench.t27: 11 tests, 11 pass, 0 vacuous passes.
  • tri test specs/analog/bench.t27: 11 pass, 0 fail.
  • t27c seal --save then --verify: all hashes MATCH.
  • Four mutants (claim rule >= flipped to <=, FIX_RC_A changed, BOARD_WALL_US off by one microsecond, a pending row marked measured) each fail the tests.

🤖 Generated with Claude Code

…r reference for the M0/M1 circuits (Closes #10505)

specs/analog/bench.t27 records, for five circuits (the M0/M1 RC, the series RLC,
3-, 5- and 10-node RC ladders), ngspice-47 wall time (median of 10 runs, process
start included), ngspice's own .tran analysis time, internal time points, and two
deviations. It also encodes the claim rule: may_claim_speedup is true only with a
measured board time and wall(ngspice) / wall(board incl. readout) >= 1.

Fixed-step finding: ngspice reproduces backward Euler on the exact grid to float64
rounding (largest deviation 1e-15 to 9.4e-15 V against an f64 LU recurrence) with
method=gear maxord=1 trtol=1e7, a B source (no breakpoints) and a pre-roll in which
the circuit rests at 0 V. A PWL source cannot: its corners are breakpoints and ngspice
restarts its step ramp after each, leaving 4 of 217 points on the grid and v(out) at
5 us off by 1.7e-5 V. specs/analog/decks/ holds a fixed and an adaptive deck per
circuit and rc_pwl_naive.cir as the negative control.

Measured on Apple M1, macOS 26.3.1, sandboxed session: ngspice wall is 14 to 15 ms
for every row, of which .tran is 0.8 to 1.0 ms; it is flat from 1 to 10 unknowns.
M0's board time is 12 us compute + 9375 us UART line = 9387 us, so the wall ratio is
1.52; that compares two fixed overheads. Only M0 has a board number; the RLC and the
5-node ladder wait for M1b (#10496); the bitstream build time is not in any receipt,
so it is recorded as not measured and no break-even count is stated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) October 18, 2026 16:07
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 16:07:48 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 49
PRs with All Checks Green 1
READY 0
FAILING 49
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 49 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=fad12492937a != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag disabled auto-merge October 18, 2026 16:08
…aim for any row yet (Closes #10505)

Review on PR #10517: may_claim_speedup allowed M0 (wall ratio 1.52), but
that ratio compares ngspice process start-up with the UART line, measured
inside a sandboxed session, and the bitstream build time is not measured,
so the break-even run count FR-001 asks for does not exist. The rule now
also requires build_us > 0; with BUILD_US = 0 no row is claimable, and a
test shows the same M0 numbers would pass once a build is measured.
11/11 tests, 0 vacuous; seal re-saved and verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 16:10:40 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 50
PRs with All Checks Green 0
READY 0
FAILING 50
PENDING 0
NO CHECKS YET 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=fad12492937a != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit b90b619 into master Oct 18, 2026
31 of 33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

analog bench: wall time of ngspice against the board for the same circuits -- no speed claim without it

2 participants