Six coverage families.
One database.
Six separate questions, never averaged into one number.
A single coverage percentage is the easiest number to trust and the easiest to mislead with. Blend statement, branch, toggle, FSM, covergroup and assertion coverage into one weighted average and the families that are cheap to hit carry the ones that matter, while a family that was never collected quietly reads as complete because its denominator was left empty. FSiMX Studio takes the opposite stance: every metric family is measured into one database, each stays a separate question with its own numerator and denominator, and a family with no feed is reported as not-collected rather than folded in at full marks.
The database under discussion is wz_mini_soc, a WIOWIZ SoC and testbench built by fsimx and read back by the vwiz-cov coverage database and its viewer. The instrumented run emits code, branch, toggle, FSM, covergroup and assertion data into one .covdb; expression coverage in this run was left off. The dashboard, the source view, and each per-metric workspace all read from that one file.
The dashboard keeps the families apart
The signoff cockpit puts each metric family in its own card with its own fraction. Statement sits beside branch, branch beside toggle, toggle beside FSM, and none of them is summed into a headline figure. Below the cards is a feed-completeness note that states how many families were fed, in the form N of 8 types present, so a reader sees at a glance whether a card is missing because a family scored zero or because it was never collected.
That distinction is the whole design rule: absent is not zero, and absent is not full. An unfed family shows as N/A with the feed-completeness note next to it, never as 0% and never as a silent full bar. The verdict line and its blockers read only the families that were measured.
Code coverage, anchored to the source line
Statement and branch coverage are answered where they can be read against the text that produced them. The source view tints each executed line and marks each unexecuted one, so a covered line and an uncovered line appear together in the same file rather than as two totals in a summary. The active line carries a marker, and an Uncovered walker steps from one unexecuted line to the next so a gap is found by position, not by scrolling.
Statement coverage answers whether a line ran. Branch coverage answers a different question on the same line: whether each arm of a decision was taken. The two are kept as separate fractions because a fully executed file can still leave one side of an if untaken, and collapsing them would hide exactly that.
Branch coverage is also where proof refinement enters, and it enters as its own step rather than as an edit to the number. On this SoC the branch denominator moved from a raw 77/89 to a proof-refined 77/86 after three branches were shown structurally dead by formal evidence, with 0 manual waivers. The raw fraction and the proof-refined fraction are shown side by side, so a point that left the denominator can be traced to the proof that removed it.
Toggle and FSM are two different questions
Toggle coverage asks whether each bit of each signal moved through both 0 and 1. FSM arc coverage asks a structurally different question: whether each state was entered and each transition between states was taken. These are never merged, because a design can toggle every net and still never drive a state machine through a given arc, and a merged number would let the busy datapath cover for the idle control path.
FSM coverage is presented as a from-state by to-state matrix: each cell is a transition, tinted covered or uncovered, with the state summary and detail beside it. An unentered state and an untaken arc are visible as distinct cells, so "the machine reached this state" and "the machine took this transition" stay separate facts.
Covergroups, crosses and assertions, counted separately
Functional coverage is counted per bin, and a cross is counted as its own set of bins rather than being reduced to the coverage of its parent points. A covergroup with well-covered individual points can still have empty cross bins, and the workspace keeps that cross as a separate fraction so an uncovered combination is not hidden behind two well-covered axes.
Assertions are counted twice over, by attempt and by result. Each named property carries its evaluation count, its pass count, and its failure count, so a property that was evaluated thousands of times and a property that was never reached are distinguishable rather than both reading as green. On the closure SoC the assertion set stands at 16/16 refined across 8,629 evaluations with 0 failures: the attempt count shows the properties were exercised, and the result count shows none failed. A property with zero evaluations would show as reached-never, not as passing.
The verdict does not average in what it did not measure
The signoff verdict reads the measured families and their blockers, and it declines to include a family that was not collected. Expression coverage was left off in this run, and the metric-status readout says exactly that rather than reporting expression as complete or as zero:
# METRIC_STATUS line COMPLETE # METRIC_STATUS statement COMPLETE # METRIC_STATUS branch COMPLETE # METRIC_STATUS toggle COMPLETE # METRIC_STATUS fsm COMPLETE # METRIC_STATUS functional COMPLETE # METRIC_STATUS assertion COMPLETE # METRIC_STATUS expression NOT_COLLECTED set FSX_COV_EXPR=1
Seven families report COMPLETE; the eighth reports NOT_COLLECTED with the flag that would turn it on. The verdict is computed over the seven that were measured, and the eighth cannot inflate it, because a family with no feed contributes no numerator and no denominator. The line also tells the operator how to close the gap: rerun with FSX_COV_EXPR=1 and expression joins the other seven as a measured family with its own fraction.
This is the same rule that governs merge and exclusion. Merging two runs of the same DUT keeps every bin from both and blocks signoff on a model-hash conflict rather than averaging two incompatible databases into one green figure. An exclusion leaves the denominator only through the audited ledger or through hash-gated formal proof, never through a number quietly nudged down. In each case the mechanism is the same: keep the question separate, and state what was not measured.
Each stays its own question, and the one you did not measure says so.
