Skip to content

rsz: Merge rsz-buffering-boost for Rebuffer QoR gain#10866

Open
minjukim55 wants to merge 18 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:secure-rsz-buffering-boost
Open

rsz: Merge rsz-buffering-boost for Rebuffer QoR gain#10866
minjukim55 wants to merge 18 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:secure-rsz-buffering-boost

Conversation

@minjukim55

Copy link
Copy Markdown
Contributor

Summary

Port of the upstream rsz rebuffering-accuracy series (original author
Martin Povišer). Core idea: rebuffer builds its buffer trees from an internal
delay/slew estimate that had drifted away from the model repair_design (and
signoff STA) actually use — so rebuffer would optimize for numbers that later
stages disagree with. The series realigns that estimate and fixes several
errors in the buffered-net cost model.

The 8 substantive commits:

  1. Move the shape factor to Resizer — relocate the slew "shape factor"
    (the NLDM-derived slew/load correction) into the shared Resizer so
    rebuffer and repair_design read one consistent value instead of keeping
    separate copies that can diverge.
  2. Use the new slew degradation model in rebufferrepair_design
    recently got a new slew degradation model; adopt the identical model inside
    rebuffer so its internal estimate matches the signed-off timing model.
  3. Fix the wire-splitting formula — stop scaling r_drvr by the shape
    factor. r_drvr is the asymptotic slew/load ratio derived from NLDM data
    and already contains the shape factor, so the extra scaling double-counted
    it.
  4. Adjust the buffering-test methodology — when measuring the delay on a
    buffered net, include the driving gate delay so the measurement uses the
    same delay definition as the estimator.
  5. Improve junction placement in the buffer topology rewrite — place the
    Steiner junctions of the rewritten buffer tree more accurately, tightening
    the estimated wirelengths and loads the cost model sees.
  6. Fix buffer-load miscount — pass loads to the gate-delay calculator
    exclusive of the driving port capacitance (the driver's own pin cap was
    being counted into the load it drives).
  7. Redo the long-wire algorithm — rework the long-wire buffering /
    length-estimation path so the iterative length estimate stays accurate on
    long, high-fanout nets.
  8. Add zero-RC guards — guard the RC math against zero wire RC (0 * inf
    NaN); fixes the STA-1350 "gate delay load cap is NaN" crash in
    fully_rebuffer on nets with no parasitics.

(The branch also carries small housekeeping commits: two clang-format fixes and
one test-golden update for the numeric churn below.)

QoR

5 random placement seeds × 2 binaries (base = pre-series, test = this branch)
on a customer design (advanced-node PDK), full flow place → CTS → route.
Everything downstream of the binary is identical (same floorplan, same seeds),
so the delta isolates the change.

  • WS = global setup worst slack (ns). % = test vs base (+ = better).
  • fmax % is derived from the global WNS so it always tracks WS — the
    per-clock fmax metric picks a different worst path and can move opposite to
    WS.

PLACE

seed WS base WS test WS % fmax %
1 -0.0959 -0.0638 +33.4% +7.39%
2 -0.0906 -0.0876 +3.3% +0.65%
3 -0.1222 -0.0707 +42.2% +11.69%
4 -0.0825 -0.1017 -23.2% -4.06%
5 -0.0871 -0.1140 -30.8% -5.55%
mean -0.0957 -0.0876 +8.5% +1.85%

CTS

seed WS base WS test WS % fmax %
1 -0.0892 -0.0569 +36.2% +7.56%
2 -0.0785 -0.0691 +12.0% +2.14%
3 -0.0885 -0.0607 +31.4% +6.45%
4 -0.1004 -0.0553 +44.9% +10.58%
5 -0.1132 -0.0366 +67.7% +18.83%
mean -0.0939 -0.0557 +40.7% +8.98%

GRT (global route)

seed WS base WS test WS % fmax %
1 -0.1433 -0.0971 +32.3% +9.89%
2 -0.0948 -0.0724 +23.6% +5.06%
3 -0.0907 -0.0889 +2.0% +0.40%
4 -0.1571 -0.0890 +43.3% +14.84%
5 -0.1201 -0.0906 +24.6% +6.42%
mean -0.1212 -0.0876 +27.7% +7.08%

