Skip to content
41 changes: 25 additions & 16 deletions src/mpl/src/SimulatedAnnealingCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,18 @@ SimulatedAnnealingCore<T>::SimulatedAnnealingCore(PhysicalHierarchy* tree,
logger_ = logger;
macros_ = macros;

setDieArea(tree->die_area);
setBlockedBoundariesForIOs();
}

template <class T>
void SimulatedAnnealingCore<T>::setDieArea(const Rect& die_area)
{
die_area_ = die_area;
die_area_.moveHor(-outline_.xMin());
die_area_.moveVer(-outline_.yMin());
}

template <class T>
void SimulatedAnnealingCore<T>::setBlockedBoundariesForIOs()
{
Expand Down Expand Up @@ -327,42 +336,42 @@ void SimulatedAnnealingCore<T>::calWirelength()
template <class T>
void SimulatedAnnealingCore<T>::addBoundaryDistToWirelength(
const T& macro,
const T& io,
const T& unplaced_ios,
const float net_weight)
{
Cluster* io_cluster = io.getCluster();
const Rect die = io_cluster->getBBox();
const float die_hpwl = die.getWidth() + die.getHeight();
// To generate maximum cost.
const float max_dist = die_area_.getPerimeter() / 2;

if (isOutsideTheOutline(macro)) {
wirelength_ += net_weight * die_hpwl;
wirelength_ += net_weight * max_dist;
return;
}

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

Boundary constraint_boundary = io_cluster->getConstraintBoundary();
Boundary constraint_boundary
= unplaced_ios.getCluster()->getConstraintBoundary();

if (constraint_boundary == NONE) {
float dist_to_left = die_hpwl;
float dist_to_left = max_dist;
if (!left_is_blocked_) {
dist_to_left = std::abs(x1 - die.xMin());
dist_to_left = std::abs(x1 - die_area_.xMin());
}

float dist_to_right = die_hpwl;
float dist_to_right = max_dist;
if (!right_is_blocked_) {
dist_to_right = std::abs(x1 - die.xMax());
dist_to_right = std::abs(x1 - die_area_.xMax());
}

float dist_to_bottom = die_hpwl;
float dist_to_bottom = max_dist;
if (!bottom_is_blocked_) {
dist_to_right = std::abs(y1 - die.yMin());
dist_to_right = std::abs(y1 - die_area_.yMin());
}

float dist_to_top = die_hpwl;
float dist_to_top = max_dist;
if (!top_is_blocked_) {
dist_to_top = std::abs(y1 - die.yMax());
dist_to_top = std::abs(y1 - die_area_.yMax());
}

wirelength_
Expand All @@ -371,11 +380,11 @@ void SimulatedAnnealingCore<T>::addBoundaryDistToWirelength(
{dist_to_left, dist_to_right, dist_to_bottom, dist_to_top});
} else if (constraint_boundary == Boundary::L
|| constraint_boundary == Boundary::R) {
const float x2 = io.getPinX();
const float x2 = unplaced_ios.getPinX();
wirelength_ += net_weight * std::abs(x2 - x1);
} else if (constraint_boundary == Boundary::T
|| constraint_boundary == Boundary::B) {
const float y2 = io.getPinY();
const float y2 = unplaced_ios.getPinY();
wirelength_ += net_weight * std::abs(y2 - y1);
}
}
Expand Down
8 changes: 3 additions & 5 deletions src/mpl/src/SimulatedAnnealingCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class SimulatedAnnealingCore
void fastSA();

void initSequencePair();
void setDieArea(const Rect& die_area);
void setBlockedBoundariesForIOs();
void updateBestValidResult();
void useBestValidResult();
Expand All @@ -136,7 +137,7 @@ class SimulatedAnnealingCore
void calOutlinePenalty();
void calWirelength();
void addBoundaryDistToWirelength(const T& macro,
const T& io,
const T& unplaced_ios,
float net_weight);
bool isOutsideTheOutline(const T& macro) const;
void calGuidancePenalty();
Expand All @@ -163,11 +164,8 @@ class SimulatedAnnealingCore
void reportLocations() const;
void report(const PenaltyData& penalty) const;

/////////////////////////////////////////////
// private member variables
/////////////////////////////////////////////
// boundary constraints
Rect outline_;
Rect die_area_; // Offset to the current outline.

// Boundaries blocked for IO pins
std::set<Boundary> blocked_boundaries_;
Expand Down
14 changes: 14 additions & 0 deletions src/mpl/src/clusterEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ void ClusteringEngine::init()
return;
}

