Skip to content

Commit 3f90681

Browse files
authored
Merge pull request #6689 from AcKoucher/mpl-io-fixed-terminals
mpl: fix fixed terminals for cluster of unplaced IOs and max cost
2 parents b849e7f + d7d583e commit 3f90681

File tree

9 files changed

+135
-87
lines changed

9 files changed

+135
-87
lines changed

src/mpl/src/SimulatedAnnealingCore.cpp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,18 @@ SimulatedAnnealingCore<T>::SimulatedAnnealingCore(PhysicalHierarchy* tree,
6161
logger_ = logger;
6262
macros_ = macros;
6363

64+
setDieArea(tree->die_area);
6465
setBlockedBoundariesForIOs();
6566
}
6667

68+
template <class T>
69+
void SimulatedAnnealingCore<T>::setDieArea(const Rect& die_area)
70+
{
71+
die_area_ = die_area;
72+
die_area_.moveHor(-outline_.xMin());
73+
die_area_.moveVer(-outline_.yMin());
74+
}
75+
6776
template <class T>
6877
void SimulatedAnnealingCore<T>::setBlockedBoundariesForIOs()
6978
{
@@ -301,42 +310,42 @@ void SimulatedAnnealingCore<T>::calWirelength()
301310
template <class T>
302311
void SimulatedAnnealingCore<T>::addBoundaryDistToWirelength(
303312
const T& macro,
304-
const T& io,
313+
const T& unplaced_ios,
305314
const float net_weight)
306315
{
307-
Cluster* io_cluster = io.getCluster();
308-
const Rect die = io_cluster->getBBox();
309-
const float die_hpwl = die.getWidth() + die.getHeight();
316+
// To generate maximum cost.
317+
const float max_dist = die_area_.getPerimeter() / 2;
310318

311319
if (isOutsideTheOutline(macro)) {
312-
wirelength_ += net_weight * die_hpwl;
320+
wirelength_ += net_weight * max_dist;
313321
return;
314322
}
315323

316324
const float x1 = macro.getPinX();
317325
const float y1 = macro.getPinY();
318326

319-
Boundary constraint_boundary = io_cluster->getConstraintBoundary();
327+
Boundary constraint_boundary
328+
= unplaced_ios.getCluster()->getConstraintBoundary();
320329

321330
if (constraint_boundary == NONE) {
322-
float dist_to_left = die_hpwl;
331+
float dist_to_left = max_dist;
323332
if (!left_is_blocked_) {
324-
dist_to_left = std::abs(x1 - die.xMin());
333+
dist_to_left = std::abs(x1 - die_area_.xMin());
325334
}
326335

327-
float dist_to_right = die_hpwl;
336+
float dist_to_right = max_dist;
328337
if (!right_is_blocked_) {
329-
dist_to_right = std::abs(x1 - die.xMax());
338+
dist_to_right = std::abs(x1 - die_area_.xMax());
330339
}
331340

332-
float dist_to_bottom = die_hpwl;
341+
float dist_to_bottom = max_dist;
333342
if (!bottom_is_blocked_) {
334-
dist_to_right = std::abs(y1 - die.yMin());
343+
dist_to_right = std::abs(y1 - die_area_.yMin());
335344
}
336345

337-
float dist_to_top = die_hpwl;
346+
float dist_to_top = max_dist;
338347
if (!top_is_blocked_) {
339-
dist_to_top = std::abs(y1 - die.yMax());
348+
dist_to_top = std::abs(y1 - die_area_.yMax());
340349
}
341350

342351
wirelength_
@@ -345,11 +354,11 @@ void SimulatedAnnealingCore<T>::addBoundaryDistToWirelength(
345354
{dist_to_left, dist_to_right, dist_to_bottom, dist_to_top});
346355
} else if (constraint_boundary == Boundary::L
347356
|| constraint_boundary == Boundary::R) {
348-
const float x2 = io.getPinX();
357+
const float x2 = unplaced_ios.getPinX();
349358
wirelength_ += net_weight * std::abs(x2 - x1);
350359
} else if (constraint_boundary == Boundary::T
351360
|| constraint_boundary == Boundary::B) {
352-
const float y2 = io.getPinY();
361+
const float y2 = unplaced_ios.getPinY();
353362
wirelength_ += net_weight * std::abs(y2 - y1);
354363
}
355364
}

src/mpl/src/SimulatedAnnealingCore.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class SimulatedAnnealingCore
9898
void fastSA();
9999

100100
void initSequencePair();
101+
void setDieArea(const Rect& die_area);
101102
void setBlockedBoundariesForIOs();
102103
void updateBestValidResult();
103104
void useBestValidResult();
@@ -107,7 +108,7 @@ class SimulatedAnnealingCore
107108
void calOutlinePenalty();
108109
void calWirelength();
109110
void addBoundaryDistToWirelength(const T& macro,
110-
const T& io,
111+
const T& unplaced_ios,
111112
float net_weight);
112113
bool isOutsideTheOutline(const T& macro) const;
113114
void calGuidancePenalty();
@@ -134,11 +135,8 @@ class SimulatedAnnealingCore
134135
void reportLocations() const;
135136
void report(const PenaltyData& penalty) const;
136137

137-
/////////////////////////////////////////////
138-
// private member variables
139-
/////////////////////////////////////////////
140-
// boundary constraints
141138
Rect outline_;
139+
Rect die_area_; // Offset to the current outline.
142140

143141
// Boundaries blocked for IO pins
144142
std::set<Boundary> blocked_boundaries_;

src/mpl/src/clusterEngine.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ void ClusteringEngine::init()
8787
return;
8888
}
8989

