Commit Graph
9 Commits
Author SHA1 Message Date
micheleandClaude Sonnet 5 f0a66363de test: certify spi_neuron_top mux/pins (C.8), find critical BUG-007
Legitimate dispatch mux and data_ready_n/irq_n pins certified via
existing pre-session tests.

BUG-007 (CRITICAL), confirmed end-to-end over real simulated SPI:
SET_NET_TYPE has no check against graph_busy/seq_busy in
rtl/spi_engine.v, and rtl/spi_neuron_top.v's arbiter Port C mux
selects between graph_engine/layer_sequencer purely combinationally on
the current net_type value -- not latched to whichever engine actually
started the in-flight run. Started a valid graph RUN_NETWORK, sent
SET_NET_TYPE(dense) immediately after (before completion): STATUS.busy
gets stuck (30+ consecutive polls with no done/err, vs. ~12-25us normal
completion) -- the graph engine is left waiting for a ram_ready that
never arrives via the now-disconnected mux path. Also verified
recovery: RESET during the hang brings the system back to a fully
working state (a subsequent legitimate dense op completes normally) --
not a permanent lockup, but plain STATUS polling alone would never
unstick without a host-side RESET fallback.

Full regression: 40/40 real tests pass, 1 new observational test
deterministically reproduces BUG-007 and verifies RESET recovery.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-04 18:50:06 +02:00
micheleandClaude Sonnet 5 95849c9002 docs: certify SPI slave/engine (C.7), confirm len=0 is properly guarded
Certified via existing extensive pre-session coverage (10 tests in
spi_engine_tb.v, CDC ratio-variation test in spi_slave_tb.v, explicit
unknown-opcode-as-NOP handling), re-confirmed passing in Phase 0.

Targeted check given this campaign's recurring pattern (missing
zero-value guards, BUG-002 through 006): WRITE_RAM/READ_RAM len=0 IS
explicitly guarded (rtl/spi_engine.v:817, transitions to ST_IGNORE) --
confirms the project does not systematically lack these guards, the
gap is specific to the modules already flagged.

No new bugs found in this aspect.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-04 14:54:56 +02:00
micheleandClaude Sonnet 5 6db44efcfd test: certify graph_engine gather/guard (C.6), find related BUG-006
Gather/padding/src_id<out_id guard certified via existing solid
pre-session tests (graph_engine_tb.v checks act_buffer contents via
hierarchical reference, not just final output; graph_engine_guard_tb.v
covers 4 adversarial cases incl. recovery).

BUG-006 (LOW severity): num_neurons_graph=0 shares BUG-005's exact
root cause (neuron_idx is a full 16-bit register, no guard), but
graph_engine's existing per-edge src_id<out_id guard incidentally
catches most garbage-data patterns fast (err at cycle 58 for a
non-trivial test pattern, vs. layer_sequencer's 21761-cycle full run
in BUG-005) -- not a designed protection for this case, so not closed
as a non-issue, but lower severity given the observed practical risk.
Not run to full 65536-iteration completion (impractical for this
campaign's time budget) -- limitation stated explicitly.

Full regression: 40/40 real tests pass, 1 new observational test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-04 14:52:52 +02:00
micheleandClaude Sonnet 5 f81d7fa1b3 test: certify layer_sequencer chain (C.5), find critical BUG-005
Layer chain / ping-pong / busy-done certified via the existing
pre-session test, which already verifies the actual ping-pong buffer
address used (not just the value) and correct busy/done timing.

New finding, BUG-005 (CRITICAL): run_num_layers=0 has no guard at
compile time or runtime, and unlike BUG-002's 1-bit group_index (which
can never represent the wraparound value), layer_idx here is a full
8-bit register that naturally reaches it. Confirmed empirically with a
minimal neuron_memory stub: RUN_NETWORK(0) runs through all 256
possible layer indices (21761 cycles), reading arbitrary PSRAM bytes
far past the real descriptor table as if they were valid layer
descriptors, running real neuron_memory passes on them, and writing
results to ping-pong buffer addresses derived from that arbitrary
data. More severe than BUG-002/003/004: reachable via a single
documented SPI opcode (RUN_NETWORK), real PSRAM corruption risk rather
than just a hang or wrong result. Root cause fully isolated, not just
the symptom.

Full regression: 40/40 real tests pass, 1 new observational test
(no pass/fail by design) deterministically reproduces BUG-005.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-04 14:47:41 +02:00
micheleandClaude Sonnet 5 b528901510 test: certify mem_arbiter priority order (C.4)
Priority B>C>A>D confirmed correct with distinguishable per-port data
(not just "someone got served" but "the right requester got its own
data back") across 4 contention scenarios. D-alone case confirms low
priority does not mean never granted.

Found and fixed a real race in the test harness itself: blocking
assignments withdrew loser requests in the same clock edge meant to
grant the winner, racing the DUT's own synchronous block -- dut.owner
never left SEL_NONE, every wait() blocked forever. Fixed by switching
request-signal drives to non-blocking assignments throughout.

Documented (not filed as a bug) that D can starve indefinitely under
sustained continuous B contention -- standard behavior for a
fixed-priority arbiter with no aging, and explicitly outside the
header's own stated operating assumption (B/C temporally disjoint in
normal operation). Flagged the header's "never starves or corrupts
A/B/C" wording as ambiguous about whether it promises D's own
progress.

