No silent data corruption sounds like one requirement until the error response, the SRAM bit flip, the dropped completion and the early end of a stream each demand different detection in different places with different deadlines. A goal the architecture cannot decompose is a slogan the verification team cannot test. The way out is a table of faults, each with its detection, reaction, reporting and deadline, and a check that no row is missing an answer.
The goal for the NanoSoC safety extension is stated plainly: no fault in the memory-to-memory stream shall corrupt data silently; every detected fault shall be reported to software within its deadline. Decomposition walks each structure in the stream path and asks four questions. What can go wrong here? How is it detected? What reacts? What is reported, through which fault-controller input, and how fast? NanoSoC v1 already answers part of this: an AXI error response (DECERR or SLVERR) sets STATUS.ERR in the stream bridge, and an early end of stream sets ERR in the DMA. It has no answer for a flipped SRAM bit or a completion that never arrives. The table marks which rows v1 already covers and which need the extension.
Fault | Detection | Reaction | Report | In NanoSoC v1? |
|---|---|---|---|---|
AXI error response at the stream bridge | STATUS.ERR in the bridge | Job stops | Fault controller input 0 | Detection yes; fault input is the extension |
Early end of stream at the DMA | DMA STATUS.ERR | m_tlast set, job ends | Fault controller input 1 | Detection yes; fault input is the extension |
SRAM bit flip on stream data | Per-byte read parity | Halt job, flag word | Fault controller input 2 | No: extension (needs 36-bit macros) |
Completion never arrives | Timeout counter in the fault controller | Raise fault, keep status | Fault controller input 3 | No: extension |
The check below holds the same table as data and requires all four answers and a positive deadline for every fault. It then removes the reaction from one row to show the check refuses an incomplete decomposition.
# Fault decomposition completeness: every fault needs all four answers.
FAULTS = [
{"fault": "AXI error response at SBR", "detect": "SBR STATUS.ERR",
"react": "job stops", "report": "fault input 0", "us": 2.0},
{"fault": "early end of stream at DMA", "detect": "DMA STATUS.ERR",
"react": "m_tlast set, job ends", "report": "fault input 1", "us": 2.0},
{"fault": "SRAM bit flip on stream data", "detect": "read parity check",
"react": "halt job, flag word", "report": "fault input 2", "us": 2.0},
{"fault": "completion never arrives", "detect": "timeout counter",
"react": "raise fault, keep status", "report": "fault input 3", "us": 10.0},
]
def gaps(faults):
out = []
for f in faults:
for k in ("detect", "react", "report"):
if not f.get(k):
out.append(f"{f['fault']}: no {k}")
if not f.get("us") or f["us"] <= 0:
out.append(f"{f['fault']}: no deadline")
reports = [f["report"] for f in faults if f.get("report")]
out += ["duplicate input: " + r for r in set(reports) if reports.count(r) > 1]
return out
assert gaps(FAULTS) == []
assert max(f["us"] for f in FAULTS) == 10.0
broken = [dict(FAULTS[0], react="")] + FAULTS[1:]
assert gaps(broken) == ["AXI error response at SBR: no react"]
dup = FAULTS[:3] + [dict(FAULTS[3], report="fault input 2")]
assert gaps(dup) == ["duplicate input: fault input 2"]
print("PASS: 4 faults decomposed, worst deadline 10 us; missing reaction and shared input are caught")The goal written in one sentence, with the decomposition table covering every structure in the protected path.
No fault with detection but no reaction, and none with reaction but no reporting input assigned.
Deadlines stated per fault, each traced to the system consequence of missing it, and the v1 column honest about what exists today.
Inject each fault in simulation and confirm the full chain: detection flag, reaction behaviour and the fault-controller input, in that order. A test that checks only the status bit proves detection; the reaction and the report each need their own assertion. When a fault is found in silicon without a table row, the decomposition was incomplete, and the fix is a new row with its deadline, not just a new test.
Only when the deadline allows it and the table says so: polling adds the poll period plus interrupt latency to the reaction time. If the deadline is shorter than the worst poll gap, the reaction must be hardware, halting the job before software is involved.