Skip to main content

ClosureSettings

Struct ClosureSettings 

Source
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: u32

Percent 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: u32

Margin 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//status VmHWM.

§cap_margin_pct: u32

Percent 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: u32

Fanout 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: u32

Iterations 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: f64

Placement 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: f64

Global-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: u32

The 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: u32

The 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: u32

Ratio 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: u32

Iterations for the same pre-detailed-route repair. PDK default 15.

§diodes_before_resize: bool

Insert 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: bool

At 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: bool

After 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: u32

How 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: bool

Detect 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: bool

Upsize 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: bool

Build 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: bool

Split 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: u32

Loads 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: bool

Run 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: AntennaStrategy

Whether antenna is closed with diodes, or with the jog-router alone. See AntennaStrategy.

§routing_cores: u32

Pin 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: bool

The 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

Source§

fn clone(&self) -> ClosureSettings

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ClosureSettings

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ClosureSettings

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl PartialEq for ClosureSettings

Source§

fn eq(&self, other: &ClosureSettings) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for ClosureSettings

Source§

impl StructuralPartialEq for ClosureSettings

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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>

Convert 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)

Convert &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)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,