Skip to content

rsz: Fix global sizing overflow cases#10658

Draft
jhkim-pii wants to merge 8 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:secure-explore-global-sizing
Draft

rsz: Fix global sizing overflow cases#10658
jhkim-pii wants to merge 8 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:secure-explore-global-sizing

Conversation

@jhkim-pii

Copy link
Copy Markdown
Contributor

Summary

  • Publish the secure exploration OpenROAD branch required by the ORFS global sizing CI branch.

Problem

  • ORFS public CI cannot fetch OpenROAD submodule commit 5e83a17805e9d009e46ae2c5be952f5771db43fc from the public OpenROAD repository.
  • Jenkins fails during checkout before any ORFS design or metric checks can run.

Solution

  • Sync the private secure-explore-global-sizing OpenROAD branch through the approved private-to-public workflow.
  • Keep the branch content intact so ORFS can test the exact submodule commit already pinned in tools/OpenROAD.

Impact

  • Enables public ORFS CI checkout for the global sizing exploration branch.
  • No ORFS metric baseline changes are included in this OpenROAD PR.

Testing

  • Pending CI.

Reviewer Notes

  • This PR is required for the ORFS branch that pins OpenROAD commit 5e83a17805.

Related

erendn added 8 commits June 12, 2026 11:35
Signed-off-by: Eren Dogan <erendogan@google.com>
Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Signed-off-by: Eren Dogan <erendogan@google.com>
Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Signed-off-by: Eren Dogan <erendogan@google.com>
Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Signed-off-by: Eren Dogan <erendogan@google.com>
Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Signed-off-by: Eren Dogan <erendogan@google.com>
Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Signed-off-by: Eren Dogan <erendogan@google.com>
Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Signed-off-by: Eren Dogan <erendogan@google.com>
Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Signed-off-by: Eren Dogan <erendogan@google.com>
Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
@jhkim-pii jhkim-pii self-assigned this Jun 15, 2026

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces a Lagrangian-Relaxation-driven global sizing and Vt assignment optimization phase (GLOBAL_SIZING) to the Resizer. It adds the LRSubproblem class to evaluate per-gate costs in a worker-safe parallel manner, and the GlobalSizingPolicy class to manage the outer optimization loop. The review feedback highlights critical issues regarding the handling of invalid timing path delays (-sta::INF), which could corrupt cost calculations and slack budgets. Additionally, the reviewer identified subtle out-of-bounds bugs where std::cmp_greater_equal and std::cmp_less fail to protect against negative signed indices, recommending safer static_cast<size_t> checks instead.

Comment on lines +438 to +440
const float d = sta::delayAsFloat(resizer_->gateDelay(
cand_port, o.load_cap, scene, max_, arc_delay_calc));
cost += timing_weight * o.lambda_sum * d;

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.

high

If resizer_->gateDelay returns -sta::INF (indicating no valid timing path exists for the candidate cell), sta::delayAsFloat will return a very large negative value. This will incorrectly decrease the cost, making the invalid candidate highly favored. We should check if the delay is invalid (e.g., d < -1e9f) and return std::numeric_limits<float>::infinity() to reject the candidate.

    const float d = sta::delayAsFloat(resizer_->gateDelay(
        cand_port, o.load_cap, scene, max_, arc_delay_calc));
    if (d < -1e9f) {
      return std::numeric_limits<float>::infinity();
    }
    cost += timing_weight * o.lambda_sum * d;

Comment on lines +462 to +464
const float d_U = sta::delayAsFloat(resizer_->gateDelay(
u.drv_port, load_pert, scene, max_, arc_delay_calc));
cost += timing_weight * u.lambda_U_drv * d_U;

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.

high

Similarly, if the upstream gate delay d_U is invalid (-sta::INF), it will incorrectly decrease the cost. We should check if d_U < -1e9f and return infinity.

    const float d_U = sta::delayAsFloat(resizer_->gateDelay(
        u.drv_port, load_pert, scene, max_, arc_delay_calc));
    if (d_U < -1e9f) {
      return std::numeric_limits<float>::infinity();
    }
    cost += timing_weight * u.lambda_U_drv * d_U;