90+
setDieArea();
9091
setFloorplanShape();
9192
searchForFixedInstsInsideFloorplanShape();
9293

@@ -106,6 +107,19 @@ void ClusteringEngine::init()
106107
reportDesignData();
107108
}
108109

110+
// Note: The die area's dimensions will be used inside
111+
// SA Core when computing the wirelength in a situation in which
112+
// the target cluster is a cluster of unplaced IOs.
113+
void ClusteringEngine::setDieArea()
114+
{
115+
const odb::Rect& die = block_->getDieArea();
116+
117+
tree_->die_area = Rect(block_->dbuToMicrons(die.xMin()),
118+
block_->dbuToMicrons(die.yMin()),
119+
block_->dbuToMicrons(die.xMax()),
120+
block_->dbuToMicrons(die.yMax()));
121+
}
122+
109123
float ClusteringEngine::computeMacroWithHaloArea(
110124
const std::vector<odb::dbInst*>& unfixed_macros)
111125
{

src/mpl/src/clusterEngine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ struct PhysicalHierarchy
9797
float macro_with_halo_area{0.0f};
9898
Rect global_fence;
9999
Rect floorplan_shape;
100+
Rect die_area;
100101

101102
bool has_io_clusters{true};
102103
bool has_only_macros{false};
@@ -156,6 +157,7 @@ class ClusteringEngine
156157
void init();
157158
Metrics* computeModuleMetrics(odb::dbModule* module);
158159
std::vector<odb::dbInst*> getUnfixedMacros();
160+
void setDieArea();
159161
void setFloorplanShape();
160162
void searchForFixedInstsInsideFloorplanShape();
161163
float computeMacroWithHaloArea(

src/mpl/src/graphics.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -613,14 +613,12 @@ void Graphics::drawDistToIoConstraintBoundary(gui::Painter& painter,
613613
return;
614614
}
615615

616-
Cluster* io_cluster = io.getCluster();
617-
618616
const int x1 = block_->micronsToDbu(macro.getPinX());
619617
const int y1 = block_->micronsToDbu(macro.getPinY());
620618
odb::Point from(x1, y1);
621619

622620
odb::Point to;
623-
Boundary constraint_boundary = io_cluster->getConstraintBoundary();
621+
Boundary constraint_boundary = io.getCluster()->getConstraintBoundary();
624622

625623
if (constraint_boundary == Boundary::L
626624
|| constraint_boundary == Boundary::R) {
@@ -635,12 +633,14 @@ void Graphics::drawDistToIoConstraintBoundary(gui::Painter& painter,
635633
to.setX(x2);
636634
to.setY(y2);
637635
} else {
638-
// For NONE, the shape of the io cluster is the die area.
639-
const Rect die = io_cluster->getBBox();
636+
// We need to use the bbox of the SoftMacro to get the necessary
637+
// offset compensation (the cluster bbox is the bbox w.r.t. to the
638+
// actual die area).
639+
const Rect offset_die = io.getBBox();
640640
Boundary closest_unblocked_boundary
641-
= getClosestUnblockedBoundary(macro, die);
641+
= getClosestUnblockedBoundary(macro, offset_die);
642642

643-
to = getClosestBoundaryPoint(macro, die, closest_unblocked_boundary);
643+
to = getClosestBoundaryPoint(macro, offset_die, closest_unblocked_boundary);
644644
}
645645

646646
addOutlineOffsetToLine(from, to);
@@ -671,19 +671,15 @@ odb::Point Graphics::getClosestBoundaryPoint(const T& macro,
671671
if (closest_boundary == Boundary::L) {
672672
to.setX(block_->micronsToDbu(die.xMin()));
673673
to.setY(block_->micronsToDbu(macro.getPinY()));
674-
to.addX(-outline_.xMin());
675674
} else if (closest_boundary == Boundary::R) {
676675
to.setX(block_->micronsToDbu(die.xMax()));
677676
to.setY(block_->micronsToDbu(macro.getPinY()));
678-
to.addX(-outline_.xMin());
679677
} else if (closest_boundary == Boundary::B) {
680678
to.setX(block_->micronsToDbu(macro.getPinX()));
681679
to.setY(block_->micronsToDbu(die.yMin()));
682-
to.addY(-outline_.yMin());
683680
} else { // Top
684681
to.setX(block_->micronsToDbu(macro.getPinX()));
685682
to.setY(block_->micronsToDbu(die.yMax()));
686-
to.addY(-outline_.yMin());
687683
}
688684

689685
return to;

src/mpl/src/hier_rtlmp.cpp

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,41 +1932,53 @@ void HierRTLMP::createFixedTerminals(
19321932
parents.push(parent);
19331933

19341934
while (!parents.empty()) {
1935-
auto frontwave = parents.front();
1935+
Cluster* frontwave = parents.front();
19361936
parents.pop();
19371937

19381938
Cluster* grandparent = frontwave->getParent();
19391939
for (auto& cluster : grandparent->getChildren()) {
19401940
if (cluster->getId() != frontwave->getId()) {
1941-
soft_macro_id_map[cluster->getName()]
1942-
= static_cast<int>(soft_macros.size());
1943-
1944-
const float center_x = cluster->getX() + cluster->getWidth() / 2.0;
1945-
const float center_y = cluster->getY() + cluster->getHeight() / 2.0;
1946-
Point location = {center_x - outline.xMin(), center_y - outline.yMin()};
1947-
1948-
// The information of whether or not a cluster is a group of
1949-
// unplaced IO pins is needed inside the SA Core, so if a fixed
1950-
// terminal corresponds to a cluster of unplaced IO pins it needs
1951-
// to contain that cluster data.
1952-
Cluster* fixed_terminal_cluster
1953-
= cluster->isClusterOfUnplacedIOPins() ? cluster.get() : nullptr;
1954-
1955-
// Note that a fixed terminal is just a point.
1956-
soft_macros.emplace_back(location,
1957-
cluster->getName(),
1958-
0.0f /* width */,
1959-
0.0f /* height */,
1960-
fixed_terminal_cluster);
1941+
const int id = static_cast<int>(soft_macros.size());
1942+
soft_macro_id_map[cluster->getName()] = id;
1943+
createFixedTerminal(cluster.get(), outline, soft_macros);
19611944
}
19621945
}
19631946

1964-
if (frontwave->getParent()->getParent() != nullptr) {
1947+
if (frontwave->getParent()->getParent()) {
19651948
parents.push(frontwave->getParent());
19661949
}
19671950
}
19681951
}
19691952

1953+
template <typename Macro>
1954+
void HierRTLMP::createFixedTerminal(Cluster* cluster,
1955+
const Rect& outline,
1956+
std::vector<Macro>& macros)
1957+
{
1958+
// A conventional fixed terminal is just a point without
1959+
// the cluster data.
1960+
Point location = cluster->getCenter();
1961+
float width = 0.0f;
1962+
float height = 0.0f;
1963+
Cluster* terminal_cluster = nullptr;
1964+
1965+
if (cluster->isClusterOfUnplacedIOPins()) {
1966+
// Clusters of unplaced IOs are not treated as conventional
1967+
// fixed terminals. As they correspond to regions, we need
1968+
// both their actual shape and their cluster data inside SA.
1969+
location = {cluster->getX(), cluster->getY()};
1970+
width = cluster->getWidth();
1971+
height = cluster->getHeight();
1972+
terminal_cluster = cluster;
1973+
}
1974+
1975+
location.first -= outline.xMin();
1976+
location.second -= outline.yMin();
1977+
1978+
macros.emplace_back(
1979+
location, cluster->getName(), width, height, terminal_cluster);
1980+
}
1981+
19701982
// Determine the shape of each cluster based on target utilization
19711983
// and target dead space. In constrast to all previous works, we
19721984
// use two parameters: target utilization, target_dead_space.
@@ -2416,6 +2428,7 @@ void HierRTLMP::computeFencesAndGuides(
24162428
}
24172429
}
24182430

2431+
// Create terminals for macro placement (Hard) annealing.
24192432
void HierRTLMP::createFixedTerminals(const Rect& outline,
24202433
const UniqueClusterVector& macro_clusters,
24212434
std::map<int, int>& cluster_to_macro,
@@ -2433,22 +2446,12 @@ void HierRTLMP::createFixedTerminals(const Rect& outline,
24332446
if (cluster_to_macro.find(cluster_id) != cluster_to_macro.end()) {
24342447
continue;
24352448
}
2436-
auto& temp_cluster = tree_->maps.id_to_cluster[cluster_id];
2437-
2438-
// model other cluster as a fixed macro with zero size
2439-
cluster_to_macro[cluster_id] = sa_macros.size();
2440-
sa_macros.emplace_back(
2441-
std::pair<float, float>(
2442-
temp_cluster->getX() + temp_cluster->getWidth() / 2.0
2443-
- outline.xMin(),
2444-
temp_cluster->getY() + temp_cluster->getHeight() / 2.0
2445-
- outline.yMin()),
2446-
temp_cluster->getName(),
2447-
// The information of whether or not a cluster is a group of
2448-
// unplaced IO pins is needed inside the SA Core, so if a fixed
2449-
// terminal corresponds to a cluster of unplaced IO pins it needs
2450-
// to contain that cluster data.
2451-
temp_cluster->isClusterOfUnplacedIOPins() ? temp_cluster : nullptr);
2449+
2450+
Cluster* temp_cluster = tree_->maps.id_to_cluster[cluster_id];
2451+
const int terminal_id = static_cast<int>(sa_macros.size());
2452+
2453+
cluster_to_macro[cluster_id] = terminal_id;
2454+
createFixedTerminal(temp_cluster, outline, sa_macros);
24522455
}
24532456
}
24542457

src/mpl/src/hier_rtlmp.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ class HierRTLMP
214214
odb::Rect micronsToDbu(const Rect& micron_rect);
215215
Rect dbuToMicrons(const odb::Rect& dbu_rect);
216216

217+
template <typename Macro>
218+
void createFixedTerminal(Cluster* cluster,
219+
const Rect& outline,
220+
std::vector<Macro>& macros);
221+
217222
// For debugging
218223
template <typename SACore>
219224
void printPlacementResult(Cluster* parent,

0 commit comments

Comments
 (0)