@@ -37,6 +37,8 @@ PadPlacer::PadPlacer(utl::Logger* logger,
3737{
3838 populateInstWidths ();
3939 populateObstructions ();
40+
41+ addInstsOverlapCache (insts);
4042}
4143
4244void PadPlacer::populateInstWidths ()
@@ -398,8 +400,10 @@ void PadPlacer::populateObstructions()
398400 covers.insert (check_inst);
399401 continue ;
400402 }
401- instance_obstructions_.insert (
402- {check_inst->getBBox ()->getBox (), check_inst});
403+
404+ instance_obstructions_.insert ({check_inst->getBBox ()->getBox (),
405+ getInstanceOutline (check_inst),
406+ check_inst});
403407 }
404408 }
405409 }
@@ -411,9 +415,83 @@ void PadPlacer::populateObstructions()
411415 }
412416}
413417
418+ std::optional<odb::Polygon> PadPlacer::getMasterOutline (
419+ odb::dbMaster* master) const
420+ {
421+ std::vector<odb::Rect> master_obs;
422+ for (auto * obs : master->getObstructions ()) {
423+ auto * layer = obs->getTechLayer ();
424+ if (layer != nullptr ) {
425+ if (layer->getType () != odb::dbTechLayerType::OVERLAP ) {
426+ continue ;
427+ }
428+ master_obs.push_back (obs->getBox ());
429+ }
430+ }
431+
432+ if (master_obs.empty ()) {
433+ return std::nullopt ;
434+ }
435+
436+ if (master_obs.size () == 1 ) {
437+ return odb::Polygon (master_obs.front ());
438+ }
439+
440+ const auto overlaps = odb::Polygon::merge (master_obs);
441+ if (overlaps.size () == 1 ) {
442+ return overlaps.front ();
443+ }
444+
445+ return std::nullopt ;
446+ }
447+
448+ std::optional<odb::Polygon> PadPlacer::getInstanceOutline (
449+ odb::dbInst* inst) const
450+ {
451+ const auto checker = master_overlap_cache_.find (inst->getMaster ());
452+ if (checker != master_overlap_cache_.end ()) {
453+ if (!checker->second ) {
454+ return std::nullopt ;
455+ }
456+
457+ odb::Polygon poly = checker->second .value ();
458+ const odb::dbTransform xform = inst->getTransform ();
459+ xform.apply (poly);
460+ return poly;
461+ }
462+
463+ const auto master_outline = getMasterOutline (inst->getMaster ());
464+ if (!master_outline) {
465+ return std::nullopt ;
466+ }
467+
468+ const odb::dbTransform xform = inst->getTransform ();
469+ odb::Polygon poly = master_outline.value ();
470+ xform.apply (poly);
471+ return poly;
472+ }
473+
474+ void PadPlacer::addInstsOverlapCache (const std::vector<odb::dbInst*>& insts)
475+ {
476+ for (auto * inst : insts) {
477+ addInstOverlapCache (inst);
478+ }
479+ }
480+
481+ void PadPlacer::addInstOverlapCache (odb::dbInst* inst)
482+ {
483+ if (master_overlap_cache_.find (inst->getMaster ())
484+ != master_overlap_cache_.end ()) {
485+ return ;
486+ }
487+ master_overlap_cache_[inst->getMaster ()]
488+ = getMasterOutline (inst->getMaster ());
489+ }
490+
414491void PadPlacer::addInstanceObstructions (odb::dbInst* inst)
415492{
416- instance_obstructions_.insert ({inst->getBBox ()->getBox (), inst});
493+ instance_obstructions_.insert (
494+ {inst->getBBox ()->getBox (), getInstanceOutline (inst), inst});
417495 if (inst->getMaster ()->isCover ()) {
418496 for (const auto & [layer, shapes] : getInstanceObstructions (inst)) {
419497 term_obstructions_[layer].insert (shapes.begin (), shapes.end ());
@@ -426,6 +504,8 @@ PadPlacer::checkInstancePlacement(odb::dbInst* inst,
426504 bool return_intersect) const
427505{
428506 const odb::Rect inst_rect = inst->getBBox ()->getBox ();
507+ const std::optional<odb::Polygon> inst_poly = getInstanceOutline (inst);
508+
429509 for (auto itr = blockage_obstructions_.qbegin (
430510 boost::geometry::index::intersects (inst_rect));
431511 itr != blockage_obstructions_.qend ();
@@ -446,11 +526,29 @@ PadPlacer::checkInstancePlacement(odb::dbInst* inst,
446526 boost::geometry::index::intersects (inst_rect));
447527 itr != instance_obstructions_.qend ();
448528 itr++) {
449- const auto & [check_rect, check_inst] = *itr;
529+ const auto & [check_rect, check_poly, check_inst] = *itr;
450530 if (check_rect.overlaps (inst_rect)) {
451531 if (check_inst == inst) {
452532 continue ;
453533 }
534+ if (check_poly && inst_poly) {
535+ // Both have overlap polygons, check them for a more accurate result
536+ if (!boost::geometry::intersects (*check_poly, *inst_poly)) {
537+ continue ;
538+ }
539+ } else if (check_poly) {
540+ // Only the obstruction has an overlap polygon, check it for a more
541+ // accurate result
542+ if (!boost::geometry::intersects (inst_rect, *check_poly)) {
543+ continue ;
544+ }
545+ } else if (inst_poly) {
546+ // Only the instance has an overlap polygon, check it for a more
547+ // accurate result
548+ if (!boost::geometry::intersects (check_rect, *inst_poly)) {
549+ continue ;
550+ }
551+ }
454552 debugPrint (getLogger (),
455553 utl::PAD ,
456554 " Check" ,
@@ -570,10 +668,12 @@ void UniformPadPlacer::place()
570668
571669// /////////////////////////////////////////
572670
573- CheckerOnlyPadPlacer::CheckerOnlyPadPlacer (utl::Logger* logger,
574- odb::dbBlock* block,
575- odb::dbRow* row)
576- : PadPlacer(logger, block, {}, odb::Direction2D::North, row)
671+ CheckerOnlyPadPlacer::CheckerOnlyPadPlacer (
672+ utl::Logger* logger,
673+ odb::dbBlock* block,
674+ odb::dbRow* row,
675+ const std::vector<odb::dbInst*>& insts)
676+ : PadPlacer(logger, block, insts, odb::Direction2D::North, row)
577677{
578678}
579679
0 commit comments