Skip to content

Commit 75ee729

Browse files
committed
pad: allow placeInstance to shift the pad cell to make it fit
Signed-off-by: Peter Gadfort <[email protected]>
1 parent a47d549 commit 75ee729

File tree

2 files changed

+71
-14
lines changed

2 files changed

+71
-14
lines changed

src/pad/include/pad/ICeWall.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ class ICeWall
110110
int index,
111111
odb::dbInst* inst,
112112
const odb::dbOrientType& base_orient,
113-
bool allow_overlap = false) const;
113+
bool allow_overlap = false,
114+
bool allow_shift = false) const;
114115

115116
void makeBTerm(odb::dbNet* net,
116117
odb::dbTechLayer* layer,
@@ -160,7 +161,9 @@ class ICeWall
160161
odb::dbInst* inst,
161162
const std::map<odb::dbInst*, std::set<odb::dbITerm*>>&
162163
iterm_connections) const;
163-
odb::dbInst* checkInstancePlacement(odb::dbInst* inst, odb::dbRow* row) const;
164+
std::optional<std::pair<odb::dbInst*, odb::Rect>> checkInstancePlacement(
165+
odb::dbInst* inst,
166+
odb::dbRow* row) const;
164167

165168
// Data members
166169
odb::dbDatabase* db_ = nullptr;

src/pad/src/ICeWall.cpp

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ void ICeWall::placeCorner(odb::dbMaster* master, int ring_index)
554554
inst->setLocation(row_bbox.xMin(), row_bbox.yMin());
555555
inst->setPlacementStatus(odb::dbPlacementStatus::FIRM);
556556

