The data path section is where fixes are chosen. Scan the Incr column for the largest steps, look at what drives them (fanout, wire length, slew), and decide the fix class. Hold reports look similar but use the earliest delays and a different requirement; reading them correctly matters just as much.
path = [("clk-to-q", 0.40), ("buf1", 0.12), ("nand", 0.18), ("net n7 (fanout 24)", 0.62), ("xor", 0.22), ("aoi", 0.16)]
total = sum(d for _, d in path)
assert abs(total - 1.70) < 1e-9
biggest = max(path, key=lambda s: s[1])
assert biggest[0].startswith("net n7")
share = biggest[1] / total
assert abs(share - 0.62/1.70) < 1e-9
print("PASS: biggest step", biggest[0], "is", round(100 * share), "% of the path")One net with fanout 24 takes 0.62 ns, 36% of the path. A report with one outlier increment points to a single targeted fix: buffer or duplicate the driver, or reduce the fanout. A flat distribution of many 0.15 ns steps points to logic depth instead.
# illustrative hold (min) report: earliest data against the capture clock plus hold time
Path Type: min (hold)
clock network delay (propagated) 0.30 0.30 <- launch
ff1/Q (DFF, min) 0.35 0.65
u1/Z (BUF, min) 0.10 0.75
ff2/D 0.03 0.78 data arrival (earliest)
clock network delay (propagated) 0.35 0.35 <- capture
library hold time 0.05 0.40
clock uncertainty 0.05 0.45
data required time 0.45
slack (MET) = arrival - required 0.33arrival = 0.30 + 0.35 + 0.10 + 0.03
required = 0.35 + 0.05 + 0.05
slack = arrival - required
assert abs(arrival - 0.78) < 1e-9 and abs(required - 0.45) < 1e-9 and abs(slack - 0.33) < 1e-9
print("PASS: hold slack", round(slack, 2), "(arrival minus required: the sign flips against setup)")In a hold report the slack is arrival minus required, the early-launch earliest data against the latest capture requirement. No derates are applied here. The period does not appear anywhere, and the delays are the minimum ones. A hold violation shows a small total on the data path: look at the clock sections for skew first and the data path second.
The report type (max or min) is checked before reading any number.
Setup reports are read for the dominant increments; hold reports for skew and for a path that is too short.
Annotations (fanout, transition, capacitance) are used to confirm the cause rather than guess.
Slack = 0.78 - 0.95 = -0.17 ns, a violation. Add delay on the data path (or reduce capture clock lateness) by at least 0.17 ns, and check the same path's setup slack afterwards.