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
76 lines
4.0 KiB
Markdown
76 lines
4.0 KiB
Markdown
# C.5 — Sequencer dense (`layer_sequencer.v`)
|
||
|
||
Data: 2026-09-04.
|
||
|
||
---
|
||
|
||
## 5.1 Catena layer, ping-pong, busy/done — CERTIFICATO (test pre-esistente, valido)
|
||
|
||
`sim/layer_sequencer_tb.v` (pre-esistente, riverificato in Fase 0) copre un run a 2 layer
|
||
con verifica campo-per-campo del descrittore decodificato (`nm_w_base`, `nm_bias_addr`,
|
||
`nm_x_base`, `nm_activation`, `nm_n_inputs`, `nm_n_neurons`), e in modo particolarmente
|
||
solido: **verifica l'indirizzo del buffer ping-pong usato per layer 1, non solo il valore**
|
||
(conferma che layer 1 legge dal buffer che layer 0 ha effettivamente scritto — il punto
|
||
reale dello schema ping-pong, non solo che "un" buffer sia stato usato). Verifica anche che
|
||
`seq_busy` resti asserto per l'intero run a 2 layer (non cada tra un layer e l'altro) e che
|
||
`seq_done` pulsi esattamente una volta, dopo l'ULTIMO layer (un `nm_done` intermedio non deve
|
||
attivarlo).
|
||
|
||
**Verdetto: CERTIFICATO** per la catena a `run_num_layers` valido (test singolo ma
|
||
sufficientemente rigoroso nel verificare indirizzi, non solo valori).
|
||
|
||
---
|
||
|
||
## 5.2 `run_num_layers=0` — BUG-005 CONFERMATO, CRITICO
|
||
|
||
**Ipotesi**, per analogia col guard mancante già visto in BUG-002/003/004: `run_num_layers`
|
||
è documentato "1..N_LAYERS" ma **non ha alcun guard**, né a compile-time né a runtime.
|
||
`layer_idx` (`rtl/layer_sequencer.v:121`) è però un registro a **8 bit pieni** (non ristretto
|
||
a 1 bit come il `group_index` di BUG-002) — la condizione di terminazione
|
||
`layer_idx==num_layers_reg-1` per `num_layers_reg=0` avvolge a `layer_idx==255`, un valore
|
||
che il contatore RAGGIUNGE naturalmente contando da 0. Ipotesi: non un hang, ma
|
||
un'esecuzione di 256 layer fasulli.
|
||
|
||
**Verificato empiricamente** (`sim/layer_sequencer_bug005_zero_layers_tb.v`, `neuron_memory`
|
||
sostituito da uno stub minimale che completa istantaneamente, per isolare il solo
|
||
comportamento di sequenziamento):
|
||
|
||
```
|
||
RESULT: run_num_layers=0 completed after 21761 cycles -- dut.layer_idx ended at 255
|
||
```
|
||
|
||
**Confermata l'ipotesi**: non un hang. Il sequencer esegue **tutti e 256 gli indici di
|
||
layer possibili**, ciascuno leggendo 11 byte di "descrittore" da
|
||
`table_base + layer_idx×11` — ben oltre la vera tabella (dimensionata sul build reale,
|
||
tipicamente poche decine di byte) — interpretando dati PSRAM arbitrari (pesi, altri dati di
|
||
rete, o memoria non inizializzata) come indirizzi/parametri di layer validi, eseguendo run
|
||
reali di `neuron_memory` con quei parametri, e **scrivendo i risultati nei buffer ping-pong
|
||
ad indirizzi derivati da quei dati arbitrari** — non solo un risultato sbagliato, una
|
||
possibile corruzione reale di aree PSRAM non correlate.
|
||
|
||
**Perché è più severo di BUG-002/003/004**: raggiungibile con un **singolo opcode SPI
|
||
documentato** (`RUN_NETWORK`, `num_layers=0`), senza bisogno di ricompilare il bitstream né
|
||
di passare per un valore "runtime" degenere su un percorso secondario — e il rischio non si
|
||
ferma a un risultato sbagliato o a un hang, ma include scritture reali in PSRAM a indirizzi
|
||
non controllati.
|
||
|
||
**Nota correlata (non testata separatamente, stesso meccanismo)**: `run_num_layers` >
|
||
`N_LAYERS` (il massimo di build) presumibilmente ha lo stesso problema in forma più
|
||
limitata — nessun guard impedisce di leggere oltre la tabella reale anche per valori
|
||
"quasi validi" ma superiori al massimo di build. Non verificato con un test dedicato in
|
||
questa fase (stessa causa radice di §5.2, non una scoperta separata).
|
||
|
||
**Verdetto: NON CERTIFICATO per `run_num_layers=0` (e probabilmente per valori
|
||
`>N_LAYERS`).** Vedi `docs/validation/bugs.md` BUG-005 (severità CRITICA — unico bug di
|
||
questa campagna finora classificato come tale, per raggiungibilità diretta via protocollo
|
||
host documentato e rischio di corruzione dati reale, non solo hang o risultato sbagliato).
|
||
|
||
---
|
||
|
||
## 5.3 Verdetto complessivo C.5
|
||
|
||
| Sotto-aspetto | Verdetto |
|
||
|---|---|
|
||
| Catena layer, ping-pong, busy/done (valori validi) | **CERTIFICATO** |
|
||
| `run_num_layers=0` | **NON CERTIFICATO** — BUG-005 (CRITICO, causa isolata con certezza) |
|