Skip to content

Commit 169302f

Browse files
committed
mpl:
1) Evaluate connection between clusters based on connections' ratio instead of using a fixed threshold; 2) Retire threshold for evaluating connections. Signed-off-by: Arthur Koucher <arthurkoucher@precisioninno.com>
1 parent bae59f6 commit 169302f

11 files changed

Lines changed: 152 additions & 139 deletions

File tree

src/mpl/README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ rtl_macro_placer
2626
[-max_num_level max_num_level]
2727
[-coarsening_ratio coarsening_ratio]
2828
[-large_net_threshold large_net_threshold]
29-
[-signature_net_threshold signature_net_threshold]
3029
[-halo_width halo_width]
3130
[-halo_height halo_height]
3231
[-fence_lx fence_lx]
@@ -59,7 +58,6 @@ rtl_macro_placer
5958
| `-max_num_level` | Maximum depth of physical hierarchical tree. The default value is `2`, and the allowed values are integers `[0, MAX_INT]`. |
6059
| `-coarsening_ratio` | The larger the coarsening_ratio, the faster the convergence process. The allowed values are floats, and the default value is `10.0`. |
6160
| `-large_net_threshold` | Ignore nets with many connections during clustering, such as global nets. The default value is `50`, and the allowed values are integers `[0, MAX_INT]`. |
62-
| `-signature_net_threshold` | Minimum number of connections between two clusters to be identified as connected. The default value is `50`, and the allowed values are integers `[0, MAX_INT]`. |
6361
| `-halo_width` | Horizontal/vertical halo around macros (microns). The allowed values are floats, and the default value is `0.0`. |
6462
| `-fence_lx`, `-fence_ly`, `-fence_ux`, `-fence_uy` | Defines the global fence bounding box coordinates. The default values are the core area coordinates). |
6563
| `-target_util` | Specifies the target utilization of `MixedCluster` and has higher priority than target_dead_space. The allowed values are floats, and the default value is `0.25`. |

src/mpl/include/mpl/rtl_mp.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ class MacroPlacer
5151
int max_num_level,
5252
float coarsening_ratio,
5353
int large_net_threshold,
54-
int signature_net_threshold,
5554
float halo_width,
5655
float halo_height,
5756
float fence_lx,

src/mpl/src/clusterEngine.cpp

