Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/dpl/src/Opendp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Opendp::Opendp(odb::dbDatabase* db, utl::Logger* logger)
grid_ = std::make_unique<Grid>();
grid_->init(logger);
network_ = std::make_unique<Network>();
network_->init(logger);
arch_ = std::make_unique<Architecture>();
}

Expand Down
91 changes: 61 additions & 30 deletions src/dpl/src/infrastructure/network.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "infrastructure/architecture.h"
#include "odb/db.h"
#include "odb/dbTypes.h"
#include "utl/Logger.h"
namespace dpl {

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -256,43 +257,64 @@ odb::Rect getBoundarySegment(const odb::Rect& bbox,
return segment;
}

// 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
// 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) from polluting the
// rail detection.
std::pair<int, int> getMasterPwrs(odb::dbMaster* master)
{
int maxPwr = std::numeric_limits<int>::min();
int minPwr = std::numeric_limits<int>::max();
int maxGnd = std::numeric_limits<int>::min();
int minGnd = std::numeric_limits<int>::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* 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 pin_rect = pin_box->getBox();
if (pin_rect.yMin() <= y_cell_bot) {
(is_pwr ? bot_has_pwr : bot_has_gnd) = true;
}
if (pin_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;
};
const int top_pwr = resolve(top_has_pwr, top_has_gnd);
const int bot_pwr = resolve(bot_has_pwr, bot_has_gnd);
return {top_pwr, bot_pwr};
}

} // namespace
Expand All @@ -318,6 +340,15 @@ Master* Network::addMaster(odb::dbMaster* db_master,
auto master_pwrs = getMasterPwrs(db_master);
master->setTopPowerType(master_pwrs.first);
master->setBottomPowerType(master_pwrs.second);
debugPrint(logger_,
utl::DPL,
"rail_align",
1,
"{}, height: {}, return: top_pwr:{} bot_pwr:{}",
db_master->getConstName(),
db_master->getHeight(),
master_pwrs.first,
master_pwrs.second);
master->clearEdges();
if (!drc_engine->hasCellEdgeSpacingTable()) {
return master;
Expand Down
6 changes: 6 additions & 0 deletions src/dpl/src/infrastructure/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ class dbBTerm;
class dbNet;
} // namespace odb

namespace utl {
class Logger;
} // namespace utl

namespace dpl {
class Master;
class Pin;
Expand All @@ -32,6 +36,7 @@ class PlacementDRC;
class Network
{
public:
void init(utl::Logger* logger) { logger_ = logger; }
std::vector<std::unique_ptr<Node>>& getNodes() { return nodes_; }
int getNumNodes() const { return (int) nodes_.size(); }
uint32_t getNumCells() const { return cells_cnt_; }
Expand Down Expand Up @@ -80,6 +85,7 @@ class Network
void connect(Pin* pin, Node* node);
void connect(Pin* pin, Edge* edge);

utl::Logger* logger_ = nullptr;
odb::Rect core_; // Core area of the design.
std::vector<std::unique_ptr<Master>> masters_;
std::vector<std::unique_ptr<Node>> nodes_; // The nodes in the netlist...
Expand Down
Loading