Skip to content

cts: tie-break dummy-cell sort for deterministic output#10656

Merged
maliberty merged 4 commits into
The-OpenROAD-Project:masterfrom
oharboe:cts-deterministic-dummy-cell
Jun 17, 2026
Merged

cts: tie-break dummy-cell sort for deterministic output#10656
maliberty merged 4 commits into
The-OpenROAD-Project:masterfrom
oharboe:cts-deterministic-dummy-cell

Conversation

@oharboe

@oharboe oharboe commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

findCandidateDummyCells() gathers dummyCandidates by iterating the STA libraries, then std::ranges::sorts them by getInputCap() alone.

std::ranges::sort is not stable, and findBestDummyCell() subsequently takes the first candidate with the minimal |cap - deltaCap|. So among candidates with equal input cap, the selected dummy cell depends on the unspecified sort order and varies run to run — a source of nondeterminism in CTS output.

This tie-breaks the sort on the cell name so equal-cap candidates get a stable, reproducible order. Same shape as the previously-merged OptMirror tie-break.

findCandidateDummyCells() gathers dummyCandidates by iterating the STA
libraries, then sorts them by getInputCap() alone with the non-stable
std::ranges::sort. findBestDummyCell() then takes the first candidate
with the minimal |cap - deltaCap|, so among equal-cap candidates the
choice depends on the unspecified sort order and varies run to run.
Tie-break the sort on the cell name for a stable, reproducible pick.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@oharboe oharboe requested a review from a team as a code owner June 14, 2026 17:37
@oharboe oharboe requested a review from luis201420 June 14, 2026 17:37

@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 updates the sorting logic for dummyCandidates in TritonCTS::findCandidateDummyCells to include a tie-breaker based on cell names when input capacities are equal, ensuring stable output. The review feedback suggests optimizing this tie-breaker by using std::strcmp instead of constructing std::string objects to avoid unnecessary dynamic memory allocations.

Comment thread src/cts/src/TritonCTS.cpp Outdated
return false;
}
// dummyCandidates is unordered; tie-break for stable output.
return std::string(cell1->name()) < std::string(cell2->name());

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

Constructing std::string objects inside the sort comparator on every comparison is inefficient because it can trigger dynamic memory allocations. Since <cstring> is already included, using std::strcmp is a much more efficient way to compare the cell names without any heap allocation overhead.

        return std::strcmp(cell1->name(), cell2->name()) < 0;

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.

We really should be using return cell1->id() < cell2->id()
string compares are by far the most expensive tie break.

@oharboe

oharboe commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator Author

/gemini propose fixes

@gemini-code-assist

Copy link
Copy Markdown
Contributor

The proposed fix correctly addresses the non-determinism by adding a tie-break on the cell name. The logic is sound and effectively ensures a stable sort order.

If you prefer a more concise implementation, you could use std::tie with std::string_view to avoid creating std::string objects during every comparison:

std::ranges::sort(
    dummyCandidates,
    [](const sta::LibertyCell* cell1, const sta::LibertyCell* cell2) {
      return std::tie(getInputCap(cell1), std::string_view(cell1->name())) <
             std::tie(getInputCap(cell2), std::string_view(cell2->name()));
    });

This approach is functionally equivalent and slightly more idiomatic for multi-key comparisons.

Per review (gadfort), tie-break on LibertyCell::id() rather than the cell
name: an integer compare instead of constructing a string per comparison.
String compares are the most expensive tie-break, and id() matches the
deterministic comparator style already used in Resizer.cc.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@github-actions github-actions Bot added size/XS and removed size/S labels Jun 14, 2026
@oharboe

oharboe commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks @gadfort — switched both the cts and rsz (#10655) tie-breaks to cell->id() < cell->id(). Integer compare, no string construction, and it matches the existing buffer comparator in Resizer.cc (findFastBuffers). Pushed as a follow-up commit.

@oharboe

oharboe commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator Author

/gemini review

@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 updates the sorting comparator for dummy candidates in TritonCTS.cpp to ensure a deterministic sort order. When the input capacitances of two cells are equal, it now falls back to comparing their cell IDs. I have no further feedback to provide as there are no review comments.

Per review, express the (input-cap, id) lexicographic order as a single
std::make_tuple comparison instead of the explicit if-chain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@oharboe

oharboe commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

Simplified the comparator to a single std::make_tuple((input-cap, id)) compare. (Used make_tuple rather than std::tiegetInputCap()/id() return prvalues, which can't bind to tie's lvalue references.)

@oharboe

oharboe commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

/gemini review

@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 updates the sorting logic for dummy candidate cells in TritonCTS.cpp to ensure a deterministic sort order. By using std::tuple with both the input capacitance and the cell ID, the comparator now has a stable fallback when capacitances are equal. I have no feedback to provide.

Per review, use a direct (input-cap, id) compare with cached locals
instead of std::make_tuple temporaries; also drops the <tuple> include.
Matches the explicit comparator style in Resizer.cc.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@oharboe

oharboe commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

/gemini review

@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 updates the sorting comparator for dummy cell candidates in TritonCTS to ensure a deterministic sort order. When the input capacitances of two cells are equal, it now falls back to comparing their cell IDs. There are no review comments, so no additional feedback is provided.

@oharboe

oharboe commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator Author

@maliberty This was pr merge green, so should be irrelevant

@maliberty maliberty merged commit d66535c into The-OpenROAD-Project:master Jun 17, 2026
15 of 16 checks passed
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.

3 participants