Back to Learn

Closure & enterprise workflow

Verification Plan: Closure Tracking for RTL Projects

"Are we ready to tape out?" is not a single question, and a green CI badge is not a single answer. A verification plan turns the question into a list of explicit objectives, each with a status and evidence, and computes a closure percentage you can defend in a tapeout review. This is what turns the workspace from a tool runner into a closure dashboard.

What a verification plan is

A verification plan (sometimes vplan, sometimes the tapeout checklist) is the enumerated set of correctness, coverage, and process objectives that the project has agreed must be true at tapeout. Each objective has a stable identifier, a category, and a current status. Status moves through one of five states:

  • planned — the objective exists but no one has recorded progress against it yet.
  • in_progress — work toward the objective has started but it is not yet satisfied.
  • covered — the objective is satisfied. Someone has set this status, typically with evidence attached.
  • waived — the team has accepted residual risk against this objective. See verification waivers for the discipline that goes around this.
  • blocked — a known problem is incompatible with the objective. It will not move to covered until that problem is fixed or waived.

The closure percentage is the number of objectives currently in covered or waived divided by the total. A project at 100% closure is one where every documented requirement has either been demonstrated or explicitly accepted with paperwork.

The data model

The plan is not a file in your repository. It is a set of objectives stored server-side per project, created and updated through the verification-plan API (or the dashboard UI). There is no plan.json import and no plan DSL. One objective looks like this on the wire:

POST /api/projects/{id}/verification-plan/objectives
{
  "title": "No inferred latches in synthesizable RTL",
  "category": "static",
  "target": "synth_lint clean on rtl/",
  "status": "covered",
  "tags": ["lint", "tapeout-gate"],
  "evidence": [
    {
      "note": "synth_lint run run_2026_05_07 reported 0 inferred latches",
      "recorded_at": "2026-05-07T11:42:00Z"
    }
  ]
}
// -> 201, the server adds: id, project_id, created_at, updated_at

Each objective has a few significant fields:

  • id — stable server-assigned identifier. Reviews and tracking issues reference it.
  • title / target — what the objective requires and, optionally, the concrete bar it must clear.
  • category / tags — free strings that drive how the dashboard groups and filters objectives.
  • status — one of planned, in_progress, covered, waived, or blocked.
  • evidence — an append-only list of notes, each with a timestamp, recording why the status is what it is (a run ID, a reviewer name, a coverage number).

Advancing an objective

Status changes are explicit. A person — or an integration you build on top of the API — PATCHes an objective to move it from planned toward covered, attaching evidence as it goes. ChipVerify does not auto-flip objective status from engine output: there is no rule-ID-to-objective auto-cover mechanism. Engine runs (synth-lint, simulation, design-structure) produce findings and a project score in their own panels; an engineer reads those and records the result against the relevant objective as evidence. A typical board:

objective                            status        category
------------------------------------+-------------+-----------
No inferred latches in synth RTL     covered       static
No silent width truncation           covered       static
All CDC paths use a 2-FF sync        blocked       structural
UART loopback test passes            covered       directed
Branch coverage >= 90% on rtl/dsp    planned       coverage
Architecture spec frozen             covered       process
Legacy UART latch reviewed/waived    waived        process

closure: (covered 5 + waived 1) / 7 = 85.7 %

Six of seven objectives are covered or waived. The CDC objective is blocked because a reviewer recorded an unsynchronized CDC path from the design-structure panel; the coverage objective is still planned because no one has yet recorded a passing coverage run against it.

Manual cover, and why some objectives need it

Engines do not see everything. Anything in the manual category requires an engineer to flip the status by hand, with a justification attached:

  • Spec sign-off. The architecture document is reviewed and frozen. There is no engine that can prove this; the project lead clicks the box.
  • DV review. A senior engineer has read the testbench and confirmed it exercises the interface contract beyond what coverage metrics measure.
  • Process gates. The project has run the foundry’s pre-tapeout DRC clean; the FPGA prototype has booted Linux; the post-silicon test program is written.

