Skip to content

Conversation

@openroad-ci
Copy link
Collaborator

This PR changes which objects are used to detect notches, changing from "not a std cell clusters" to "mixed clusters and macro clusters". This is necessary since it doesn't really make sense to include IO pins and PADs in notch detection (and some designs such as bp_quad have a huge amount of them, causing MPL to take way too long to finish).

The PR also includes suggestions made in PR #9282.

@github-actions
Copy link
Contributor

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

Copy link
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 refactors the notch calculation logic, primarily by changing which objects are considered. This is a good optimization. However, I've identified a critical bug in the isSegmentEmpty function that could lead to incorrect notch detection. There's also a significant, and likely unintentional, change in how notches are defined in calNotchPenalty, where fully enclosed empty spaces might no longer be penalized. I've also pointed out a minor typo in a function declaration. Please address these issues to ensure the correctness of the implementation.

Comment on lines 719 to 736
bool SACoreSoftMacro::isSegmentEmpty(const std::vector<std::vector<bool>>& grid,
const int start_row,
const int start_col,
const int end_row,
const int end_col)
{
for (int i = start_row; i <= end_row; i++) {
for (int j = start_col; j <= end_col; j++) {
if (grid[i][j]) {
return false;
}
if (grid[i][end_col]) {
return false;
}
}

for (int j = start_col; j <= end_col; j++) {
if (grid[end_row][j]) {
return false;
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

critical

The new implementation of isSegmentEmpty is incorrect. It no longer checks if the entire specified segment is empty, but only its rightmost column and bottommost row. This can lead to incorrect behavior. For example, if grid[start_row][start_col] is occupied and the segment is larger than 1x1, this function will incorrectly return true.

The previous implementation was correct. If this change is for optimization, it should be implemented differently. A correct optimization would be to check only the newly added row or column. This could be done with helper functions like isRowEmpty and isColEmpty and calling them appropriately from the expansion loop in calNotchPenalty.

As it is, this is a critical bug that will cause incorrect notch detection. I recommend reverting this function to its previous correct implementation.

bool SACoreSoftMacro::isSegmentEmpty(const std::vector<std::vector<bool>>& grid,
                                     const int start_row,
                                     const int start_col,
                                     const int end_row,
                                     const int end_col)
{
  for (int i = start_row; i <= end_row; i++) {
    for (int j = start_col; j <= end_col; j++) {
      if (grid[i][j]) {
        return false;
      }
    }
  }
  return true;
}

Comment on lines 869 to 879
bool is_notch = false;
if (current_neighbors.total() == 4) {
is_notch = true;
} else if (current_neighbors.top && current_neighbors.bottom) {
if (current_vicinity.top && current_vicinity.bottom) {
if (height < notch_h_th_) {
is_notch = true;
}
} else if (current_neighbors.left && current_neighbors.right) {
}

if (current_vicinity.left && current_vicinity.right) {
if (width < notch_v_th_) {
is_notch = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The logic for identifying a notch has been changed significantly. The original code considered any fully enclosed empty space as a notch (current_neighbors.total() == 4). This condition has been removed.

The new logic is:

bool is_notch = false;
if (current_vicinity.top && current_vicinity.bottom) {
  if (height < notch_h_th_) {
    is_notch = true;
  }
}

if (current_vicinity.left && current_vicinity.right) {
  if (width < notch_v_th_) {
    is_notch = true;
  }
}

For a fully enclosed space, this will only flag it as a notch if it is thin in at least one dimension (height < notch_h_th_ or width < notch_v_th_). A large, fully enclosed empty area will no longer be considered a notch, which seems incorrect as it represents wasted space that should be penalized.

This change is not mentioned in the PR description and appears to be a bug. If this change is intentional, it should be documented. Otherwise, the original logic for fully enclosed spaces should be restored.

      bool is_notch = false;
      if (current_vicinity.total() == 4) {
        is_notch = true;
      } else if (current_vicinity.top && current_vicinity.bottom) {
        if (height < notch_h_th_) {
          is_notch = true;
        }
      } else if (current_vicinity.left && current_vicinity.right) {
        if (width < notch_v_th_) {
          is_notch = true;
        }
      }

Comment on lines 109 to 113
static bool isSegmentEmpty(const std::vector<std::vector<bool>>& grid,
int start_row,
int tart_col,
int end_row,
int end_col);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There is a typo in the parameter name tart_col. It should be start_col.

Suggested change
static bool isSegmentEmpty(const std::vector<std::vector<bool>>& grid,
int start_row,
int tart_col,
int end_row,
int end_col);
static bool isSegmentEmpty(const std::vector<std::vector<bool>>& grid,
int start_row,
int start_col,
int end_row,
int end_col);

@github-actions
Copy link
Contributor

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

Signed-off-by: João Mai <jmai@precisioninno.com>
Signed-off-by: João Mai <jmai@precisioninno.com>
Signed-off-by: João Mai <jmai@precisioninno.com>
Signed-off-by: João Mai <jmai@precisioninno.com>
Signed-off-by: João Mai <jmai@precisioninno.com>
Signed-off-by: João Mai <jmai@precisioninno.com>
Signed-off-by: João Mai <jmai@precisioninno.com>
Signed-off-by: João Mai <jmai@precisioninno.com>
@github-actions
Copy link
Contributor

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

@joaomai
Copy link
Contributor

joaomai commented Feb 11, 2026

Paired with PR #3881 on ORFS.

Comment on lines 588 to 589
// painter.setBrush(gui::Painter::kYellow, gui::Painter::kNone);

Copy link
Member

Choose a reason for hiding this comment

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

rm?

Comment on lines -782 to +794
if (macro.isStdCellCluster()) {
if (!macro.isMacroCluster() && !macro.isMixedCluster()) {
Copy link
Member

Choose a reason for hiding this comment

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

What is the semantic difference?

Copy link
Contributor

Choose a reason for hiding this comment

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

Using isMacroCluster keeps PADs, IOs, etc., which is undesired. I'll be opening an issue to better categorize the cluster "types" beyond standard cells, mixed and macro.

Signed-off-by: João Mai <jmai@precisioninno.com>
int num_x = grid.front().size();

Neighbors neighbors;
NotchVicinity vicnity;
Copy link
Contributor

Choose a reason for hiding this comment

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

typo

Signed-off-by: João Mai <jmai@precisioninno.com>
@github-actions
Copy link
Contributor

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

1 similar comment
@github-actions
Copy link
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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants