1111#include < map>
1212#include < optional>
1313#include < set>
14+ #include < tuple>
1415#include < utility>
1516#include < vector>
1617
18+ #include " boost/geometry/index/predicates.hpp"
1719#include " gui/gui.h"
1820#include " odb/db.h"
1921#include " odb/dbTransform.h"
@@ -32,6 +34,7 @@ PadPlacer::PadPlacer(utl::Logger* logger,
3234 : logger_(logger), block_(block), insts_(insts), edge_(edge), row_(row)
3335{
3436 populateInstWidths ();
37+ populateObstructions ();
3538}
3639
3740void PadPlacer::populateInstWidths ()
@@ -301,89 +304,180 @@ int PadPlacer::placeInstance(int index,
301304 return next_pos;
302305}
303306
304- std::optional<std::pair<odb::dbInst*, odb::Rect>>
305- PadPlacer::checkInstancePlacement (odb::dbInst* inst) const
307+ PadPlacer::LayerTermObsTree PadPlacer::getInstanceObstructions (
308+ odb::dbInst* inst,
309+ bool bloat) const
310+ {
311+ std::map<odb::dbTechLayer*, std::vector<TermObsValue>> shapes;
312+
313+ // populate map as needed
314+ const auto xform = inst->getTransform ();
315+ for (auto * obs : inst->getMaster ()->getObstructions ()) {
316+ odb::Rect obs_rect = obs->getBox ();
317+ xform.apply (obs_rect);
318+ odb::dbTechLayer* layer = obs->getTechLayer ();
319+ if (bloat && layer != nullptr ) {
320+ odb::Rect bloat_rect;
321+ obs_rect.bloat (layer->getSpacing (), bloat_rect);
322+ obs_rect = bloat_rect;
323+ }
324+ shapes[obs->getTechLayer ()].emplace_back (obs_rect, nullptr , inst);
325+ }
326+ for (auto * iterm : inst->getITerms ()) {
327+ for (const auto & [layer, box] : iterm->getGeometries ()) {
328+ odb::Rect term_rect = box;
329+ if (bloat && layer != nullptr ) {
330+ odb::Rect bloat_rect;
331+ box.bloat (layer->getSpacing (), bloat_rect);
332+ term_rect = bloat_rect;
333+ }
334+ shapes[layer].emplace_back (term_rect, iterm->getNet (), inst);
335+ }
336+ }
337+
338+ LayerTermObsTree rshapes;
339+ for (const auto & [layer, layer_shapes] : shapes) {
340+ if (layer == nullptr ) {
341+ continue ;
342+ }
343+ rshapes[layer] = TermObsTree (layer_shapes.begin (), layer_shapes.end ());
344+ }
345+ return rshapes;
346+ }
347+
348+ void PadPlacer::populateObstructions ()
306349{
350+ blockage_obstructions_.clear ();
351+ instance_obstructions_.clear ();
352+ term_obstructions_.clear ();
353+
354+ const odb::Rect row = row_->getBBox ();
355+
307356 std::set<odb::dbInst*> covers;
308357 auto * block = getBlock ();
309358 if (block) {
310- const odb::Rect inst_rect = inst-> getBBox ()-> getBox ();
359+ // Get placement blockages
311360 for (odb::dbBlockage* blockage : block->getBlockages ()) {
312- if (blockage->getBBox ()->getBox ().overlaps (inst_rect)) {
313- return std::make_pair (
314- nullptr , blockage->getBBox ()->getBox ().intersect (inst_rect));
361+ if (blockage->getBBox ()->getBox ().overlaps (row)) {
362+ blockage_obstructions_.insert (blockage->getBBox ()->getBox ());
315363 }
316364 }
317- for (auto * check_inst : block->getInsts ()) {
318- if (check_inst == inst) {
319- continue ;
365+ // Get obstructions that might interfere with RDL routing
366+ for (odb::dbObstruction* obs : block->getObstructions ()) {
367+ if (obs->getBBox ()->getBox ().overlaps (row)) {
368+ term_obstructions_[obs->getBBox ()->getTechLayer ()].insert (
369+ {obs->getBBox ()->getBox (), nullptr , nullptr });
320370 }
371+ }
372+ for (auto * check_inst : block->getInsts ()) {
321373 if (!check_inst->isFixed ()) {
322374 continue ;
323375 }
324- if (check_inst->getMaster ()->isCover ( )) {
325- covers. insert (check_inst);
326- continue ;
327- }
328- if (check_inst-> getBBox ()-> getBox (). overlaps (inst_rect)) {
329- return std::make_pair (
330- check_inst, check_inst ->getBBox ()->getBox (). intersect (inst_rect) );
376+ if (check_inst->getBBox ()->getBox (). overlaps (row )) {
377+ if (check_inst-> getMaster ()-> isCover ()) {
378+ covers. insert (check_inst) ;
379+ continue ;
380+ }
381+ instance_obstructions_. insert (
382+ { check_inst->getBBox ()->getBox (), check_inst} );
331383 }
332384 }
333385 }
334386
335- // Check if inst overlaps with bumps
336- std::map<odb::dbTechLayer*, std::set<std::pair<odb::Rect, odb::dbNet*>>>
337- check_shapes;
338- if (!covers.empty ()) {
339- // populate map as needed
340- const auto xform = inst->getTransform ();
341- for (auto * obs : inst->getMaster ()->getObstructions ()) {
342- odb::Rect obs_rect = obs->getBox ();
343- xform.apply (obs_rect);
344- odb::dbTechLayer* layer = obs->getTechLayer ();
345- if (layer != nullptr ) {
346- odb::Rect bloat;
347- obs_rect.bloat (layer->getSpacing (), bloat);
348- obs_rect = bloat;
349- }
350- check_shapes[obs->getTechLayer ()].emplace (obs_rect, nullptr );
387+ for (odb::dbInst* check_inst : covers) {
388+ for (const auto & [layer, shapes] : getInstanceObstructions (check_inst)) {
389+ term_obstructions_[layer].insert (shapes.begin (), shapes.end ());
351390 }
352- for (auto * iterm : inst->getITerms ()) {
353- for (const auto & [layer, box] : iterm->getGeometries ()) {
354- odb::Rect term_rect = box;
355- if (layer != nullptr ) {
356- odb::Rect bloat;
357- box.bloat (layer->getSpacing (), bloat);
358- term_rect = bloat;
359- }
360- check_shapes[layer].emplace (term_rect, iterm->getNet ());
361- }
391+ }
392+ }
393+
394+ void PadPlacer::addInstanceObstructions (odb::dbInst* inst)
395+ {
396+ instance_obstructions_.insert ({inst->getBBox ()->getBox (), inst});
397+ if (inst->getMaster ()->isCover ()) {
398+ for (const auto & [layer, shapes] : getInstanceObstructions (inst)) {
399+ term_obstructions_[layer].insert (shapes.begin (), shapes.end ());
362400 }
363401 }
402+ }
364403
365- for (odb::dbInst* check_inst : covers) {
366- const auto xform = check_inst->getTransform ();
367- for (auto * obs : check_inst->getMaster ()->getObstructions ()) {
368- odb::Rect obs_rect = obs->getBox ();
369- xform.apply (obs_rect);
370- for (const auto & [inst_rect, check_net] :
371- check_shapes[obs->getTechLayer ()]) {
372- if (inst_rect.intersects (obs_rect)) {
373- return std::make_pair (check_inst, inst_rect.intersect (obs_rect));
374- }
404+ std::optional<std::pair<odb::dbInst*, odb::Rect>>
405+ PadPlacer::checkInstancePlacement (odb::dbInst* inst,
406+ bool return_intersect) const
407+ {
408+ const odb::Rect inst_rect = inst->getBBox ()->getBox ();
409+ for (auto itr = blockage_obstructions_.qbegin (
410+ boost::geometry::index::intersects (inst_rect));
411+ itr != blockage_obstructions_.qend ();
412+ itr++) {
413+ if (itr->overlaps (inst_rect)) {
414+ debugPrint (getLogger (),
415+ utl::PAD,
416+ " Check" ,
417+ 2 ,
418+ " {} blocked by blockage: {}" ,
419+ inst->getName (),
420+ *itr);
421+ return std::make_pair (
422+ nullptr , return_intersect ? itr->intersect (inst_rect) : *itr);
423+ }
424+ }
425+ for (auto itr = instance_obstructions_.qbegin (
426+ boost::geometry::index::intersects (inst_rect));
427+ itr != instance_obstructions_.qend ();
428+ itr++) {
429+ const auto & [check_rect, check_inst] = *itr;
430+ if (check_rect.overlaps (inst_rect)) {
431+ if (check_inst == inst) {
432+ continue ;
375433 }
434+ debugPrint (getLogger (),
435+ utl::PAD,
436+ " Check" ,
437+ 2 ,
438+ " {} blocked by fixed instance: {}" ,
439+ inst->getName (),
440+ check_inst->getName ());
441+ return std::make_pair (
442+ check_inst,
443+ return_intersect ? check_rect.intersect (inst_rect) : check_rect);
444+ }
445+ }
446+
447+ for (const auto & [layer, term_shapes] : getInstanceObstructions (inst, true )) {
448+ if (term_obstructions_.find (layer) == term_obstructions_.end ()) {
449+ continue ;
376450 }
377451
378- for (auto * iterm : check_inst->getITerms ()) {
379- for (const auto & [layer, box] : iterm->getGeometries ()) {
380- for (const auto & [inst_rect, check_net] : check_shapes[layer]) {
381- const bool nets_match
382- = iterm->getNet () == check_net
383- && (check_net != nullptr || iterm->getNet () != nullptr );
384- if (!nets_match && inst_rect.intersects (box)) {
385- return std::make_pair (check_inst, inst_rect.intersect (box));
386- }
452+ const auto & obs_layer = term_obstructions_.at (layer);
453+
454+ for (const auto & [term_shape, term_net, term_inst] : term_shapes) {
455+ for (auto itr
456+ = obs_layer.qbegin (boost::geometry::index::intersects (term_shape));
457+ itr != obs_layer.qend ();
458+ itr++) {
459+ const auto & [check_rect, check_net, check_inst] = *itr;
460+ if (check_inst == inst) {
461+ continue ;
462+ }
463+ const bool nets_match
464+ = term_net == check_net
465+ && (check_net != nullptr || term_net != nullptr );
466+ if (!nets_match) {
467+ debugPrint (
468+ getLogger (),
469+ utl::PAD,
470+ " Check" ,
471+ 2 ,
472+ " {} ({} / {}) blocked by terminal obstruction: {} / {}" ,
473+ inst->getName (),
474+ term_shape,
475+ term_net == nullptr ? " unconnected" : term_net->getName (),
476+ check_rect,
477+ check_net == nullptr ? " unconnected" : check_net->getName ());
478+ return std::make_pair (
479+ check_inst,
480+ return_intersect ? check_rect.intersect (inst_rect) : check_rect);
387481 }
388482 }
389483 }
@@ -444,6 +538,7 @@ void UniformPadPlacer::place()
444538 odb::dbOrientType::R0,
445539 /* allow_overlap */ false ,
446540 /* allow_shift */ true );
541+ addInstanceObstructions (inst);
447542 offset += getInstWidths ().at (inst);
448543 offset += target_spacing;
449544
@@ -480,9 +575,10 @@ SingleInstPadPlacer::SingleInstPadPlacer(utl::Logger* logger,
480575void SingleInstPadPlacer::place (odb::dbInst* inst,
481576 int location,
482577 const odb::dbOrientType& base_orient,
483- bool allow_overlap) const
578+ bool allow_overlap)
484579{
485580 placeInstance (snapToRowSite (location), inst, base_orient, allow_overlap);
581+ addInstanceObstructions (inst);
486582}
487583
488584// /////////////////////////////////////////
@@ -578,6 +674,7 @@ void BumpAlignedPadPlacer::place()
578674 * getRow ()->getSpacing ();
579675
580676 performPadFlip (ginst);
677+ addInstanceObstructions (ginst);
581678
582679 if (gui_debug) {
583680 gui::Gui::get ()->pause ();
0 commit comments