Full regression: 40/40 real tests pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-04 14:41:44 +02:00
micheleandClaude Sonnet 5 3dd75e9e0d test: certify memory subsystem addressing (C.3)
int8_memory_access.v byte<->word conversion and byte-lane selection:
exhaustive 2048-address test + 6 real read/write round-trips through
the FSM handshake. 2054/2054 checks, 0 mismatches, after fixing two
bugs in the test harness itself (a same-timestep race reading a
non-blocking update one iteration late, and a behavioral memory stub
that ignored byte-lane enables on write) -- both documented as
test-side, not RTL, issues.

memory_interface.v and psram_controller.v not re-verified from
scratch: cited against coverage already established/re-confirmed
earlier in this same session (page-mode/tCEM against the ISSI
datasheet, a real pre-existing power-up request-loss bug found and
fixed), re-run clean via the Phase 0 regression harness rather than
trusted from WORKLOG text alone.

Full regression: 39/39 real tests pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-04 14:33:05 +02:00
micheleandClaude Sonnet 5 14c8d87194 test: certify runtime width early-termination (C.2), document BUG-003/004
n_inputs_real/n_neurons_real early termination for valid values is
certified real: a "poison" region (data that would saturate the result
if read past the claimed limit) confirms no over-read, cycle counts
scale proportionally. n_inputs_real non-multiple-of-PARALLEL at runtime
matches the documented silent-truncation risk exactly.

n_inputs_real=0 / n_neurons_real=0 (BUG-003/004): confirmed incorrect
behavior in every repetition, but the exact triggering mechanism was
NOT fully isolated -- nearly-identical repeated tests produced
different symptoms (clean hang vs. silently processing the full build
width vs. a third cycle count matching neither). Reported in full,
including the inconsistency itself, rather than picking the cleanest
result. The two new permanent testbenches reflect this honestly: the
solid early-termination checks are hard assertions, the n_*_real=0
probe is deliberately observe-only given the non-deterministic result.

Full regression: 38/38 real tests pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-04 14:27:14 +02:00
micheleandClaude Sonnet 5 20b0b1f4c0 test: certify mac_unit/mac8 datapath (C.1), confirm real N_INPUTS=0 guard gap
mac_unit.v: exhaustive unit test (all 65536 (x,w) combinations at
DATA_WIDTH=8, plus 486 boundary acc_in vectors) against an independent
Python oracle (tools/validation/mac_oracle.py). 66022/66022 match, 0
reserves.

mac8.v: first-ever dedicated unit test (previously only indirect
coverage at whatever single PARALLEL neuron_parallel_tb.v happens to
use). Verified at PARALLEL=2/8/32 with structural adversarial vectors
(catches swapped/duplicated tree wiring), 300 random INT8 pairs per
PARALLEL with realistic accumulating acc_in, and worst-case magnitude
adversarial vectors. 939/939 match.

Confirms BUG-002 (N_INPUTS=0 bypasses the N_INPUTS%PARALLEL elaboration
guard) is real, on both simulation and real Yosys synthesis -- root
cause: [DATA_WIDTH*N_INPUTS-1:0] becomes [-1:0] for N_INPUTS=0, which
both tools treat as a genuine 2-bit undriven vector rather than
collapsing to zero width. Includes a documented self-correction: the
first verification attempt produced a false "hang" using an invalid
one-shot late check of a single-cycle done pulse -- caught by
reproducing the same false result on a known-good sanity config before
trusting it.

Full regression re-run clean after adding 3 new testbenches: 36/36 real
tests pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-04 13:42:57 +02:00
micheleandClaude Sonnet 5 313a1994a4 docs: certification campaign Phase 0 -- real inventory, new regression harness
Builds tools/run_regression.py (no reproducible regression script existed
before -- every prior "N testbenches, all pass" claim was assembled by
hand). Resolves each testbench's dependencies by static analysis of
instantiation sites, not from memory, then compiles+runs everything fresh.

Independently re-verifies the 33-testbench regression clean (0 real
failures) after fixing two false negatives in the harness itself (two
tests are deliberate compile-time-failure negative tests, one file is a
benchmark with no pass/fail verdict by design -- confirmed by reading
each file's own header, not assumed).

Findings recorded in docs/validation/: sim/top.v is dead code (references
a removed FRAC_BITS parameter from the pre-INT8 Q8.8 era); mac_unit.v/
mac8.v have no dedicated unit testbench, only indirect coverage; the
N_INPUTS%PARALLEL elaboration guard does not mathematically cover
N_INPUTS=0 (open finding, not yet confirmed reachable -- BUG-002).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-04 13:26:11 +02:00