@@ -32,6 +32,7 @@ PadPlacer::PadPlacer(utl::Logger* logger,
3232 : logger_(logger), block_(block), insts_(insts), edge_(edge), row_(row)
3333{
3434 populateInstWidths ();
35+ populateObstructions ();
3536}
3637
3738void PadPlacer::populateInstWidths ()
@@ -301,89 +302,181 @@ int PadPlacer::placeInstance(int index,
301302 return next_pos;
302303}
303304
304- std::optional<std::pair<odb::dbInst*, odb::Rect>>
305- PadPlacer::checkInstancePlacement (odb::dbInst* inst) const
305+ PadPlacer::LayerTermObsTree PadPlacer::getInstanceObstructions (
306+ odb::dbInst* inst,
307+ bool bloat) const
308+ {
309+ std::map<odb::dbTechLayer*, std::vector<TermObsValue>> shapes;
310+
311+ // populate map as needed
312+ const auto xform = inst->getTransform ();
313+ for (auto * obs : inst->getMaster ()->getObstructions ()) {
314+ odb::Rect obs_rect = obs->getBox ();
315+ xform.apply (obs_rect);
316+ odb::dbTechLayer* layer = obs->getTechLayer ();
317+ if (bloat && layer != nullptr ) {
318+ odb::Rect bloat_rect;
319+ obs_rect.bloat (layer->getSpacing (), bloat_rect);
320+ obs_rect = bloat_rect;
321+ }
322+ shapes[obs->getTechLayer ()].emplace_back (obs_rect, nullptr , inst);
323+ }
324+ for (auto * iterm : inst->getITerms ()) {
325+ for (const auto & [layer, box] : iterm->getGeometries ()) {
326+ odb::Rect term_rect = box;
327+ if (bloat && layer != nullptr ) {
328+ odb::Rect bloat_rect;
329+ box.bloat (layer->getSpacing (), bloat_rect);
330+ term_rect = bloat_rect;
331+ }
332+ shapes[layer].emplace_back (term_rect, iterm->getNet (), inst);
333+ }
334+ }
335+
336+ LayerTermObsTree rshapes;
337+ for (const auto & [layer, layer_shapes] : shapes) {
338+ if (layer == nullptr ) {
339+ continue ;
340+ }
341+ rshapes[layer] = TermObsTree (layer_shapes.begin (), layer_shapes.end ());
342+ }
343+ return rshapes;
344+ }
345+
346+ void PadPlacer::populateObstructions ()
306347{
348+ blockage_obstructions_.clear ();
349+ instance_obstructions_.clear ();
350+ term_obstructions_.clear ();
351+
352+ const odb::Rect row = row_->getBBox ();
353+
307354 std::set<odb::dbInst*> covers;
308355 auto * block = getBlock ();
309356 if (block) {
310- const odb::Rect inst_rect = inst-> getBBox ()-> getBox ();
357+ // Get placement blockages
311358 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));
359+ if (blockage->getBBox ()->getBox ().overlaps (row)) {
360+ blockage_obstructions_.insert (blockage->getBBox ()->getBox ());
315361 }
316362 }
317- for (auto * check_inst : block->getInsts ()) {
318- if (check_inst == inst) {
319- continue ;
363+ // Get obstructions that might interfere with RDL routing
364+ for (odb::dbObstruction* obs : block->getObstructions ()) {
365+ if (obs->getBBox ()->getBox ().overlaps (row)) {
366+ term_obstructions_[obs->getBBox ()->getTechLayer ()].insert (
367+ {obs->getBBox ()->getBox (), nullptr , nullptr });
320368 }
369+ }
370+ for (auto * check_inst : block->getInsts ()) {
321371 if (!check_inst->isFixed ()) {
322372 continue ;
323373 }
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));
374+ if (check_inst->getBBox ()->getBox ().overlaps (row)) {
375+ if (check_inst->getMaster ()->isCover ()) {
376+ covers.insert (check_inst);
377+ continue ;
378+ } else {
379+ instance_obstructions_.insert (
380+ {check_inst->getBBox ()->getBox (), check_inst});
381+ }
331382 }
332383 }
333384 }
334385
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 );
386+ for (odb::dbInst* check_inst : covers) {
387+ for (const auto & [layer, shapes] : getInstanceObstructions (check_inst)) {
388+ term_obstructions_[layer].insert (shapes.begin (), shapes.end ());
351389 }
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- }
390+ }
391+ }
392+
393+ void PadPlacer::addInstanceObstructions (odb::dbInst* inst)
394+ {
395+ instance_obstructions_.insert ({inst->getBBox ()->getBox (), inst});
396+ if (inst->getMaster ()->isCover ()) {
397+ for (const auto & [layer, shapes] : getInstanceObstructions (inst)) {
398+ term_obstructions_[layer].insert (shapes.begin (), shapes.end ());
362399 }
363400 }
401+ }
364402
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- }
403+ std::optional<std::pair<odb::dbInst*, odb::Rect>>
404+ PadPlacer::checkInstancePlacement (odb::dbInst* inst,
405+ bool return_intersect) const
406+ {
407+ const odb::Rect inst_rect = inst->getBBox ()->getBox ();
408+ for (auto itr = blockage_obstructions_.qbegin (
409+ boost::geometry::index::intersects (inst_rect));
410+ itr != blockage_obstructions_.qend ();
411+ itr++) {
412+ if (itr->overlaps (inst_rect)) {
413+ debugPrint (getLogger (),
414+ utl::PAD,
415+ " Check" ,
416+ 2 ,
417+ " {} blocked by blockage: {}" ,
418+ inst->getName (),
419+ *itr);
420+ return std::make_pair (
421+ nullptr , return_intersect ? itr->intersect (inst_rect) : *itr);
422+ }
423+ }
424+ for (auto itr = instance_obstructions_.qbegin (
425+ boost::geometry::index::intersects (inst_rect));
426+ itr != instance_obstructions_.qend ();
427+ itr++) {
428+ const auto & [check_rect, check_inst] = *itr;
429+ if (check_rect.overlaps (inst_rect)) {
430+ if (check_inst == inst) {
431+ continue ;
375432 }
433+ debugPrint (getLogger (),
434+ utl::PAD,
435+ " Check" ,
436+ 2 ,
437+ " {} blocked by fixed instance: {}" ,
438+ inst->getName (),
439+ check_inst->getName ());
440+ return std::make_pair (
441+ check_inst,
442+ return_intersect ? check_rect.intersect (inst_rect) : check_rect);
443+ }
444+ }
445+
446+ for (const auto & [layer, term_shapes] : getInstanceObstructions (inst, true )) {
447+ if (term_obstructions_.find (layer) == term_obstructions_.end ()) {
448+ continue ;
376449 }
377450
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- }
451+ const auto & obs_layer = term_obstructions_.at (layer);
452+
453+ for (const auto & [term_shape, term_net, term_inst] : term_shapes) {
454+ for (auto itr
455+ = obs_layer.qbegin (boost::geometry::index::intersects (term_shape));
456+ itr != obs_layer.qend ();
457+ itr++) {
458+ const auto & [check_rect, check_net, check_inst] = *itr;
459+ if (check_inst == inst) {
460+ continue ;
461+ }
462+ const bool nets_match
463+ = term_net == check_net
464+ && (check_net != nullptr || term_net != nullptr );
465+ if (!nets_match) {
466+ debugPrint (
467+ getLogger (),
468+ utl::PAD,
469+ " Check" ,
470+ 2 ,
471+ " {} ({} / {}) blocked by terminal obstruction: {} / {}" ,
472+ inst->getName (),
473+ term_shape,
474+ term_net == nullptr ? " unconnected" : term_net->getName (),
475+ check_rect,
476+ check_net == nullptr ? " unconnected" : check_net->getName ());
477+ return std::make_pair (
478+ check_inst,
479+ return_intersect ? check_rect.intersect (inst_rect) : check_rect);
387480 }
388481 }
389482 }
@@ -444,6 +537,7 @@ void UniformPadPlacer::place()
444537 odb::dbOrientType::R0,
445538 /* allow_overlap */ false ,
446539 /* allow_shift */ true );
540+ addInstanceObstructions (inst);
447541 offset += getInstWidths ().at (inst);
448542 offset += target_spacing;
449543
@@ -480,9 +574,10 @@ SingleInstPadPlacer::SingleInstPadPlacer(utl::Logger* logger,
480574void SingleInstPadPlacer::place (odb::dbInst* inst,
481575 int location,
482576 const odb::dbOrientType& base_orient,
483- bool allow_overlap) const
577+ bool allow_overlap)
484578{
485579 placeInstance (snapToRowSite (location), inst, base_orient, allow_overlap);
580+ addInstanceObstructions (inst);
486581}
487582
488583// /////////////////////////////////////////
@@ -578,6 +673,7 @@ void BumpAlignedPadPlacer::place()
578673 * getRow ()->getSpacing ();
579674
580675 performPadFlip (ginst);
676+ addInstanceObstructions (ginst);
581677
582678 if (gui_debug) {
583679 gui::Gui::get ()->pause ();
0 commit comments