Takeaway: consistent setup-WS / fmax improvement from CTS onward
(CTS +8.98%, GRT +7.08% fmax mean; 5/5 seeds improve at both stages). PLACE is
seed-noisy and nets to a small gain — the estimate matches the signed-off timing
model once CTS/routing make that model accurate.

Related Issues

Upstream rsz rebuffering-accuracy series. QoR validation tracked internally
(private).

povik and others added 11 commits July 7, 2026 15:12
Signed-off-by: Martin Povišer <povik@cutebit.org>
Recently repair_design received a new slew degradation model, use the
same model in rebuffer.

Signed-off-by: Martin Povišer <povik@cutebit.org>
r_drvr should not be scaled by the shape factor as it is derived from
NLDM data as the asymptotic slew/load ratio and as such it already
includes the shape factor.

Signed-off-by: Martin Povišer <povik@cutebit.org>
When measuring the delay on a buffered net include the driving gate
delay.

Signed-off-by: Martin Povišer <povik@cutebit.org>
Signed-off-by: Martin Povišer <povik@cutebit.org>
Fix load values passed to the gate delay calculator to be exclusive
of the driving port capacitance.

Signed-off-by: Martin Povišer <povik@cutebit.org>
Signed-off-by: Martin Povišer <povik@cutebit.org>
Signed-off-by: Minju Kim <mkim@precisioninno.com>
Signed-off-by: Minju Kim <mkim@precisioninno.com>
Cherry-picked from 86b8145b48 to fix STA-1350 gate delay load cap is
NaN crash in fully_rebuffer when a net has zero wire RC (0 * inf).

Signed-off-by: Martin Povišer <povik@cutebit.org>
Signed-off-by: Minju Kim <mkim@precisioninno.com>
Regenerate unit .ok logs (rsz/gpl/openroad), their secondary golden
outputs (.defok/.vok DEF/verilog), and aes/jpeg/ibex sky130 flow
.metrics + .metrics_limits for the numeric churn from the
estimation-accuracy rebuffering changes.

The flow pass/fail gate is .metrics_limits (check_test_metrics compares
the result against it; .metrics is the reference used to recompute the
limits). Both are regenerated from a local run of the branch binary.

Secondary DEF/verilog goldens are regenerated alongside the .ok logs so
the in-test diff_file/diff_files comparisons pass and no "Differences
found" text leaks into the committed .ok (No-Diffs-In-Ok-Files check).

Note: ibex_sky130hs DRT::ANT::errors limit moves 0 -> 1 (one antenna
violation from the changed routing). All other diffs are expected metric
shifts (buffer counts, slew/cap slack, clock skew). No crashes; verified
locally: rsz 241/241 pass, gpl tcl+py pass, openroad.upf_aes pass.

Signed-off-by: Minju Kim <mkim@precisioninno.com>
@minjukim55 minjukim55 self-assigned this Jul 10, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Note

The number of changes in this pull request is too large for Gemini Code Assist to generate a review.

…g-boost

Signed-off-by: Minju Kim <mkim@precisioninno.com>

# Conflicts:
#	src/rsz/src/RepairDesign.cc
repair_design6 is a master-added test (reroute feature). After merging
the rsz rebuffering estimation-accuracy series, the improved slew/RC
estimation inserts 215 buffers (was 285) with slightly better slack
(+115.5% vs +112.4%); no new violations. Regenerate the golden.

Signed-off-by: Minju Kim <mkim@precisioninno.com>
@minjukim55

Copy link
Copy Markdown
Contributor Author