557-
if (checkInstancePlacement(inst, row) != nullptr) {
557+
if (checkInstancePlacement(inst, row)) {
558558
if (create_inst) {
559559
logger_->warn(utl::PAD,
560560
45,
@@ -981,7 +981,9 @@ void ICeWall::placePadsBumpAligned(
981981
offset += placeInstance(row,
982982
snapToRowSite(row, select_pos),
983983
ginst,
984-
odb::dbOrientType::R0)
984+
odb::dbOrientType::R0,
985+
false,
986+
true)
985987
* row->getSpacing();
986988

987989
performPadFlip(row, ginst, iterm_connections);
@@ -1011,7 +1013,12 @@ void ICeWall::placePadsUniform(const std::vector<odb::dbInst*>& insts,
10111013
inst->getName(),
10121014
offset / dbus);
10131015

1014-
placeInstance(row, snapToRowSite(row, offset), inst, odb::dbOrientType::R0);
1016+
placeInstance(row,
1017+
snapToRowSite(row, offset),
1018+
inst,
1019+
odb::dbOrientType::R0,
1020+
false,
1021+
true);
10151022
offset += inst_widths.at(inst);
10161023
offset += target_spacing;
10171024
}
@@ -1071,7 +1078,8 @@ int ICeWall::placeInstance(odb::dbRow* row,
10711078
int index,
10721079
odb::dbInst* inst,
10731080
const odb::dbOrientType& base_orient,
1074-
bool allow_overlap) const
1081+
bool allow_overlap,
1082+
bool allow_shift) const
10751083
{
10761084
const int origin_offset = index * row->getSpacing();
10771085

@@ -1149,8 +1157,42 @@ int ICeWall::placeInstance(odb::dbRow* row,
11491157
row_bbox.yMax() / dbus);
11501158
}
11511159

1152-
odb::dbInst* check_inst = checkInstancePlacement(inst, row);
1153-
if (!allow_overlap && check_inst != nullptr) {
1160+
const auto check_obs = checkInstancePlacement(inst, row);
1161+
if (allow_shift && check_obs) {
1162+
const auto& [check_inst, check_rect] = *check_obs;
1163+
1164+
int obs_index = index;
1165+
switch (row_edge) {
1166+
case odb::Direction2D::North:
1167+
obs_index = snapToRowSite(row, check_rect.xMin());
1168+
break;
1169+
case odb::Direction2D::South:
1170+
obs_index = snapToRowSite(row, check_rect.xMin());
1171+
break;
1172+
case odb::Direction2D::West:
1173+
obs_index = snapToRowSite(row, check_rect.yMin());
1174+
break;
1175+
case odb::Direction2D::East:
1176+
obs_index = snapToRowSite(row, check_rect.yMin());
1177+
break;
1178+
}
1179+
1180+
int next_index = std::max(index + 1, obs_index);
1181+
1182+
debugPrint(logger_,
1183+
utl::PAD,
1184+
"Place",
1185+
2,
1186+
"Shift required for {} to avoid {} ({} -> {})",
1187+
inst->getName(),
1188+
check_inst->getName(),
1189+
index,
1190+
next_index);
1191+
1192+
return placeInstance(
1193+
row, next_index, inst, base_orient, allow_overlap, allow_shift);
1194+
} else if (!allow_overlap && check_obs) {
1195+
const auto& [check_inst, obs_rect] = *check_obs;
11541196
const odb::Rect check_rect = check_inst->getBBox()->getBox();
11551197
logger_->error(utl::PAD,
11561198
1,
@@ -1909,8 +1951,8 @@ void ICeWall::routeRDLDebugNet(const char* net)
19091951
}
19101952
}
19111953

1912-
odb::dbInst* ICeWall::checkInstancePlacement(odb::dbInst* inst,
1913-
odb::dbRow* row) const
1954+
std::optional<std::pair<odb::dbInst*, odb::Rect>>
1955+
ICeWall::checkInstancePlacement(odb::dbInst* inst, odb::dbRow* row) const
19141956
{
19151957
std::set<odb::dbInst*> covers;
19161958
auto* block = getBlock();
@@ -1938,11 +1980,23 @@ odb::dbInst* ICeWall::checkInstancePlacement(odb::dbInst* inst,
19381980
for (auto* obs : inst->getMaster()->getObstructions()) {
19391981
odb::Rect obs_rect = obs->getBox();
19401982
xform.apply(obs_rect);
1983+
odb::dbTechLayer* layer = obs->getTechLayer();
1984+
if (layer != nullptr) {
1985+
odb::Rect bloat;
1986+
obs_rect.bloat(layer->getSpacing(), bloat);
1987+
obs_rect = bloat;
1988+
}
19411989
check_shapes[obs->getTechLayer()].emplace(obs_rect, nullptr);
19421990
}
19431991
for (auto* iterm : inst->getITerms()) {
19441992
for (const auto& [layer, box] : iterm->getGeometries()) {
1945-
check_shapes[layer].emplace(box, iterm->getNet());
1993+
odb::Rect term_rect = box;
1994+
if (layer != nullptr) {
1995+
odb::Rect bloat;
1996+
box.bloat(layer->getSpacing(), bloat);
1997+
term_rect = bloat;
1998+
}
1999+
check_shapes[layer].emplace(term_rect, iterm->getNet());
19462000
}
19472001
}
19482002
}
@@ -1955,7 +2009,7 @@ odb::dbInst* ICeWall::checkInstancePlacement(odb::dbInst* inst,
19552009
for (const auto& [inst_rect, check_net] :
19562010
check_shapes[obs->getTechLayer()]) {
19572011
if (inst_rect.intersects(obs_rect)) {
1958-
return check_inst;
2012+
return std::make_pair(check_inst, inst_rect.intersect(obs_rect));
19592013
}
19602014
}
19612015
}
@@ -1967,14 +2021,14 @@ odb::dbInst* ICeWall::checkInstancePlacement(odb::dbInst* inst,
19672021
= iterm->getNet() == check_net
19682022
&& (check_net != nullptr || iterm->getNet() != nullptr);
19692023
if (!nets_match && inst_rect.intersects(box)) {
1970-
return check_inst;
2024+
return std::make_pair(check_inst, inst_rect.intersect(box));
19712025
}
19722026
}
19732027
}
19742028
}
19752029
}
19762030

1977-
return nullptr;
2031+
return {};
19782032
}
19792033

19802034
} // namespace pad

0 commit comments

Comments
 (0)