Comment on lines +549 to +555
const float d_cur = sta::delayAsFloat(
resizer_->gateDelay(o.port, o.load_cap, scene, max_, arc_delay_calc));
const float d_cand = sta::delayAsFloat(resizer_->gateDelay(
cand_port, o.load_cap, scene, max_, arc_delay_calc));
if (d_cand - d_cur > budget) {
return false;
}

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.

high

If d_cand or d_cur is invalid (-sta::INF), the budget check d_cand - d_cur > budget can produce incorrect results (e.g., -infinity > budget is false, incorrectly allowing the downsize). We should return false if either delay is invalid.

    const float d_cur = sta::delayAsFloat(
        resizer_->gateDelay(o.port, o.load_cap, scene, max_, arc_delay_calc));
    const float d_cand = sta::delayAsFloat(resizer_->gateDelay(
        cand_port, o.load_cap, scene, max_, arc_delay_calc));
    if (d_cand < -1e9f || d_cur < -1e9f) {
      return false;
    }
    if (d_cand - d_cur > budget) {
      return false;
    }

Comment on lines +754 to +757
const float d = sta::delayAsFloat(
resizer_.gateDelay(port, load, scene, policy_max_));
gate_t += lam_sum * d;
has_pressure = true;

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.

high

If resizer_.gateDelay returns -sta::INF, d will be extremely negative, which can corrupt the median timing calculation in computeAutoTimingWeight. We should skip adding the delay to gate_t if it is invalid.

Suggested change
const float d = sta::delayAsFloat(
resizer_.gateDelay(port, load, scene, policy_max_));
gate_t += lam_sum * d;
has_pressure = true;
const float d = sta::delayAsFloat(
resizer_.gateDelay(port, load, scene, policy_max_));
if (d > -1e9f) {
gate_t += lam_sum * d;
has_pressure = true;
}

Comment on lines +256 to +259
const sta::EdgeId id = graph_->id(e);
if (std::cmp_greater_equal(id, lambda_size)) {
continue;
}

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.

medium

Using std::cmp_greater_equal(id, lambda_size) does not protect against out-of-bounds access if id is negative, because a negative signed integer compared to a positive lambda_size will return false, leading to an out-of-bounds access on lambda[id]. Using static_cast<size_t>(id) >= static_cast<size_t>(lambda_size) is safer and more consistent with the rest of the codebase.

Suggested change
const sta::EdgeId id = graph_->id(e);
if (std::cmp_greater_equal(id, lambda_size)) {
continue;
}
const sta::EdgeId id = graph_->id(e);
if (static_cast<size_t>(id) >= static_cast<size_t>(lambda_size)) {
continue;
}

Comment on lines +277 to +280
const sta::VertexId vid = graph_->id(v);
const float vbudget = std::cmp_less(vid, budget_size)
? budget[vid]
: std::numeric_limits<float>::max();

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.

medium

Using std::cmp_less(vid, budget_size) can lead to out-of-bounds access on budget[vid] if vid is negative, because a negative signed integer is less than budget_size, resulting in a true condition. Using static_cast<size_t>(vid) < static_cast<size_t>(budget_size) is safer and correctly handles negative IDs by wrapping them to large unsigned values.

Suggested change
const sta::VertexId vid = graph_->id(v);
const float vbudget = std::cmp_less(vid, budget_size)
? budget[vid]
: std::numeric_limits<float>::max();
const sta::VertexId vid = graph_->id(v);
const float vbudget = (static_cast<size_t>(vid) < static_cast<size_t>(budget_size))
? budget[vid]
: std::numeric_limits<float>::max();

Comment on lines +372 to +375
const sta::EdgeId id = graph_->id(e);
if (std::cmp_greater_equal(id, lambda_size)) {
continue;
}

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.

medium

Using std::cmp_greater_equal(id, lambda_size) does not protect against out-of-bounds access if id is negative. Using static_cast<size_t>(id) >= static_cast<size_t>(lambda_size) is safer and more consistent with the rest of the codebase.

Suggested change
const sta::EdgeId id = graph_->id(e);
if (std::cmp_greater_equal(id, lambda_size)) {
continue;
}
const sta::EdgeId id = graph_->id(e);
if (static_cast<size_t>(id) >= static_cast<size_t>(lambda_size)) {
continue;
}

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.

2 participants