Skip to content

dpl: fix topological sort cycle with multi-height cells in shift lega…#10137

Open
Divinesoumyadip wants to merge 3 commits intoThe-OpenROAD-Project:masterfrom
Divinesoumyadip:fix/dpl-topological-sort-cycle
Open

dpl: fix topological sort cycle with multi-height cells in shift lega…#10137
Divinesoumyadip wants to merge 3 commits intoThe-OpenROAD-Project:masterfrom
Divinesoumyadip:fix/dpl-topological-sort-cycle

Conversation

@Divinesoumyadip
Copy link
Copy Markdown
Contributor

Summary

improve_placement fails with DPL-0400 Cells incorrectly ordered during shifting on designs with multi-height cells. Multi-height cells appear in segments across multiple rows. When a single-height cell sits inside the row span of two multi-height cells, the ordering differs per row, creating a cycle in the topological sort. Fix: in legalize_shift.cxx, only add dependency edges when both cells' bottom Y matches the current segment's row bottom. Multi-height cells contribute edges only from their primary (bottom) row, eliminating the cycle.

Type of Change

Bug fix

Impact

improve_placement no longer crashes with DPL-0400 on designs containing multi-height cells such as SRAMs. No behavioral change for single-height-only designs.

Related Issues

Fixes #9932

…lizer

Multi-height cells appear in segments across multiple rows. When a
single-height cell sits inside the row span of two multi-height cells,
the ordering differs per row, creating a cycle in the topological sort
which triggers DPL-0400.

Fix: only add dependency edges when both cells' bottom Y matches the
current segment's row bottom, ensuring each multi-height cell
contributes edges only from its primary (bottom) row.

Fixes The-OpenROAD-Project#9932

Signed-off-by: Divinesoumyadip <soumyacode7@gmail.com>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

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 modifies the dependency graph construction in ShiftLegalizer::legalize by only adding edges between cells that align with the current row's bottom, aiming to prevent cycles in the topological sort. The reviewer pointed out that this logic is flawed as it ignores necessary constraints between cells of varying heights, which could lead to overlaps. A more robust solution was suggested: making the cell comparison deterministic by using cell IDs as a tie-breaker in the sorting logic, while also noting that the current changes create an inconsistency with the shifting logic in the same class.

Comment on lines +132 to +134
if (prev->getBottom() != rowBottom || curr->getBottom() != rowBottom) {
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.

high

The logic introduced here to avoid cycles by only adding edges when both cells' bottom matches the current row's bottom is problematic for correctness. It effectively ignores dependency constraints between cells of different heights or cells that start at different rows.

For example, if a multi-height cell $M$ (spanning rows 0 and 1) is to the left of a single-height cell $S$ (in row 1), the edge $M \to S$ will never be added:

  • In Row 0: $S$ is not present.
  • In Row 1: $M.getBottom()$ (Row 0) does not match rowBottom (Row 1), so the edge is skipped.

This lack of constraints can lead to overlaps during the shifting process, as the legalizer will not maintain the required relative ordering of these cells.

The root cause of the topological sort cycles is likely the non-deterministic sorting in DetailedMgr::compareNodesX (in detailed_manager.h). When two cells have the same X center, std::sort may produce different relative orders in different row segments, creating a cycle. A more robust fix would be to make the cell comparison deterministic by adding a tie-breaker, such as the cell ID:

struct compareNodesX {
  bool operator()(Node* p, Node* q) const {
    if (p->getCenterX() != q->getCenterX())
      return p->getCenterX() < q->getCenterX();
    return p->getId() < q->getId();
  }
};

Additionally, note that this PR only modifies the first loop that builds the dependency graph for the topological sort check, but leaves the second loop in ShiftLegalizer::shift (lines 273-282) unchanged. This inconsistency means the clump logic will still operate on the original, potentially cyclic/inconsistent graph.

References
  1. Iteration or sorting over pointer-based collections requires a custom comparator or a unique tie-breaker (like an ID) to ensure deterministic behavior across different runs.

@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@maliberty maliberty requested a review from gudeh April 15, 2026 18:23
@maliberty
Copy link
Copy Markdown
Member

FYI, our efforts are mostly going towards the new negotiation based legalizer which will become the new default.

@Divinesoumyadip
Copy link
Copy Markdown
Contributor Author

FYI, our efforts are mostly going towards the new negotiation based legalizer which will become the new default.

should I still pursue this or skip given the new legalizer?

@gudeh
Copy link
Copy Markdown
Contributor

gudeh commented Apr 15, 2026

The new legalizer is executed before improve placement. So I say you should go for the fix!

We should still run improve placement even with the new legalizer.

Legalization is performed with detailed_placement command

@github-actions github-actions bot added size/S and removed size/XS labels Apr 15, 2026
…aker

Signed-off-by: Divinesoumyadip <soumyacode7@gmail.com>
@Divinesoumyadip Divinesoumyadip force-pushed the fix/dpl-topological-sort-cycle branch from d9f111e to 7b5d315 Compare April 15, 2026 21:09
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

{
return p->getCenterX() < q->getCenterX();
if (p->getCenterX() != q->getCenterX())
return p->getCenterX() < q->getCenterX();
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.

warning: statement should be inside braces [google-readability-braces-around-statements]

Suggested change
return p->getCenterX() < q->getCenterX();
if (p->getCenterX() != q->getCenterX()) {
return p->getCenterX() < q->getCenterX();
}

Copy link
Copy Markdown
Contributor

@gudeh gudeh left a comment

Choose a reason for hiding this comment

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

LGTM

OR tests seem to indicate no-op. I also triggered a secure-CI to be sure.

@Divinesoumyadip have you confirmed this solves the issue with the reproducible ?

@gudeh
Copy link
Copy Markdown
Contributor

gudeh commented Apr 17, 2026

You also need to solve the clang-format and clang-tidy

Signed-off-by: Divinesoumyadip <soumyacode7@gmail.com>
@Divinesoumyadip Divinesoumyadip force-pushed the fix/dpl-topological-sort-cycle branch from 61728a3 to 39a00e7 Compare April 18, 2026 10:13
@Divinesoumyadip Divinesoumyadip requested a review from gudeh April 18, 2026 10:14
@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

1 similar comment
@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

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.

DPL: topological sort cycle in shift legalizer with multi-height cells (DPL-0400)

3 participants