If all paths were ranked together, a clock domain with a severe violation would absorb all optimisation effort while a faster, tighter domain sat just outside the reports. Grouping makes each domain, and categories such as I/O, visible and optimised on its own terms.
Group | Contents | Why separate |
|---|---|---|
One group per capture clock | All paths captured by that clock | Each clock's closure is tracked independently |
Input to register | Paths from input ports | Constraints come from the interface contract |
Register to output | Paths to output ports | Same |
Clock gating checks | Enable-to-gate checks | Different check type |
Asynchronous / recovery-removal | Reset and async set/clear checks | Different check type |
Optimisation tools can weight groups or set a margin target per group (a group that must reach +0.05 ns rather than zero). Weights are a project policy: they say which group matters most when effort is scarce.
groups = {"clk_core": [0.12, -0.05, 0.30], "clk_io": [-0.40, -0.25, -0.02], "in2reg": [0.50], "gating": [0.10, 0.08]}
summary = {g: (min(s), sum(x for x in s if x < 0), sum(1 for x in s if x < 0)) for g, s in groups.items()}
assert summary["clk_core"] == (-0.05, -0.05, 1)
assert summary["clk_io"][0] == -0.40 and abs(summary["clk_io"][1] + 0.67) < 1e-9 and summary["clk_io"][2] == 3
assert summary["gating"][2] == 0
worst_group = min(summary, key=lambda g: summary[g][0])
assert worst_group == "clk_io"
print("PASS: per-group (WNS, TNS, FEP):", summary)Looking only at the chip-wide WNS (-0.40, in clk_io) would miss that clk_core also fails. Per group, clk_core has a single marginal endpoint (-0.05), clk_io fails three endpoints (TNS -0.67), and the other two groups are clean. The work divides naturally: one group needs a systemic look, the other a local fix.
Every group is reported with its WNS, TNS and failing endpoint count; groups with zero endpoints are explained (a missing clock?).
Group weights are a documented policy, not tuned per run.
Checks such as gating and recovery appear in their own groups and are not left out of the summary.
Probably A: a systemic problem across 5,000 endpoints (for example a clock or constraint issue) has the highest total impact, even though its worst slack is small. B is a local fix for two paths.