Skip to content
23 changes: 15 additions & 8 deletions src/mpl/src/SimulatedAnnealingCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,16 @@ void SimulatedAnnealingCore<T>::addBoundaryDistToWirelength(
const T& io,
const float net_weight)
{
Cluster* io_cluster = io.getCluster();
const Rect die = io_cluster->getBBox();
const float die_hpwl = die.getWidth() + die.getHeight();
// Important!
// We need to use the bbox of the SoftMacro and NOT the Cluster to
// get shape of the cluster of unconstrained IOs - which has the
// shape of the die but it's offset based on the current outline.
// Reminder:
// - The SoftMacro bbox is the bbox w.r.t to the current outline.
// - The Cluster bbox is the bbox w.r.t. to the origin of the actual
// die area.
const Rect offset_die = io.getBBox();
const float die_hpwl = offset_die.getWidth() + offset_die.getHeight();

if (isOutsideTheOutline(macro)) {
wirelength_ += net_weight * die_hpwl;
Expand All @@ -342,27 +349,27 @@ void SimulatedAnnealingCore<T>::addBoundaryDistToWirelength(
const float x1 = macro.getPinX();
const float y1 = macro.getPinY();

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

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

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

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

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

wirelength_
Expand Down
2 changes: 0 additions & 2 deletions src/mpl/src/bus_synthesis.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@

namespace mpl {

using Point = std::pair<float, float>;

// Each point in the hanan grid is represented by a vertex (with no size)
// And each bundled IO pin is represented by a vertex
struct Vertex
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 @@ -634,14 +634,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 @@ -656,12 +654,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 @@ -692,19 +692,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 @@ -3075,41 +3075,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 @@ -3583,6 +3595,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 @@ -3600,22 +3613,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 @@ -259,6 +259,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);

sta::dbNetwork* network_ = nullptr;
odb::dbDatabase* db_ = nullptr;
odb::dbBlock* block_ = nullptr;
Expand Down
38 changes: 28 additions & 10 deletions src/mpl/src/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,11 @@ Rect Cluster::getBBox() const
return soft_macro_->getBBox();
}

Point Cluster::getCenter() const
{
return {getX() + getWidth() / 2.0, getY() + getHeight() / 2.0};
}

// Hierarchy Support
void Cluster::setParent(Cluster* parent)
{
Expand Down Expand Up @@ -802,17 +807,19 @@ void Cluster::addVirtualConnection(int src, int target)

///////////////////////////////////////////////////////////////////////
// HardMacro
HardMacro::HardMacro(std::pair<float, float> loc,
HardMacro::HardMacro(std::pair<float, float> location,
const std::string& name,
float width,
float height,
Cluster* cluster)
{
width_ = 0.0;
height_ = 0.0;
width_ = width;
height_ = height;
name_ = name;
pin_x_ = 0.0;
pin_y_ = 0.0;
x_ = loc.first;
y_ = loc.second;
x_ = location.first;
y_ = location.second;
cluster_ = cluster;
}

Expand Down Expand Up @@ -887,6 +894,11 @@ bool HardMacro::isClusterOfUnplacedIOPins() const
return cluster_->isClusterOfUnplacedIOPins();
}

Rect HardMacro::getBBox() const
{
return Rect(x_, y_, x_ + width_, y_ + height_);
}

// Get Physical Information
// Note that the default X and Y include halo_width
void HardMacro::setLocation(const std::pair<float, float>& location)
Expand Down Expand Up @@ -1025,19 +1037,25 @@ SoftMacro::SoftMacro(float width, float height, const std::string& name)
cluster_ = nullptr;
}

// Create a SoftMacro representing the IO cluster or fixed terminals
SoftMacro::SoftMacro(const std::pair<float, float>& pos,
// Create a SoftMacro representing a cluster of unplaced IOs or fixed terminals
SoftMacro::SoftMacro(const std::pair<float, float>& location,
const std::string& name,
float width,
float height,
Cluster* cluster)
{
name_ = name;
x_ = pos.first;
y_ = pos.second;
x_ = location.first;
y_ = location.second;
width_ = width;
height_ = height;
area_ = 0.0; // width_ * height_ = 0.0 for this case

// Even though clusters of unplaced IOs have shapes, i.e., are not
// just points, their area should be zero, because we use the area
// to check whether or not a SoftMacro if a fixed terminal or cluster
// of unplaced IOs inside SA. Ideally we should check the fixed flag.
area_ = 0.0f;

cluster_ = cluster;
fixed_ = true;
}
Expand Down
18 changes: 11 additions & 7 deletions src/mpl/src/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class SoftMacro;
class Cluster;

using UniqueClusterVector = std::vector<std::unique_ptr<Cluster>>;
using Point = std::pair<float, float>;

// ****************************************************************************
// This file includes the basic functions and basic classes for the HierRTLMP
Expand Down Expand Up @@ -239,6 +240,7 @@ class Cluster
void setY(float y);
const std::pair<float, float> getLocation() const;
Rect getBBox() const;
Point getCenter() const;

// Hierarchy Support
void setParent(Cluster* parent);
Expand Down Expand Up @@ -356,9 +358,11 @@ class HardMacro
public:
// Create a macro with specified size
// Model fixed terminals
HardMacro(std::pair<float, float> loc,
HardMacro(std::pair<float, float> location,
const std::string& name,
Cluster* cluster = nullptr);
float width,
float height,
Cluster* cluster);

// In this case, we model the pin position at the center of the macro
HardMacro(float width, float height, const std::string& name);
Expand All @@ -374,6 +378,7 @@ class HardMacro
void setCluster(Cluster* cluster) { cluster_ = cluster; }
Cluster* getCluster() const { return cluster_; }
bool isClusterOfUnplacedIOPins() const;
Rect getBBox() const;

// Get Physical Information
// Note that the default X and Y include halo_width
Expand Down Expand Up @@ -497,12 +502,11 @@ class SoftMacro
// Create a SoftMacro representing the blockage
SoftMacro(float width, float height, const std::string& name);

// Create a SoftMacro representing the IO cluster
SoftMacro(const std::pair<float, float>& pos,
SoftMacro(const std::pair<float, float>& location,
const std::string& name,
float width = 0.0,
float height = 0.0,
Cluster* cluster = nullptr);
float width,
float height,
Cluster* cluster);

// create a SoftMacro from a cluster
SoftMacro(Cluster* cluster);
Expand Down