Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mpl: fix fixed terminals for cluster of unplaced IOs #6689

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
32 changes: 25 additions & 7 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,7 +1037,7 @@ SoftMacro::SoftMacro(float width, float height, const std::string& name)
cluster_ = nullptr;
}

// Create a SoftMacro representing the IO cluster or fixed terminals
// Create a SoftMacro representing a cluster of unplaced IOs or fixed terminals
SoftMacro::SoftMacro(const std::pair<float, float>& pos,
const std::string& name,
float width,
Expand All @@ -1037,7 +1049,13 @@ SoftMacro::SoftMacro(const std::pair<float, float>& pos,
y_ = pos.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