Manual coverage is logged the same way auto coverage is — who, when, and against which run. The dashboard shows the engineer and timestamp next to the green check; a manual cover from six months ago on a project that has had 200 commits since is a flag for re-review.

The closure %

Closure is the simplest possible metric: covered + waived divided by total objectives. It is reported on every pipeline run, plotted over time, and is the single number the management view of the report leads with. Two properties of the metric matter:

  • It is a denominator metric. Adding objectives to the plan reduces closure %. This is correct behavior. A project that "discovers" a forgotten objective the week before tapeout should see its closure number drop — the work to do has gone up.
  • It includes waivers. A waived objective is closure-positive, but the dashboard distinguishes covered-vs-waived in a sub-bar. A project at 100% closure with 30% of that being waivers is not the same risk profile as a project at 100% covered.

The two views: engineer and manager

The same plan is rendered two ways:

  • Manager view (Report tab). Closure %, status histogram (covered / waived / blocked / planned), category breakdown, and the open-objective count. The point is to give the tapeout-readiness review meeting a single page.
  • Engineer view (Plan tab). The full table of objectives. Each row shows its status, category, tags, and the evidence notes recorded against it — for a blocked objective, that is where the reviewer wrote down what is blocking it and which run or finding it came from.

Workflow over a project

  1. At project kickoff, create the objectives. Twenty to fifty for a medium block; two-to-three hundred for an SoC. Tag and categorize each one so the dashboard can group them.
  2. Run the engines (analysis, simulation, synth-lint, design-structure). They produce findings, scores, and coverage in their own panels — the source material you cite as evidence.
  3. As each objective is satisfied, PATCH it to covered with an evidence note (the run ID, the coverage number, the reviewer). Objectives that hit a problem move to blocked.
  4. For each blocked objective, fix the underlying problem or waive it (with a tracking issue). For each planned objective, do the work that lets you record evidence and mark it covered.
  5. Milestone objectives — spec freeze, DV review, FPGA bring-up — are covered by a person recording the evidence.
  6. Tapeout gate: closure must reach the bar your team sets (often 100% covered-or-waived), with high-risk waivers reviewed.

Anti-patterns that quietly inflate closure

A closure number is only as honest as the plan it counts against. A few patterns to watch for:

  • Plan-shrinking. When an objective is too hard to cover, it gets quietly deleted from the plan instead of waived. The closure number goes up; the risk profile does not. Plan history should be tracked — the dashboard shows objective deletions and the engineer who removed them.
  • Evidence-free cover. An objective flipped to covered with no evidence note — or a note that does not actually demonstrate the objective — inflates closure on paper. Periodic plan review should verify each covered objective points at a real run, coverage number, or review.
  • Manual cover that never gets re-reviewed. "Spec frozen" was true six months ago; the spec has been amended twice since. The dashboard surfaces stale manual covers (older than the most recent significant code change in the related scope) so they get flipped back to planned for re-review.
  • Coarse-grained objectives. "All lint clean" is a single objective until the day a single lint finding appears, at which point the entire objective blocks. Better: one objective per high-yield rule class so partial progress is visible.

Why this changes the product

A pure tool-orchestration product gives you a list of pipelines and a list of findings. The team has to read every list, mentally merge them, and decide whether the project is ready. The verification plan gives you a closure dashboard — the merge and the decision are computed for you, and the artifact at the top of the page answers the only question that matters.

The tool runs do not go away. They become inputs to the dashboard rather than the dashboard itself. A senior engineer or manager looking at the project does not need to read a Yosys log to find out whether the latch problem is fixed; they read the closure number and, if it dropped, click into the objective that moved.

Related reading

Try it on your project

Paste a GitHub URL at chipverify.ai/tinytapeout (free) for a one-shot scan, or sign in at chipverify.ai/dashboard to set up the verification plan, record evidence against objectives, and watch closure % move as you go.

Track closure against an explicit plan

Sign in and ChipVerify AI lets you record evidence against each verification objective and rolls it into a defensible closure percentage — pre-signoff tracking, not a foundry signoff.