Skip to content

Commit d58027b

Browse files
authored
Merge pull request #10454 from calewis/fix-mbff-kmeans-div-by-zero
Fix mbff kmeans div by zero
2 parents b74c2ea + b5bbc8a commit d58027b

2 files changed

Lines changed: 49 additions & 0 deletions

File tree

src/gpl/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ cc_library(
6969
"//src/rsz",
7070
"//src/sta:opensta_lib",
7171
"//src/utl",
72+
"@abseil-cpp//absl/container:inlined_vector",
7273
"@boost.polygon",
7374
"@boost.stacktrace",
7475
"@boost.unordered",

src/gpl/src/mbff.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <vector>
1818

1919
#include "AbstractGraphics.h"
20+
#include "absl/container/inlined_vector.h"
2021
#include "db_sta/dbNetwork.hh"
2122
#include "db_sta/dbSta.hh"
2223
#include "lemon/core.h"
@@ -1737,8 +1738,13 @@ void MBFF::KMeans(const std::vector<Flop>& flops,
17371738
}
17381739

17391740
// find new center locations
1741+
absl::InlinedVector<int, 4> empty_clusters;
17401742
for (int i = 0; i < knn; i++) {
17411743
const int cur_sz = clusters[i].size();
1744+
if (cur_sz == 0) {
1745+
empty_clusters.push_back(i);
1746+
continue;
1747+
}
17421748
float cX = 0;
17431749
float cY = 0;
17441750

@@ -1752,6 +1758,48 @@ void MBFF::KMeans(const std::vector<Flop>& flops,
17521758
centers[i].pt = Point{new_x, new_y};
17531759
}
17541760

1761+
if (!empty_clusters.empty()) {
1762+
// To revive empty clusters and avoid division by zero, we re-seed their
1763+
// centers with active flops that are currently furthest from their
1764+
// assigned cluster centers. We use an inlined vector to track chosen
1765+
// flops and prevent promoting the same flop to multiple empty clusters.
1766+
absl::InlinedVector<int, 8> used_flops;
1767+
for (int empty_idx : empty_clusters) {
1768+
float max_dist = -1;
1769+
Point best_pt = centers[empty_idx].pt; // Fallback to previous center
1770+
int best_idx = -1;
1771+
1772+
for (int j = 0; j < knn; j++) {
1773+
if (clusters[j].empty()) {
1774+
continue;
1775+
}
1776+
for (const Flop& flop : clusters[j]) {
1777+
if (std::find(used_flops.begin(), used_flops.end(), flop.idx)
1778+
!= used_flops.end()) {
1779+
continue;
1780+
}
1781+
// Find the flop that has the worst-fit (largest displacement)
1782+
// to its currently assigned center.
1783+
const float dist = GetDist(flop.pt, centers[j].pt);
1784+
if (dist > max_dist) {
1785+
max_dist = dist;
1786+
best_pt = flop.pt;
1787+
best_idx = flop.idx;
1788+
}
1789+
}
1790+
}
1791+
1792+
if (best_idx != -1) {
1793+
// Re-seeding the center directly onto the flop's coordinate.
1794+
// This guarantees that in the next iteration, the distance from this
1795+
// flop to this center is 0.0, forcing it to be assigned to this
1796+
// cluster and keeping it active.
1797+
centers[empty_idx].pt = best_pt;
1798+
used_flops.push_back(best_idx);
1799+
}
1800+
}
1801+
}
1802+
17551803
// get total displacement
17561804
float tot_disp = 0;
17571805
for (int i = 0; i < knn; i++) {

0 commit comments

Comments
 (0)