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