-
Notifications
You must be signed in to change notification settings - Fork 779
mpl: improved notches #9282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mpl: improved notches #9282
Changes from all commits
7e3d07d
7d60fa8
4764698
47aede1
13275b6
3d18105
93d2b8d
135cd5e
1bdae97
407f91a
a46e9a6
b735830
3cb7632
e98234c
6868275
47c2f9a
5086c09
3912863
c5bcb53
99f71e2
38bf6ed
0147564
bfe2c4e
2a11a3e
3cf07f2
2e83e45
a13a488
cae5a35
cd6f980
fc73bb5
33cc3b1
60bd6e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -624,15 +624,124 @@ void SACoreSoftMacro::attemptMacroClusterAlignment() | |
| } | ||
| } | ||
|
|
||
| float SACoreSoftMacro::calSingleNotchPenalty(float width, float height) | ||
| void SACoreSoftMacro::fillCoordsLists(std::vector<int>& x_coords, | ||
| std::vector<int>& y_coords) | ||
| { | ||
| return std::sqrt((width * height) | ||
| / block_->dbuAreaToMicrons(outline_.area())); | ||
| std::vector<int> x_point; | ||
| std::vector<int> y_point; | ||
|
|
||
| for (auto& macro : macros_) { | ||
| if (macro.isStdCellCluster()) { | ||
| continue; | ||
| } | ||
| x_point.push_back(macro.getX()); | ||
| x_point.push_back(macro.getX() + macro.getWidth()); | ||
| y_point.push_back(macro.getY()); | ||
| y_point.push_back(macro.getY() + macro.getHeight()); | ||
| } | ||
| x_point.push_back(0); | ||
| y_point.push_back(0); | ||
| x_point.push_back(outline_.dx()); | ||
| y_point.push_back(outline_.dy()); | ||
|
|
||
| std::ranges::sort(x_point); | ||
| std::ranges::sort(y_point); | ||
|
|
||
| int epsilon = outline_.dx() / 100; | ||
| for (int i = 0; i < x_point.size(); i++) { | ||
| if (i + 1 < x_point.size() | ||
| && std::abs(x_point[i + 1] - x_point[i]) <= epsilon) { | ||
| continue; | ||
| } | ||
| x_coords.push_back(x_point[i]); | ||
| } | ||
|
|
||
| epsilon = outline_.dy() / 100; | ||
| for (int i = 0; i < y_point.size(); i++) { | ||
| if (i + 1 < y_point.size() | ||
| && std::abs(y_point[i + 1] - y_point[i]) <= epsilon) { | ||
| continue; | ||
| } | ||
| y_coords.push_back(y_point[i]); | ||
| } | ||
| } | ||
|
|
||
| SACoreSoftMacro::Neighbors SACoreSoftMacro::findNeighbors( | ||
| std::vector<std::vector<bool>>& grid, | ||
| int start_row, | ||
| int start_col, | ||
| int end_row, | ||
| int end_col) | ||
|
Comment on lines
+669
to
+674
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same: const + static |
||
| { | ||
| int num_y = grid.size(); | ||
| int num_x = grid.front().size(); | ||
|
|
||
| Neighbors neighbors; | ||
| if (start_row > 0) { | ||
| for (int i = start_col; i <= end_col; i++) { | ||
| if (!grid[start_row - 1][i]) { | ||
| neighbors.bottom = false; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (end_row < num_y - 1) { | ||
| for (int i = start_col; i <= end_col; i++) { | ||
| if (!grid[end_row + 1][i]) { | ||
| neighbors.top = false; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (start_col > 0) { | ||
| for (int i = start_row; i <= end_row; i++) { | ||
| if (!grid[i][start_col - 1]) { | ||
| neighbors.left = false; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (end_col < num_x - 1) { | ||
| for (int i = start_row; i <= end_row; i++) { | ||
| if (!grid[i][end_col + 1]) { | ||
| neighbors.right = false; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return neighbors; | ||
| } | ||
|
|
||
| bool SACoreSoftMacro::isSegmentEmpty(std::vector<std::vector<bool>>& grid, | ||
| int start_row, | ||
| int start_col, | ||
| int end_row, | ||
| int end_col) | ||
|
Comment on lines
+716
to
+720
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All arguments should be const and the method itself can be static. |
||
| { | ||
| 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; | ||
| } | ||
|
|
||
| float SACoreSoftMacro::calSingleNotchPenalty(int width, int height) | ||
| { | ||
| return std::sqrt((static_cast<double>(width) * height) / outline_.area()); | ||
| } | ||
|
|
||
| // If there is no HardMacroCluster, we do not consider the notch penalty | ||
| void SACoreSoftMacro::calNotchPenalty() | ||
| { | ||
| if (graphics_) { | ||
| graphics_->clearNotches(); | ||
| } | ||
|
|
||
| if (notch_weight_ <= 0.0) { | ||
| return; | ||
| } | ||
|
|
@@ -649,37 +758,28 @@ void SACoreSoftMacro::calNotchPenalty() | |
| if (!isValid()) { | ||
| width = std::max(width_, outline_.dx()); | ||
| height = std::max(height_, outline_.dy()); | ||
| notch_penalty_ = calSingleNotchPenalty(block_->dbuToMicrons(width), | ||
| block_->dbuToMicrons(height)); | ||
| notch_penalty_ = calSingleNotchPenalty(width, height); | ||
|
|
||
| if (graphics_) { | ||
| graphics_->setNotchPenalty({.name = "Notch", | ||
| .weight = notch_weight_, | ||
| .value = notch_penalty_, | ||
| .normalization_factor = norm_notch_penalty_}); | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| // Create grids based on location of MixedCluster and HardMacroCluster | ||
| std::set<int> x_point; | ||
| std::set<int> y_point; | ||
| for (auto& macro : macros_) { | ||
| if (!macro.isMacroCluster() && !macro.isMixedCluster()) { | ||
| continue; | ||
| } | ||
| x_point.insert(macro.getX()); | ||
| x_point.insert(macro.getX() + macro.getWidth()); | ||
| y_point.insert(macro.getY()); | ||
| y_point.insert(macro.getY() + macro.getHeight()); | ||
| } | ||
| x_point.insert(0); | ||
| y_point.insert(0); | ||
| x_point.insert(outline_.dx()); | ||
| y_point.insert(outline_.dy()); | ||
| std::vector<int> x_coords; | ||
| std::vector<int> y_coords; | ||
| fillCoordsLists(x_coords, y_coords); | ||
|
|
||
| std::vector<int> x_coords(x_point.begin(), x_point.end()); | ||
| std::vector<int> y_coords(y_point.begin(), y_point.end()); | ||
| int num_x = x_coords.size() - 1; | ||
| int num_y = y_coords.size() - 1; | ||
|
|
||
| // Assign cluster locations for notch detection | ||
| std::vector<std::vector<bool>> grid(num_y, std::vector<bool>(num_x, false)); | ||
| for (auto& macro : macros_) { | ||
| if (!macro.isMacroCluster() && !macro.isMixedCluster()) { | ||
| if (macro.isStdCellCluster()) { | ||
| continue; | ||
| } | ||
| int x_start = getSegmentIndex(macro.getX(), x_coords); | ||
|
|
@@ -693,34 +793,83 @@ void SACoreSoftMacro::calNotchPenalty() | |
| } | ||
| } | ||
|
|
||
| // An empty grid cell surrounded by 3 or more edges is considered a notch | ||
| for (int row = 0; row < num_y; row++) { | ||
| for (int col = 0; col < num_x; col++) { | ||
| if (grid[row][col]) { | ||
| for (int start_row = 0; start_row < num_y; start_row++) { | ||
| for (int start_col = 0; start_col < num_x; start_col++) { | ||
| if (grid[start_row][start_col]) { | ||
| continue; | ||
| } | ||
|
|
||
| int surroundings = 0; | ||
| if (row == 0 || grid[row - 1][col]) { | ||
| surroundings++; | ||
| } | ||
| if (row == num_y - 1 || grid[row + 1][col]) { | ||
| surroundings++; | ||
| } | ||
| if (col == 0 || grid[row][col - 1]) { | ||
| surroundings++; | ||
| } | ||
| if (col == num_x - 1 || grid[row][col + 1]) { | ||
| surroundings++; | ||
| int end_row = start_row; | ||
| int end_col = start_col; | ||
|
|
||
| Neighbors current_neighbors | ||
| = findNeighbors(grid, start_row, start_col, end_row, end_col); | ||
| bool expand_rows = true; | ||
| bool expand_cols = true; | ||
|
|
||
| while (expand_rows || expand_cols) { | ||
| if (expand_rows) { | ||
| end_row += 1; | ||
| if (end_row < num_y | ||
| && isSegmentEmpty(grid, start_row, start_col, end_row, end_col)) { | ||
| Neighbors expanded_neighbors | ||
| = findNeighbors(grid, start_row, start_col, end_row, end_col); | ||
| if (expanded_neighbors.total() > current_neighbors.total() | ||
| || expanded_neighbors == current_neighbors) { | ||
| current_neighbors = expanded_neighbors; | ||
| } else { | ||
| expand_rows = false; | ||
| end_row -= 1; | ||
| } | ||
| } else { | ||
| expand_rows = false; | ||
| end_row -= 1; | ||
| } | ||
| } | ||
|
|
||
| if (expand_cols) { | ||
| end_col += 1; | ||
| if (end_col < num_x | ||
| && isSegmentEmpty(grid, start_row, start_col, end_row, end_col)) { | ||
| Neighbors expanded_neighbors | ||
| = findNeighbors(grid, start_row, start_col, end_row, end_col); | ||
| if (expanded_neighbors.total() > current_neighbors.total() | ||
| || expanded_neighbors == current_neighbors) { | ||
| current_neighbors = expanded_neighbors; | ||
| } else { | ||
| expand_cols = false; | ||
| end_col -= 1; | ||
| } | ||
| } else { | ||
| expand_cols = false; | ||
| end_col -= 1; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (surroundings >= 3) { | ||
| width = x_coords[col + 1] - x_coords[col]; | ||
| height = y_coords[row + 1] - y_coords[row]; | ||
| width = x_coords[end_col + 1] - x_coords[start_col]; | ||
| height = y_coords[end_row + 1] - y_coords[start_row]; | ||
|
|
||
| bool is_notch = false; | ||
| if (current_neighbors.total() == 4) { | ||
| is_notch = true; | ||
|
Comment on lines
+854
to
+855
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pathological but you could have neighbors on all sides of a region larger than notch_h/v_th_ in both directions (e.g. a ring of macros). Probably that shouldn't be a notch. |
||
| } else if (current_neighbors.top && current_neighbors.bottom) { | ||
| if (height < notch_h_th_) { | ||
| is_notch = true; | ||
| } | ||
| } else if (current_neighbors.left && current_neighbors.right) { | ||
| if (width < notch_v_th_) { | ||
| is_notch = true; | ||
| } | ||
| } | ||
|
|
||
| if (width <= notch_h_th_ || height <= notch_v_th_) { | ||
| notch_penalty_ += calSingleNotchPenalty(block_->dbuToMicrons(width), | ||
| block_->dbuToMicrons(height)); | ||
| if (is_notch) { | ||
| notch_penalty_ += calSingleNotchPenalty(width, height); | ||
| if (graphics_) { | ||
| graphics_->addNotch(odb::Rect(x_coords[start_col], | ||
| y_coords[start_row], | ||
| x_coords[end_col + 1], | ||
| y_coords[end_row + 1])); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -1052,7 +1201,7 @@ void SACoreSoftMacro::attemptCentralization(const float pre_cost) | |
| calPenalty(); | ||
|
|
||
| // revert centralization | ||
| if (calNormCost() > pre_cost) { | ||
| if (calNormCost() > pre_cost && !force_centralization_) { | ||
| centralization_was_reverted_ = true; | ||
|
|
||
| setClustersLocations(clusters_locations); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -71,7 +71,22 @@ class SACoreSoftMacro : public SimulatedAnnealingCore<SoftMacro> | |
|
|
||
| void enableEnhancements() { enhancements_on_ = true; }; | ||
|
|
||
| void forceCentralization() { force_centralization_ = true; } | ||
|
|
||
| private: | ||
| // Used to calculate notches | ||
| struct Neighbors | ||
|
Comment on lines
+77
to
+78
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had to read the code to understand the semantics of these bools. A better descriptive comment would be helpful. |
||
| { | ||
| bool top = true; | ||
| bool bottom = true; | ||
| bool left = true; | ||
| bool right = true; | ||
|
|
||
| int total() { return top + bottom + left + right; } | ||
|
|
||
| bool operator==(const Neighbors&) const = default; | ||
| }; | ||
|
|
||
| float calNormCost() const override; | ||
| void calPenalty() override; | ||
|
|
||
|
|
@@ -84,7 +99,18 @@ class SACoreSoftMacro : public SimulatedAnnealingCore<SoftMacro> | |
| int getSegmentIndex(int segment, const std::vector<int>& coords); | ||
|
|
||
| void calBoundaryPenalty(); | ||
| float calSingleNotchPenalty(float width, float height); | ||
| void fillCoordsLists(std::vector<int>& x_coords, std::vector<int>& y_coords); | ||
| Neighbors findNeighbors(std::vector<std::vector<bool>>& grid, | ||
| int start_row, | ||
| int start_col, | ||
| int end_row, | ||
| int end_col); | ||
| bool isSegmentEmpty(std::vector<std::vector<bool>>& grid, | ||
| int start_row, | ||
| int tart_col, | ||
| int end_row, | ||
| int end_col); | ||
| float calSingleNotchPenalty(int width, int height); | ||
| void calNotchPenalty(); | ||
| void calMacroBlockagePenalty(); | ||
| void calFixedMacrosPenalty(); | ||
|
|
@@ -136,6 +162,7 @@ class SACoreSoftMacro : public SimulatedAnnealingCore<SoftMacro> | |
|
|
||
| bool enhancements_on_ = false; | ||
| bool centralization_was_reverted_ = false; | ||
| bool force_centralization_ = false; | ||
| }; | ||
|
|
||
| } // namespace mpl | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has the potential to skip too many points. Imagine a series of points all 0.9 epsilon apart. You would collapse them all. It would be better to set a threshold from an accepted point and skip all points within that threshold.
Changing this will require another secure CI so I suggest you do it in a follow up PR.