Every scenario costs run time, memory and review effort. Scenarios that are never the worst at any endpoint add cost but no information. Pruning removes them, but only against a stated tolerance, and only after checking the evidence, because a scenario dropped on the basis of one run can come back as the worst on the next.
# Setup slack (ns) at five endpoints in four scenarios (illustrative).
slack = {
"S1_ss_cworst": [0.05, 0.12, -0.02, 0.30, 0.08],
"S2_ss_rcworst": [0.07, 0.10, 0.01, 0.28, 0.20],
"S3_ss_cold_cw": [0.04, 0.15, 0.03, 0.35, 0.09],
"S4_tt": [0.20, 0.25, 0.18, 0.40, 0.30],
}
names = list(slack)
n = 5
worst = [min(names, key=lambda s: slack[s][i]) for i in range(n)]
counts = {s: worst.count(s) for s in names}
assert counts == {"S1_ss_cworst": 2, "S2_ss_rcworst": 2, "S3_ss_cold_cw": 1, "S4_tt": 0}
def needed(tol):
# scenarios needed so that every endpoint has a kept scenario within tol of its true worst slack
covered = [False] * n
kept = []
remaining = list(names)
while not all(covered):
best = max(remaining, key=lambda s: sum(
1 for i in range(n) if not covered[i] and slack[s][i] - min(slack[t][i] for t in names) <= tol + 1e-12))
kept.append(best)
remaining.remove(best)
for i in range(n):
if slack[best][i] - min(slack[t][i] for t in names) <= tol + 1e-12:
covered[i] = True
return sorted(kept)
assert needed(0.0) == ["S1_ss_cworst", "S2_ss_rcworst", "S3_ss_cold_cw"]
assert needed(0.025) == ["S1_ss_cworst"]
print("PASS: worst-counts", counts, "; kept at tol 0:", len(needed(0.0)), "; kept at tol 0.025:", needed(0.025))With zero tolerance, three scenarios are needed and the typical-corner scenario S4 is the one to drop: it is never the worst. With a tolerance of 0.025 ns, S1 alone is within tolerance of the true worst slack at every endpoint, so S2 and S3 could also be dropped, at the price of reporting slacks up to 0.02 ns optimistic at some endpoints. The tolerance is a policy: it should be smaller than the margin the team keeps elsewhere.
Rule | Why |
|---|---|
Prune on endpoint data from the current netlist | A change in netlist or constraints can move the worst scenario |
Keep at least one scenario per voltage domain and per mode | Pruning must not remove a condition completely |
Re-test the pruned set against the full set before final signoff | Pruning is for closure effort; final signoff runs the full list unless the signoff policy accepts an evidenced pruned set |
Write down the tolerance | Otherwise the optimism is invisible |
Pruned scenarios appear in a list with the evidence and tolerance used.
Final signoff runs the full list unless the signoff policy accepts an evidenced pruned set.
Pruning is reviewed after each major netlist or constraint change.
It is never the worst at any endpoint: another scenario has smaller slack everywhere, so S4 adds no information about the worst case.