Skip to content
19 changes: 16 additions & 3 deletions src/cts/src/TreeBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,22 @@ void TreeBuilder::mergeBlockages()
for (odb::dbInst* inst : block->getInsts()) {
if (inst->getMaster()->getType().isBlock()
&& inst->getPlacementStatus().isPlaced()) {
macros_max_dx = std::max(macros_max_dx, inst->getBBox()->getDX());
macros_max_dy = std::max(macros_max_dy, inst->getBBox()->getDY());
blockage_polygons += inst->getBBox()->getBox();
odb::dbBox* halo = inst->getHalo();
odb::Rect transformed_halo = odb::Rect();

if (halo != nullptr && !halo->isSoft()) {
transformed_halo = inst->getTransformedHalo();
}

odb::Rect inst_box = inst->getBBox()->getBox();
odb::Rect box = odb::Rect(inst_box.xMin() - transformed_halo.xMin(),
inst_box.yMin() - transformed_halo.yMin(),
inst_box.xMax() + transformed_halo.xMax(),
inst_box.yMax() + transformed_halo.yMax());

macros_max_dx = std::max(macros_max_dx, static_cast<uint32_t>(box.dx()));
macros_max_dy = std::max(macros_max_dy, static_cast<uint32_t>(box.dy()));
blockage_polygons += box;
}
}

Expand Down
32 changes: 32 additions & 0 deletions src/gpl/src/placerBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1324,6 +1324,38 @@ void PlacerBase::initInstsForUnusableSites()
}
}

if (inst->isMacro() && inst->dbInst()->getHalo() != nullptr) {
Rect halo = inst->dbInst()->getTransformedHalo();
Rect box = inst->dbInst()->getBBox()->getBox();

std::pair<int, int> pairX = getMinMaxIdx(box.xMin() - halo.xMin(),
box.xMax() + halo.xMax(),
die_.coreLx(),
siteSizeX_,
0,
siteCountX);
std::pair<int, int> pairY = getMinMaxIdx(box.yMin() - halo.yMin(),
box.yMax() + halo.yMax(),
die_.coreLy(),
siteSizeY_,
0,
siteCountY);

for (int i = pairX.first; i < pairX.second; i++) {
for (int j = pairY.first; j < pairY.second; j++) {
siteGrid[(j * siteCountX) + i] = Blocked;
debugPrint(log_,
GPL,
"dummies",
1,
"Blocking site at ({}, {}) due to fixed macro {} halo.",
i,
j,
db_inst->getName());
}
}
}