@minjukim55
minjukim55 marked this pull request as ready for review July 13, 2026 06:43
@minjukim55
minjukim55 requested review from a team as code owners July 13, 2026 06:43
openroad-ci pushed a commit to The-OpenROAD-Project-staging/OpenROAD-flow-scripts that referenced this pull request Jul 13, 2026
Pin tools/OpenROAD at the rsz rebuffering estimation-accuracy series head
(The-OpenROAD-Project/OpenROAD#10866, upstream author Martin Poviser). This
drops the earlier SparseLU-guard bump so the submodule pin resolves against
public OpenROAD for ORFS CI.

Signed-off-by: Minju Kim <mkim@precisioninno.com>

@gudeh gudeh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes to GPL are only golden test files.

@jhkim-pii

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17d1e1d0f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/rsz/src/Rebuffer.cc
Comment on lines 371 to +373
const float load_slew
= (size.driver_resistance
+ resizer_->dbuToMeters(bnet->maxLoadWireLength() + extra_wire_length)
* wire_res)
* (bnet->cap() + extra_cap) * elmore_skew_factor_;
= size.driver_resistance * (bnet->cap() + segment_cap)
+ segment_cap * segment_res * resizer_->slew_shape_factor_ / 2;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include downstream cap in slew check

When extra_wire_length is nonzero, this check is deciding whether a buffer can drive the added wire segment, but it only charges the wire's own capacitance and omits the Elmore term for the downstream load (segment_res * bnet->cap()). addWire() and annotateTiming() propagate slew limits with wire_res * (wire_cap / 2 + p->cap()), so on long/high-cap fanout branches this underestimates the slew and can keep/export buffer options that still violate the sink max-slew budget.

Useful? React with 👍 / 👎.

int rejected_move_count_ = 0;

// For Elmore slew modeling, see computeSlewShapeFactor()
float slew_shape_factor_ = 0.0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Initialize slew factor before direct rebuffering

For standalone rsz::fully_rebuffer callers that do not run resizePreamble() first, this cached factor remains at 0 because Resizer::fullyRebuffer() only delegates to Rebuffer::fullyRebuffer() and Rebuffer::init() does not call computeSlewShapeFactor(). Existing direct flows such as src/rsz/test/rebuffer1.tcl call fully_rebuffer after parasitic estimation, so all new slew_shape_factor_ uses suppress wire/via slew degradation and can silently choose incorrect buffer trees; the previous lazy RepairDesign::getSlewRCFactor() path initialized the factor on demand.

Useful? React with 👍 / 👎.

Comment on lines +1562 to +1565
float a = wire_res * wire_cap * resizer_->slew_shape_factor_ / 2;
float b = (r_drvr * wire_cap)
+ (wire_res * ref_cap * resizer_->slew_shape_factor_);
float c = (r_drvr * ref_cap) - max_load_slew_margined;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Solve the same slew equation used for the violation

When repairing a max-slew wire violation, this quadratic should solve the same load_slew expression used to enter and update the loop a few lines above, where the entire (r_drvr * ... + wire ...) sum is multiplied by resizer_->slew_shape_factor_. Leaving the driver terms unscaled here makes the computed split length correspond to a different equation whenever the shape factor is not 1, so repeaters can be placed too far from the load and the segment can remain over the max-slew budget or require extra repair iterations.

Useful? React with 👍 / 👎.

Signed-off-by: Minju Kim <mkim@precisioninno.com>

# Conflicts:
#	test/aes_sky130hd.metrics
#	test/aes_sky130hd.metrics_limits
#	test/ibex_sky130hs.metrics
#	test/ibex_sky130hs.metrics_limits
#	test/jpeg_sky130hs.metrics
#	test/jpeg_sky130hs.metrics_limits
#	test/upf_aes.defok
#	test/upf_aes.ok
double load_slew
= (r_drvr * (c_wire + ref_cap) + r_wire * ref_cap + r_wire * c_wire / 2)
* (*slew_rc_factor_);
* resizer_->slew_shape_factor_;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r_drvr considers the slew shape factor already. Multiplication by slew_shape_factor_ (double multiplication of slew_shape_factor_) looks incorrect.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jhkim-pii r_drvr ultimately comes from LibertyPort::driveResistance(). What makes you say it considers the shape factor already?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I forgot how driveResistance is defined. So I agree, in effect it has the shape factor baked in and should not be multiplied by it.

load_slew = (r_drvr * (c_wire + ref_cap) + r_wire * ref_cap
+ r_wire * c_wire / 2)
* (*slew_rc_factor_);
* resizer_->slew_shape_factor_;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same issue

float r_drvr = resizer_->driveResistance(drvr_pin_);
assert(slew_rc_factor_.has_value());
float load_slew = r_drvr * load_cap * (*slew_rc_factor_);
float load_slew = r_drvr * load_cap * resizer_->slew_shape_factor_;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same issue

double slew_left = r_drvr * cap_left * resizer_->slew_shape_factor_;
double slew_slack_left = maxSlewMargined(max_load_slew_left) - slew_left;
double slew_right = r_drvr * cap_right * (*slew_rc_factor_);
double slew_right = r_drvr * cap_right * resizer_->slew_shape_factor_;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same issue

Comment thread src/rsz/src/Rebuffer.cc
const BnetPtr in2 = addWire(aux2, node->location(), -1);
odb::Point p1 = aux1->location();
odb::Point p2 = aux2->location();
odb::Point p3 = crit2->location();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the third point should be node->location().
crit2 is not related to the new junction point of aux1, aux2, and node.

@github-actions github-actions Bot added size/L and removed size/XL labels Jul 16, 2026
Comment thread src/rsz/test/repair_design6.ok Outdated
Pin Limit Slew Slack
---------------------------------------------------------------
_548_/B 320.000 317.570 2.430 (MET)
_326_/B 320.000 405.257 -85.257 (VIOLATED)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@minjukim55 I see this test where the violation has shown up has repair_design -reroute. Perhaps that matters

@minjukim55
minjukim55 force-pushed the secure-rsz-buffering-boost branch from c340f92 to b383f98 Compare July 16, 2026 15:07
@github-actions github-actions Bot added size/XL and removed size/L labels Jul 17, 2026
Integrate the rsz policy/optimizer refactor, reroute feature, and other
master changes. The rebuffering estimation-accuracy series source is
resolved against the refactored rsz; the affected test goldens are
regenerated in the following commit.

Signed-off-by: Minju Kim <mkim@precisioninno.com>
@minjukim55
minjukim55 force-pushed the secure-rsz-buffering-boost branch from 09ec48a to 20a3489 Compare July 20, 2026 12:12
@github-actions github-actions Bot added size/L and removed size/XL labels Jul 20, 2026
Regenerate unit .ok logs (rsz/gpl/openroad), their secondary golden
outputs (.defok/.vok DEF/verilog), and aes/jpeg/ibex sky130 flow
.metrics + .metrics_limits for the numeric churn from the
estimation-accuracy rebuffering changes.

The flow pass/fail gate is .metrics_limits (check_test_metrics compares
the result against it; .metrics is the reference used to recompute the
limits). Both are regenerated from a local run of the branch binary.

Secondary DEF/verilog goldens are regenerated alongside the .ok logs so
the in-test diff_file/diff_files comparisons pass and no "Differences
found" text leaks into the committed .ok (No-Diffs-In-Ok-Files check).

Also regenerate the repair_design6 golden (a master-added reroute test):
the improved slew/RC estimation inserts fewer buffers with slightly
better slack and no new violations.

Note: ibex_sky130hs DRT::ANT::errors limit moves 0 -> 1 (one antenna
violation from the changed routing). All other diffs are expected metric
shifts (buffer counts, slew/cap slack, clock skew).

Signed-off-by: Minju Kim <mkim@precisioninno.com>
@minjukim55
minjukim55 force-pushed the secure-rsz-buffering-boost branch from 20a3489 to 0cb1ec3 Compare July 20, 2026 12:41
@github-actions github-actions Bot added size/XL and removed size/L labels Jul 20, 2026
Advance the branch to current OR master so PR The-OpenROAD-Project#3585 stays mergeable
(master moved 20d2d5c -> 06c1421: rsz max-iter/drive-resistance/cell-order,
dpl negotiation, rcx). Golden conflicts (aes/jpeg sky130hd metrics) are
resolved and regenerated against the merged binary in the following commit.

Signed-off-by: Minju Kim <mkim@precisioninno.com>
After advancing to OR master 06c1421 (merge M2) and with the
slew_shape_factor fix reverted, regenerate the flow goldens against the
merged binary:
- aes_sky130hd / ibex_sky130hs / jpeg_sky130hd: recompute .metrics_limits
  (DRV slew/cap slack + clock_skew shift from the reverted slew estimate).
- tinyRocket_nangate45: reverting the fix restores the slew_shape_factor
  double-count, which over-estimates slew -> extra buffering -> global-route
  congestion overflow (GRT-0228). Enlarge the pipe-cleaner floorplan
  (die 500->540, core 490->530) so it routes; regen .metrics/.metrics_limits.

Signed-off-by: Minju Kim <mkim@precisioninno.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants