Skip to content

Commit

Permalink
Merge pull request The-OpenROAD-Project#4958 from The-OpenROAD-Projec…
Browse files Browse the repository at this point in the history
…t-staging/drt-enclosure

Support LEF58_ENCLOSURE
  • Loading branch information
maliberty authored Apr 17, 2024
2 parents 7c6ac49 + ce3e573 commit fe7f4aa
Show file tree
Hide file tree
Showing 19 changed files with 416 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/drt/src/db/tech/frConstraint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ std::string frConstraint::getViolName() const
return "TwoWiresForbiddenSpc";
case frConstraintTypeEnum::frcLef58ForbiddenSpcConstraint:
return "ForbiddenSpc";
case frConstraintTypeEnum::frcLef58EnclosureConstraint:
return "Lef58Enclosure";
}
return "";
}
Expand Down
38 changes: 38 additions & 0 deletions src/drt/src/db/tech/frConstraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -2223,6 +2223,44 @@ class frLef58KeepOutZoneConstraint : public frConstraint
private:
odb::dbTechLayerKeepOutZoneRule* db_rule_;
};

class frLef58EnclosureConstraint : public frConstraint
{
public:
frLef58EnclosureConstraint(odb::dbTechLayerCutEnclosureRule* ruleIn)
: db_rule_(ruleIn)
{
}
void setCutClassIdx(int in) { cut_class_idx_ = in; }
int getCutClassIdx() const { return cut_class_idx_; }
bool isAboveOnly() const { return db_rule_->isAbove(); }
bool isBelowOnly() const { return db_rule_->isBelow(); }
bool isValidOverhang(frCoord endOverhang, frCoord sideOverhang) const
{
if (db_rule_->getType() == odb::dbTechLayerCutEnclosureRule::ENDSIDE) {
return endOverhang >= db_rule_->getFirstOverhang()
&& sideOverhang >= db_rule_->getSecondOverhang();
}
return (endOverhang >= db_rule_->getFirstOverhang()
&& sideOverhang >= db_rule_->getSecondOverhang())
|| (endOverhang >= db_rule_->getSecondOverhang()
&& sideOverhang >= db_rule_->getFirstOverhang());
}
frCoord getWidth() const { return db_rule_->getMinWidth(); }
void report(utl::Logger* logger) const override
{
logger->report("LEF58_ENCLOSURE");
}
frConstraintTypeEnum typeId() const override
{
return frConstraintTypeEnum::frcLef58EnclosureConstraint;
}

private:
odb::dbTechLayerCutEnclosureRule* db_rule_;
int cut_class_idx_;
};

class frNonDefaultRule
{
public:
Expand Down
54 changes: 54 additions & 0 deletions src/drt/src/db/tech/frLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,56 @@ class frLayer
return lef58DefaultInterCutSpacingTableConstraint_;
}

void addLef58EnclosureConstraint(frLef58EnclosureConstraint* con)
{
auto addToLef58EncConstraints
= [](std::vector<
std::map<frCoord, std::vector<frLef58EnclosureConstraint*>>>&
lef58EncConstraints,
frLef58EnclosureConstraint* con) {
int cutClassIdx = con->getCutClassIdx();
if (lef58EncConstraints.size() <= cutClassIdx) {
lef58EncConstraints.resize(cutClassIdx + 1);
}
lef58EncConstraints[cutClassIdx][con->getWidth()].push_back(con);
};
if (!con->isAboveOnly()) {
addToLef58EncConstraints(belowLef58EncConstraints_, con);
}
if (!con->isBelowOnly()) {
addToLef58EncConstraints(aboveLef58EncConstraints_, con);
}
}

bool hasLef58EnclosureConstraint(int cutClassIdx, bool above) const
{
auto& lef58EncConstraints
= above ? aboveLef58EncConstraints_ : belowLef58EncConstraints_;
if (cutClassIdx < 0 || lef58EncConstraints.size() <= cutClassIdx) {
return false;
}
return !lef58EncConstraints.at(cutClassIdx).empty();
}

