Chapter 13 of 15
Reading the Failure Signature
Before the deep diagnostic work, how a failure presents is already a hint toward which of ch1's four categories it belongs to -- immediate and deterministic, order-dependent, failing before simulation even starts, or matching a spec-defined outcome exactly -- grounded in how axil_regfile's three real incidents actually first looked.
Ch1 split every failure into four structural categories. This chapter is the fast pass before the deep one: how a failure presents is already evidence for which category it's likely in, well before chapter 3's isolate-instrument-hypothesize-confirm process starts in earnest. A hint, not a verdict — but a hint worth reading before spending real diagnostic effort.
Four signatures, one per category
A DUT bug tends to be immediate and deterministic. The combinational loop in an earlier s_axi_awready/s_axi_wready (uvm-advanced ch1) didn't fail sometimes and pass other times — a genuine combinational loop has no stable solution at all, so the affected signals show wrong values (or a simulator's own complaint about the structure) from the very first cycle they're exercised, the same way on every single run. A structural defect in the RTL doesn't depend on scheduling luck to show up; it's wrong by construction, every time.
A testbench race tends to be order-dependent. Whether a race-driven failure shows up depends on the relative timing between two independent processes — not on the DUT doing anything wrong at all. Worth being precise about how this project's own incident (BVALID and irq landing on the identical clock edge, uvm-advanced ch4) actually got caught: not by waiting for a flaky failure to eventually show up in a run, but by directly instrumenting both signals with $time-printing always blocks and confirming they land on the same timestamp — reasoning about relative event order directly, rather than hoping an intermittent symptom eventually surfaces on its own. That's often the faster and more reliable way to catch this signature: don't wait for the coin flip to come up wrong: check whether a coin flip is happening at all.
An environment mismatch tends to fail before simulation logic is even involved. Icarus Verilog not implementing clocking blocks at all (SV ch13) doesn't show up as a wrong value on some signal — it shows up as a parse failure, confirmed directly by trying the simplest possible isolated case and watching it fail to even compile. Nothing about the DUT's logic or the testbench's sequencing is involved yet; the same code either compiles somewhere else or it doesn't, which is itself the signature.
Not a bug tends to match a named outcome in the spec exactly. A genuinely wrong value is usually just wrong — noise with no meaningful correspondence to anything the spec describes. A write to STATUS returning SLVERR, once that test exists, is the opposite: the "unexpected" result is a specific, documented, named response code the spec assigns to exactly this scenario, not an arbitrary incorrect value. When a mismatch lands precisely on a defined error path rather than landing nowhere in particular, that's the signature worth checking against the spec before assuming anything is broken.
A hint, not a verdict
Reading a signature narrows the search; it doesn't finish the job. A DUT bug that only manifests under a specific, rare combination of inputs can present as intermittently as a race does, and a race can behave deterministically inside one particular simulator's scheduling implementation even though nothing about the underlying protocol actually guarantees that order. Signature-reading is chapter 2's contribution to a debugging session — a fast, cheap first hypothesis about where to look first — not a substitute for chapter 3's actual confirmation process, which is what turns a hypothesis into a verified root cause.
Summary
- A DUT bug tends to present immediately and deterministically — wrong (or complained about) from the first exercise of the affected logic, on every run, the way a structural defect like a combinational loop has no stable solution to begin with.
- A testbench race tends to present as order-dependent — whether it fails depends on scheduling between independent processes, not DUT logic. Directly instrumenting to check relative event order, the way
uvm-advancedch4 did, catches this signature faster than waiting for an intermittent failure to eventually show up. - An environment mismatch tends to fail before any simulation logic is involved at all — a parse or compile failure, or the same code behaving differently across tools, confirmed by isolating the smallest possible case.
- "Not a bug" tends to look like a mismatch that lands precisely on a named, spec-defined outcome rather than an arbitrary wrong value — worth checking against the spec before assuming anything is broken.
- A signature is a fast first hypothesis, not a confirmed diagnosis — narrowing where to look first is this chapter's job; chapter 3's diagnostic method is what actually confirms it.
A signal shows a wrong value (or X) from the very first cycle it's exercised, identically on every single run. Which category from ch1 does this signature most strongly suggest?
uvm-advanced ch4's BVALID/irq race was caught by instrumenting both signals with $time-printing always blocks and confirming they land on the same timestamp -- not by observing an intermittent failure in an actual test run. What does this chapter argue this demonstrates?
Icarus Verilog failing to even parse a bare clocking block (SV ch13) is classified under the environment-mismatch signature. What makes this signature distinct from a DUT or testbench bug's?
After reading a failure's signature and forming a hypothesis about which of ch1's four categories it belongs to, is that hypothesis considered confirmed?