Closure is a trajectory, and a single run tells you almost nothing about it. A per-group history shows whether you are converging, whether a recent change helped or hurt, and when the project can realistically sign off.
Field | Why |
|---|---|
Run identifier and date, netlist and constraint versions | So the run can be reproduced and compared |
Per group: WNS, TNS, failing endpoints (setup and hold) | The progress measure |
Corner or view | Results from different views are not comparable |
Open systemic issues and owners | What is being worked on and by whom |
Notes on changes since the last run | Explains movement |
history = [ # (day, group, FEP)
(1, "clk_core", 5000), (2, "clk_core", 3100), (3, "clk_core", 900), (4, "clk_core", 40), (5, "clk_core", 0),
(1, "clk_io", 30), (2, "clk_io", 30), (3, "clk_io", 55), (4, "clk_io", 60), (5, "clk_io", 62),
]
def trend(g):
pts = [f for d, gg, f in history if gg == g]
return pts[-1] - pts[0]
assert trend("clk_core") == -5000
assert trend("clk_io") == 32
stalled = [g for g in ("clk_core", "clk_io") if trend(g) > 0]
assert stalled == ["clk_io"]
print("PASS: converging: clk_core; regressing group:", stalled)clk_core converges to zero in five days; clk_io, which looked healthy on day one, slowly regresses from 30 to 62 failing endpoints. The summed total would fall from 5,030 to 62 and hide the regression in one group, and a latest-run view would never show the trend. Tracking per group per day is what catches slow regressions.
The dashboard shows setup and hold, per group, per view, with a trend line.
Every reported improvement is checked against the inputs: a better number from a looser constraint is not progress.
Closure criteria (zero failing endpoints, or a signed-off list) are defined at the start.
A change in constraints moves slack without any design change. With the version recorded, a jump in results can be explained by the inputs, preventing false progress or false regression.