1111#include < limits>
1212#include < map>
1313#include < memory>
14+ #include < optional>
1415#include < set>
1516#include < utility>
1617#include < vector>
@@ -520,7 +521,6 @@ void ICeWall::placeCorner(odb::dbMaster* master, int ring_index)
520521
521522 // Check for instances overlapping the corner site
522523 bool place_inst = true ;
523- std::set<odb::dbInst*> covers;
524524 for (auto * check_inst : block->getInsts ()) {
525525 if (check_inst == inst) {
526526 continue ;
@@ -529,7 +529,6 @@ void ICeWall::placeCorner(odb::dbMaster* master, int ring_index)
529529 continue ;
530530 }
531531 if (check_inst->getMaster ()->isCover ()) {
532- covers.insert (check_inst);
533532 continue ;
534533 }
535534 const odb::Rect check_rect = check_inst->getBBox ()->getBox ();
@@ -556,58 +555,7 @@ void ICeWall::placeCorner(odb::dbMaster* master, int ring_index)
556555 inst->setLocation (row_bbox.xMin (), row_bbox.yMin ());
557556 inst->setPlacementStatus (odb::dbPlacementStatus::FIRM);
558557
559- // Check if inst overlaps with bumps
560- std::map<odb::dbTechLayer*, std::set<odb::Rect>> check_shapes;
561- if (!covers.empty ()) {
562- // populate map as needed
563- const auto xform = inst->getTransform ();
564- for (auto * obs : inst->getMaster ()->getObstructions ()) {
565- odb::Rect obs_rect = obs->getBox ();
566- xform.apply (obs_rect);
567- check_shapes[obs->getTechLayer ()].insert (obs_rect);
568- }
569- for (auto * iterm : inst->getITerms ()) {
570- for (const auto & [layer, box] : iterm->getGeometries ()) {
571- check_shapes[layer].insert (box);
572- }
573- }
574- }
575-
576- bool remove = false ;
577- for (auto * check_inst : covers) {
578- const auto xform = check_inst->getTransform ();
579- for (auto * obs : check_inst->getMaster ()->getObstructions ()) {
580- odb::Rect obs_rect = obs->getBox ();
581- xform.apply (obs_rect);
582- for (const auto & inst_rect : check_shapes[obs->getTechLayer ()]) {
583- if (inst_rect.intersects (obs_rect)) {
584- remove = true ;
585- break ;
586- }
587- }
588- }
589- if (remove) {
590- break ;
591- }
592- for (auto * iterm : check_inst->getITerms ()) {
593- for (const auto & [layer, box] : iterm->getGeometries ()) {
594- for (const auto & inst_rect : check_shapes[layer]) {
595- if (inst_rect.intersects (box)) {
596- remove = true ;
597- break ;
598- }
599- }
600- }
601- if (remove) {
602- break ;
603- }
604- }
605- if (remove) {
606- break ;
607- }
608- }
609-
610- if (remove) {
558+ if (checkInstancePlacement (inst, row)) {
611559 if (create_inst) {
612560 logger_->warn (utl::PAD,
613561 45 ,
@@ -1034,7 +982,9 @@ void ICeWall::placePadsBumpAligned(
1034982 offset += placeInstance (row,
1035983 snapToRowSite (row, select_pos),
1036984 ginst,
1037- odb::dbOrientType::R0)
985+ odb::dbOrientType::R0,
986+ /* allow_overlap */ false ,
987+ /* allow_shift */ true )
1038988 * row->getSpacing ();
1039989
1040990 performPadFlip (row, ginst, iterm_connections);
@@ -1064,7 +1014,12 @@ void ICeWall::placePadsUniform(const std::vector<odb::dbInst*>& insts,
10641014 inst->getName (),
10651015 offset / dbus);
10661016
1067- placeInstance (row, snapToRowSite (row, offset), inst, odb::dbOrientType::R0);
1017+ placeInstance (row,
1018+ snapToRowSite (row, offset),
1019+ inst,
1020+ odb::dbOrientType::R0,
1021+ /* allow_overlap */ false ,
1022+ /* allow_shift */ true );
10681023 offset += inst_widths.at (inst);
10691024 offset += target_spacing;
10701025 }
@@ -1124,7 +1079,8 @@ int ICeWall::placeInstance(odb::dbRow* row,
11241079 int index,
11251080 odb::dbInst* inst,
11261081 const odb::dbOrientType& base_orient,
1127- bool allow_overlap) const
1082+ bool allow_overlap,
1083+ bool allow_shift) const
11281084{
11291085 const int origin_offset = index * row->getSpacing ();
11301086
@@ -1202,38 +1158,65 @@ int ICeWall::placeInstance(odb::dbRow* row,
12021158 row_bbox.yMax () / dbus);
12031159 }
12041160
1205- // check for overlaps with other instances
1206- for (auto * check_inst : block->getInsts ()) {
1207- if (check_inst == inst) {
1208- continue ;
1209- }
1210- if (!check_inst->isFixed ()) {
1211- continue ;
1212- }
1213- if (check_inst->getMaster ()->isCover ()) {
1214- continue ;
1161+ const auto check_obs = checkInstancePlacement (inst, row);
1162+ if (allow_shift && check_obs) {
1163+ const auto & [check_inst, check_rect] = *check_obs;
1164+
1165+ int obs_index = index;
1166+ switch (row_edge) {
1167+ case odb::Direction2D::North:
1168+ case odb::Direction2D::South:
1169+ obs_index = snapToRowSite (row, check_rect.xMin ());
1170+ break ;
1171+ case odb::Direction2D::West:
1172+ case odb::Direction2D::East:
1173+ obs_index = snapToRowSite (row, check_rect.yMin ());
1174+ break ;
12151175 }
1216- const odb::Rect check_rect = check_inst->getBBox ()->getBox ();
1217- if (!allow_overlap && inst_rect.overlaps (check_rect)) {
1218- logger_->error (utl::PAD,
1219- 1 ,
1220- " Unable to place {} ({}) at ({:.3f}um, {:.3f}um) - "
1221- " ({:.3f}um, {:.3f}um) as it "
1222- " overlaps with {} ({}) at ({:.3f}um, {:.3f}um) - "
1223- " ({:.3f}um, {:.3f}um)" ,
1224- inst->getName (),
1225- inst->getMaster ()->getName (),
1226- inst_rect.xMin () / dbus,
1227- inst_rect.yMin () / dbus,
1228- inst_rect.xMax () / dbus,
1229- inst_rect.yMax () / dbus,
1230- check_inst->getName (),
1231- check_inst->getMaster ()->getName (),
1232- check_rect.xMin () / dbus,
1233- check_rect.yMin () / dbus,
1234- check_rect.xMax () / dbus,
1235- check_rect.yMax () / dbus);
1176+
1177+ int next_index = std::max (index + 1 , obs_index);
1178+
1179+ debugPrint (logger_,
1180+ utl::PAD,
1181+ " Place" ,
1182+ 2 ,
1183+ " Shift required for {} to avoid {} ({} -> {})" ,
1184+ inst->getName (),
1185+ check_inst ? check_inst->getName () : " blockage" ,
1186+ index,
1187+ next_index);
1188+
1189+ return placeInstance (
1190+ row, next_index, inst, base_orient, allow_overlap, allow_shift);
1191+ }
1192+ if (!allow_overlap && check_obs) {
1193+ const auto & [check_inst, obs_rect] = *check_obs;
1194+ odb::Rect check_rect;
1195+ if (check_inst == nullptr ) {
1196+ check_rect = obs_rect;
1197+ } else {
1198+ check_rect = check_inst->getBBox ()->getBox ();
12361199 }
1200+ logger_->error (utl::PAD,
1201+ 1 ,
1202+ " Unable to place {} ({}) at ({:.3f}um, {:.3f}um) - "
1203+ " ({:.3f}um, {:.3f}um) as it "
1204+ " overlaps with {} at ({:.3f}um, {:.3f}um) - "
1205+ " ({:.3f}um, {:.3f}um)" ,
1206+ inst->getName (),
1207+ inst->getMaster ()->getName (),
1208+ inst_rect.xMin () / dbus,
1209+ inst_rect.yMin () / dbus,
1210+ inst_rect.xMax () / dbus,
1211+ inst_rect.yMax () / dbus,
1212+ check_inst ? fmt::format (" {} ({})" ,
1213+ check_inst->getName (),
1214+ check_inst->getMaster ()->getName ())
1215+ : " blockage" ,
1216+ check_rect.xMin () / dbus,
1217+ check_rect.yMin () / dbus,
1218+ check_rect.xMax () / dbus,
1219+ check_rect.yMax () / dbus);
12371220 }
12381221 inst->setPlacementStatus (odb::dbPlacementStatus::FIRM);
12391222
@@ -1973,4 +1956,95 @@ void ICeWall::routeRDLDebugNet(const char* net)
19731956 }
19741957}
19751958
1959+ std::optional<std::pair<odb::dbInst*, odb::Rect>>
1960+ ICeWall::checkInstancePlacement (odb::dbInst* inst, odb::dbRow* row) const
1961+ {
1962+ std::set<odb::dbInst*> covers;
1963+ auto * block = getBlock ();
1964+ if (block) {
1965+ const odb::Rect inst_rect = inst->getBBox ()->getBox ();
1966+ for (odb::dbBlockage* blockage : block->getBlockages ()) {
1967+ if (blockage->getBBox ()->getBox ().overlaps (inst_rect)) {
1968+ return std::make_pair (
1969+ nullptr , blockage->getBBox ()->getBox ().intersect (inst_rect));
1970+ }
1971+ }
1972+ for (auto * check_inst : block->getInsts ()) {
1973+ if (check_inst == inst) {
1974+ continue ;
1975+ }
1976+ if (!check_inst->isFixed ()) {
1977+ continue ;
1978+ }
1979+ if (check_inst->getMaster ()->isCover ()) {
1980+ covers.insert (check_inst);
1981+ continue ;
1982+ }
1983+ if (check_inst->getBBox ()->getBox ().overlaps (inst_rect)) {
1984+ return std::make_pair (
1985+ check_inst, check_inst->getBBox ()->getBox ().intersect (inst_rect));
1986+ }
1987+ }
1988+ }
1989+
1990+ // Check if inst overlaps with bumps
1991+ std::map<odb::dbTechLayer*, std::set<std::pair<odb::Rect, odb::dbNet*>>>
1992+ check_shapes;
1993+ if (!covers.empty ()) {
1994+ // populate map as needed
1995+ const auto xform = inst->getTransform ();
1996+ for (auto * obs : inst->getMaster ()->getObstructions ()) {
1997+ odb::Rect obs_rect = obs->getBox ();
1998+ xform.apply (obs_rect);
1999+ odb::dbTechLayer* layer = obs->getTechLayer ();
2000+ if (layer != nullptr ) {
2001+ odb::Rect bloat;
2002+ obs_rect.bloat (layer->getSpacing (), bloat);
2003+ obs_rect = bloat;
2004+ }
2005+ check_shapes[obs->getTechLayer ()].emplace (obs_rect, nullptr );
2006+ }
2007+ for (auto * iterm : inst->getITerms ()) {
2008+ for (const auto & [layer, box] : iterm->getGeometries ()) {
2009+ odb::Rect term_rect = box;
2010+ if (layer != nullptr ) {
2011+ odb::Rect bloat;
2012+ box.bloat (layer->getSpacing (), bloat);
2013+ term_rect = bloat;
2014+ }
2015+ check_shapes[layer].emplace (term_rect, iterm->getNet ());
2016+ }
2017+ }
2018+ }
2019+
2020+ for (odb::dbInst* check_inst : covers) {
2021+ const auto xform = check_inst->getTransform ();
2022+ for (auto * obs : check_inst->getMaster ()->getObstructions ()) {
2023+ odb::Rect obs_rect = obs->getBox ();
2024+ xform.apply (obs_rect);
2025+ for (const auto & [inst_rect, check_net] :
2026+ check_shapes[obs->getTechLayer ()]) {
2027+ if (inst_rect.intersects (obs_rect)) {
2028+ return std::make_pair (check_inst, inst_rect.intersect (obs_rect));
2029+ }
2030+ }
2031+ }
2032+
2033+ for (auto * iterm : check_inst->getITerms ()) {
2034+ for (const auto & [layer, box] : iterm->getGeometries ()) {
2035+ for (const auto & [inst_rect, check_net] : check_shapes[layer]) {
2036+ const bool nets_match
2037+ = iterm->getNet () == check_net
2038+ && (check_net != nullptr || iterm->getNet () != nullptr );
2039+ if (!nets_match && inst_rect.intersects (box)) {
2040+ return std::make_pair (check_inst, inst_rect.intersect (box));
2041+ }
2042+ }
2043+ }
2044+ }
2045+ }
2046+
2047+ return {};
2048+ }
2049+
19762050} // namespace pad
0 commit comments