@@ -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