std::vector<frLef58EnclosureConstraint*>
getLef58EnclosureConstraints(int cutClassIdx, frCoord width, bool above) const
{
// initialize with empty vector
std::vector<frLef58EnclosureConstraint*> result;
// check class and size match first
if (hasLef58EnclosureConstraint(cutClassIdx, above)) {
auto& lef58EncConstraints
= above ? aboveLef58EncConstraints_ : belowLef58EncConstraints_;
const auto& mmap = lef58EncConstraints.at(cutClassIdx);
auto it = mmap.upper_bound(width);
if (it != mmap.begin()) {
it--;
result = it->second;
}
}
return result;
}

void setDrEolSpacingConstraint(frCoord width, frCoord space, frCoord within)
{
drEolCon_.eolWidth = width;
Expand Down Expand Up @@ -812,6 +862,10 @@ class frLayer
std::vector<frLef58TwoWiresForbiddenSpcConstraint*>
twForbiddenSpcConstraints_;
std::vector<frLef58ForbiddenSpcConstraint*> forbiddenSpcConstraints_;
std::vector<std::map<frCoord, std::vector<frLef58EnclosureConstraint*>>>
aboveLef58EncConstraints_;
std::vector<std::map<frCoord, std::vector<frLef58EnclosureConstraint*>>>
belowLef58EncConstraints_;
drEolSpacingConstraint drEolCon_;

friend class io::Parser;
Expand Down
2 changes: 2 additions & 0 deletions src/drt/src/frBaseTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ std::ostream& operator<<(std::ostream& os, frConstraintTypeEnum type)
return os << "frcLef58TwoWiresForbiddenSpcConstraint";
case frConstraintTypeEnum::frcLef58ForbiddenSpcConstraint:
return os << "frcLef58ForbiddenSpcConstraint";
case frConstraintTypeEnum::frcLef58EnclosureConstraint:
return os << "frcLef58EnclosureConstraint";
}
return os << "Bad frConstraintTypeEnum";
}
Expand Down
1 change: 1 addition & 0 deletions src/drt/src/frBaseTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ enum class frConstraintTypeEnum
frcLef58KeepOutZoneConstraint,
frcLef58TwoWiresForbiddenSpcConstraint,
frcLef58ForbiddenSpcConstraint,
frcLef58EnclosureConstraint,
frcSpacingRangeConstraint
};

Expand Down
97 changes: 97 additions & 0 deletions src/drt/src/gc/FlexGC_cut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,4 +691,101 @@ void FlexGCWorker::Impl::checkMetalWidthViaTable()
}
}