setDieArea();
setFloorplanShape();
searchForFixedInstsInsideFloorplanShape();

Expand All @@ -130,6 +131,19 @@ void ClusteringEngine::init()
reportDesignData();
}

// Note: The die area's dimensions will be used inside
// SA Core when computing the wirelength in a situation in which
// the target cluster is a cluster of unplaced IOs.
void ClusteringEngine::setDieArea()
{
const odb::Rect& die = block_->getDieArea();

tree_->die_area = Rect(block_->dbuToMicrons(die.xMin()),
block_->dbuToMicrons(die.yMin()),
block_->dbuToMicrons(die.xMax()),
block_->dbuToMicrons(die.yMax()));
}

float ClusteringEngine::computeMacroWithHaloArea(
const std::vector<odb::dbInst*>& unfixed_macros)
{
Expand Down
2 changes: 2 additions & 0 deletions src/mpl/src/clusterEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ struct PhysicalHierarchy
float macro_with_halo_area{0.0f};
Rect global_fence;
Rect floorplan_shape;
Rect die_area;

bool has_io_clusters{true};
bool has_only_macros{false};
Expand Down Expand Up @@ -182,6 +183,7 @@ class ClusteringEngine
void init();
Metrics* computeModuleMetrics(odb::dbModule* module);
std::vector<odb::dbInst*> getUnfixedMacros();
void setDieArea();
void setFloorplanShape();
void searchForFixedInstsInsideFloorplanShape();
float computeMacroWithHaloArea(
Expand Down
18 changes: 7 additions & 11 deletions src/mpl/src/graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -638,14 +638,12 @@ void Graphics::drawDistToIoConstraintBoundary(gui::Painter& painter,
return;
}

Cluster* io_cluster = io.getCluster();

const int x1 = block_->micronsToDbu(macro.getPinX());
const int y1 = block_->micronsToDbu(macro.getPinY());
odb::Point from(x1, y1);

odb::Point to;
Boundary constraint_boundary = io_cluster->getConstraintBoundary();
Boundary constraint_boundary = io.getCluster()->getConstraintBoundary();

if (constraint_boundary == Boundary::L
|| constraint_boundary == Boundary::R) {
Expand All @@ -660,12 +658,14 @@ void Graphics::drawDistToIoConstraintBoundary(gui::Painter& painter,
to.setX(x2);
to.setY(y2);
} else {
// For NONE, the shape of the io cluster is the die area.
const Rect die = io_cluster->getBBox();
// We need to use the bbox of the SoftMacro to get the necessary
// offset compensation (the cluster bbox is the bbox w.r.t. to the
// actual die area).
const Rect offset_die = io.getBBox();
Boundary closest_unblocked_boundary
= getClosestUnblockedBoundary(macro, die);
= getClosestUnblockedBoundary(macro, offset_die);

to = getClosestBoundaryPoint(macro, die, closest_unblocked_boundary);
to = getClosestBoundaryPoint(macro, offset_die, closest_unblocked_boundary);
}

addOutlineOffsetToLine(from, to);
Expand Down Expand Up @@ -696,19 +696,15 @@ odb::Point Graphics::getClosestBoundaryPoint(const T& macro,
if (closest_boundary == Boundary::L) {
to.setX(block_->micronsToDbu(die.xMin()));
to.setY(block_->micronsToDbu(macro.getPinY()));
to.addX(-outline_.xMin());
} else if (closest_boundary == Boundary::R) {
to.setX(block_->micronsToDbu(die.xMax()));
to.setY(block_->micronsToDbu(macro.getPinY()));
to.addX(-outline_.xMin());
} else if (closest_boundary == Boundary::B) {
to.setX(block_->micronsToDbu(macro.getPinX()));
to.setY(block_->micronsToDbu(die.yMin()));
to.addY(-outline_.yMin());
} else { // Top
to.setX(block_->micronsToDbu(macro.getPinX()));
to.setY(block_->micronsToDbu(die.yMax()));
to.addY(-outline_.yMin());
}

return to;
Expand Down
79 changes: 41 additions & 38 deletions src/mpl/src/hier_rtlmp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1949,41 +1949,53 @@ void HierRTLMP::createFixedTerminals(
parents.push(parent);

while (!parents.empty()) {
auto frontwave = parents.front();
Cluster* frontwave = parents.front();
parents.pop();

Cluster* grandparent = frontwave->getParent();
for (auto& cluster : grandparent->getChildren()) {
if (cluster->getId() != frontwave->getId()) {
soft_macro_id_map[cluster->getName()]
= static_cast<int>(soft_macros.size());

const float center_x = cluster->getX() + cluster->getWidth() / 2.0;
const float center_y = cluster->getY() + cluster->getHeight() / 2.0;
Point location = {center_x - outline.xMin(), center_y - outline.yMin()};

// The information of whether or not a cluster is a group of
// unplaced IO pins is needed inside the SA Core, so if a fixed
// terminal corresponds to a cluster of unplaced IO pins it needs
// to contain that cluster data.
Cluster* fixed_terminal_cluster
= cluster->isClusterOfUnplacedIOPins() ? cluster.get() : nullptr;

// Note that a fixed terminal is just a point.
soft_macros.emplace_back(location,
cluster->getName(),
0.0f /* width */,
0.0f /* height */,
fixed_terminal_cluster);
const int id = static_cast<int>(soft_macros.size());
soft_macro_id_map[cluster->getName()] = id;
createFixedTerminal(cluster.get(), outline, soft_macros);
}
}

if (frontwave->getParent()->getParent() != nullptr) {
if (frontwave->getParent()->getParent()) {
parents.push(frontwave->getParent());
}
}
}

template <typename Macro>
void HierRTLMP::createFixedTerminal(Cluster* cluster,
const Rect& outline,
std::vector<Macro>& macros)
{
// A conventional fixed terminal is just a point without
// the cluster data.
Point location = cluster->getCenter();
float width = 0.0f;
float height = 0.0f;
Cluster* terminal_cluster = nullptr;

if (cluster->isClusterOfUnplacedIOPins()) {
// Clusters of unplaced IOs are not treated as conventional
// fixed terminals. As they correspond to regions, we need
// both their actual shape and their cluster data inside SA.
location = {cluster->getX(), cluster->getY()};
width = cluster->getWidth();
height = cluster->getHeight();
terminal_cluster = cluster;
}

location.first -= outline.xMin();
location.second -= outline.yMin();

macros.emplace_back(
location, cluster->getName(), width, height, terminal_cluster);
}

// Determine the shape of each cluster based on target utilization
// and target dead space. In constrast to all previous works, we
// use two parameters: target utilization, target_dead_space.
Expand Down Expand Up @@ -2429,6 +2441,7 @@ void HierRTLMP::computeFencesAndGuides(
}
}

// Create terminals for macro placement (Hard) annealing.
void HierRTLMP::createFixedTerminals(const Rect& outline,
const UniqueClusterVector& macro_clusters,
std::map<int, int>& cluster_to_macro,
Expand All @@ -2446,22 +2459,12 @@ void HierRTLMP::createFixedTerminals(const Rect& outline,
if (cluster_to_macro.find(cluster_id) != cluster_to_macro.end()) {
continue;
}
auto& temp_cluster = tree_->maps.id_to_cluster[cluster_id];

// model other cluster as a fixed macro with zero size
cluster_to_macro[cluster_id] = sa_macros.size();
sa_macros.emplace_back(
std::pair<float, float>(
temp_cluster->getX() + temp_cluster->getWidth() / 2.0
- outline.xMin(),
temp_cluster->getY() + temp_cluster->getHeight() / 2.0
- outline.yMin()),
temp_cluster->getName(),
// The information of whether or not a cluster is a group of
// unplaced IO pins is needed inside the SA Core, so if a fixed
// terminal corresponds to a cluster of unplaced IO pins it needs
// to contain that cluster data.
temp_cluster->isClusterOfUnplacedIOPins() ? temp_cluster : nullptr);

Cluster* temp_cluster = tree_->maps.id_to_cluster[cluster_id];
const int terminal_id = static_cast<int>(sa_macros.size());

cluster_to_macro[cluster_id] = terminal_id;
createFixedTerminal(temp_cluster, outline, sa_macros);
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/mpl/src/hier_rtlmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,11 @@ class HierRTLMP
odb::Rect micronsToDbu(const Rect& micron_rect);
Rect dbuToMicrons(const odb::Rect& dbu_rect);

template <typename Macro>
void createFixedTerminal(Cluster* cluster,
const Rect& outline,
std::vector<Macro>& macros);

// For debugging
template <typename SACore>
void printPlacementResult(Cluster* parent,
Expand Down
Loading