pub struct ClosureSettings {Show 31 fields
pub synth_strategy: Option<SynthStrategy>,
pub slew_margin_pct: u32,
pub pl_slew_margin_pct: u32,
pub cap_margin_pct: u32,
pub heuristic_antenna_threshold: u32,
pub antenna_eco_iters: u32,
pub target_density: f64,
pub met1_route_penalty: f64,
pub grt_overflow_iters: Option<u32>,
pub grt_adjustment: Option<f64>,
pub dpl_cell_padding_per_side: Option<u32>,
pub clock_max_wire_um: u32,
pub signal_max_wire_um: u32,
pub grt_antenna_margin_pct: u32,
pub grt_antenna_iters: u32,
pub diodes_before_resize: bool,
pub eco_diode_fallback: bool,
pub post_diode_upsize: bool,
pub post_diode_upsize_margin_pct: u32,
pub post_diode_upsize_all_corners: bool,
pub post_antenna_upsize: bool,
pub cts_within_fanout: bool,
pub diode_fanout_repair: bool,
pub fanout_margin_loads: u32,
pub glb_skip_pin_swap: bool,
pub antenna: AntennaStrategy,
pub routing_cores: u32,
pub pdn_vpitch_um: Option<f64>,
pub hold_slack_margin_ns: Option<f64>,
pub setup_slack_margin_ns: Option<f64>,
pub comparative: bool,
}Expand description
The electrical-closure settings, separated from the rest because they are the ones that were actually measured and the ones a future change is most likely to get wrong.
Fields§
§synth_strategy: Option<SynthStrategy>The ABC script technology mapping runs, or OpenLane’s default (AREA 0) when None.
MEASURED on wpe_user_project (191,641 generic gates between 32,779 inputs and 32,773 outputs, the
on-die tables’ read multiplexers most of them): AREA 0 opens with fx; mfs, and its ABC pass had
run 2 h 15 min without finishing when it was stopped (RUN_2026.09.25_19.58.43). AREA 3
(strash; dch; map) mapped the same extracted netlist in 6 min 8 s, to 240,032 cells and
1.86 mm² of logic with an 8.56 ns critical path against a 40 ns clock.
slew_margin_pct: u32Percent margin repair_design targets below the slew limit.
MEASURED on gpu_simt (79,965 cells): at OpenLane’s defaults (PL 20 / GLB 10) the block
signed off carrying 6 max-slew violations. At 30 it reached slew 0 — and the design
got better in every other respect at the same time: max-fanout 3,999 -> 847, setup slack
+3.75 -> +4.48 ns, cell count 79,965 -> 69,080. Buffering for slew shortens the electrical
paths that were forcing large drivers elsewhere.
IT INTERACTS WITH THE CLOCK-DRIVER DECLARATION, and the interaction is large. Declaring
SYNTH_CLK_DRIVING_CELL (see PdkTarget::clk_driving_cell) makes the clock port’s assumed
edge FAST, which removes the pessimism that was inflating every downstream transition — and
with it the resizer’s reason to buffer. On systolic_os_pipe8_realbist (392k cells) the two
nearly-identical runs differ only in that setting: slew went 3 -> 89, all 89 of them
MARGINAL (0.93-1.01 against a 0.75 limit) and the design 3k cells SMALLER. At margin 45 the
same configuration reached slew 0, with setup +2.03 and XOR back to 0. So the clock fix is
right and needs the margin raised alongside it, not reverted.
45 IS NOT A SAFE DEFAULT. The placement resizer destabilises at high margin in a size-dependent way: measured OK at 45 on 417k and 392k cells, CRASHES at 45 on 819k and 204k, and crashes at 60 on 417k. Raise it per block against a measured failure, not globally.
AND THE FAILURE MODE AT SIZE IS MEMORY, NOT A CRASH — which matters because it does not
look like a failure. On systolic_pipe16_realbist (457k cells) at margin 45 the
PLACEMENT RESIZER alone reached 92.9 GB resident after 38 minutes, still at step 9, with
detailed routing — the real peak — ahead of it. The kernel had already taken one openroad
at 98.7 GB on this 125 GB box that day, and an OOM kill leaves an EMPTY .errors file and
a log that simply stops, so it reads as a mystery crash rather than as this setting. Three
runs were lost that way before the cause was identified. At margin 30 the same block
completes.
So the size dependence is a memory curve with a cliff, and 457k cells sits just past the safe edge: 392k and 417k are fine at 45, 457k is not. Between “works” and “OOM” there is no warning, because the resizer gives none.
MARGIN 35 ALSO OOMs ON 457k. The cliff is not between 35 and 45; it is below 35, and only
the default 30 completes on that block. Measured with a 45-SECOND SAMPLER the peak read
83 GB — comfortably under the wall — while the kernel still took the process, because a
sampler misses the spike between polls. Read /proc/<pid>/status VmHWM for the true
high-water mark; a sampled peak is an underestimate and will tell you a run was safe when
it was not.
THIS DRIVES THE ROUTING-STAGE (GLB) RESIZER ONLY. It used to drive the placement (PL)
resizer too, and that coupling is a trap: the two have DIFFERENT failure modes, so
raising the one that helps necessarily raised the one that explodes.
GLB (step 15, repair_design after global route) is where the slew repair that closed
systolic_os_pipe8_realbist happened — 89 -> 0 at margin 45.
PL (step 9, before CTS) is where the memory goes. On systolic_pipe16_realbist (457k
cells) it reached a TRUE peak of 114 GB (VmHWM) at margin 35 on a 125 GB box and was
OOM-killed; margin 45 and margin 35-with-fewer-diodes did the same.
Split so a block can take the slew repair it needs without the placement resizer that
cannot afford it. See pl_slew_margin_pct.
pl_slew_margin_pct: u32Margin for the PLACEMENT resizer (step 9). Kept at the safe default independently of
slew_margin_pct because this is the one with the memory cliff — measured OK at 45 on
392k and 417k cells, OOM at 35 on 457k, OOM at 45 on 819k.
A NOTE ON MEASURING IT: a sampled peak is not a peak. A 45-second sampler read 83 GB on a
run whose true VmHWM was 114 GB, i.e. it reported “comfortably under the wall” about a
process the kernel was killing. Read /proc/
cap_margin_pct: u32Percent margin below the capacitance limit. Same mechanism, same call
(repair_design -cap_margin); fabric_horner_seq is the only block with nonzero max-cap
(7), so this is carried at the same value rather than tuned separately.
heuristic_antenna_threshold: u32Fanout above which the heuristic diode pass inserts a protection diode.
THE RELATIONSHIP IS NOT MONOTONIC, and reading it as monotonic wastes runs in both directions. It is a U-curve whose optimum depends on how large the residual already is.
AT A LARGE RESIDUAL, RAISE IT. A low threshold floods the design with diodes that crowd
out the ones that would have mattered — post-fill there is no free site left for the
diode the ARC check actually wants. Measured: gpu_simt 10 -> 300 took antenna 4 -> 2;
coproc_core residual 15 at 300 against 23 at 160; systolic_os_pipe8_realbist built at
10 came out 536,104 cells with 8 max-slew violations against 392,221 cells with 3 at 300.
The flood is not subtle at the bottom end: soft_core_scalar at threshold 10 inserted
7,527 diodes into a 14,700-cell design — over half the instances — and died at GRT-0119.
AT A SMALL RESIDUAL, LOWER IT. Once the count is down to single digits the remaining
violators are often nets the pass simply never selected, and there is no flooding risk
left to avoid. Measured the same afternoon, on the same blocks that produced the numbers
above: systolic_os_pipe8_realbist 300 -> 150 took antenna 3 -> 0 and CLOSED the block;
coproc_core 300 -> 150 took 5 -> 2 with max-slew still 0.
So the default stays 300 because a block’s FIRST run is always in the large-residual regime, and 150 is the endgame move once the count is small and a diode-less violator is visible in the report. Both directions are real; neither generalises.
AND IT CANNOT FIX EVERYTHING. A violator whose pin ALREADY carries a diode is beyond this
lever entirely — measured on coproc_core, where all 7 survivors had one. That case needs
grt_antenna_margin_pct (which acts before the blocking geometry exists), a base-route
change, or narrower RTL.
antenna_eco_iters: u32Iterations of the SAT jog-router antenna ECO.
MEASURED on gpu_simt: the ECO converges 8 -> 2 -> 1 in its first THREE iterations and
then sits at 1 for twenty-eight more. So this is sized for convergence, not for grinding;
raising it further buys nothing. A residual that survives here is a side-area violation,
which no number of diode iterations can fix.
target_density: f64Placement density.
NEGATIVE RESULT, recorded so it is not re-tried: 0.40 is WORSE than 0.45 for gpu_simt
(antenna 4 vs 2, cells 43,952 vs 43,564) even though 0.40 is exactly what finally cleared
coproc_core’s last violator. The difference is the violation’s KIND — coproc’s residual
was a met5 routing detour that a different base route removed, gpu_simt’s is a met1
side-area violation that a density change does not touch. Sweep density only against an
upper-layer detour.
met1_route_penalty: f64Global-route cost penalty on met1, 0..1 (higher = the router avoids met1 more).
MEASURED — this is what finally closed gpu_simt. After slew/cap margin and the diode
threshold, one met1 SIDE-AREA antenna violator survived at ratio 1.14. It could not be
dioded (a diode addresses gate area; side area is perimeter with no diffusion term), the
jog router plateaued on it (8 -> 2 -> 1 in three ECO iterations, then 1 for twenty-eight
more), and a density sweep made it WORSE. Forbidding met1 for signals outright
(RT_MIN_SIGNAL_LAYER=met2) FAILED TO ROUTE even at 25% core utilisation — the design
needs met1 capacity. A cost penalty is the version that works: met1 stays available so it
cannot congest, but the router stops building long met1 runs. At 0.7 the block reached
antenna 0/0 with every other gate still at zero.
grt_overflow_iters: Option<u32>The rip-up iterations global routing spends removing overflow (GRT_OVERFLOW_ITERS), or OpenLane’s own 50 when
None. Every global route of the flow takes it, the resizers’ re-routes and the fanout step’s included.
MEASURED on wpe_user_project at 16 ns (the private tree’s RUN_2026.10.19_19.38.51 and its variants): at 50 the
route stopped at GRT-0119 with gcells at the die center over by one to three tracks; at 150 and at 400, every
other setting held, it stopped the same way, the iterations ending once the overflow could no longer grow
(GRT-0230; RUN_2026.10.19_20.34.27, RUN_2026.10.19_22.07.52). Iterations alone do not route a block whose
gcells are over capacity; with capacity given back (ClosureSettings::grt_adjustment or
ClosureSettings::met1_route_penalty) the same block routed at 150 with no overflow.
grt_adjustment: Option<f64>The share of every gcell’s capacity global routing holds back, 0..1 (GRT_ADJUSTMENT), or OpenLane’s own 0.3
when None. The reserve is room detailed routing has for vias, pins and blockages the global grid does not see;
a block that cannot route under it trades some of that room for capacity.
MEASURED on wpe_user_project at 16 ns, 150 overflow iterations: at 0.3 the global route stopped at GRT-0119
(RUN_2026.10.19_20.34.27); at 0.2 it routed with no overflow, 18,902,039 um (RUN_2026.10.20_17.57.25, x5).
dpl_cell_padding_per_side: Option<u32>The sites a side every cell keeps free of its neighbours when placement is legalized (DPL_CELL_PADDING, which
OpenLane takes as a total and halves to a side), or OpenLane’s none when None. Abutting cells in a dense patch
leave detailed routing no way to reach their met1 pins; global placement is left unpadded, so its density target
still holds.
clock_max_wire_um: u32The longest wire repair_clock_nets leaves between a clock input and the tree’s root, in um
(CTS_CLK_MAX_WIRE_LENGTH).
MEASURED on wpe_user_project (2.8 x 3.4 mm, RUN_2026.09.26_17.51.01, the CTS libraries at every corner):
OpenROAD’s own limit, 3,331 um, left the 1.7 mm run from wb_clk_i to the root buffer whole, 1.125 ns at
its end against the 0.75 ns limit; at 800 um it takes four buffers and no point on it exceeds 0.353 ns —
under the post-diode upsize’s detection limit too. At 1,000 um it reaches 0.429 ns; at 500 um it rewires
fourteen of the tree’s own nets.
0 keeps OpenROAD’s own limit, as every block hardened before this was measured was built
(parse_wire_limit_um).
signal_max_wire_um: u32The longest wire either resizer leaves on a signal net, in um (PL_RESIZER_MAX_WIRE_LENGTH,
GLB_RESIZER_MAX_WIRE_LENGTH).
MEASURED on wpe_user_project (RUN_2026.09.27_06.33.43): under OpenROAD’s own 3,331 um, nets of 1,447 to
1,814 um driven by buf_12 — the strongest buffer the flow may place — signed off at 0.76-0.87 ns against the
0.75 ns limit at ss_100C_1v60, max RC, below what the post-diode upsize’s global-route estimate detects. 800 um,
the clock’s limit, splits the 2,709 of 310,043 nets routed longer (0.9%).
0 keeps OpenROAD’s own limit (parse_wire_limit_um).
grt_antenna_margin_pct: u32Ratio margin for the GLOBAL-ROUTE antenna repair (repair_antennas -ratio_margin),
as a percent. The PDK default is 10.
WHY THIS LEVER IS DIFFERENT FROM EVERY OTHER ANTENNA LEVER, and why it was worth adding:
it is the ONLY antenna repair that runs BEFORE detailed routing. Everything else in this
struct acts afterwards, and by then TritonRoute has patched nets with via-enclosure RECTs
that the jog router cannot bridge (odb exposes no way to round-trip that geometry from
Python — getRect needs out-params, there are no SWIG pointer helpers, and
dbWireShapeItr is unbound; all three checked). A net that reaches detailed routing
already violating, and already carrying a diode, has NO repair left. This one gets in
first.
MEASURED on coproc_core (180k cells, narrow-multiply RTL): raising 10 -> 50 with
grt_antenna_iters 15 -> 25 took the antenna residual 11 -> 5 with max-slew still 0 and
every other gate at zero. Nothing else in the run changed. The repair itself is cheap —
3 diodes placed at margin 50 against 1 at margin 10 — because global route works from an
ESTIMATE and only sees the worst offenders; that is also why it cannot be the whole fix.
IT HAS AN OPTIMUM, NOT A DIRECTION. Pushing further on the same block — 50/25 -> 100/40,
every other setting held — took the residual from 1 net back up to 8, including a new met5
violator (ratio 1.10 against a 3486.68 requirement). Over-repairing at global route inserts
diodes and layer changes against an ESTIMATE, and detailed routing then lands elsewhere.
Measured points on coproc_core: 10 -> 11 nets, 50 -> 5 (then 1 with threshold 100),
100 -> 8. Stay at 50.
grt_antenna_iters: u32Iterations for the same pre-detailed-route repair. PDK default 15.
diodes_before_resize: boolInsert antenna diodes BEFORE the slew/cap resizer instead of after it
(LOGOS_DIODES_BEFORE_RESIZE, implemented in scripts/tcl_commands/routing.tcl).
The base order sizes every driver and THEN hangs diodes on its net, so the resizer never
sees the load it is sizing for. Measured on two blocks: 25 of coproc_core’s 69 slew
violators were diode pins, and every violating driver net on systolic_pipe16_realbist
carried diodes. Both symptom-side fixes failed — re-repairing after the diodes congested
or backfired (3,587 buffers for 7 violations, slew 69 -> 181), and raising the resizer
margins hit a 114 GB OOM in the placement resizer and a 40-minute stall in the routing one.
Heuristic diode insertion reads placement, not routing, so it can legally run first.
MEASURED NEGATIVE, which is why it stays off. On systolic_pipe16_realbist (margins 30/30,
everything else held) it made max-slew 27 -> 123, antenna 18 -> 25 nets, and squeezed setup
to +0.42 ns. Sizing drivers for diodes that are already present does not help when the
diodes themselves are the problem: most of the design’s ~18k heuristic diodes are joined to
their nets above the violating layer and are not credited there at all (see
eco_diode_fallback), so they are load with no antenna benefit.
eco_diode_fallback: boolAt the jog router’s fixpoint, add ONE more diode at each still-violating pin (the
manual-stub ECO in routing.tcl, LOGOS_ECO_DIODE_FALLBACK) instead of stopping.
The jog and the diode ECO were written either/or: with the jog enabled the diode ECO was
unreachable code, so the nets the jog cannot bridge were exactly the nets nothing repaired.
Every remaining violator on coproc_core and systolic_pipe16_realbist had that shape —
one heuristic diode already on the pin, ratio still 1.0-1.4x, and a via-enclosure RECT the
jog cannot round-trip. One diode’s diffusion is not enough and no pass ever added a second.
The stub ECO runs no router, so it cannot strand a net; any geometry problem it caused
would surface at the fail-closed DRC/LVS/XOR gates rather than as a false clean.
post_diode_upsize: boolAfter the diodes are in, grow the driver of each net that violates max slew WITH its diodes
present, or buffer that one net when its driver is already the strongest of its function
(LOGOS_POST_DIODE_UPSIZE, scripts/openroad/logos_post_diode_upsize.tcl).
The surgical successor to the whole-design post-diode repair (3,587 buffers for 7
violations, slew 69 -> 181). Every surviving slew violator on systolic_pipe16_realbist
was driven by an a21oi_4/a31oi_4 — the top of its family, so no upsize reaches it.
Measured offline on that block’s post-diode netlist: 22 nets selected, 28 drivers grown,
15 nets rebuffered, +26 cells of 457k, 0 residual after 7 rounds, about five minutes; the
three culprit drivers went from 0.41-0.43 ns estimated slew to at most 0.13 ns.
post_diode_upsize_margin_pct: u32How far below the real limit the upsize DETECTS, in percent. The global-route estimate is about 2x optimistic on the nets signoff flags (0.37-0.43 ns estimated vs 0.75-0.85 ns signed off) but ranks them correctly: at 52% (0.36 ns) all 15 of pipe16’s signoff-violating pins are selected among 103 pins on 22 nets; at 0.40 ns two are missed; 0.34 ns selects 442 pins and 0.30 ns 2,081. Signoff still judges against the real limit.
post_diode_upsize_all_corners: boolDetect the upsize’s violators at EVERY library corner (ss / tt / ff), not the typical one
alone (LOGOS_UPSIZE_ALL_CORNERS). Signoff judges slew at ss_100C_1v60; every surviving
violator on systolic_pipe16_realbist and systolic_os_pipe8_realbist
(RUN_2026.09.23_14.05.55 / _11.27.15) was slow-corner only, typical slew 0.
post_antenna_upsize: boolUpsize again after global routing’s antenna repair, with that repair’s diodes present, then re-route without
it (LOGOS_POST_ANTENNA_UPSIZE, scripts/tcl_commands/routing.tcl).
repair_antennas runs after the post-diode upsize and hangs diodes on nets it has already sized. MEASURED on
wpe_user_project (RUN_2026.09.27_06.33.43): up to 20 on a single-sink net of 255-299 um (ANT-0009, more than
10 diodes per gate), and 13 of its 21 slow-corner slew violators were such nets, each driven by the strongest
cell of its function. Replayed on that run’s post-repair route, the upsize found and repaired all 13 (+151
cells). Off unless chosen: it adds a global route.
cts_within_fanout: boolBuild the clock tree within the SDC’s set_max_fanout (LOGOS_CTS_FANOUT, scripts/openroad/cts.tcl and
logos_cts.py): leaf clusters of at most the limit’s sinks, H-tree splits balanced, and the tree deep enough
that a balanced leaf averages under the limit.
At OpenLane’s defaults a leaf cluster may hold 25 sinks and each H-tree split may hand one branch 60% of its
parent’s clusters, so the imbalance compounds level by level. MEASURED on gpu_simt’s placement
(RUN_2026.09.23_09.37.32, CTS replayed): 33 clock nets over a limit of 10 at the defaults; 3 with clusters
held to 10, every one an H-tree leaf driving 11-12 cluster buffers; 0 with the splits balanced too, from the
same 317 clock buffers, skew 0.54 -> 0.48 ns. A shallower or deeper unbalanced tree is worse, not better:
at a maximum of 7 or 5 leaf sinks, 4 nets stayed over (up to 16) and 5 added 160 buffers. Every signed-off
block’s clock violators were these leaves: 703 on wpe_user_project, 295 on systolic_pipe16_realbist.
diode_fanout_repair: boolSplit every net the diode passes take over set_max_fanout by whole gates, each with the diodes placed for
it (LOGOS_DIODE_FANOUT, scripts/openroad/logos_diode_fanout.tcl), after the pre-route diodes and again
after global routing’s antenna repair; and hold the post-route diode ECO under the limit.
The resizer meets the limit on every logic net — all 23 signed-off blocks had 0 logic nets over it — and
the liberty counts a diode as a load, so every non-clock violator signoff reported was a diode count:
5,052 of wpe_user_project’s 5,755 (ten mux2 inputs with a heuristic diode each read as 20; global
routing’s repair put up to 26 on one net), 2,384 on systolic_pipe16_realbist, 1,101 on coproc_core.
OpenROAD’s own single-net repair clears them but groups pins, not gates: replayed on gpu_simt’s
post-diode placement it moved 295 of 1,907 diodes off their gate’s net. Grouping whole gates cleared all
151 signal nets there with 283 buffers and every diode still on its gate’s net.
fanout_margin_loads: u32Loads every net is built under the SDC’s set_max_fanout (LOGOS_FANOUT_MARGIN,
scripts/openroad/logos_fanout_limit.tcl): CTS and the diode-aware fanout step build to the limit less this,
and every report and signoff judge the limit itself.
It is room for the one load a pass after routing can add. The post-route antenna ECO adds a diode at a pin the
checker still flags; on a net built to the limit it has nowhere to put it. MEASURED on gpu_simt
(RUN_2026.10.03_07.00.23, built to the limit): pin _13114_/C, met1 ratio 1.02, on a net of ten gates and no
diode — refused, and the block missed antenna by that one pin.
The margin is kept by the steps that know which loads are critical, never by the SDC the resizers repair
against. MEASURED NEGATIVE, the SDC way (RUN_2026.10.03_07.23.27): repair_design split every ten-load net
without regard to slack, the slow-corner critical path went from 2 to 6 fanout-buffer pins, and setup slack
from +0.27 to -0.01 ns, past what a full setup repair could recover. Kept by the fanout step instead — a net at
the limit split like a diode-laden one, its least-slack gates left on the driver — the same block signed off
with every gate at zero and setup +0.19 ns (RUN_2026.10.03_07.35.09; 493 nets split, 644 buffers, 2.6% of its
nets sit at exactly the limit).
glb_skip_pin_swap: boolRun global-route timing repair without pin swapping (LOGOS_GLB_SKIP_PIN_SWAP). OpenROAD
41a51eaf’s post-route repair_timing lost one net’s driver from its route tree on
soft_core_realbist (RSZ-0073 x51 on _19008_/Y, every signal net routed) and died on SIGSEGV
under both antenna recipes; the same step with -skip_pin_swap completes. Sizing, buffering
and hold repair are untouched.
antenna: AntennaStrategyWhether antenna is closed with diodes, or with the jog-router alone. See AntennaStrategy.
routing_cores: u32Pin the router’s thread count so a run reproduces regardless of what else the box is doing. The divergence this prevents (a design converging 25 -> 0 DRC reaching 22,090 -> 27,653 under load) is thread oversubscription, not load itself.
pdn_vpitch_um: Option<f64>The vertical power-strap pitch in um (FP_PDN_VPITCH), or OpenLane’s own (153.6 on sky130) when None.
A standard cell is fed along its met1 rail from the nearest vertical strap, so a cell midway between two
straps sees the longest rail, and the drop along it grows with the square of that run. MEASURED on
fabric_horner_seq (RUN_2026.10.03_14.54.29, anchored area sources on the strap pitch): worst 90.13 mV
against the 90 mV gate, at x 98.6-101.9 um — midway between its straps at x 21.8/25.1 and 175.4/178.7 —
while the block’s average was 9.36 mV. Only the pitch shortens the rail; placement density and die size do not.
The gate is each cell’s droop, its supply’s drop plus its ground’s rise at the cell: the same block’s worst cell
drooped 106.45 mV at 76.8 um and 66.50 mV at 38.4 um (RUN_2026.10.20_17.57.25: supply 33.88 mV, ground 34.06 mV).
hold_slack_margin_ns: Option<f64>The hold repair’s slack margin in ns, for the placement and the global-route repair both
(PL_/GLB_RESIZER_HOLD_SLACK_MARGIN), or OpenLane’s own (0.1 and 0.05) when None.
The repair judges hold on estimated parasitics and signoff on extracted ones, so the margin must cover the
difference. MEASURED on systolic_pipe16_realbist (RUN_2026.10.03_18.45.27): the global-route repair met
its 0.05 ns, and signoff read -0.01, -0.03 and -0.04 ns at the fastest corner on the min, nominal and max RC
corners, after routing took the clock skew from 0.52 ns at CTS to 1.05 ns at max RC — an estimate 0.09 ns
optimistic.
setup_slack_margin_ns: Option<f64>The setup repair’s slack margin in ns, for the placement and the global-route repair both
(PL_/GLB_RESIZER_SETUP_SLACK_MARGIN), or OpenLane’s own (0.05 and 0.025) when None.
The repairs judge setup on global-route estimates at the nominal RC corner and stop once those close; signoff
times the routed design extracted at the max-RC corner. MEASURED on wpe_user_project at 18.5 ns
(RUN_2026.10.25_06.23.41, every net routed): the repairs closed to +0.03 ns on their estimates, and the routed
design read -0.37 ns extracted at the nominal corner and -1.13 ns at the max-RC corner, at ss_100C_1v60.
comparative: boolThe block is measured beside others (the comparative-synthesis bench), not signed off. A run whose typical
corner misses setup completes and records the slack it missed by, so a period search can read the period the
block needs; yosys’s check findings (latches, out-of-range selects, undriven wires) are left to the recorder,
which records them, rather than stopping the flow. Hold stops it either way. Antenna closes with every repair
the flow has, ClosureSettings::eco_diode_fallback among them: one flow serves every candidate of a
comparison, and the bench’s first attempts met timing and ended on the residual it repairs
(qorsyn_k1_bambu_pipe_c_a7p10_p32_5, RUN_2026.10.17_01.53.18: one met4 net at 1.02 times its limit). A
signoff block never sets it. It is synthesized for delay (COMPARATIVE_SYNTH_STRATEGY) unless its caller
names a strategy.
Trait Implementations§
Source§impl Clone for ClosureSettings
impl Clone for ClosureSettings
Source§fn clone(&self) -> ClosureSettings
fn clone(&self) -> ClosureSettings
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ClosureSettings
impl Debug for ClosureSettings
Source§impl Default for ClosureSettings
impl Default for ClosureSettings
Source§impl PartialEq for ClosureSettings
impl PartialEq for ClosureSettings
impl Copy for ClosureSettings
impl StructuralPartialEq for ClosureSettings
Auto Trait Implementations§
impl Freeze for ClosureSettings
impl RefUnwindSafe for ClosureSettings
impl Send for ClosureSettings
impl Sync for ClosureSettings
impl Unpin for ClosureSettings
impl UnsafeUnpin for ClosureSettings
impl UnwindSafe for ClosureSettings
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.