void FlexGCWorker::Impl::checkLef58Enclosure_main(gcRect* viaRect,
gcRect* encRect)
{
auto layer = getTech()->getLayer(viaRect->getLayerNum());
auto cutClassIdx = layer->getCutClassIdx(viaRect->width(), viaRect->length());
bool above = encRect->getLayerNum() > viaRect->getLayerNum();
frCoord sideOverhang = 0;
frCoord endOverhang = 0;
sideOverhang = std::min(gtl::xh(*encRect) - gtl::xh(*viaRect),
gtl::xl(*viaRect) - gtl::xl(*encRect));
endOverhang = std::min(gtl::yh(*encRect) - gtl::yh(*viaRect),
gtl::yl(*viaRect) - gtl::yl(*encRect));
if (gtl::delta(*viaRect, gtl::orientation_2d_enum::HORIZONTAL)
> gtl::delta(*viaRect, gtl::orientation_2d_enum::VERTICAL)) {
std::swap(sideOverhang, endOverhang);
}
frLef58EnclosureConstraint* lastCon = nullptr;
for (auto con : layer->getLef58EnclosureConstraints(
cutClassIdx, encRect->width(), above)) {
lastCon = con;
if (con->isValidOverhang(endOverhang, sideOverhang)) {
return; // valid overhangs
}
}
Rect markerBox(gtl::xl(*viaRect),
gtl::yl(*viaRect),
gtl::xh(*viaRect),
gtl::yh(*viaRect));
auto net = viaRect->getNet();
auto marker = std::make_unique<frMarker>();
marker->setBBox(markerBox);
marker->setLayerNum(encRect->getLayerNum());
marker->setConstraint(lastCon);
marker->addSrc(net->getOwner());
frCoord llx = gtl::xl(*encRect);
frCoord lly = gtl::yl(*encRect);
frCoord urx = gtl::xh(*encRect);
frCoord ury = gtl::xh(*encRect);
marker->addAggressor(net->getOwner(),
std::make_tuple(encRect->getLayerNum(),
Rect(llx, lly, urx, ury),
encRect->isFixed()));
llx = gtl::xl(*viaRect);
lly = gtl::yl(*viaRect);
urx = gtl::xh(*viaRect);
ury = gtl::xh(*viaRect);
marker->addVictim(net->getOwner(),
std::make_tuple(viaRect->getLayerNum(),
Rect(llx, lly, urx, ury),
viaRect->isFixed()));
marker->addSrc(net->getOwner());
addMarker(std::move(marker));
}
void FlexGCWorker::Impl::checkLef58Enclosure_main(gcRect* rect)
{
if (rect->isFixed()) {
return;
}
auto layer = getTech()->getLayer(rect->getLayerNum());
auto cutClassIdx = layer->getCutClassIdx(rect->width(), rect->length());
bool hasAboveConstraints
= layer->hasLef58EnclosureConstraint(cutClassIdx, true);
bool hasBelowConstraints
= layer->hasLef58EnclosureConstraint(cutClassIdx, false);
if (!hasAboveConstraints && !hasBelowConstraints) {
return;
}
auto getEnclosure = [this](gcRect* rect, frLayerNum layerNum) {
std::vector<rq_box_value_t<gcRect*>> results;
auto& workerRegionQuery = getWorkerRegionQuery();
workerRegionQuery.queryMaxRectangle(*rect, layerNum, results);
gcRect* encRect = nullptr;
for (auto& [box, ptr] : results) {
if (ptr->getNet() != rect->getNet()) {
continue;
}
if (!gtl::contains(*ptr, *rect)) {
continue;
}
if (encRect == nullptr) {
encRect = ptr;
} else if (ptr->width() > encRect->width()) {
encRect = ptr;
}
}
return encRect;
};
if (hasBelowConstraints) {
gcRect* belowEnc = getEnclosure(rect, layer->getLayerNum() - 1);
checkLef58Enclosure_main(rect, belowEnc);
}
if (hasAboveConstraints) {
gcRect* aboveEnc = getEnclosure(rect, layer->getLayerNum() + 1);
checkLef58Enclosure_main(rect, aboveEnc);
}
}

} // namespace drt
3 changes: 3 additions & 0 deletions src/drt/src/gc/FlexGC_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,9 @@ class FlexGCWorker::Impl
bool checkLef58CutSpacing_spc_hasTwoCuts_helper(
gcRect* rect,
frLef58CutSpacingConstraint* con);
// LEF58_ENCLOSURE
void checkLef58Enclosure_main(gcRect* rect);
void checkLef58Enclosure_main(gcRect* via, gcRect* enc);
// LEF58_KEEPOUTZONE
void checKeepOutZone_main(gcRect* rect, frLef58KeepOutZoneConstraint* con);

Expand Down
4 changes: 3 additions & 1 deletion src/drt/src/gc/FlexGC_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3529,6 +3529,7 @@ void FlexGCWorker::Impl::checkCutSpacing()
for (auto& pin : targetNet_->getPins(i)) {
for (auto& maxrect : pin->getMaxRectangles()) {
checkCutSpacing_main(maxrect.get());
checkLef58Enclosure_main(maxrect.get());
}
}
}
Expand All @@ -3547,6 +3548,7 @@ void FlexGCWorker::Impl::checkCutSpacing()
for (auto& pin : net->getPins(i)) {
for (auto& maxrect : pin->getMaxRectangles()) {
checkCutSpacing_main(maxrect.get());
checkLef58Enclosure_main(maxrect.get());
}
}
}
Expand Down Expand Up @@ -4046,7 +4048,7 @@ int FlexGCWorker::Impl::main()
checkMetalShape(false);
// check eolSpc based on polygon
checkMetalEndOfLine();
// check CShort, cutSpc
// check CShort, cutSpc, enclosure
checkCutSpacing();
// check SpacingTable Influence
checkMetalSpacingTableInfluence();
Expand Down
92 changes: 92 additions & 0 deletions src/drt/src/io/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ void io::Parser::createNDR(odb::dbTechNonDefaultRule* ndr)
fnd->addViaRule(design_->getTech()->getViaRule(via->getName()), z);
}
}

