ppa-measure · git:20260821.2618654 · 2026-08-21 · sha256 ad8f54e88b452056
ppa-measure git:20260821.2618654A
Immutable. This exact content is served forever at /api/v1/blob/ad8f54e88b452056.
---
name: ppa-measure
description: Read PPA artefacts that the tools already wrote — STA reports, power reports, area reports, DEF/GDS summaries — and turn them into an evidence-linked measurement report of canonical `vibeic.ppa.metric.v1` records, each carrying its scope and its source hash. Use when the user says "measure PPA", "what is the real area/power/timing", "collect the PPA numbers", "post-route PPA", or when a report must state what was measured AND what was not.
---
# PPA Measure
## The boundary this skill lives inside
This skill produces an **evidence-linked report**. It never produces a
gate verdict, and no part of it asks the model to settle whether the design is
good enough. The pass/fail call belongs to a deterministic program —
`_ppa/feasibility.py` per `docs/PPA_INTERFACES.md` §4 — and this report only
supplies the records that program consumes.
Concretely, this skill may say *"setup WNS is -0.124 ns at the `ss` corner,
parsed from `<file>` whose sha256 is `<hash>`"*. It may not say what that number
means for the release. If a caller wants the release answer, the handoff is the
gate program, and the report says so on its own `Verdict authority:` line.
The reason for the split is not tidiness. A number that a model produced and a
number a parser produced look identical once they are in a table, and only one
of them can be re-derived from an artefact. Keeping the verdict in a program
keeps the re-derivable half load-bearing.
## When to use
Trigger when the user:
- Has finished a synthesis / PnR / STA / power run and wants the numbers collected
- Asks what the design's real post-route PPA is, as opposed to an early estimate
- Needs the inputs a feasibility gate or a Pareto comparison will read
- Needs an honest statement of PPA coverage — which metrics exist and which do not
**Not** this skill: an early, pre-synthesis guess. That is `ppa-predict`, and the
two must never be mixed in one table. A `ppa-predict` number carries status
`ESTIMATED`, which `docs/PPA_INTERFACES.md` §2 forbids from ever entering final
PPA; a `ppa-measure` number carries status `MEASURED` and a source hash.
## Inputs to gather
1. The design / run directory, and which stage it reached (synthesis, post-place,
post-route, post-route-extracted)
2. The artefacts themselves: STA report(s), power report(s), area report, DEF or
GDS summary — by path, one per view
3. The analysis views actually run: process corner, voltage, temperature, RC
corner, clock, check type
4. The activity basis for any power number: vectorless, or a named VCD/SAIF
5. Whether an extracted-parasitics run exists, or only the pre-extraction estimate
If an input is absent, that absence is a result. Record it as `NOT_MEASURED`
with a `reason`; do not substitute a value from a different stage and do not
leave the row out.
## Workflow
1. **Enumerate the views before reading any number.** Write down the list of
(stage, mode, process, voltage, temperature, rc_corner, clock, check) tuples
the run was supposed to cover. This list is the denominator; without it a
report of three green rows cannot be told apart from a run that only produced
three rows.
2. **Parse, never recompute.** Each number is lifted from an artefact by a parser
and hashed as parsed. A number you arrived at by arithmetic is `DERIVED` and
must carry its formula alongside; a number you arrived at by judgement is not
a measurement at all and does not belong in the table.
3. **Bind every record to its source.** `source.path`, `source.sha256`,
`source.tool`, `source.parser`. A record without a resolvable source is
`INVALID`, not `MEASURED`.
4. **Keep the taxonomy split.** Synthesis area and post-route area are different
metrics, not two samples of one. Vectorless power and VCD power are different
metrics. Pre-extraction and post-extraction timing are different metrics.
Collapsing them is the single most common way a PPA table becomes a fiction.
5. **Emit the coverage line.** Count `MEASURED`, `NOT_MEASURED`,
`NOT_APPLICABLE`. An unstated denominator is how "we measured everything"
and "we measured what happened to be lying around" print the same page.
6. **Hand off.** Name the program that will read these records and state that the
verdict is its output, not this document's.
## Do not
- Do not write `0`, `-1` or an empty string to mean "not measured". There are no
numeric sentinels; there is a status field and it is `NOT_MEASURED` with a reason.
- Do not omit a row because it has no number. A missing row and a measured zero
are different facts and a reader cannot tell them apart after the fact.
- Do not compare two numbers whose `scope` differs. That comparison is
`UNDETERMINED`; it does not have a winner.
- Do not carry a `ppa-predict` estimate into this report, in any column, under
any heading.
- Do not restate a program's exit code as your own conclusion. Quote it with its
program name and its rc.
- Do not report a number whose artefact you could not open. "I could not read it"
and "I read it and it was empty" are different results and must print differently.
## Output format
The deliverable is one markdown report. The template below is the whole shape;
`<...>` are the parts you fill in.
# PPA Measurement — <design> @ <stage>
Verdict authority: _ppa/feasibility.py — this report states no pass/fail of its own.
## Summary
<two or three sentences: which stage, which views were run, what is absent>
Coverage: MEASURED=7 NOT_MEASURED=2 NOT_APPLICABLE=1
## Measurements
| metric | status | value | unit | stage | corner | source sha256 |
|---|---|---|---|---|---|---|
| timing.setup.wns_ns | MEASURED | -0.124 | ns | post_route_extracted | ss/1.62V/125C | sha256:3f9a1c7d |
| power.total_mw | NOT_MEASURED | - | - | post_route_extracted | - | - |
## Not measured, and why
| metric | reason |
|---|---|
| power.total_mw | no activity basis: neither a vectorless run nor a VCD exists |
## Evidence
| artefact | sha256 | tool |
|---|---|---|
| phase3/stage3/sta/sta_mcorner_ocv.rpt | sha256:b204e8a1 | opensta |
Next: run /ppa-diagnose
Every row of `## Measurements` is the human view of one canonical record. The
records themselves are the machine deliverable and go in the report's JSON
sidecar, one per row, in the frozen shape:
```json
{
"schema": "vibeic.ppa.metric.v1",
"metric": "timing.setup.wns_ns",
"status": "MEASURED",
"value": -0.124,
"unit": "ns",
"scope": {"stage": "post_route_extracted", "mode": "functional",
"process": "ss", "voltage_v": 1.62, "temperature_c": 125,
"rc_corner": "max", "clock": "clk", "check": "setup"},
"source": {"path": "phase3/stage3/sta/sta_mcorner_ocv.rpt",
"sha256": "sha256:77c1de40", "tool": "opensta",
"parser": "ppa_metric_extract.py"}
}
```
Serialize with `programs/_ppa/canonical_json.py` and nothing else — sorted keys,
no spaces, UTF-8, no NaN. A hash taken over a hand-rolled `json.dumps` is a hash
of a different document than the one the next reader will re-serialize.
## Compliance gate (mandatory)
After producing your output, save it to a file and run:
```bash
python3 plugins/vibe-ic/_shared/skill_compliance_check.py \
--requirements plugins/vibe-ic/skills/ppa-measure/compliance.yaml \
<your_output_file>
```
Exit 0 = PASS, exit 1 = FAIL with specific missing elements listed, exit 2 =
the checker could not read one of its own inputs and reached no conclusion.
`compliance.yaml` in this skill directory enumerates every required element of
your output, and its `X_verdict_boundary` cross-check is what stops this report
from drifting into being a gate.
**Your task is not complete until the audit returns PASS.** Missing elements are
the single largest source of skill-execution non-determinism across agents.