Lines changed: 132 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,23 +1743,10 @@ void ClusteringEngine::mergeChildrenBelowThresholds(
17431743
}
17441744
// Firstly we perform Type 1 merge
17451745
for (int i = 0; i < num_small_children; i++) {
1746-
const int cluster_id = small_children[i]->getCloseCluster(
1747-
small_children_ids, tree_->min_net_count_for_connection);
1748-
debugPrint(
1749-
logger_,
1750-
MPL,
1751-
"multilevel_autoclustering",
1752-
1,
1753-
"Candidate cluster: {} - {}",
1754-
small_children[i]->getName(),
1755-
(cluster_id != -1 ? tree_->maps.id_to_cluster[cluster_id]->getName()
1756-
: " "));
1757-
if (cluster_id != -1
1758-
&& !tree_->maps.id_to_cluster[cluster_id]->isIOCluster()) {
1759-
Cluster* close_cluster = tree_->maps.id_to_cluster[cluster_id];
1760-
if (attemptMerge(close_cluster, small_children[i])) {
1761-
cluster_class[i] = close_cluster->getId();
1762-
}
1746+
Cluster* close_cluster = findSingleWellFormedConnectedCluster(
1747+
small_children[i], small_children_ids);
1748+
if (close_cluster && attemptMerge(close_cluster, small_children[i])) {
1749+
cluster_class[i] = close_cluster->getId();
17631750
}
17641751
}
17651752

@@ -1772,8 +1759,7 @@ void ClusteringEngine::mergeChildrenBelowThresholds(
17721759
continue;
17731760
}
17741761

1775-
if (small_children[i]->isSameConnSignature(
1776-
*small_children[j], tree_->min_net_count_for_connection)) {
1762+
if (sameConnectionSignature(small_children[i], small_children[j])) {
17771763
if (attemptMerge(small_children[i], small_children[j])) {
17781764
cluster_class[j] = i;
17791765
} else {
@@ -1860,6 +1846,127 @@ void ClusteringEngine::mergeChildrenBelowThresholds(
18601846
"Finished merging clusters");
18611847
}
18621848

1849+
bool ClusteringEngine::sameConnectionSignature(Cluster* a, Cluster* b) const
1850+
{
1851+
std::vector<int> a_neighbors = findNeighbors(a, /* ignore */ b);
1852+
if (a_neighbors.empty()) {
1853+
return false;
1854+
}
1855+
1856+
std::vector<int> b_neighbors = findNeighbors(b, /* ignore */ a);
1857+
if (b_neighbors.size() != a_neighbors.size()) {
1858+
return false;
1859+
}
1860+
1861+
std::sort(a_neighbors.begin(), a_neighbors.end());
1862+
std::sort(b_neighbors.begin(), b_neighbors.end());
1863+
1864+
for (int i = 0; i < a_neighbors.size(); i++) {
1865+
if (a_neighbors[i] != b_neighbors[i]) {
1866+
return false;
1867+
}
1868+
}
1869+
1870+
return true;
1871+
}
1872+
1873+
std::vector<int> ClusteringEngine::findNeighbors(Cluster* target_cluster,
1874+
Cluster* ignored_cluster) const
1875+
{
1876+
std::vector<int> neighbors;
1877+
const ConnectionsMap& target_connections
1878+
= target_cluster->getConnectionsMap();
1879+
1880+
for (const auto& [cluster_id, connection_weight] : target_connections) {
1881+
if (cluster_id == target_cluster->getId()) {
1882+
logger_->error(MPL,
1883+
53,
1884+
"Cluster {} is connected to itself.",
1885+
target_cluster->getName());
1886+
}
1887+
1888+
if (cluster_id == ignored_cluster->getId()) {
1889+
continue;
1890+
}
1891+
1892+
Cluster* other_cluster = tree_->maps.id_to_cluster.at(cluster_id);
1893+
1894+
if (strongConnection(target_cluster, other_cluster, &connection_weight)) {
1895+
neighbors.push_back(cluster_id);
1896+
}
1897+
}
1898+
1899+
return neighbors;
1900+
}
1901+
1902+
bool ClusteringEngine::strongConnection(Cluster* a,
1903+
Cluster* b,
1904+
const float* connection_weight) const
1905+
{
1906+
if (a == b) {
1907+
logger_->error(
1908+
MPL,
1909+
61,
1910+
"Attempt to evaluate if cluster {} has strong connection with itself.",
1911+
a->getName());
1912+
}
1913+
1914+
const float minimum_connection_ratio = 0.1;
1915+
const float total_weight
1916+
= a->allConnectionsWeight() + b->allConnectionsWeight();
1917+
1918+
float connection_ratio = 0.0;
1919+
if (connection_weight) {
1920+
connection_ratio = *connection_weight / total_weight;
1921+
} else {
1922+
const ConnectionsMap& a_connections = a->getConnectionsMap();
1923+
auto itr = a_connections.find(b->getId());
1924+
1925+
if (itr != a_connections.end()) {
1926+
const float conn_weight = itr->second;
1927+
connection_ratio = conn_weight / total_weight;
1928+
}
1929+
}
1930+
1931+
return connection_ratio >= minimum_connection_ratio;
1932+
}
1933+
1934+
Cluster* ClusteringEngine::findSingleWellFormedConnectedCluster(
1935+
Cluster* target_cluster,
1936+
const std::vector<int>& small_clusters_id_list) const
1937+
{
1938+
int number_of_close_clusters = 0;
1939+
Cluster* close_cluster = nullptr;
1940+
const ConnectionsMap& target_connections
1941+
= target_cluster->getConnectionsMap();
1942+
1943+
for (auto& [cluster_id, connection_weight] : target_connections) {
1944+
Cluster* candidate = tree_->maps.id_to_cluster.at(cluster_id);
1945+
1946+
if (candidate->isIOCluster()) {
1947+
continue;
1948+
}
1949+
1950+
if (strongConnection(target_cluster, candidate, &connection_weight)) {
1951+
auto small_child_found = std::find(small_clusters_id_list.begin(),
1952+
small_clusters_id_list.end(),
1953+
cluster_id);
1954+
1955+
// A small child is not well-formed, so we avoid them.
1956+
if (small_child_found == small_clusters_id_list.end()) {
1957+
number_of_close_clusters++;
1958+
close_cluster = candidate;
1959+
}
1960+
}
1961+
}
1962+
1963+
if (number_of_close_clusters == 1) {
1964+
return close_cluster;
1965+
}
1966+
1967+
return nullptr;
1968+
}
1969+
18631970
bool ClusteringEngine::attemptMerge(Cluster* receiver, Cluster* incomer)
18641971
{
18651972
// Cache incomer data in case it is deleted.
@@ -2209,8 +2316,7 @@ void ClusteringEngine::classifyMacrosByConnSignature(
22092316
continue;
22102317
}
22112318

2212-
if (macro_clusters[i]->isSameConnSignature(
2213-
*macro_clusters[j], tree_->min_net_count_for_connection)) {
2319+
if (sameConnectionSignature(macro_clusters[i], macro_clusters[j])) {
22142320
signature_class[j] = i;
22152321
}
22162322
}
@@ -2238,8 +2344,11 @@ void ClusteringEngine::classifyMacrosByInterconn(
22382344
if (interconn_class[i] == -1) {
22392345
interconn_class[i] = i;
22402346
for (int j = 0; j < macro_clusters.size(); j++) {
2241-
if (macro_clusters[i]->hasMacroConnectionWith(
2242-
*macro_clusters[j], tree_->min_net_count_for_connection)) {
2347+
if (macro_clusters[i] == macro_clusters[j]) {
2348+
continue;
2349+
}
2350+
2351+
if (strongConnection(macro_clusters[i], macro_clusters[j])) {
22432352
if (interconn_class[j] != -1) {
22442353
interconn_class[i] = interconn_class[j];
22452354
break;

src/mpl/src/clusterEngine.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ struct PhysicalHierarchy
117117

118118
int max_level{0};
119119
int large_net_threshold{0}; // used to ignore global nets
120-
int min_net_count_for_connection{0};
121120
float cluster_size_ratio{0.0f};
122121
float cluster_size_tolerance{0.0f};
123122

@@ -212,6 +211,15 @@ class ClusteringEngine
212211
bool partitionerSolutionIsFullyUnbalanced(const std::vector<int>& solution,
213212
int num_other_cluster_vertices);
214213
void mergeChildrenBelowThresholds(std::vector<Cluster*>& small_children);
214+
bool sameConnectionSignature(Cluster* a, Cluster* b) const;
215+
bool strongConnection(Cluster* a,
216+
Cluster* b,
217+
const float* connection_weight = nullptr) const;
218+
Cluster* findSingleWellFormedConnectedCluster(
219+
Cluster* target_cluster,
220+
const std::vector<int>& small_clusters_id_list) const;
221+
std::vector<int> findNeighbors(Cluster* target_cluster,
222+
Cluster* ignored_cluster) const;
215223
bool attemptMerge(Cluster* receiver, Cluster* incomer);
216224
void fetchMixedLeaves(Cluster* parent,
217225
std::vector<std::vector<Cluster*>>& mixed_leaves);

src/mpl/src/hier_rtlmp.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,6 @@ void HierRTLMP::setLargeNetThreshold(int large_net_threshold)
158158
tree_->large_net_threshold = large_net_threshold;
159159
}
160160

161-
void HierRTLMP::setSignatureNetThreshold(int signature_net_threshold)
162-
{
163-
tree_->min_net_count_for_connection = signature_net_threshold;
164-
}
165-
166161
void HierRTLMP::setTargetUtil(float target_util)
167162
{
168163
target_util_ = target_util;

src/mpl/src/hier_rtlmp.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ class HierRTLMP
9292
void setMaxNumLevel(int max_num_level);
9393
void setClusterSizeRatioPerLevel(float coarsening_ratio);
9494
void setLargeNetThreshold(int large_net_threshold);
95-
void setSignatureNetThreshold(int signature_net_threshold);
9695
void setAreaWeight(float area_weight);
9796
void setOutlineWeight(float outline_weight);
9897
void setWirelengthWeight(float wirelength_weight);

src/mpl/src/mpl.i

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ bool rtl_macro_placer_cmd(const int max_num_macro,
3434
const int max_num_level,
3535
const float coarsening_ratio,
3636
const int large_net_threshold,
37-
const int signature_net_threshold,
3837
const float halo_width,
3938
const float halo_height,
4039
const float fence_lx,
@@ -66,7 +65,6 @@ bool rtl_macro_placer_cmd(const int max_num_macro,
6665
max_num_level,
6766
coarsening_ratio,
6867
large_net_threshold,
69-
signature_net_threshold,
7068
halo_width,
7169
halo_height,
7270
fence_lx,

src/mpl/src/mpl.tcl

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ sta::define_cmd_args "rtl_macro_placer" { -max_num_macro max_num_macro \
99
-max_num_level max_num_level \
1010
-coarsening_ratio coarsening_ratio \
1111
-large_net_threshold large_net_threshold \
12-
-signature_net_threshold signature_net_threshold \
1312
-halo_width halo_width \
1413
-halo_height halo_height \
1514
-fence_lx fence_lx \
@@ -35,7 +34,7 @@ proc rtl_macro_placer { args } {
3534
sta::parse_key_args "rtl_macro_placer" args \
3635
keys {-max_num_macro -min_num_macro -max_num_inst -min_num_inst -tolerance \
3736
-max_num_level -coarsening_ratio -large_net_threshold \
38-
-signature_net_threshold -halo_width -halo_height \
37+
-halo_width -halo_height \
3938
-fence_lx -fence_ly -fence_ux -fence_uy \
4039
-area_weight -outline_weight -wirelength_weight -guidance_weight -fence_weight \
4140
-boundary_weight -notch_weight \
@@ -63,7 +62,6 @@ proc rtl_macro_placer { args } {
6362
set max_num_level 2
6463
set coarsening_ratio 10.0
6564
set large_net_threshold 50
66-
set signature_net_threshold 50
6765
set halo_width 0.0
6866
set halo_height 0.0
6967
set fence_lx 0.0
@@ -110,9 +108,6 @@ proc rtl_macro_placer { args } {
110108
if { [info exists keys(-large_net_threshold)] } {
111109
set large_net_threshold $keys(-large_net_threshold)
112110
}
113-
if { [info exists keys(-signature_net_threshold)] } {
114-
set signature_net_threshold $keys(-signature_net_threshold)
115-
}
116111

117112
if { [info exists keys(-halo_width)] && [info exists keys(-halo_height)] } {
118113
set halo_width $keys(-halo_width)
@@ -189,7 +184,6 @@ proc rtl_macro_placer { args } {
189184
$max_num_level \
190185
$coarsening_ratio \
191186
$large_net_threshold \
192-
$signature_net_threshold \
193187
$halo_width \
194188
$halo_height \
195189
$fence_lx $fence_ly $fence_ux $fence_uy \

0 commit comments

Comments
 (0)