Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
287 changes: 83 additions & 204 deletions src/mpl/src/SACoreSoftMacro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ SACoreSoftMacro::SACoreSoftMacro(PhysicalHierarchy* tree,
{
boundary_weight_ = soft_weights.boundary;
macro_blockage_weight_ = soft_weights.macro_blockage;
original_notch_weight_ = soft_weights.notch;
notch_weight_ = soft_weights.notch;
resize_prob_ = resize_prob;
notch_h_th_ = notch_h_threshold;
notch_v_th_ = notch_v_threshold;
Expand Down Expand Up @@ -519,199 +519,105 @@ void SACoreSoftMacro::alignMacroClusters()
}
}

float SACoreSoftMacro::calSingleNotchPenalty(float width, float height)
{
return std::sqrt((width * height) / outline_.getArea());
}

// If there is no HardMacroCluster, we do not consider the notch penalty
void SACoreSoftMacro::calNotchPenalty()
{
// Initialization
notch_penalty_ = 0.0;
if (notch_weight_ <= 0.0) {
return;
}
// If the floorplan cannot fit into the outline

// Initialization
notch_penalty_ = 0.0;
notch_h_th_ = outline_.getHeight() / 10.0;
notch_v_th_ = outline_.getWidth() / 10.0;
float width = 0;
float height = 0;

// If the floorplan is not valid
// We think the entire floorplan is a "huge" notch
if (width_ > outline_.getWidth() * 1.001
|| height_ > outline_.getHeight() * 1.001) {
notch_penalty_ += outline_.getWidth() * outline_.getHeight()
/ (outline_.getWidth() * outline_.getHeight());
if (!isValid()) {
width = std::max(width_, outline_.getWidth());
height = std::max(height_, outline_.getHeight());
notch_penalty_ = calSingleNotchPenalty(width, height);
return;
}

// Macros need to be saved (and restored) since alignMacroClusters and
// fillDeadSpace move them
std::vector<SoftMacro> pre_macros = macros_;
// align macro clusters to reduce notches
alignMacroClusters();
// Fill dead space
fillDeadSpace();
// Create grids based on location of MixedCluster and HardMacroCluster
std::set<float> x_point;
std::set<float> y_point;
std::vector<bool> macro_mask;
for (auto& macro : macros_) {
if (macro.getArea() <= 0.0
|| (!macro.isMacroCluster() && !macro.isMixedCluster())) {
macro_mask.push_back(false);
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());
macro_mask.push_back(true);
}
x_point.insert(0.0);
y_point.insert(0.0);
x_point.insert(outline_.getWidth());
y_point.insert(outline_.getHeight());
// create grid
std::vector<float> x_grid(x_point.begin(), x_point.end());
std::vector<float> y_grid(y_point.begin(), y_point.end());
// create grid in a row-based manner
std::vector<std::vector<int>> grids; // store the macro id
const int num_x = x_grid.size() - 1;
const int num_y = y_grid.size() - 1;
for (int j = 0; j < num_y; j++) {
std::vector<int> macro_ids(num_x, -1);
grids.push_back(macro_ids);
}
// detect the notch region around each MixedCluster and HardMacroCluster
for (int macro_id = 0; macro_id < macros_.size(); macro_id++) {
if (!macro_mask[macro_id]) {

std::vector<float> x_coords(x_point.begin(), x_point.end());
std::vector<float> 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()) {
continue;
}
int x_start = 0;
int x_end = 0;
calSegmentLoc(macros_[macro_id].getX(),
macros_[macro_id].getX() + macros_[macro_id].getWidth(),
x_start,
x_end,
x_grid);
int y_start = 0;
int y_end = 0;
calSegmentLoc(macros_[macro_id].getY(),
macros_[macro_id].getY() + macros_[macro_id].getHeight(),
y_start,
y_end,
y_grid);
for (int j = y_start; j < y_end; j++) {
for (int i = x_start; i < x_end; i++) {
grids[j][i] = macro_id;
int x_start = getSegmentIndex(macro.getX(), x_coords);
int x_end = getSegmentIndex(macro.getX() + macro.getWidth(), x_coords);
int y_start = getSegmentIndex(macro.getY(), y_coords);
int y_end = getSegmentIndex(macro.getY() + macro.getHeight(), y_coords);
for (int row = y_start; row < y_end; row++) {
for (int col = x_start; col < x_end; col++) {
grid[row][col] = true;
}
}
}
// check surroundings of each HardMacroCluster and MixecCluster
for (int macro_id = 0; macro_id < macros_.size(); macro_id++) {
if (!macro_mask[macro_id]) {
continue;
}
int x_start = 0;
int x_end = 0;
calSegmentLoc(macros_[macro_id].getX(),
macros_[macro_id].getX() + macros_[macro_id].getWidth(),
x_start,
x_end,
x_grid);
int y_start = 0;
int y_end = 0;
calSegmentLoc(macros_[macro_id].getY(),
macros_[macro_id].getY() + macros_[macro_id].getHeight(),
y_start,
y_end,
y_grid);
int x_start_new = x_start;
int x_end_new = x_end;
int y_start_new = y_start;
int y_end_new = y_end;
// check left first
for (int i = x_start - 1; i >= 0; i--) {
bool flag = true;
for (int j = y_start; j < y_end; j++) {
if (grids[j][i] != -1) {
flag = false; // we cannot extend the current cluster
break;
} // end if
} // end y
if (!flag) { // extension done
break;
}
x_start_new--; // extend left
for (int j = y_start; j < y_end; j++) {
grids[j][i] = macro_id;

// 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]) {
continue;
}
} // end left
// check top second
for (int j = y_end; j < num_y; j++) {
bool flag = true;
for (int i = x_start; i < x_end; i++) {
if (grids[j][i] != -1) {
flag = false; // we cannot extend the current cluster
break;
} // end if
} // end y
if (!flag) { // extension done
break;

int surroundings = 0;
if (row == 0 || grid[row - 1][col]) {
surroundings++;
}
y_end_new++; // extend top
for (int i = x_start; i < x_end; i++) {
grids[j][i] = macro_id;
if (row == num_y - 1 || grid[row + 1][col]) {
surroundings++;
}
} // end top
// check right third
for (int i = x_end; i < num_x; i++) {
bool flag = true;
for (int j = y_start; j < y_end; j++) {
if (grids[j][i] != -1) {
flag = false; // we cannot extend the current cluster
break;
} // end if
} // end y
if (!flag) { // extension done
break;
if (col == 0 || grid[row][col - 1]) {
surroundings++;
}
x_end_new++; // extend right
for (int j = y_start; j < y_end; j++) {
grids[j][i] = macro_id;
}
} // end right
// check down second
for (int j = y_start - 1; j >= 0; j--) {
bool flag = true;
for (int i = x_start; i < x_end; i++) {
if (grids[j][i] != -1) {
flag = false; // we cannot extend the current cluster
break;
} // end if
} // end y
if (!flag) { // extension done
break;
if (col == num_x - 1 || grid[row][col + 1]) {
surroundings++;
}
y_start_new--; // extend down
for (int i = x_start; i < x_end; i++) {
grids[j][i] = macro_id;

if (surroundings >= 3) {
width = x_coords[col + 1] - x_coords[col];
height = y_coords[row + 1] - y_coords[row];

if (width <= notch_h_th_ || height <= notch_v_th_) {
notch_penalty_ += calSingleNotchPenalty(width, height);
}
}
} // end down
// check the notch area
if ((x_grid[x_start] - x_grid[x_start_new]) <= notch_h_th_) {
notch_penalty_ += (x_grid[x_start] - x_grid[x_start_new])
* macros_[macro_id].getHeight();
}
if ((x_grid[x_end_new] - x_grid[x_end]) <= notch_h_th_) {
notch_penalty_ += (x_grid[x_end_new] - x_grid[x_end])
* macros_[macro_id].getHeight();
}
if ((y_grid[y_start] - y_grid[y_start_new]) <= notch_v_th_) {
notch_penalty_ += (y_grid[y_start] - y_grid[y_start_new])
* macros_[macro_id].getWidth();
}
if ((y_grid[y_end_new] - y_grid[y_end]) <= notch_v_th_) {
notch_penalty_
+= (y_grid[y_end_new] - y_grid[y_end]) * macros_[macro_id].getWidth();
}
}
macros_ = pre_macros;
// normalization
notch_penalty_
= notch_penalty_ / (outline_.getWidth() * outline_.getHeight());

if (graphics_) {
graphics_->setNotchPenalty(
{"Notch", notch_weight_, notch_penalty_, norm_notch_penalty_});
Expand Down Expand Up @@ -866,20 +772,14 @@ void SACoreSoftMacro::fillDeadSpace()
if (macros_[macro_id].getArea() <= 0.0) {
continue;
}
int x_start = 0;
int x_end = 0;
calSegmentLoc(macros_[macro_id].getX(),
macros_[macro_id].getX() + macros_[macro_id].getWidth(),
x_start,
x_end,
x_grid);
int y_start = 0;
int y_end = 0;
calSegmentLoc(macros_[macro_id].getY(),
macros_[macro_id].getY() + macros_[macro_id].getHeight(),
y_start,
y_end,
y_grid);

int x_start = getSegmentIndex(macros_[macro_id].getX(), x_grid);
int x_end = getSegmentIndex(
macros_[macro_id].getX() + macros_[macro_id].getWidth(), x_grid);
int y_start = getSegmentIndex(macros_[macro_id].getY(), y_grid);
int y_end = getSegmentIndex(
macros_[macro_id].getY() + macros_[macro_id].getHeight(), y_grid);

for (int j = y_start; j < y_end; j++) {
for (int i = x_start; i < x_end; i++) {
grids[j][i] = macro_id;
Expand All @@ -898,20 +798,14 @@ void SACoreSoftMacro::fillDeadSpace()
if (!forward_flag) {
continue;
}
int x_start = 0;
int x_end = 0;
calSegmentLoc(macros_[macro_id].getX(),
macros_[macro_id].getX() + macros_[macro_id].getWidth(),
x_start,
x_end,
x_grid);
int y_start = 0;
int y_end = 0;
calSegmentLoc(macros_[macro_id].getY(),
macros_[macro_id].getY() + macros_[macro_id].getHeight(),
y_start,
y_end,
y_grid);

int x_start = getSegmentIndex(macros_[macro_id].getX(), x_grid);
int x_end = getSegmentIndex(
macros_[macro_id].getX() + macros_[macro_id].getWidth(), x_grid);
int y_start = getSegmentIndex(macros_[macro_id].getY(), y_grid);
int y_end = getSegmentIndex(
macros_[macro_id].getY() + macros_[macro_id].getHeight(), y_grid);

int x_start_new = x_start;
int x_end_new = x_end;
int y_start_new = y_start;
Expand Down Expand Up @@ -996,27 +890,12 @@ void SACoreSoftMacro::fillDeadSpace()
}
}

// A utility function for FillDeadSpace.
// It's used for calculate the start point and end point for a segment in a grid
void SACoreSoftMacro::calSegmentLoc(float seg_start,
float seg_end,
int& start_id,
int& end_id,
std::vector<float>& grid)
int SACoreSoftMacro::getSegmentIndex(float segment,
const std::vector<float>& coords)
{
start_id = -1;
end_id = -1;
for (int i = 0; i < grid.size() - 1; i++) {
if ((grid[i] <= seg_start) && (grid[i + 1] > seg_start)) {
start_id = i;
}
if ((grid[i] <= seg_end) && (grid[i + 1] > seg_end)) {
end_id = i;
}
}
if (end_id == -1) {
end_id = grid.size() - 1;
}
int index = std::distance(
coords.begin(), std::lower_bound(coords.begin(), coords.end(), segment));
return index;
}

// The blockages here are only those that overlap with the annealing outline.
Expand Down
11 changes: 3 additions & 8 deletions src/mpl/src/SACoreSoftMacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,10 @@ class SACoreSoftMacro : public SimulatedAnnealingCore<SoftMacro>
// actions used
void resizeOneCluster();

// A utility function for FillDeadSpace.
// It's used for calculate the start point and end point for a segment in a
// grid
void calSegmentLoc(float seg_start,
float seg_end,
int& start_id,
int& end_id,
std::vector<float>& grid);
int getSegmentIndex(float segment, const std::vector<float>& coords);

void calBoundaryPenalty();
float calSingleNotchPenalty(float width, float height);
void calNotchPenalty();
void calMacroBlockagePenalty();

Expand All @@ -116,6 +110,7 @@ class SACoreSoftMacro : public SimulatedAnnealingCore<SoftMacro>
// additional penalties
float boundary_weight_ = 0.0;
float macro_blockage_weight_ = 0.0;
float notch_weight_ = 0.0;

float boundary_penalty_ = 0.0;
float notch_penalty_ = 0.0;
Expand Down
Loading