void io::Parser::setNDRs(odb::dbDatabase* db)
{
for (auto ndr : db->getTech()->getNonDefaultRules()) {
Expand All @@ -459,6 +460,7 @@ void io::Parser::setNDRs(odb::dbDatabase* db)
layer->getLayerNum() / 2 - 1));
}
}

void io::Parser::getSBoxCoords(odb::dbSBox* box,
frCoord& beginX,
frCoord& beginY,
Expand Down Expand Up @@ -1862,6 +1864,95 @@ void io::Parser::setCutLayerProperties(odb::dbTechLayer* layer,
tech_->addUConstraint(std::move(uCon));
tmpLayer->addKeepOutZoneConstraint(rptr);
}
for (auto rule : layer->getTechLayerCutEnclosureRules()) {
if (rule->getType() == odb::dbTechLayerCutEnclosureRule::EOL) {
logger_->warn(
DRT,
340,
"LEF58_ENCLOSURE EOL is not supported. Skipping for layer {}",
layer->getName());
continue;
}
if (rule->getType() == odb::dbTechLayerCutEnclosureRule::HORZ_AND_VERT) {
logger_->warn(DRT,
341,
"LEF58_ENCLOSURE HORIZONTAL/VERTICAL is not supported. "
"Skipping for layer {}",
layer->getName());
continue;
}
if (rule->isIncludeAbutted()) {
logger_->warn(DRT,
342,
"LEF58_ENCLOSURE INCLUDEABUTTED is not supported. Skipping "
"for layer {}",
layer->getName());
continue;
}
if (rule->isOffCenterLine()) {
logger_->warn(DRT,
343,
"LEF58_ENCLOSURE OFFCENTERLINE is not supported. Skipping "
"for layer {}",
layer->getName());
continue;
}
if (rule->isLengthValid()) {
logger_->warn(
DRT,
344,
"LEF58_ENCLOSURE LENGTH is not supported. Skipping for layer {}",
layer->getName());
continue;
}
if (rule->isExtraCutValid()) {
logger_->warn(
DRT,
345,
"LEF58_ENCLOSURE EXTRACUT is not supported. Skipping for layer {}",
layer->getName());
continue;
}
if (rule->isRedundantCutValid()) {
logger_->warn(DRT,
346,
"LEF58_ENCLOSURE REDUNDANTCUT is not supported. Skipping "
"for layer {}",
layer->getName());
continue;
}
if (rule->isParallelValid()) {
logger_->warn(
DRT,
347,
"LEF58_ENCLOSURE PARALLEL is not supported. Skipping for layer {}",
layer->getName());
continue;
}
if (rule->isConcaveCornersValid()) {
logger_->warn(DRT,
348,
"LEF58_ENCLOSURE CONCAVECORNERS is not supported. Skipping "
"for layer {}",
layer->getName());
continue;
}
if (!rule->isCutClassValid()) {
logger_->warn(DRT,
349,
"LEF58_ENCLOSURE with no CUTCLASS is not supported. "
"Skipping for layer {}",
layer->getName());
continue;
}
std::unique_ptr<frConstraint> uCon
= std::make_unique<frLef58EnclosureConstraint>(rule);
auto rptr = static_cast<frLef58EnclosureConstraint*>(uCon.get());
rptr->setCutClassIdx(
tmpLayer->getCutClassIdx(rule->getCutClass()->getName()));
tech_->addUConstraint(std::move(uCon));
tmpLayer->addLef58EnclosureConstraint(rptr);
}
}

void io::Parser::addDefaultMasterSliceLayer()
Expand Down Expand Up @@ -3489,6 +3580,7 @@ void io::Writer::updateTrackAssignment(odb::dbBlock* block)
}
}
}

void io::Writer::updateDbAccessPoints(odb::dbBlock* block, odb::dbTech* db_tech)
{
for (auto ap : block->getAccessPoints()) {
Expand Down
Loading

0 comments on commit fe7f4aa

Please sign in to comment.