Skip to content

Commit 3ed56dc

Browse files
authored
Merge pull request #8078 from The-OpenROAD-Project-staging/mpl-notch-penalty
mpl: update notch penalty
2 parents e79e225 + 7d6fe26 commit 3ed56dc

File tree

9 files changed

+1394
-1534
lines changed

9 files changed

+1394
-1534
lines changed

src/mpl/src/SACoreSoftMacro.cpp

Lines changed: 83 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ SACoreSoftMacro::SACoreSoftMacro(PhysicalHierarchy* tree,
6666
{
6767
boundary_weight_ = soft_weights.boundary;
6868
macro_blockage_weight_ = soft_weights.macro_blockage;
69-
original_notch_weight_ = soft_weights.notch;
69+
notch_weight_ = soft_weights.notch;
7070
resize_prob_ = resize_prob;
7171
notch_h_th_ = notch_h_threshold;
7272
notch_v_th_ = notch_v_threshold;
@@ -519,199 +519,105 @@ void SACoreSoftMacro::alignMacroClusters()
519519
}
520520
}
521521

522+
float SACoreSoftMacro::calSingleNotchPenalty(float width, float height)
523+
{
524+
return std::sqrt((width * height) / outline_.getArea());
525+
}
526+
522527
// If there is no HardMacroCluster, we do not consider the notch penalty
523528
void SACoreSoftMacro::calNotchPenalty()
524529
{
525-
// Initialization
526-
notch_penalty_ = 0.0;
527530
if (notch_weight_ <= 0.0) {
528531
return;
529532
}
530-
// If the floorplan cannot fit into the outline
533+
534+
// Initialization
535+
notch_penalty_ = 0.0;
536+
notch_h_th_ = outline_.getHeight() / 10.0;
537+
notch_v_th_ = outline_.getWidth() / 10.0;
538+
float width = 0;
539+
float height = 0;
540+
541+
// If the floorplan is not valid
531542
// We think the entire floorplan is a "huge" notch
532-
if (width_ > outline_.getWidth() * 1.001
533-
|| height_ > outline_.getHeight() * 1.001) {
534-
notch_penalty_ += outline_.getWidth() * outline_.getHeight()
535-
/ (outline_.getWidth() * outline_.getHeight());
543+
if (!isValid()) {
544+
width = std::max(width_, outline_.getWidth());
545+
height = std::max(height_, outline_.getHeight());
546+
notch_penalty_ = calSingleNotchPenalty(width, height);
536547
return;
537548
}
538549

539-
// Macros need to be saved (and restored) since alignMacroClusters and
540-
// fillDeadSpace move them
541-
std::vector<SoftMacro> pre_macros = macros_;
542-
// align macro clusters to reduce notches
543-
alignMacroClusters();
544-
// Fill dead space
545-
fillDeadSpace();
546550
// Create grids based on location of MixedCluster and HardMacroCluster
547551
std::set<float> x_point;
548552
std::set<float> y_point;
549-
std::vector<bool> macro_mask;
550553
for (auto& macro : macros_) {
551-
if (macro.getArea() <= 0.0
552-
|| (!macro.isMacroCluster() && !macro.isMixedCluster())) {
553-
macro_mask.push_back(false);
554+
if (!macro.isMacroCluster() && !macro.isMixedCluster()) {
554555
continue;
555556
}
556557
x_point.insert(macro.getX());
557558
x_point.insert(macro.getX() + macro.getWidth());
558559
y_point.insert(macro.getY());
559560
y_point.insert(macro.getY() + macro.getHeight());
560-
macro_mask.push_back(true);
561561
}
562562
x_point.insert(0.0);
563563
y_point.insert(0.0);
564564
x_point.insert(outline_.getWidth());
565565
y_point.insert(outline_.getHeight());
566-
// create grid
567-
std::vector<float> x_grid(x_point.begin(), x_point.end());
568-
std::vector<float> y_grid(y_point.begin(), y_point.end());
569-
// create grid in a row-based manner
570-
std::vector<std::vector<int>> grids; // store the macro id
571-
const int num_x = x_grid.size() - 1;
572-
const int num_y = y_grid.size() - 1;
573-
for (int j = 0; j < num_y; j++) {
574-
std::vector<int> macro_ids(num_x, -1);
575-
grids.push_back(macro_ids);
576-
}
577-
// detect the notch region around each MixedCluster and HardMacroCluster
578-
for (int macro_id = 0; macro_id < macros_.size(); macro_id++) {
579-
if (!macro_mask[macro_id]) {
566+
567+
std::vector<float> x_coords(x_point.begin(), x_point.end());
568+
std::vector<float> y_coords(y_point.begin(), y_point.end());
569+
int num_x = x_coords.size() - 1;
570+
int num_y = y_coords.size() - 1;
571+
572+
// Assign cluster locations for notch detection
573+
std::vector<std::vector<bool>> grid(num_y, std::vector<bool>(num_x, false));
574+
for (auto& macro : macros_) {
575+
if (!macro.isMacroCluster() && !macro.isMixedCluster()) {
580576
continue;
581577
}
582-
int x_start = 0;
583-
int x_end = 0;
584-
calSegmentLoc(macros_[macro_id].getX(),
585-
macros_[macro_id].getX() + macros_[macro_id].getWidth(),
586-
x_start,
587-
x_end,
588-
x_grid);
589-
int y_start = 0;
590-
int y_end = 0;
591-
calSegmentLoc(macros_[macro_id].getY(),
592-
macros_[macro_id].getY() + macros_[macro_id].getHeight(),
593-
y_start,
594-
y_end,
595-
y_grid);
596-
for (int j = y_start; j < y_end; j++) {
597-
for (int i = x_start; i < x_end; i++) {
598-
grids[j][i] = macro_id;
578+
int x_start = getSegmentIndex(macro.getX(), x_coords);
579+
int x_end = getSegmentIndex(macro.getX() + macro.getWidth(), x_coords);
580+
int y_start = getSegmentIndex(macro.getY(), y_coords);
581+
int y_end = getSegmentIndex(macro.getY() + macro.getHeight(), y_coords);
582+
for (int row = y_start; row < y_end; row++) {
583+
for (int col = x_start; col < x_end; col++) {
584+
grid[row][col] = true;
599585
}
600586
}
601587
}
602-
// check surroundings of each HardMacroCluster and MixecCluster
603-
for (int macro_id = 0; macro_id < macros_.size(); macro_id++) {
604-
if (!macro_mask[macro_id]) {
605-
continue;
606-
}
607-
int x_start = 0;
608-
int x_end = 0;
609-
calSegmentLoc(macros_[macro_id].getX(),
610-
macros_[macro_id].getX() + macros_[macro_id].getWidth(),
611-
x_start,
612-
x_end,
613-
x_grid);
614-
int y_start = 0;
615-
int y_end = 0;
616-
calSegmentLoc(macros_[macro_id].getY(),
617-
macros_[macro_id].getY() + macros_[macro_id].getHeight(),
618-
y_start,
619-
y_end,
620-
y_grid);
621-
int x_start_new = x_start;
622-
int x_end_new = x_end;
623-
int y_start_new = y_start;
624-
int y_end_new = y_end;
625-
// check left first
626-
for (int i = x_start - 1; i >= 0; i--) {
627-
bool flag = true;
628-
for (int j = y_start; j < y_end; j++) {
629-
if (grids[j][i] != -1) {
630-
flag = false; // we cannot extend the current cluster
631-
break;
632-
} // end if
633-
} // end y
634-
if (!flag) { // extension done
635-
break;
636-
}
637-
x_start_new--; // extend left
638-
for (int j = y_start; j < y_end; j++) {
639-
grids[j][i] = macro_id;
588+
589+
// An empty grid cell surrounded by 3 or more edges is considered a notch
590+
for (int row = 0; row < num_y; row++) {
591+
for (int col = 0; col < num_x; col++) {
592+
if (grid[row][col]) {
593+
continue;
640594
}
641-
} // end left
642-
// check top second
643-
for (int j = y_end; j < num_y; j++) {
644-
bool flag = true;
645-
for (int i = x_start; i < x_end; i++) {
646-
if (grids[j][i] != -1) {
647-
flag = false; // we cannot extend the current cluster
648-
break;
649-
} // end if
650-
} // end y
651-
if (!flag) { // extension done
652-
break;
595+
596+
int surroundings = 0;
597+
if (row == 0 || grid[row - 1][col]) {
598+
surroundings++;
653599
}
654-
y_end_new++; // extend top
655-
for (int i = x_start; i < x_end; i++) {
656-
grids[j][i] = macro_id;
600+
if (row == num_y - 1 || grid[row + 1][col]) {
601+
surroundings++;
657602
}
658-
} // end top
659-
// check right third
660-
for (int i = x_end; i < num_x; i++) {
661-
bool flag = true;
662-
for (int j = y_start; j < y_end; j++) {
663-
if (grids[j][i] != -1) {
664-
flag = false; // we cannot extend the current cluster
665-
break;
666-
} // end if
667-
} // end y
668-
if (!flag) { // extension done
669-
break;
603+
if (col == 0 || grid[row][col - 1]) {
604+
surroundings++;
670605
}
671-
x_end_new++; // extend right
672-
for (int j = y_start; j < y_end; j++) {
673-
grids[j][i] = macro_id;
674-
}
675-
} // end right
676-
// check down second
677-
for (int j = y_start - 1; j >= 0; j--) {
678-
bool flag = true;
679-
for (int i = x_start; i < x_end; i++) {
680-
if (grids[j][i] != -1) {
681-
flag = false; // we cannot extend the current cluster
682-
break;
683-
} // end if
684-
} // end y
685-
if (!flag) { // extension done
686-
break;
606+
if (col == num_x - 1 || grid[row][col + 1]) {
607+
surroundings++;
687608
}
688-
y_start_new--; // extend down
689-
for (int i = x_start; i < x_end; i++) {
690-
grids[j][i] = macro_id;
609+
610+
if (surroundings >= 3) {
611+
width = x_coords[col + 1] - x_coords[col];
612+
height = y_coords[row + 1] - y_coords[row];
613+
614+
if (width <= notch_h_th_ || height <= notch_v_th_) {
615+
notch_penalty_ += calSingleNotchPenalty(width, height);
616+
}
691617
}
692-
} // end down
693-
// check the notch area
694-
if ((x_grid[x_start] - x_grid[x_start_new]) <= notch_h_th_) {
695-
notch_penalty_ += (x_grid[x_start] - x_grid[x_start_new])
696-
* macros_[macro_id].getHeight();
697-
}
698-
if ((x_grid[x_end_new] - x_grid[x_end]) <= notch_h_th_) {
699-
notch_penalty_ += (x_grid[x_end_new] - x_grid[x_end])
700-
* macros_[macro_id].getHeight();
701-
}
702-
if ((y_grid[y_start] - y_grid[y_start_new]) <= notch_v_th_) {
703-
notch_penalty_ += (y_grid[y_start] - y_grid[y_start_new])
704-
* macros_[macro_id].getWidth();
705-
}
706-
if ((y_grid[y_end_new] - y_grid[y_end]) <= notch_v_th_) {
707-
notch_penalty_
708-
+= (y_grid[y_end_new] - y_grid[y_end]) * macros_[macro_id].getWidth();
709618
}
710619
}
711-
macros_ = pre_macros;
712-
// normalization
713-
notch_penalty_
714-
= notch_penalty_ / (outline_.getWidth() * outline_.getHeight());
620+
715621
if (graphics_) {
716622
graphics_->setNotchPenalty(
717623
{"Notch", notch_weight_, notch_penalty_, norm_notch_penalty_});
@@ -866,20 +772,14 @@ void SACoreSoftMacro::fillDeadSpace()
866772
if (macros_[macro_id].getArea() <= 0.0) {
867773
continue;
868774
}
869-
int x_start = 0;
870-
int x_end = 0;
871-
calSegmentLoc(macros_[macro_id].getX(),
872-
macros_[macro_id].getX() + macros_[macro_id].getWidth(),
873-
x_start,
874-
x_end,
875-
x_grid);
876-
int y_start = 0;
877-
int y_end = 0;
878-
calSegmentLoc(macros_[macro_id].getY(),
879-
macros_[macro_id].getY() + macros_[macro_id].getHeight(),
880-
y_start,
881-
y_end,
882-
y_grid);
775+
776+
int x_start = getSegmentIndex(macros_[macro_id].getX(), x_grid);
777+
int x_end = getSegmentIndex(
778+
macros_[macro_id].getX() + macros_[macro_id].getWidth(), x_grid);
779+
int y_start = getSegmentIndex(macros_[macro_id].getY(), y_grid);
780+
int y_end = getSegmentIndex(
781+
macros_[macro_id].getY() + macros_[macro_id].getHeight(), y_grid);
782+
883783
for (int j = y_start; j < y_end; j++) {
884784
for (int i = x_start; i < x_end; i++) {
885785
grids[j][i] = macro_id;
@@ -898,20 +798,14 @@ void SACoreSoftMacro::fillDeadSpace()
898798
if (!forward_flag) {
899799
continue;
900800
}
901-
int x_start = 0;
902-
int x_end = 0;
903-
calSegmentLoc(macros_[macro_id].getX(),
904-
macros_[macro_id].getX() + macros_[macro_id].getWidth(),
905-
x_start,
906-
x_end,
907-
x_grid);
908-
int y_start = 0;
909-
int y_end = 0;
910-
calSegmentLoc(macros_[macro_id].getY(),
911-
macros_[macro_id].getY() + macros_[macro_id].getHeight(),
912-
y_start,
913-
y_end,
914-
y_grid);
801+
802+
int x_start = getSegmentIndex(macros_[macro_id].getX(), x_grid);
803+
int x_end = getSegmentIndex(
804+
macros_[macro_id].getX() + macros_[macro_id].getWidth(), x_grid);
805+
int y_start = getSegmentIndex(macros_[macro_id].getY(), y_grid);
806+
int y_end = getSegmentIndex(
807+
macros_[macro_id].getY() + macros_[macro_id].getHeight(), y_grid);
808+
915809
int x_start_new = x_start;
916810
int x_end_new = x_end;
917811
int y_start_new = y_start;
@@ -996,27 +890,12 @@ void SACoreSoftMacro::fillDeadSpace()
996890
}
997891
}
998892

999-
// A utility function for FillDeadSpace.
1000-
// It's used for calculate the start point and end point for a segment in a grid
1001-
void SACoreSoftMacro::calSegmentLoc(float seg_start,
1002-
float seg_end,
1003-
int& start_id,
1004-
int& end_id,
1005-
std::vector<float>& grid)
893+
int SACoreSoftMacro::getSegmentIndex(float segment,
894+
const std::vector<float>& coords)
1006895
{
1007-
start_id = -1;
1008-
end_id = -1;
1009-
for (int i = 0; i < grid.size() - 1; i++) {
1010-
if ((grid[i] <= seg_start) && (grid[i + 1] > seg_start)) {
1011-
start_id = i;
1012-
}
1013-
if ((grid[i] <= seg_end) && (grid[i + 1] > seg_end)) {
1014-
end_id = i;
1015-
}
1016-
}
1017-
if (end_id == -1) {
1018-
end_id = grid.size() - 1;
1019-
}
896+
int index = std::distance(
897+
coords.begin(), std::lower_bound(coords.begin(), coords.end(), segment));
898+
return index;
1020899
}
1021900

1022901
// The blockages here are only those that overlap with the annealing outline.

src/mpl/src/SACoreSoftMacro.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,16 +81,10 @@ class SACoreSoftMacro : public SimulatedAnnealingCore<SoftMacro>
8181
// actions used
8282
void resizeOneCluster();
8383

84-
// A utility function for FillDeadSpace.
85-
// It's used for calculate the start point and end point for a segment in a
86-
// grid
87-
void calSegmentLoc(float seg_start,
88-
float seg_end,
89-
int& start_id,
90-
int& end_id,
91-
std::vector<float>& grid);
84+
int getSegmentIndex(float segment, const std::vector<float>& coords);
9285

9386
void calBoundaryPenalty();
87+
float calSingleNotchPenalty(float width, float height);
9488
void calNotchPenalty();
9589
void calMacroBlockagePenalty();
9690

@@ -116,6 +110,7 @@ class SACoreSoftMacro : public SimulatedAnnealingCore<SoftMacro>
116110
// additional penalties
117111
float boundary_weight_ = 0.0;
118112
float macro_blockage_weight_ = 0.0;
113+
float notch_weight_ = 0.0;
119114

120115
float boundary_penalty_ = 0.0;
121116
float notch_penalty_ = 0.0;

0 commit comments

Comments
 (0)