From dae18ff72da20e2fcdf0e9a4857543ab5aa60ad3 Mon Sep 17 00:00:00 2001 From: Augusto Berndt Date: Mon, 8 Jun 2026 19:50:19 +0000 Subject: [PATCH 1/4] dpl: fix power-rail detection in getMasterPwrs Check rails with cell borders instead of using bbox centers. Previous code would incorrectly collapsed multi-box pins to the cell middle, instead of borders, mislabeling double-height cells. Signed-off-by: Augusto Berndt --- src/dpl/src/infrastructure/network.cxx | 79 ++++++++++++++++---------- 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/src/dpl/src/infrastructure/network.cxx b/src/dpl/src/infrastructure/network.cxx index dc3919ff0e6..c5f10614902 100644 --- a/src/dpl/src/infrastructure/network.cxx +++ b/src/dpl/src/infrastructure/network.cxx @@ -256,43 +256,62 @@ odb::Rect getBoundarySegment(const odb::Rect& bbox, return segment; } +// Returns (topPwr, botPwr) for the master's rails. Power_UNK when an edge +// has no rail, or when POWER and GROUND both touch it. +// +// Each MPin rectangle is tested individually, since a single MPin can hold +// rails on both edges (e.g. double-height cells with VSS at top and bottom) +// or include internal straps that would pull a per-pin bbox center off the +// rail. Only ROUTING-layer geometry counts, to ignore NWELL/PWELL implants +// encoded as POWER/GROUND pins on MASTERSLICE layers. +// layers) from polluting the rail detection. std::pair getMasterPwrs(odb::dbMaster* master) { - int maxPwr = std::numeric_limits::min(); - int minPwr = std::numeric_limits::max(); - int maxGnd = std::numeric_limits::min(); - int minGnd = std::numeric_limits::max(); + odb::Rect bbox; + master->getPlacementBoundary(bbox); + const int y_cell_bot = bbox.yMin(); + const int y_cell_top = bbox.yMax(); + + bool bot_has_pwr = false; + bool bot_has_gnd = false; + bool top_has_pwr = false; + bool top_has_gnd = false; - bool isVdd = false; - bool isGnd = false; for (odb::dbMTerm* mterm : master->getMTerms()) { - if (mterm->getSigType() == odb::dbSigType::POWER) { - isVdd = true; - for (odb::dbMPin* mpin : mterm->getMPins()) { - // Geometry or box? - const int y = mpin->getBBox().yCenter(); - minPwr = std::min(minPwr, y); - maxPwr = std::max(maxPwr, y); - } - } else if (mterm->getSigType() == odb::dbSigType::GROUND) { - isGnd = true; - for (odb::dbMPin* mpin : mterm->getMPins()) { - // Geometry or box? - const int y = mpin->getBBox().yCenter(); - minGnd = std::min(minGnd, y); - maxGnd = std::max(maxGnd, y); + const odb::dbSigType st = mterm->getSigType(); + const bool is_pwr = (st == odb::dbSigType::POWER); + const bool is_gnd = (st == odb::dbSigType::GROUND); + if (!is_pwr && !is_gnd) { + continue; + } + for (odb::dbMPin* mpin : mterm->getMPins()) { + for (odb::dbBox* box : mpin->getGeometry()) { + auto* layer = box->getTechLayer(); + if (layer == nullptr + || layer->getType() != odb::dbTechLayerType::ROUTING) { + continue; // Skip wells/implants/cut layers. + } + const odb::Rect rect = box->getBox(); + if (rect.yMin() <= y_cell_bot) { + (is_pwr ? bot_has_pwr : bot_has_gnd) = true; + } + if (rect.yMax() >= y_cell_top) { + (is_pwr ? top_has_pwr : top_has_gnd) = true; + } } } } - int topPwr = Architecture::Row::Power_UNK; - int botPwr = Architecture::Row::Power_UNK; - if (isVdd && isGnd) { - topPwr = (maxPwr > maxGnd) ? Architecture::Row::Power_VDD - : Architecture::Row::Power_VSS; - botPwr = (minPwr < minGnd) ? Architecture::Row::Power_VDD - : Architecture::Row::Power_VSS; - } - return {topPwr, botPwr}; + + const auto resolve = [](bool has_pwr, bool has_gnd) { + if (has_pwr && !has_gnd) { + return Architecture::Row::Power_VDD; + } + if (has_gnd && !has_pwr) { + return Architecture::Row::Power_VSS; + } + return Architecture::Row::Power_UNK; + }; + return {resolve(top_has_pwr, top_has_gnd), resolve(bot_has_pwr, bot_has_gnd)}; } } // namespace From f488e22c1fb1f10aeb94d5345544e313a5184088 Mon Sep 17 00:00:00 2001 From: Augusto Berndt Date: Wed, 10 Jun 2026 13:39:58 +0000 Subject: [PATCH 2/4] dpl: rename variables for clarity Signed-off-by: Augusto Berndt --- src/dpl/src/infrastructure/network.cxx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/dpl/src/infrastructure/network.cxx b/src/dpl/src/infrastructure/network.cxx index c5f10614902..4e6a890bb0f 100644 --- a/src/dpl/src/infrastructure/network.cxx +++ b/src/dpl/src/infrastructure/network.cxx @@ -285,17 +285,17 @@ std::pair getMasterPwrs(odb::dbMaster* master) continue; } for (odb::dbMPin* mpin : mterm->getMPins()) { - for (odb::dbBox* box : mpin->getGeometry()) { - auto* layer = box->getTechLayer(); + for (odb::dbBox* pin_box : mpin->getGeometry()) { + auto* layer = pin_box->getTechLayer(); if (layer == nullptr || layer->getType() != odb::dbTechLayerType::ROUTING) { continue; // Skip wells/implants/cut layers. } - const odb::Rect rect = box->getBox(); - if (rect.yMin() <= y_cell_bot) { + const odb::Rect pin_rect = pin_box->getBox(); + if (pin_rect.yMin() <= y_cell_bot) { (is_pwr ? bot_has_pwr : bot_has_gnd) = true; } - if (rect.yMax() >= y_cell_top) { + if (pin_rect.yMax() >= y_cell_top) { (is_pwr ? top_has_pwr : top_has_gnd) = true; } } @@ -311,7 +311,11 @@ std::pair getMasterPwrs(odb::dbMaster* master) } return Architecture::Row::Power_UNK; }; - return {resolve(top_has_pwr, top_has_gnd), resolve(bot_has_pwr, bot_has_gnd)}; + const int topPwr = resolve(top_has_pwr, top_has_gnd); + const int botPwr = resolve(bot_has_pwr, bot_has_gnd); + std::cout << master->getConstName() << ", height: " << master->getHeight() + << ", return: topPwr:" << topPwr << " botPwr:" << botPwr << "\n"; + return {topPwr, botPwr}; } } // namespace From 19ffe4fc9dd4181bc06d0b0bc630d5b452f9756b Mon Sep 17 00:00:00 2001 From: Augusto Berndt Date: Wed, 10 Jun 2026 13:44:25 +0000 Subject: [PATCH 3/4] dpl: remove accidental debug messages Signed-off-by: Augusto Berndt --- src/dpl/src/infrastructure/network.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dpl/src/infrastructure/network.cxx b/src/dpl/src/infrastructure/network.cxx index 4e6a890bb0f..393a0d18fd6 100644 --- a/src/dpl/src/infrastructure/network.cxx +++ b/src/dpl/src/infrastructure/network.cxx @@ -256,7 +256,7 @@ odb::Rect getBoundarySegment(const odb::Rect& bbox, return segment; } -// Returns (topPwr, botPwr) for the master's rails. Power_UNK when an edge +// Returns (top_pwr, bot_pwr) for the master's rails. Power_UNK when an edge // has no rail, or when POWER and GROUND both touch it. // // Each MPin rectangle is tested individually, since a single MPin can hold @@ -311,11 +311,11 @@ std::pair getMasterPwrs(odb::dbMaster* master) } return Architecture::Row::Power_UNK; }; - const int topPwr = resolve(top_has_pwr, top_has_gnd); - const int botPwr = resolve(bot_has_pwr, bot_has_gnd); - std::cout << master->getConstName() << ", height: " << master->getHeight() - << ", return: topPwr:" << topPwr << " botPwr:" << botPwr << "\n"; - return {topPwr, botPwr}; + const int top_pwr = resolve(top_has_pwr, top_has_gnd); + const int bot_pwr = resolve(bot_has_pwr, bot_has_gnd); + // std::cout << master->getConstName() << ", height: " << master->getHeight() + // << ", return: top_pwr:" << top_pwr << " bot_pwr:" << bot_pwr << "\n"; + return {top_pwr, bot_pwr}; } } // namespace From 2136357c158a2d06918ce6649d81a2432ee4234a Mon Sep 17 00:00:00 2001 From: Augusto Berndt Date: Thu, 11 Jun 2026 20:40:20 +0000 Subject: [PATCH 4/4] dpl: fix commet typo Signed-off-by: Augusto Berndt --- src/dpl/src/infrastructure/network.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dpl/src/infrastructure/network.cxx b/src/dpl/src/infrastructure/network.cxx index 393a0d18fd6..01f56b6d0ba 100644 --- a/src/dpl/src/infrastructure/network.cxx +++ b/src/dpl/src/infrastructure/network.cxx @@ -263,8 +263,8 @@ odb::Rect getBoundarySegment(const odb::Rect& bbox, // rails on both edges (e.g. double-height cells with VSS at top and bottom) // or include internal straps that would pull a per-pin bbox center off the // rail. Only ROUTING-layer geometry counts, to ignore NWELL/PWELL implants -// encoded as POWER/GROUND pins on MASTERSLICE layers. -// layers) from polluting the rail detection. +// (encoded as POWER/GROUND pins on MASTERSLICE layers) from polluting the +// rail detection. std::pair getMasterPwrs(odb::dbMaster* master) { odb::Rect bbox;