Tracking Endpoint Slack Across Flow Steps#
When working on an optimization (resizing, buffering, CTS, repair timing,
…) it is useful to see how the slack of each timing endpoint moves from
one flow step to the next, not just how WNS/TNS change. ORFS can record the
setup and hold slack of every endpoint at the end of every flow step
(1_synth, 2_1_floorplan, …, 3_3_place_gp, …, 6_final) and compare
any two steps, including a scatter plot of slack (x: earlier step, y: later
step).
Recording#
Set REPORT_ENDPOINT_SLACK=1:
cd flow
make DESIGN_CONFIG=designs/nangate45/gcd/config.mk REPORT_ENDPOINT_SLACK=1
Every step then writes $(REPORTS_DIR)/<step>_endpoint_slack.json, e.g.
3_3_place_gp_endpoint_slack.json. The snapshot is taken by
write_endpoint_slack in flow/scripts/util.tcl, called from
orfs_write_db so the step name is the name of the .odb the step writes.
It works in the single-process flow/scripts/flow.tcl flow as well. Steps
that just copy their input (orfs_copy_db, e.g. 5_3_fillcell without fill
cells) re-time the design if it is loaded, or else copy the previous step’s
snapshot. Intermediate .odb files written through orfs_write_db (e.g. CTS
save_progress) also get a snapshot; *-failed ones don’t.
A placed step is timed with the parasitics OpenROAD has for it: a bare
estimate_parasitics estimates from the global routes when there are any,
else from placement, and does nothing once read_spef has read the
extracted parasitics:
Steps |
Parasitics |
|---|---|
before placement, and |
|
placed, before global route |
|
global route and later |
|
|
|
The parasitics model is recorded in each snapshot and shown by
endpointSlack.py. Slack changes between steps with different models (e.g.
2_4_floorplan_pdn to the first placed step, 4_1_cts to 5_1_grt, or
6_1_fill to 6_final) include the change of model. Detailed routing is
only extracted in 6_final, so 5_2_route to 6_1_fill show global routing
estimates.
Each file contains design, step, parasitics, time_unit (seconds per
time unit of the values) and endpoints: a map from every endpoint pin
(sta::endpoints) to [setup slack, hold slack], null where the endpoint
is unconstrained. The slack is the pin’s worst slack over all path groups
and clocks (get_property $pin slack_max|slack_min). On asap7/swerv_wrapper
(about 30k endpoints) a snapshot is about 1 MB and takes about 10 s, mostly
the timing update.
Analysis#
flow/util/endpointSlack.py only uses the Python standard library.
R=reports/nangate45/gcd/base
# Steps in execution order with parasitics, WNS, TNS and violation counts
python3 util/endpointSlack.py list $R
# Compare consecutive steps across the whole run; --html also writes a
# scatter for every step vs. its successor and an index.html to a directory
python3 util/endpointSlack.py track $R --html track
# Compare two steps; -o writes an interactive HTML scatter
python3 util/endpointSlack.py compare \
$R/3_5_place_dp_endpoint_slack.json $R/4_1_cts_endpoint_slack.json \
--unit ps -o compare.html
# Flatten all snapshots into one CSV (one row per endpoint per step)
python3 util/endpointSlack.py export $R -o slack.csv
For setup and hold, compare reports:
endpoints in both steps, and how many improved, degraded, stayed the same, became violating (
newly failing) or stopped violating (newly passing), with statistics of the slack change (B - A). Improved, degraded and unchanged exclude endpoints with positive slack in both steps, which are not being optimized;endpoints only in A or only in B, i.e. added or removed from the netlist;
endpoints in both netlists but constrained in only one of them;
how well the two steps agree on the critical endpoints (see below).
Unconstrained endpoints, such as the outputs of CTS dummy load cells, are ignored.
Agreement metrics#
Correlation over all endpoints is dominated by endpoints with large positive
slack and is close to 1 even when the critical endpoints change a lot (0.9997
for setup on asap7/swerv_wrapper from 3_5_place_dp to 4_1_cts). The
metrics are therefore measured on a critical set: the worst K endpoints of A
or of B (--critical K, default 1000), excluding endpoints with positive
slack in both steps, which are not being optimized. When fewer than K
endpoints violate, the critical set is the endpoints violating in either
step; when nothing violates (often hold) it is empty and the metrics are
reported as -.
Metric |
Meaning |
|---|---|
|
Spearman rank correlation of A and B slack (ties get average ranks): is the order of the critical endpoints preserved? |
|
Fraction of the critical set that is in the worst K of both steps. |
|
Mean, mean absolute, root mean square and maximum absolute slack change B - A, i.e. distance from the y = x line. |
|
Of the endpoints violating in B, the fraction already violating in A (over all endpoints). |
|
Of the endpoints violating in A, the fraction still violating in B (over all endpoints). |
They are printed by compare and track, shown in the HTML stats, and
the track index has Spearman, top agreement and MAE columns for every step
transition.
Times are shown in --unit (default ns) with a fixed number of digits after
the decimal point (3 for ns, 1 for ps, or --digits), in a fixed-width font
in the HTML.
Slack changes smaller than half the last displayed digit (0.5 ps with the
default ns and 3 digits), or --tolerance in --unit, count as unchanged
for the improved/degraded counts, the tables of most degraded and improved
endpoints and the track row colors. Otherwise numerical noise, e.g. a few
femtoseconds between 5_1_grt and 5_2_route, shows up as changes that
display as 0.
--worst N restricts the endpoints in both to the union of the worst N
endpoints of A and of B, to focus on the critical part of the design.
The HTML is self-contained (no network access needed). It has:
WNS, TNS and violation counts of both steps;
a scatter of endpoint slack with a y = x line, where above the line means the endpoint improved. It is drawn on a canvas so it handles hundreds of thousands of endpoints. Drag to zoom, double-click to reset, hover for the endpoint name;
a setup/hold toggle;
tables of the most degraded and most improved endpoints, excluding endpoints with positive slack in both steps, and of the endpoints only in one step.
track --html DIR writes the same page for every step and its successor
(<step>__<next step>.html, with previous/next links) and DIR/index.html,
a table of every transition with WNS/TNS and the improved, degraded, newly
failing and newly passing counts for setup and hold. Endpoints with positive
slack in both steps are not considered. Transitions where no considered
endpoint changed (e.g. 2_2_floorplan_macro to 2_3_floorplan_tapcell) are
greyed out, and transitions where every considered endpoint improved, for
setup and hold, are green.
For other analyses, import the module (e.g. from a notebook):
load_snapshot(), load_dir(), summary(), compare(), movement(),
metrics() and spearman()
return plain Python dicts and lists.
Testing#
flow/test/test_endpointSlack.py covers loading and comparison with
synthetic snapshots and runs in the util CI job:
python3 flow/test/test_endpointSlack.py