std::pair<int, int> pairX = getMinMaxIdx(
inst->lx(), inst->ux(), die_.coreLx(), siteSizeX_, 0, siteCountX);
std::pair<int, int> pairY = getMinMaxIdx(
Expand Down
20 changes: 9 additions & 11 deletions src/gui/src/renderThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -871,17 +871,15 @@ void RenderThread::drawBlockages(QPainter* painter,
if (restart_) {
break;
}
odb::dbBox* halo = inst->getHalo();
if (halo != nullptr) {
Rect instbox = inst->getBBox()->getBox();
Rect halobox = halo->getBox();
instbox.set_xlo(instbox.xMin() - halobox.xMin());
instbox.set_ylo(instbox.yMin() - halobox.yMin());
instbox.set_xhi(instbox.xMax() + halobox.xMax());
instbox.set_yhi(instbox.yMax() + halobox.yMax());
painter->drawRect(
instbox.xMin(), instbox.yMin(), instbox.dx(), instbox.dy());
}
odb::Rect halobox = inst->getTransformedHalo();
Rect instbox = inst->getBBox()->getBox();
Comment on lines +874 to +875
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why removing the check?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before it would draw the hatched region only when the halo had a macro, even tough the macro itself is blocking the region. I think it is more consistent to always draw the blocked region.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed!


instbox.set_xlo(instbox.xMin() - halobox.xMin());
instbox.set_ylo(instbox.yMin() - halobox.yMin());
instbox.set_xhi(instbox.xMax() + halobox.xMax());
instbox.set_yhi(instbox.yMax() + halobox.yMax());
painter->drawRect(
instbox.xMin(), instbox.yMin(), instbox.dx(), instbox.dy());
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/mpl/src/clusterEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2080,12 +2080,14 @@ void ClusteringEngine::createHardMacros()
tree_->has_fixed_macros = true;
}

HardMacro::Halo halo = tree_->default_halo;
HardMacro::Halo halo;

if (macro_to_halo_.contains(inst)) {
halo = macro_to_halo_.at(inst);
} else if (use_def_halo_ && inst->getHalo() != nullptr) {
halo = HardMacro::Halo(inst->getHalo());
} else {
halo = tree_->default_halo;
}

auto macro = std::make_unique<HardMacro>(inst, halo);
Expand Down
4 changes: 2 additions & 2 deletions src/mpl/src/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ int HardMacro::getRealX() const
{
switch (getOrientation().getValue()) {
case odb::dbOrientType::Value::R180:
case odb::dbOrientType::Value::MX:
case odb::dbOrientType::Value::MY:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would have been good to include this bug fix in the description as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did it so early in development that ended up forgetting about it. Can't change the description unfortunately.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what would you like it to be?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something along the lines of "Also includes a small bugfix in getRealLocation and related methods for HardMacro".

return x_ + halo_.right;
default:
return x_ + halo_.left;
Expand All @@ -818,7 +818,7 @@ int HardMacro::getRealY() const
{
switch (getOrientation().getValue()) {
case odb::dbOrientType::Value::R180:
case odb::dbOrientType::Value::MY:
case odb::dbOrientType::Value::MX:
return y_ + halo_.top;
default:
return y_ + halo_.bottom;
Expand Down
8 changes: 4 additions & 4 deletions src/odb/include/odb/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,10 @@ class dbBox : public dbObject
uint32_t getDY() const;

///
/// Set temporary flag visited
/// Set the halo as soft
///
void setVisited(bool value);
bool isVisited() const;
void setSoft(bool value);
bool isSoft() const;

///
/// Get the owner of this box
Expand Down Expand Up @@ -3119,7 +3119,7 @@ class dbInst : public dbObject
///
/// Sets the halo to this instance.
///
void setHalo(int left, int bottom, int right, int top);
void setHalo(int left, int bottom, int right, int top, bool is_soft);

///
/// Get the weight assigned to this instance.
Expand Down
14 changes: 7 additions & 7 deletions src/odb/src/db/dbBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1047,15 +1047,15 @@ dbBox* dbBox::getBox(dbMaster* master_, uint32_t dbid_)
return (dbBox*) master->box_tbl_->getPtr(dbid_);
}

bool dbBox::isVisited() const
bool dbBox::isSoft() const
{
const _dbBox* box = (const _dbBox*) this;
return box->flags_.visited == 1;
return box->flags_.soft == 1;
}
void dbBox::setVisited(const bool value)
void dbBox::setSoft(const bool value)
{
_dbBox* box = (_dbBox*) this;
box->flags_.visited = (value) ? 1 : 0;
box->flags_.soft = (value) ? 1 : 0;
}

void _dbBox::collectMemInfo(MemInfo& info) const
Expand All @@ -1072,7 +1072,7 @@ _dbBox::_dbBox(_dbDatabase*)
flags_.layer_id = 0;
flags_.layer_mask = 0;
flags_.via_id = 0;
flags_.visited = 0;
flags_.soft = 0;
flags_.octilinear = false;
owner_ = 0;
design_rule_width_ = -1;
Expand Down Expand Up @@ -1118,7 +1118,7 @@ dbIStream& operator>>(dbIStream& stream, _dbBox& box)
uint32_t* bit_field = (uint32_t*) &old;
stream >> *bit_field;
box.flags_.owner_type = old.owner_type;
box.flags_.visited = old.visited;
box.flags_.soft = 0;
box.flags_.octilinear = old.octilinear;
box.flags_.is_tech_via = old.is_tech_via;
box.flags_.is_block_via = old.is_block_via;
Expand All @@ -1130,7 +1130,7 @@ dbIStream& operator>>(dbIStream& stream, _dbBox& box)
uint32_t* bit_field = (uint32_t*) &old;
stream >> *bit_field;
box.flags_.owner_type = old.owner_type;
box.flags_.visited = old.visited;
box.flags_.soft = 0;
box.flags_.octilinear = old.octilinear;
box.flags_.is_tech_via = old.is_tech_via;
box.flags_.is_block_via = old.is_block_via;
Expand Down
2 changes: 1 addition & 1 deletion src/odb/src/db/dbBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct _dbBoxFlagsWithoutMask
struct _dbBoxFlags
{
dbBoxOwner::Value owner_type : 4;
uint32_t visited : 1;
uint32_t soft : 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this a safe change for the DB? or should this require a version bump?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The visited flag is unused, so I think it is safe.

uint32_t octilinear : 1;
uint32_t is_tech_via : 1;
uint32_t is_block_via : 1;
Expand Down
5 changes: 3 additions & 2 deletions src/odb/src/db/dbInst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,15 +906,16 @@ Rect dbInst::getTransformedHalo()
return halo;
}

void dbInst::setHalo(int left, int bottom, int right, int top)
void dbInst::setHalo(int left, int bottom, int right, int top, bool is_soft)
{
dbBox* halo = getHalo();

if (halo != nullptr) {
dbBox::destroy(halo);
}

dbBox::create(this, left, bottom, right, top);
halo = dbBox::create(this, left, bottom, right, top);
halo->setSoft(is_soft);
}

void dbInst::getConnectivity(std::vector<dbInst*>& result,
Expand Down
9 changes: 7 additions & 2 deletions src/odb/src/defin/definComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,19 @@ void definComponent::placement(int status, int x, int y, int orient)
_cur_inst->setPlacementStatus(placement_status);
}

void definComponent::halo(int left, int bottom, int right, int top)
void definComponent::halo(int left,
int bottom,
int right,
int top,
bool is_soft)
{
if (_cur_inst == nullptr) {
return;
}

dbBox::create(
dbBox* halo = dbBox::create(
_cur_inst, dbdist(left), dbdist(bottom), dbdist(right), dbdist(top));
halo->setSoft(is_soft);
}

void definComponent::region(const char* name)
Expand Down
2 changes: 1 addition & 1 deletion src/odb/src/defin/definComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class definComponent : public definBase
virtual void begin(const char* name, const char* cell);
virtual void placement(int status, int x, int y, int orient);
virtual void region(const char* region);
virtual void halo(int left, int bottom, int right, int top);
virtual void halo(int left, int bottom, int right, int top, bool is_soft);
virtual void source(dbSourceType source);
virtual void weight(int weight);
virtual void property(const char* name, const char* value);
Expand Down
2 changes: 1 addition & 1 deletion src/odb/src/defin/definReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ int definReader::componentsCallback(
if (comp->hasHalo() > 0) {
int left, bottom, right, top;
comp->haloEdges(&left, &bottom, &right, &top);
componentR->halo(left, bottom, right, top);
componentR->halo(left, bottom, right, top, comp->hasHaloSoft() > 0);
}

componentR->placement(comp->placementStatus(),
Expand Down
4 changes: 2 additions & 2 deletions src/odb/src/defout/defout_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,8 +696,8 @@ void DefOut::Impl::writeInst(dbInst* inst)
int right = defdist(box->xMax());
int top = defdist(box->yMax());

*_out << " + HALO " << left << " " << bottom << " " << right << " "
<< top;
*_out << " + HALO " << (box->isSoft() ? "SOFT " : "") << left << " "
<< bottom << " " << right << " " << top;
}
}

Expand Down
27 changes: 20 additions & 7 deletions src/odb/src/zutil/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,11 @@ static void cutRow(dbBlock* block,
odb::dbInst* inst
= static_cast<odb::dbInst*>(row_blockage_bbox->getBoxOwner());
odb::dbBox* halo = inst->getHalo();
if (halo != nullptr) {
row_blockage_xs.emplace_back(row_blockage_bbox->xMin() - halo->xMin(),
row_blockage_bbox->xMax() + halo->xMax());
if (halo != nullptr && !halo->isSoft()) {
Rect halo_rect = inst->getTransformedHalo();
row_blockage_xs.emplace_back(
row_blockage_bbox->xMin() - halo_rect.xMin(),
row_blockage_bbox->xMax() + halo_rect.xMax());
} else {
row_blockage_xs.emplace_back(row_blockage_bbox->xMin() - halo_x,
row_blockage_bbox->xMax() + halo_x);
Expand Down Expand Up @@ -131,15 +133,22 @@ static bool overlaps(dbBox* blockage, dbRow* row, int halo_x, int halo_y)
const Rect rowBB = row->getBBox();

odb::dbBox* halo = nullptr;
odb::Rect transformed_halo;
if (blockage->getOwnerType() == odb::dbBoxOwner::INST) {
halo = static_cast<odb::dbInst*>(blockage->getBoxOwner())->getHalo();
transformed_halo = static_cast<odb::dbInst*>(blockage->getBoxOwner())
->getTransformedHalo();
}
Comment on lines 137 to 141
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This block of code has a couple of minor inefficiencies:

  1. static_cast<odb::dbInst*>(blockage->getBoxOwner()) is performed twice.
  2. getTransformedHalo() is called even if the halo is null or soft. This call is unnecessary in those cases.

Consider refactoring to store the instance pointer and only call getTransformedHalo() when it's confirmed to be a hard halo. Note that for dbBoxOwner::INST, getBoxOwner() is guaranteed to return a valid instance.

Suggested change
if (blockage->getOwnerType() == odb::dbBoxOwner::INST) {
halo = static_cast<odb::dbInst*>(blockage->getBoxOwner())->getHalo();
transformed_halo = static_cast<odb::dbInst*>(blockage->getBoxOwner())
->getTransformedHalo();
}
if (blockage->getOwnerType() == odb::dbBoxOwner::INST) {
auto* inst = static_cast<odb::dbInst*>(blockage->getBoxOwner());
halo = inst->getHalo();
if (halo != nullptr && !halo->isSoft()) {
transformed_halo = inst->getTransformedHalo();
}
}
References
  1. A dbBox with owner type dbBoxOwner::INST will always have a valid owner instance; getBoxOwner() will not return null.

// Check if Y has overlap first since rows are long and skinny
const int blockage_lly
= blockage->yMin() - (halo != nullptr ? halo->yMin() : halo_y);
= blockage->yMin()
- (halo != nullptr && !halo->isSoft() ? transformed_halo.yMin()
: halo_y);
const int blockage_ury
= blockage->yMax() + (halo != nullptr ? halo->yMax() : halo_y);
= blockage->yMax()
+ (halo != nullptr && !halo->isSoft() ? transformed_halo.yMax()
: halo_y);
const int row_lly = rowBB.yMin();
const int row_ury = rowBB.yMax();

Expand All @@ -148,9 +157,13 @@ static bool overlaps(dbBox* blockage, dbRow* row, int halo_x, int halo_y)
}

const int blockage_llx
= blockage->xMin() - (halo != nullptr ? halo->xMin() : halo_x);
= blockage->xMin()
- (halo != nullptr && !halo->isSoft() ? transformed_halo.xMin()
: halo_x);
const int blockage_urx
= blockage->xMax() + (halo != nullptr ? halo->xMax() : halo_x);
= blockage->xMax()
+ (halo != nullptr && !halo->isSoft() ? transformed_halo.xMax()
: halo_x);
const int row_llx = rowBB.xMin();
const int row_urx = rowBB.xMax();

Expand Down
2 changes: 1 addition & 1 deletion src/pdn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ define_pdn_grid
| `[-default]` | For a macro, specifies this is a default grid that can be overwritten. |
| `[-existing]` | Flag to enable defining for existing routing solution. |
| `[-grid_over_pg_pins]`, `[-grid_over_boundary]` | Place the power grid over the power ground pins of the macro. (Default True), or Place the power grid over the entire macro. |
| `[-halo]` | Specifies the default minimum separation of selected macros from other cells in the design. This is only used if the macro does not define halo values in the LEF description. If 1 value is specified it will be used on all 4 sides, if two values are specified, the first will be applied to left/right sides and the second will be applied to top/bottom sides, if 4 values are specified, then they are applied to left, bottom, right and top sides respectively (Default: 0). |
| `[-halo]` | Specifies the default minimum separation of selected macros from other cells in the design. This is only used if the macro does not define hard halo values in the LEF description. If 1 value is specified it will be used on all 4 sides, if two values are specified, the first will be applied to left/right sides and the second will be applied to top/bottom sides, if 4 values are specified, then they are applied to left, bottom, right and top sides respectively (Default: 0). |
| `[-instances]` | For a macro, defines a set of valid instances. Macros with a matching instance name will use this grid specification. |
| `[-macro]` | Defines the type of grid being added as a macro. |
| `[-name]` | Defines a name to use when referring to this grid definition. |
Expand Down
12 changes: 4 additions & 8 deletions src/pdn/src/grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1407,16 +1407,12 @@ InstanceGrid::InstanceGrid(
: Grid(domain, name, start_with_power, generate_obstructions), inst_(inst)
{
auto* halo = inst->getHalo();
if (halo != nullptr) {
odb::Rect halo_box = halo->getBox();

odb::Rect inst_box = inst->getBBox()->getBox();
if (halo != nullptr && !halo->isSoft()) {
odb::Rect halo_box = inst->getTransformedHalo();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

somethings off about this.
What is actually stored in the halo_? It was the deltaX, and deltaY of the instance (ie. the halo), but looking at the getTransformedHalo that seems to be doing something completely different

Copy link
Contributor

@joaomai joaomai Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

halo_ stores the values of left, bottom, right and top spacing as positive values in xMin, yMin, xMax and yMax respectively. getTransformedHalo returns the halo re-oriented considering the instance orientation.


// copy halo from db
addHalo({halo_box.xMin() - inst_box.xMin(),
halo_box.yMin() - inst_box.yMin(),
inst_box.xMin() - halo_box.xMax(),
inst_box.yMin() - halo_box.yMax()});
addHalo(
{halo_box.xMin(), halo_box.yMin(), halo_box.xMax(), halo_box.yMax()});
}
}

Expand Down
Loading