From dad5671fc54de150371591b9d4aabda793d1ca9f Mon Sep 17 00:00:00 2001 From: Osama Date: Sun, 28 Jan 2024 15:06:57 +0200 Subject: [PATCH 1/4] drt: unblock bterm needed edges & repair_pdn_layer layer range Signed-off-by: Osama --- src/drt/include/triton_route/TritonRoute.h | 3 +- src/drt/src/TritonRoute.cpp | 81 +++++++++++++++------- src/drt/src/TritonRoute.i | 6 +- src/drt/src/TritonRoute.tcl | 17 +++-- src/drt/src/dr/FlexDR_init.cpp | 20 +++++- src/drt/src/gc/FlexGC_cut.cpp | 8 ++- src/drt/src/gc/FlexGC_impl.h | 1 + src/drt/src/gc/FlexGC_main.cpp | 3 + src/drt/src/global.cpp | 6 +- src/drt/src/global.h | 6 +- 10 files changed, 109 insertions(+), 42 deletions(-) diff --git a/src/drt/include/triton_route/TritonRoute.h b/src/drt/include/triton_route/TritonRoute.h index d4a76e66920..375a0dccdba 100644 --- a/src/drt/include/triton_route/TritonRoute.h +++ b/src/drt/include/triton_route/TritonRoute.h @@ -94,7 +94,8 @@ struct ParamStruct bool singleStepDR = false; int minAccessPoints = -1; bool saveGuideUpdates = false; - std::string repairPDNLayerName; + std::string repairPDNLayerBeginName; + std::string repairPDNLayerEndName; }; class TritonRoute diff --git a/src/drt/src/TritonRoute.cpp b/src/drt/src/TritonRoute.cpp index de4de6cc9c7..3622d1b00d2 100644 --- a/src/drt/src/TritonRoute.cpp +++ b/src/drt/src/TritonRoute.cpp @@ -569,13 +569,22 @@ void TritonRoute::initDesign() } } - if (!REPAIR_PDN_LAYER_NAME.empty()) { - frLayer* layer = tech->getLayer(REPAIR_PDN_LAYER_NAME); + if (!REPAIR_PDN_LAYER_BEGIN_NAME.empty()) { + frLayer* layer = tech->getLayer(REPAIR_PDN_LAYER_BEGIN_NAME); if (layer) { - GC_IGNORE_PDN_LAYER = layer->getLayerNum(); + GC_IGNORE_PDN_BEGIN_LAYER = layer->getLayerNum(); + } else { + logger_->warn(utl::DRT, + 617, + "PDN layer {} not found.", + REPAIR_PDN_LAYER_BEGIN_NAME); + } + layer = tech->getLayer(REPAIR_PDN_LAYER_END_NAME); + if (layer) { + GC_IGNORE_PDN_END_LAYER = layer->getLayerNum(); } else { logger_->warn( - utl::DRT, 617, "PDN layer {} not found.", REPAIR_PDN_LAYER_NAME); + utl::DRT, 619, "PDN layer {} not found.", REPAIR_PDN_LAYER_END_NAME); } } parser.postProcess(); @@ -651,13 +660,15 @@ void TritonRoute::endFR() writer.updateTrackAssignment(db_->getChip()->getBlock()); num_drvs_ = design_->getTopBlock()->getNumMarkers(); - if (!REPAIR_PDN_LAYER_NAME.empty()) { + if (!REPAIR_PDN_LAYER_BEGIN_NAME.empty()) { auto dbBlock = db_->getChip()->getBlock(); - auto pdnLayer = design_->getTech()->getLayer(REPAIR_PDN_LAYER_NAME); - frLayerNum pdnLayerNum = pdnLayer->getLayerNum(); + auto pdnBeginLayer + = design_->getTech()->getLayer(REPAIR_PDN_LAYER_BEGIN_NAME); + auto pdnEndLayer = design_->getTech()->getLayer(REPAIR_PDN_LAYER_END_NAME); frList> markers; auto blockBox = design_->getTopBlock()->getBBox(); - GC_IGNORE_PDN_LAYER = -1; + GC_IGNORE_PDN_BEGIN_LAYER = -1; + GC_IGNORE_PDN_END_LAYER = -1; getDRCMarkers(markers, blockBox); std::vector>> allWires; for (auto* net : dbBlock->getNets()) { @@ -665,27 +676,34 @@ void TritonRoute::endFR() continue; for (auto* swire : net->getSWires()) { for (auto* wire : swire->getWires()) { - if (!wire->isVia()) { - continue; - } - // - std::vector via_boxes; - wire->getViaBoxes(via_boxes); - for (const auto& via_box : via_boxes) { - auto* layer = via_box.getTechLayer(); - if (layer->getType() != odb::dbTechLayerType::CUT) - continue; - if (layer->getName() != pdnLayer->getName()) + if (wire->isVia()) { + std::vector via_boxes; + wire->getViaBoxes(via_boxes); + for (const auto& via_box : via_boxes) { + auto* layer = getDesign()->getTech()->getLayer( + via_box.getTechLayer()->getName()); + if (layer->getLayerNum() < pdnBeginLayer->getLayerNum() + || layer->getLayerNum() > pdnEndLayer->getLayerNum()) + continue; + allWires.push_back({via_box.getBox(), wire->getId()}); + } + } else { + auto layer = getDesign()->getTech()->getLayer( + wire->getTechLayer()->getName()); + if (layer->getLayerNum() < pdnBeginLayer->getLayerNum() + || layer->getLayerNum() > pdnEndLayer->getLayerNum()) continue; - allWires.push_back({via_box.getBox(), wire->getId()}); + allWires.push_back({wire->getBox(), wire->getId()}); } } } } RTree> pdnTree(allWires); std::set> removedBoxes; + int cnt = 0; for (const auto& marker : markers) { - if (marker->getLayerNum() != pdnLayerNum) + if (marker->getLayerNum() < pdnBeginLayer->getLayerNum() + || marker->getLayerNum() > pdnEndLayer->getLayerNum()) continue; bool supply = false; for (auto src : marker->getSrcs()) { @@ -708,13 +726,22 @@ void TritonRoute::endFR() if (removedBoxes.find(bid) == removedBoxes.end()) { removedBoxes.insert(bid); auto boxPtr = odb::dbSBox::getSBox(dbBlock, bid); + std::vector>> subResults; + pdnTree.query(bgi::intersects(boxPtr->getBox()), + back_inserter(subResults)); odb::dbSBox::destroy(boxPtr); + cnt++; + for (auto& [subRect, subBid] : subResults) { + if (removedBoxes.find(subBid) == removedBoxes.end()) { + removedBoxes.insert(subBid); + auto subBoxPtr = odb::dbSBox::getSBox(dbBlock, subBid); + odb::dbSBox::destroy(subBoxPtr); + } + } } } } - logger_->report("Removed {} pdn vias on layer {}", - removedBoxes.size(), - pdnLayer->getName()); + logger_->report("Removed {} pdn vias", cnt); } } @@ -1013,7 +1040,8 @@ void TritonRoute::getDRCMarkers(frList>& markers, void TritonRoute::checkDRC(const char* filename, int x1, int y1, int x2, int y2) { - GC_IGNORE_PDN_LAYER = -1; + GC_IGNORE_PDN_BEGIN_LAYER = -1; + GC_IGNORE_PDN_END_LAYER = -1; initDesign(); auto gcellGrid = db_->getChip()->getBlock()->getGCellGrid(); if (gcellGrid != nullptr && gcellGrid->getNumGridPatternsX() == 1 @@ -1247,7 +1275,8 @@ void TritonRoute::setParams(const ParamStruct& params) MINNUMACCESSPOINT_MACROCELLPIN = params.minAccessPoints; } SAVE_GUIDE_UPDATES = params.saveGuideUpdates; - REPAIR_PDN_LAYER_NAME = params.repairPDNLayerName; + REPAIR_PDN_LAYER_BEGIN_NAME = params.repairPDNLayerBeginName; + REPAIR_PDN_LAYER_END_NAME = params.repairPDNLayerEndName; } void TritonRoute::addWorkerResults( diff --git a/src/drt/src/TritonRoute.i b/src/drt/src/TritonRoute.i index 67c94f43f80..b319d759419 100644 --- a/src/drt/src/TritonRoute.i +++ b/src/drt/src/TritonRoute.i @@ -94,7 +94,8 @@ void detailed_route_cmd(const char* outputMazeFile, bool singleStepDR, int minAccessPoints, bool saveGuideUpdates, - const char* repairPDNLayerName, + const char* repairPDNLayerBeginName, + const char* repairPDNLayerEndName, int drcReportIterStep) { auto* router = ord::OpenRoad::openRoad()->getTritonRoute(); @@ -122,7 +123,8 @@ void detailed_route_cmd(const char* outputMazeFile, singleStepDR, minAccessPoints, saveGuideUpdates, - repairPDNLayerName}); + repairPDNLayerBeginName, + repairPDNLayerEndName}); router->main(); router->setDistributed(false); } diff --git a/src/drt/src/TritonRoute.tcl b/src/drt/src/TritonRoute.tcl index fa6ca6fb31e..9b53251a350 100644 --- a/src/drt/src/TritonRoute.tcl +++ b/src/drt/src/TritonRoute.tcl @@ -58,7 +58,7 @@ sta::define_cmd_args "detailed_route" { [-no_pin_access] [-min_access_points count] [-save_guide_updates] - [-repair_pdn_vias layer] + [-repair_pdn_vias begin_layer end_layer] } proc detailed_route { args } { @@ -79,11 +79,18 @@ proc detailed_route { args } { set single_step_dr [expr [info exists flags(-single_step_dr)]] set save_guide_updates [expr [info exists flags(-save_guide_updates)]] - if { [info exists keys(-repair_pdn_vias)] } { - set repair_pdn_vias $keys(-repair_pdn_vias) + if {[info exists keys(-repair_pdn_vias)]} { + set repair_pdn_vias $keys(-repair_pdn_vias) + if {[llength $repair_pdn_vias] != 2} { + utl::error DRT 556 "-repair_pdn_vias should be a list of 2 layers; the begin via layer and end via layer" + } else { + lassign $keys(-repair_pdn_vias) repair_pdn_vias_begin repair_pdn_vias_end + } } else { - set repair_pdn_vias "" + set repair_pdn_vias_begin "" + set repair_pdn_vias_end "" } + if { [info exists keys(-output_maze)] } { set output_maze $keys(-output_maze) } else { @@ -195,7 +202,7 @@ proc detailed_route { args } { $via_in_pin_bottom_layer $via_in_pin_top_layer \ $or_seed $or_k $bottom_routing_layer $top_routing_layer $verbose \ $clean_patches $no_pin_access $single_step_dr $min_access_points \ - $save_guide_updates $repair_pdn_vias $drc_report_iter_step + $save_guide_updates $repair_pdn_vias_begin $repair_pdn_vias_end $drc_report_iter_step } proc detailed_route_num_drvs { args } { diff --git a/src/drt/src/dr/FlexDR_init.cpp b/src/drt/src/dr/FlexDR_init.cpp index d9fd4fd0be2..e2b27dd9ea1 100644 --- a/src/drt/src/dr/FlexDR_init.cpp +++ b/src/drt/src/dr/FlexDR_init.cpp @@ -3087,6 +3087,22 @@ void FlexDRWorker::initMazeCost_planarTerm(const frDesign* design) // term no bloat switch (obj->typeId()) { case frcBTerm: { + auto bterm = static_cast(obj); + bool hasHorizontalAccess = false; + bool hasVerticalAccess = false; + for (const auto& pin : bterm->getPins()) { + for (int i = 0; i < pin->getNumPinAccess(); i++) { + const auto& pa = pin->getPinAccess(i); + for (const auto& ap : pa->getAccessPoints()) { + if (ap->getLayerNum() != layerNum) + continue; + hasVerticalAccess |= ap->hasAccess(frDirEnum::N); + hasVerticalAccess |= ap->hasAccess(frDirEnum::S); + hasHorizontalAccess |= ap->hasAccess(frDirEnum::W); + hasHorizontalAccess |= ap->hasAccess(frDirEnum::E); + } + } + } FlexMazeIdx mIdx1, mIdx2; gridGraph_.getIdxBox(mIdx1, mIdx2, box); const bool isLayerHorz = layer->isHorizontal(); @@ -3095,10 +3111,10 @@ void FlexDRWorker::initMazeCost_planarTerm(const frDesign* design) FlexMazeIdx mIdx(i, j, zIdx); gridGraph_.setBlocked(i, j, zIdx, frDirEnum::U); gridGraph_.setBlocked(i, j, zIdx, frDirEnum::D); - if (isLayerHorz) { + if (isLayerHorz && hasHorizontalAccess) { gridGraph_.setBlocked(i, j, zIdx, frDirEnum::N); gridGraph_.setBlocked(i, j, zIdx, frDirEnum::S); - } else { + } else if (!isLayerHorz && hasVerticalAccess) { gridGraph_.setBlocked(i, j, zIdx, frDirEnum::W); gridGraph_.setBlocked(i, j, zIdx, frDirEnum::E); } diff --git a/src/drt/src/gc/FlexGC_cut.cpp b/src/drt/src/gc/FlexGC_cut.cpp index 4bcf9d5524c..9b250a02d3a 100644 --- a/src/drt/src/gc/FlexGC_cut.cpp +++ b/src/drt/src/gc/FlexGC_cut.cpp @@ -354,9 +354,10 @@ void FlexGCWorker::Impl::checkLef58CutSpacingTbl_main( } } -inline bool isSkipVia(gcRect* rect) +bool FlexGCWorker::Impl::isSkipVia(gcRect* rect) { - return rect->getLayerNum() == GC_IGNORE_PDN_LAYER && rect->isFixed() + return rect->getLayerNum() >= GC_IGNORE_PDN_BEGIN_LAYER + && rect->getLayerNum() <= GC_IGNORE_PDN_END_LAYER && rect->isFixed() && rect->hasNet() && rect->getNet()->getFrNet() && rect->getNet()->getFrNet()->getType().isSupply(); } @@ -414,12 +415,15 @@ void FlexGCWorker::Impl::checkLef58CutSpacingTbl( continue; if (isSkipVia(ptr)) continue; + queryLayerNum = layerNum1; + if (isUpperVia) checkLef58CutSpacingTbl_main(viaRect, ptr, con); else checkLef58CutSpacingTbl_main(ptr, viaRect, con); } } + void FlexGCWorker::Impl::checKeepOutZone_main(gcRect* rect, frLef58KeepOutZoneConstraint* con) { diff --git a/src/drt/src/gc/FlexGC_impl.h b/src/drt/src/gc/FlexGC_impl.h index a52e1c7c3a8..45b69d964b7 100644 --- a/src/drt/src/gc/FlexGC_impl.h +++ b/src/drt/src/gc/FlexGC_impl.h @@ -534,5 +534,6 @@ class FlexGCWorker::Impl const gtl::rectangle_data& rect); bool isOppositeDir(gcCorner* corner, gcSegment* seg); bool isWrongDir(gcSegment* edge); + bool isSkipVia(gcRect* rect); }; } // namespace fr diff --git a/src/drt/src/gc/FlexGC_main.cpp b/src/drt/src/gc/FlexGC_main.cpp index f4d8ae5b5bb..d91bb410f89 100644 --- a/src/drt/src/gc/FlexGC_main.cpp +++ b/src/drt/src/gc/FlexGC_main.cpp @@ -785,6 +785,9 @@ void FlexGCWorker::Impl::checkMetalSpacing_main(gcRect* ptr1, if (ptr1 == ptr2) { return; } + if (isSkipVia(ptr1) || isSkipVia(ptr2)) { + return; + } gtl::rectangle_data markerRect(*ptr1); auto distX = gtl::euclidean_distance(markerRect, *ptr2, gtl::HORIZONTAL); auto distY = gtl::euclidean_distance(markerRect, *ptr2, gtl::VERTICAL); diff --git a/src/drt/src/global.cpp b/src/drt/src/global.cpp index c6cbdfd7242..d40cf88fe11 100644 --- a/src/drt/src/global.cpp +++ b/src/drt/src/global.cpp @@ -112,8 +112,10 @@ int MISALIGNMENTCOST = 8; int CONGCOST = 8; int HISTCOST = 32; -std::string REPAIR_PDN_LAYER_NAME; -frLayerNum GC_IGNORE_PDN_LAYER = -1; +std::string REPAIR_PDN_LAYER_BEGIN_NAME; +std::string REPAIR_PDN_LAYER_END_NAME; +frLayerNum GC_IGNORE_PDN_BEGIN_LAYER = -1; +frLayerNum GC_IGNORE_PDN_END_LAYER = -1; namespace fr { std::ostream& operator<<(std::ostream& os, const frRect& pinFigIn) diff --git a/src/drt/src/global.h b/src/drt/src/global.h index 9540dd590a2..aa5beb5b615 100644 --- a/src/drt/src/global.h +++ b/src/drt/src/global.h @@ -111,8 +111,10 @@ extern int MISALIGNMENTCOST; extern int HISTCOST; extern int CONGCOST; -extern std::string REPAIR_PDN_LAYER_NAME; -extern fr::frLayerNum GC_IGNORE_PDN_LAYER; +extern std::string REPAIR_PDN_LAYER_BEGIN_NAME; +extern std::string REPAIR_PDN_LAYER_END_NAME; +extern fr::frLayerNum GC_IGNORE_PDN_BEGIN_LAYER; +extern fr::frLayerNum GC_IGNORE_PDN_END_LAYER; #define DIRBITSIZE 3 #define WAVEFRONTBUFFERSIZE 2 From 0f1232f3524e0be7d514e32ece84c47b931f63d4 Mon Sep 17 00:00:00 2001 From: Osama Date: Mon, 29 Jan 2024 20:13:10 +0200 Subject: [PATCH 2/4] drt: update defok Signed-off-by: Osama --- src/drt/test/ta_pin_aligned.defok | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/drt/test/ta_pin_aligned.defok b/src/drt/test/ta_pin_aligned.defok index f80d9ac14e5..d4e43f88e19 100644 --- a/src/drt/test/ta_pin_aligned.defok +++ b/src/drt/test/ta_pin_aligned.defok @@ -121,6 +121,9 @@ NETS 2 ; - Metal2_in ( PIN Metal2_out ) ( PIN Metal2_in ) + USE SIGNAL + ROUTED metal2 ( 97850 19740 0 ) ( * 180180 0 ) ; - Metal3_in ( PIN Metal3_out ) ( PIN Metal3_in ) + USE SIGNAL - + ROUTED metal3 ( 19790 97860 0 ) ( 180510 * 0 ) ; + + ROUTED metal3 ( 176400 97580 ) ( * 97860 ) + NEW metal3 ( 180510 97580 ) ( * 97860 0 ) + NEW metal3 ( 176400 97580 ) ( 180510 * ) + NEW metal3 ( 19790 97860 0 ) ( 176400 * ) ; END NETS END DESIGN From 3c4cb379012660e837d11039816d9c88188426c0 Mon Sep 17 00:00:00 2001 From: osamahammad21 Date: Mon, 22 Jul 2024 12:06:30 +0300 Subject: [PATCH 3/4] drt: undo repair_pdn_layer range Signed-off-by: osamahammad21 --- src/drt/include/triton_route/TritonRoute.h | 89 +-- src/drt/src/TritonRoute.cpp | 389 +++++----- src/drt/src/TritonRoute.i | 8 +- src/drt/src/TritonRoute.tcl | 92 +-- src/drt/src/gc/FlexGC_cut.cpp | 297 ++++++-- src/drt/src/gc/FlexGC_impl.h | 85 ++- src/drt/src/gc/FlexGC_main.cpp | 838 ++++++++++++--------- src/drt/src/global.cpp | 18 +- src/drt/src/global.h | 120 ++- 9 files changed, 1134 insertions(+), 802 deletions(-) diff --git a/src/drt/include/triton_route/TritonRoute.h b/src/drt/include/triton_route/TritonRoute.h index 375a0dccdba..7143ab525ed 100644 --- a/src/drt/include/triton_route/TritonRoute.h +++ b/src/drt/include/triton_route/TritonRoute.h @@ -40,17 +40,6 @@ #include #include "odb/geom.h" -namespace fr { -class frDesign; -class DesignCallBack; -class FlexDR; -class FlexDRWorker; -class drUpdate; -struct frDebugSettings; -class FlexDR; -struct FlexDRViaData; -class frMarker; -} // namespace fr namespace odb { class dbDatabase; @@ -58,19 +47,34 @@ class dbInst; class dbBTerm; class dbNet; } // namespace odb + namespace utl { class Logger; } + namespace gui { class Gui; } + namespace stt { class SteinerTreeBuilder; } + namespace dst { class Distributed; } -namespace triton_route { + +namespace drt { + +class frDesign; +class DesignCallBack; +class FlexDR; +class FlexDRWorker; +class drUpdate; +struct frDebugSettings; +class FlexDR; +struct FlexDRViaData; +class frMarker; struct ParamStruct { @@ -94,8 +98,7 @@ struct ParamStruct bool singleStepDR = false; int minAccessPoints = -1; bool saveGuideUpdates = false; - std::string repairPDNLayerBeginName; - std::string repairPDNLayerEndName; + std::string repairPDNLayerName; }; class TritonRoute @@ -109,11 +112,11 @@ class TritonRoute dst::Distributed* dist, stt::SteinerTreeBuilder* stt_builder); - fr::frDesign* getDesign() const { return design_.get(); } + frDesign* getDesign() const { return design_.get(); } int main(); void endFR(); - void pinAccess(std::vector target_insts + void pinAccess(const std::vector& target_insts = std::vector()); void stepDR(int size, int offset, @@ -158,17 +161,16 @@ class TritonRoute void setParams(const ParamStruct& params); void addUserSelectedVia(const std::string& viaName); void setUnidirectionalLayer(const std::string& layerName); - fr::frDebugSettings* getDebugSettings() const { return debug_.get(); } + frDebugSettings* getDebugSettings() const { return debug_.get(); } // This runs a serialized worker from file_name. It is intended // for debugging and not general usage. - std::string runDRWorker(const std::string& workerStr, - fr::FlexDRViaData* viaData); + std::string runDRWorker(const std::string& workerStr, FlexDRViaData* viaData); void debugSingleWorker(const std::string& dumpDir, const std::string& drcRpt); void updateGlobals(const char* file_name); void resetDb(const char* file_name); void clearDesign(); void updateDesign(const std::vector& updates); - void updateDesign(const std::string& updates); + void updateDesign(const std::string& path); void addWorkerResults( const std::vector>& results); bool getWorkerResults(std::vector>& results); @@ -179,40 +181,41 @@ class TritonRoute void sendGlobalsUpdates(const std::string& globals_path, const std::string& serializedViaData); void reportDRC(const std::string& file_name, - const std::list>& markers, - odb::Rect bbox = odb::Rect(0, 0, 0, 0)); - void checkDRC(const char* drc_file, int x0, int y0, int x1, int y1); + const std::list>& markers, + odb::Rect drcBox = odb::Rect(0, 0, 0, 0)); + void checkDRC(const char* filename, int x1, int y1, int x2, int y2); bool initGuide(); void prep(); void processBTermsAboveTopLayer(bool has_routing = false); + odb::dbDatabase* getDb() const { return db_; } private: - std::unique_ptr design_; - std::unique_ptr debug_; - std::unique_ptr db_callback_; - odb::dbDatabase* db_; - utl::Logger* logger_; - std::unique_ptr dr_; // kept for single stepping - stt::SteinerTreeBuilder* stt_builder_; - int num_drvs_; - gui::Gui* gui_; - dst::Distributed* dist_; - bool distributed_; + std::unique_ptr design_; + std::unique_ptr debug_; + std::unique_ptr db_callback_; + odb::dbDatabase* db_{nullptr}; + utl::Logger* logger_{nullptr}; + std::unique_ptr dr_; // kept for single stepping + stt::SteinerTreeBuilder* stt_builder_{nullptr}; + int num_drvs_{-1}; + gui::Gui* gui_{nullptr}; + dst::Distributed* dist_{nullptr}; + bool distributed_{false}; std::string dist_ip_; - unsigned short dist_port_; + uint16_t dist_port_{0}; std::string shared_volume_; std::vector> workers_results_; std::mutex results_mutex_; - int results_sz_; - unsigned int cloud_sz_; - boost::asio::thread_pool dist_pool_; + int results_sz_{0}; + unsigned int cloud_sz_{0}; + boost::asio::thread_pool dist_pool_{1}; void initDesign(); void gr(); void ta(); void dr(); - void applyUpdates(const std::vector>& updates); - void getDRCMarkers(std::list>& markers, + void applyUpdates(const std::vector>& updates); + void getDRCMarkers(std::list>& markers, const odb::Rect& requiredDrcBox); void stackVias(odb::dbBTerm* bterm, int top_layer_idx, @@ -220,6 +223,8 @@ class TritonRoute bool has_routing); int countNetBTermsAboveMaxLayer(odb::dbNet* net); bool netHasStackedVias(odb::dbNet* net); - friend class fr::FlexDR; + void repairPDNVias(); + friend class FlexDR; }; -} // namespace triton_route + +} // namespace drt diff --git a/src/drt/src/TritonRoute.cpp b/src/drt/src/TritonRoute.cpp index 3622d1b00d2..acaffe987ea 100644 --- a/src/drt/src/TritonRoute.cpp +++ b/src/drt/src/TritonRoute.cpp @@ -57,8 +57,6 @@ #include "sta/StaMain.hh" #include "stt/SteinerTreeBuilder.h" #include "ta/FlexTA.h" -using namespace fr; -using namespace triton_route; namespace sta { // Tcl files encoded into strings. @@ -69,26 +67,16 @@ extern "C" { extern int Drt_Init(Tcl_Interp* interp); } +namespace drt { + TritonRoute::TritonRoute() : debug_(std::make_unique()), db_callback_(std::make_unique(this)), - db_(nullptr), - logger_(nullptr), - stt_builder_(nullptr), - num_drvs_(-1), - gui_(gui::Gui::get()), - dist_(nullptr), - distributed_(false), - dist_port_(0), - results_sz_(0), - cloud_sz_(0), - dist_pool_(1) + gui_(gui::Gui::get()) { } -TritonRoute::~TritonRoute() -{ -} +TritonRoute::~TritonRoute() = default; void TritonRoute::setDebugDR(bool on) { @@ -187,8 +175,10 @@ RipUpMode getMode(int ripupMode) return RipUpMode::DRC; case 1: return RipUpMode::ALL; - default: + case 2: return RipUpMode::NEARDRC; + default: + return RipUpMode::INCR; } } @@ -230,8 +220,9 @@ std::string TritonRoute::runDRWorker(const std::string& workerStr, worker->setViaData(viaData); worker->setSharedVolume(shared_volume_); worker->setDebugSettings(debug_.get()); - if (graphics_) + if (graphics_) { graphics_->startIter(worker->getDRIter()); + } std::string result = worker->reloadedMain(); return result; } @@ -240,7 +231,7 @@ void TritonRoute::debugSingleWorker(const std::string& dumpDir, const std::string& drcRpt) { { - io::Writer writer(design_.get(), logger_); + io::Writer writer(this, logger_); writer.updateTrackAssignment(db_->getChip()->getBlock()); } bool on = debug_->debugDR; @@ -261,26 +252,33 @@ void TritonRoute::debugSingleWorker(const std::string& dumpDir, workerFile.close(); auto worker = FlexDRWorker::load(workerStr, logger_, design_.get(), graphics_.get()); - if (debug_->mazeEndIter != -1) + if (debug_->mazeEndIter != -1) { worker->setMazeEndIter(debug_->mazeEndIter); - if (debug_->markerCost != -1) + } + if (debug_->markerCost != -1) { worker->setMarkerCost(debug_->markerCost); - if (debug_->drcCost != -1) + } + if (debug_->drcCost != -1) { worker->setDrcCost(debug_->drcCost); - if (debug_->fixedShapeCost != -1) + } + if (debug_->fixedShapeCost != -1) { worker->setFixedShapeCost(debug_->fixedShapeCost); - if (debug_->markerDecay != -1) + } + if (debug_->markerDecay != -1) { worker->setMarkerDecay(debug_->markerDecay); + } if (debug_->ripupMode != -1) { worker->setRipupMode(getMode(debug_->ripupMode)); } - if (debug_->followGuide != -1) + if (debug_->followGuide != -1) { worker->setFollowGuide((debug_->followGuide == 1)); + } worker->setSharedVolume(shared_volume_); worker->setDebugSettings(debug_.get()); worker->setViaData(&viaData); - if (graphics_) + if (graphics_) { graphics_->startIter(worker->getDRIter()); + } std::string result = worker->reloadedMain(); bool updated = worker->end(design_.get()); debugPrint(logger_, @@ -290,16 +288,18 @@ void TritonRoute::debugSingleWorker(const std::string& dumpDir, "End number of markers {}. Updated={}", worker->getBestNumMarkers(), updated); - if (updated && !drcRpt.empty()) + if (updated && !drcRpt.empty()) { reportDRC( drcRpt, design_->getTopBlock()->getMarkers(), worker->getDrcBox()); + } } void TritonRoute::updateGlobals(const char* file_name) { std::ifstream file(file_name); - if (!file.good()) + if (!file.good()) { return; + } frIArchive ar(file); registerTypes(ar); serializeGlobals(ar); @@ -373,10 +373,11 @@ void TritonRoute::applyUpdates( auto regionQuery = design_->getRegionQuery(); const auto maxSz = updates[0].size(); for (int j = 0; j < maxSz; j++) { - for (int i = 0; i < updates.size(); i++) { - if (updates[i].size() <= j) + for (const auto& update_batch : updates) { + if (update_batch.size() <= j) { continue; - const auto& update = updates[i][j]; + } + const auto& update = update_batch[j]; switch (update.getType()) { case drUpdate::REMOVE_FROM_BLOCK: { auto id = update.getIndexInOwner(); @@ -394,22 +395,25 @@ void TritonRoute::applyUpdates( case frcPathSeg: { auto seg = static_cast(pinfig); regionQuery->removeDRObj(seg); - if (update.getType() == drUpdate::REMOVE_FROM_NET) + if (update.getType() == drUpdate::REMOVE_FROM_NET) { net->removeShape(seg); + } break; } case frcPatchWire: { auto pwire = static_cast(pinfig); regionQuery->removeDRObj(pwire); - if (update.getType() == drUpdate::REMOVE_FROM_NET) + if (update.getType() == drUpdate::REMOVE_FROM_NET) { net->removePatchWire(pwire); + } break; } case frcVia: { auto via = static_cast(pinfig); regionQuery->removeDRObj(via); - if (update.getType() == drUpdate::REMOVE_FROM_NET) + if (update.getType() == drUpdate::REMOVE_FROM_NET) { net->removeVia(via); + } break; } default: @@ -429,8 +433,9 @@ void TritonRoute::applyUpdates( = std::make_unique(seg); auto sptr = uShape.get(); net->addShape(std::move(uShape)); - if (update.getType() == drUpdate::ADD_SHAPE) + if (update.getType() == drUpdate::ADD_SHAPE) { regionQuery->addDRObj(sptr); + } break; } case frcPatchWire: { @@ -440,8 +445,9 @@ void TritonRoute::applyUpdates( = std::make_unique(pwire); auto sptr = uShape.get(); net->addPatchWire(std::move(uShape)); - if (update.getType() == drUpdate::ADD_SHAPE) + if (update.getType() == drUpdate::ADD_SHAPE) { regionQuery->addDRObj(sptr); + } break; } case frcVia: { @@ -450,8 +456,9 @@ void TritonRoute::applyUpdates( auto uVia = std::make_unique(via); auto sptr = uVia.get(); net->addVia(std::move(uVia)); - if (update.getType() == drUpdate::ADD_SHAPE) + if (update.getType() == drUpdate::ADD_SHAPE) { regionQuery->addDRObj(sptr); + } break; } default: { @@ -473,12 +480,13 @@ void TritonRoute::applyUpdates( std::vector> tmp; tmp.push_back(std::move(uSeg)); auto idx = update.getIndexInOwner(); - if (idx < 0 || idx >= net->getGuides().size()) + if (idx < 0 || idx >= net->getGuides().size()) { logger_->error(DRT, 9199, "Guide {} out of range {}", idx, net->getGuides().size()); + } const auto& guide = net->getGuides().at(idx); guide->setRoutes(tmp); break; @@ -535,11 +543,11 @@ bool TritonRoute::initGuide() } void TritonRoute::initDesign() { + io::Parser parser(db_, getDesign(), logger_); if (getDesign()->getTopBlock() != nullptr) { - getDesign()->getTopBlock()->removeDeletedInsts(); + parser.updateDesign(); return; } - io::Parser parser(db_, getDesign(), logger_); parser.readTechAndLibs(db_); processBTermsAboveTopLayer(); parser.readDesign(db_); @@ -569,28 +577,20 @@ void TritonRoute::initDesign() } } - if (!REPAIR_PDN_LAYER_BEGIN_NAME.empty()) { - frLayer* layer = tech->getLayer(REPAIR_PDN_LAYER_BEGIN_NAME); - if (layer) { - GC_IGNORE_PDN_BEGIN_LAYER = layer->getLayerNum(); - } else { - logger_->warn(utl::DRT, - 617, - "PDN layer {} not found.", - REPAIR_PDN_LAYER_BEGIN_NAME); - } - layer = tech->getLayer(REPAIR_PDN_LAYER_END_NAME); + if (!REPAIR_PDN_LAYER_NAME.empty()) { + frLayer* layer = tech->getLayer(REPAIR_PDN_LAYER_NAME); if (layer) { - GC_IGNORE_PDN_END_LAYER = layer->getLayerNum(); + GC_IGNORE_PDN_LAYER_NUM = layer->getLayerNum(); } else { logger_->warn( - utl::DRT, 619, "PDN layer {} not found.", REPAIR_PDN_LAYER_END_NAME); + utl::DRT, 617, "PDN layer {} not found.", REPAIR_PDN_LAYER_NAME); } } parser.postProcess(); if (db_ != nullptr && db_->getChip() != nullptr - && db_->getChip()->getBlock() != nullptr) + && db_->getChip()->getBlock() != nullptr) { db_callback_->addOwner(db_->getChip()->getBlock()); + } } void TritonRoute::prep() @@ -617,8 +617,9 @@ void TritonRoute::dr() num_drvs_ = -1; dr_ = std::make_unique(this, getDesign(), logger_, db_); dr_->setDebug(debug_.get()); - if (distributed_) + if (distributed_) { dr_->setDistributed(dist_, dist_ip_, dist_port_, shared_volume_); + } if (SINGLE_STEP_DR) { dr_->init(); } else { @@ -654,95 +655,133 @@ void TritonRoute::endFR() dr_->end(/* done */ true); } dr_.reset(); - io::Writer writer(getDesign(), logger_); + io::Writer writer(this, logger_); writer.updateDb(db_); - if (debug_->writeNetTracks) + if (debug_->writeNetTracks) { writer.updateTrackAssignment(db_->getChip()->getBlock()); + } num_drvs_ = design_->getTopBlock()->getNumMarkers(); - if (!REPAIR_PDN_LAYER_BEGIN_NAME.empty()) { - auto dbBlock = db_->getChip()->getBlock(); - auto pdnBeginLayer - = design_->getTech()->getLayer(REPAIR_PDN_LAYER_BEGIN_NAME); - auto pdnEndLayer = design_->getTech()->getLayer(REPAIR_PDN_LAYER_END_NAME); - frList> markers; - auto blockBox = design_->getTopBlock()->getBBox(); - GC_IGNORE_PDN_BEGIN_LAYER = -1; - GC_IGNORE_PDN_END_LAYER = -1; - getDRCMarkers(markers, blockBox); - std::vector>> allWires; - for (auto* net : dbBlock->getNets()) { - if (!net->getSigType().isSupply()) - continue; - for (auto* swire : net->getSWires()) { - for (auto* wire : swire->getWires()) { - if (wire->isVia()) { - std::vector via_boxes; - wire->getViaBoxes(via_boxes); - for (const auto& via_box : via_boxes) { - auto* layer = getDesign()->getTech()->getLayer( - via_box.getTechLayer()->getName()); - if (layer->getLayerNum() < pdnBeginLayer->getLayerNum() - || layer->getLayerNum() > pdnEndLayer->getLayerNum()) - continue; - allWires.push_back({via_box.getBox(), wire->getId()}); - } + + repairPDNVias(); +} + +void TritonRoute::repairPDNVias() +{ + if (REPAIR_PDN_LAYER_NAME.empty()) { + return; + } + + auto dbBlock = db_->getChip()->getBlock(); + auto pdnLayer = design_->getTech()->getLayer(REPAIR_PDN_LAYER_NAME); + frLayerNum pdnLayerNum = pdnLayer->getLayerNum(); + frList> markers; + auto blockBox = design_->getTopBlock()->getBBox(); + REPAIR_PDN_LAYER_NUM = pdnLayerNum; + GC_IGNORE_PDN_LAYER_NUM = -1; + getDRCMarkers(markers, blockBox); + markers.erase(std::remove_if(markers.begin(), + markers.end(), + [pdnLayerNum](const auto& marker) { + if (marker->getLayerNum() != pdnLayerNum) { + return true; + } + for (auto src : marker->getSrcs()) { + if (src->typeId() == frcNet) { + frNet* net = static_cast(src); + if (net->getType().isSupply()) { + return false; + } + } + } + return true; + }), + markers.end()); + + if (markers.empty()) { + // nothing to do + return; + } + + std::vector>> all_vias; + std::vector>> block_vias; + for (auto* net : dbBlock->getNets()) { + if (!net->getSigType().isSupply()) { + continue; + } + for (auto* swire : net->getSWires()) { + for (auto* wire : swire->getWires()) { + if (!wire->isVia()) { + continue; + } + // + std::vector via_boxes; + wire->getViaBoxes(via_boxes); + for (const auto& via_box : via_boxes) { + auto* layer = via_box.getTechLayer(); + if (layer != pdnLayer->getDbLayer()) { + continue; + } + + if (wire->getTechVia() != nullptr) { + all_vias.emplace_back(via_box.getBox(), wire->getId()); } else { - auto layer = getDesign()->getTech()->getLayer( - wire->getTechLayer()->getName()); - if (layer->getLayerNum() < pdnBeginLayer->getLayerNum() - || layer->getLayerNum() > pdnEndLayer->getLayerNum()) - continue; - allWires.push_back({wire->getBox(), wire->getId()}); + block_vias.emplace_back(via_box.getBox(), wire->getId()); } } } } - RTree> pdnTree(allWires); - std::set> removedBoxes; - int cnt = 0; - for (const auto& marker : markers) { - if (marker->getLayerNum() < pdnBeginLayer->getLayerNum() - || marker->getLayerNum() > pdnEndLayer->getLayerNum()) - continue; - bool supply = false; - for (auto src : marker->getSrcs()) { - if (src->typeId() == frcNet) { - frNet* net = static_cast(src); - if (net->getType().isSupply()) { - supply = true; - break; + } + + const RTree> pdnBlockViaTree(block_vias); + std::set> removedBoxes; + for (const auto& marker : markers) { + odb::Rect queryBox; + marker->getBBox().bloat(1, queryBox); + std::vector>> results; + pdnBlockViaTree.query(bgi::intersects(queryBox), back_inserter(results)); + for (auto& [rect, bid] : results) { + if (removedBoxes.find(bid) == removedBoxes.end()) { + removedBoxes.insert(bid); + auto boxPtr = odb::dbSBox::getSBox(dbBlock, bid); + + const auto new_vias = boxPtr->smashVia(); + for (auto* new_via : new_vias) { + std::vector via_boxes; + new_via->getViaBoxes(via_boxes); + for (const auto& via_box : via_boxes) { + auto* layer = via_box.getTechLayer(); + if (layer != pdnLayer->getDbLayer()) { + continue; + } + all_vias.emplace_back(via_box.getBox(), new_via->getId()); } } - } - if (!supply) - continue; - auto markerBox = marker->getBBox(); - odb::Rect queryBox; - markerBox.bloat(1, queryBox); - std::vector>> results; - pdnTree.query(bgi::intersects(queryBox), back_inserter(results)); - for (auto& [rect, bid] : results) { - if (removedBoxes.find(bid) == removedBoxes.end()) { - removedBoxes.insert(bid); - auto boxPtr = odb::dbSBox::getSBox(dbBlock, bid); - std::vector>> subResults; - pdnTree.query(bgi::intersects(boxPtr->getBox()), - back_inserter(subResults)); + + if (!new_vias.empty()) { odb::dbSBox::destroy(boxPtr); - cnt++; - for (auto& [subRect, subBid] : subResults) { - if (removedBoxes.find(subBid) == removedBoxes.end()) { - removedBoxes.insert(subBid); - auto subBoxPtr = odb::dbSBox::getSBox(dbBlock, subBid); - odb::dbSBox::destroy(subBoxPtr); - } - } } } } - logger_->report("Removed {} pdn vias", cnt); } + removedBoxes.clear(); + + const RTree> pdnTree(all_vias); + for (const auto& marker : markers) { + odb::Rect queryBox; + marker->getBBox().bloat(1, queryBox); + std::vector>> results; + pdnTree.query(bgi::intersects(queryBox), back_inserter(results)); + for (auto& [rect, bid] : results) { + if (removedBoxes.find(bid) == removedBoxes.end()) { + removedBoxes.insert(bid); + odb::dbSBox::destroy(odb::dbSBox::getSBox(dbBlock, bid)); + } + } + } + logger_->report("Removed {} pdn vias on layer {}", + removedBoxes.size(), + pdnLayer->getName()); } void TritonRoute::reportConstraints() @@ -753,8 +792,9 @@ void TritonRoute::reportConstraints() bool TritonRoute::writeGlobals(const std::string& name) { std::ofstream file(name); - if (!file.good()) + if (!file.good()) { return false; + } frOArchive ar(file); registerTypes(ar); serializeGlobals(ar); @@ -768,7 +808,7 @@ void TritonRoute::sendDesignDist() std::string design_path = fmt::format("{}DESIGN.db", shared_volume_); std::string globals_path = fmt::format("{}DESIGN.globals", shared_volume_); ord::OpenRoad::openRoad()->writeDb(design_path.c_str()); - writeGlobals(globals_path.c_str()); + writeGlobals(globals_path); dst::JobMessage msg(dst::JobMessage::UPDATE_DESIGN, dst::JobMessage::BROADCAST), result(dst::JobMessage::NONE); @@ -782,8 +822,9 @@ void TritonRoute::sendDesignDist() rjd->setDesignUpdate(false); msg.setJobDescription(std::move(desc)); bool ok = dist_->sendJob(msg, dist_ip_.c_str(), dist_port_, result); - if (!ok) + if (!ok) { logger_->error(DRT, 12304, "Updating design remotely failed"); + } } design_->clearUpdates(); } @@ -800,8 +841,9 @@ static void serializeUpdatesBatch(const std::vector& batch, void TritonRoute::sendGlobalsUpdates(const std::string& globals_path, const std::string& serializedViaData) { - if (!distributed_) + if (!distributed_) { return; + } ProfileTask task("DIST: SENDING GLOBALS"); dst::JobMessage msg(dst::JobMessage::UPDATE_DESIGN, dst::JobMessage::BROADCAST), @@ -814,21 +856,25 @@ void TritonRoute::sendGlobalsUpdates(const std::string& globals_path, rjd->setViaData(serializedViaData); msg.setJobDescription(std::move(desc)); bool ok = dist_->sendJob(msg, dist_ip_.c_str(), dist_port_, result); - if (!ok) + if (!ok) { logger_->error(DRT, 9504, "Updating globals remotely failed"); + } } void TritonRoute::sendDesignUpdates(const std::string& globals_path) { - if (!distributed_) + if (!distributed_) { return; - if (!design_->hasUpdates()) + } + if (!design_->hasUpdates()) { return; + } std::unique_ptr serializeTask; - if (design_->getVersion() == 0) + if (design_->getVersion() == 0) { serializeTask = std::make_unique("DIST: SERIALIZE_TA"); - else + } else { serializeTask = std::make_unique("DIST: SERIALIZE_UPDATES"); + } const auto& designUpdates = design_->getUpdates(); omp_set_num_threads(MAX_THREADS); std::vector updates(designUpdates.size()); @@ -839,10 +885,11 @@ void TritonRoute::sendDesignUpdates(const std::string& globals_path) } serializeTask->done(); std::unique_ptr task; - if (design_->getVersion() == 0) + if (design_->getVersion() == 0) { task = std::make_unique("DIST: SENDING_TA"); - else + } else { task = std::make_unique("DIST: SENDING_UDPATES"); + } dst::JobMessage msg(dst::JobMessage::UPDATE_DESIGN, dst::JobMessage::BROADCAST), result(dst::JobMessage::NONE); @@ -855,8 +902,9 @@ void TritonRoute::sendDesignUpdates(const std::string& globals_path) rjd->setDesignUpdate(true); msg.setJobDescription(std::move(desc)); bool ok = dist_->sendJob(msg, dist_ip_.c_str(), dist_port_, result); - if (!ok) + if (!ok) { logger_->error(DRT, 304, "Updating design remotely failed"); + } task->done(); design_->clearUpdates(); design_->incrementVersion(); @@ -868,8 +916,9 @@ int TritonRoute::main() USENONPREFTRACKS = false; } asio::thread_pool pa_pool(1); - if (!distributed_) + if (!distributed_) { pa_pool.join(); + } if (debug_->debugDumpDR) { std::string globals_path = fmt::format("{}/init_globals.bin", debug_->dumpDir); @@ -877,7 +926,7 @@ int TritonRoute::main() } MAX_THREADS = ord::OpenRoad::openRoad()->getThreadCount(); if (distributed_) { - if (DO_PA) + if (DO_PA) { asio::post(pa_pool, [this]() { sendDesignDist(); dst::JobMessage msg(dst::JobMessage::PIN_ACCESS, @@ -888,8 +937,9 @@ int TritonRoute::main() msg.setJobDescription(std::move(uDesc)); dist_->sendJob(msg, dist_ip_.c_str(), dist_port_, result); }); - else + } else { asio::post(dist_pool_, boost::bind(&TritonRoute::sendDesignDist, this)); + } } initDesign(); if (DO_PA) { @@ -899,7 +949,7 @@ int TritonRoute::main() pa_pool.join(); pa.main(); if (distributed_ || debug_->debugDR || debug_->debugDumpDR) { - io::Writer writer(getDesign(), logger_); + io::Writer writer(this, logger_); writer.updateDb(db_, true); } if (distributed_) { @@ -935,7 +985,7 @@ int TritonRoute::main() return 0; } -void TritonRoute::pinAccess(std::vector target_insts) +void TritonRoute::pinAccess(const std::vector& target_insts) { if (distributed_) { asio::post(dist_pool_, [this]() { @@ -961,7 +1011,7 @@ void TritonRoute::pinAccess(std::vector target_insts) dist_pool_.join(); } pa.main(); - io::Writer writer(getDesign(), logger_); + io::Writer writer(this, logger_); writer.updateDb(db_, true); } @@ -989,14 +1039,16 @@ void TritonRoute::getDRCMarkers(frList>& markers, Rect drcBox; routeBox.bloat(DRCSAFEDIST, drcBox); routeBox.bloat(MTSAFEDIST, extBox); - if (!drcBox.intersects(requiredDrcBox)) + if (!drcBox.intersects(requiredDrcBox)) { continue; + } auto gcWorker = std::make_unique(design_->getTech(), logger_); gcWorker->setDrcBox(drcBox); gcWorker->setExtBox(extBox); - if (workersBatches.back().size() >= BATCHSIZE) - workersBatches.push_back(std::vector>()); + if (workersBatches.back().size() >= BATCHSIZE) { + workersBatches.emplace_back(); + } workersBatches.back().push_back(std::move(gcWorker)); } } @@ -1004,33 +1056,24 @@ void TritonRoute::getDRCMarkers(frList>& markers, omp_set_num_threads(MAX_THREADS); for (auto& workers : workersBatches) { #pragma omp parallel for schedule(dynamic) - for (int i = 0; i < workers.size(); i++) { + for (int i = 0; i < workers.size(); i++) { // NOLINT workers[i]->init(design_.get()); workers[i]->main(); } for (const auto& worker : workers) { for (auto& marker : worker->getMarkers()) { Rect bbox = marker->getBBox(); - if (!bbox.intersects(requiredDrcBox)) + if (!bbox.intersects(requiredDrcBox)) { continue; + } auto layerNum = marker->getLayerNum(); auto con = marker->getConstraint(); - std::vector srcs(2, nullptr); - int i = 0; - for (auto& src : marker->getSrcs()) { - srcs.at(i) = src; - i++; - } - if (mapMarkers.find({bbox, layerNum, con, srcs[0], srcs[1]}) - != mapMarkers.end()) { - continue; - } - if (mapMarkers.find({bbox, layerNum, con, srcs[1], srcs[0]}) + if (mapMarkers.find({bbox, layerNum, con, marker->getSrcs()}) != mapMarkers.end()) { continue; } markers.push_back(std::make_unique(*marker)); - mapMarkers[{bbox, layerNum, con, srcs[0], srcs[1]}] + mapMarkers[{bbox, layerNum, con, marker->getSrcs()}] = markers.back().get(); } } @@ -1040,8 +1083,8 @@ void TritonRoute::getDRCMarkers(frList>& markers, void TritonRoute::checkDRC(const char* filename, int x1, int y1, int x2, int y2) { - GC_IGNORE_PDN_BEGIN_LAYER = -1; - GC_IGNORE_PDN_END_LAYER = -1; + GC_IGNORE_PDN_LAYER_NUM = -1; + REPAIR_PDN_LAYER_NUM = -1; initDesign(); auto gcellGrid = db_->getChip()->getBlock()->getGCellGrid(); if (gcellGrid != nullptr && gcellGrid->getNumGridPatternsX() == 1 @@ -1275,8 +1318,7 @@ void TritonRoute::setParams(const ParamStruct& params) MINNUMACCESSPOINT_MACROCELLPIN = params.minAccessPoints; } SAVE_GUIDE_UPDATES = params.saveGuideUpdates; - REPAIR_PDN_LAYER_BEGIN_NAME = params.repairPDNLayerBeginName; - REPAIR_PDN_LAYER_END_NAME = params.repairPDNLayerEndName; + REPAIR_PDN_LAYER_NAME = params.repairPDNLayerName; } void TritonRoute::addWorkerResults( @@ -1292,8 +1334,9 @@ bool TritonRoute::getWorkerResults( std::vector>& results) { std::unique_lock lock(results_mutex_); - if (workers_results_.empty()) + if (workers_results_.empty()) { return false; + } results = workers_results_; workers_results_.clear(); results_sz_ = 0; @@ -1325,8 +1368,9 @@ void TritonRoute::reportDRC(const std::string& file_name, for (const auto& marker : markers) { // get violation bbox Rect bbox = marker->getBBox(); - if (drcBox != Rect() && !drcBox.intersects(bbox)) + if (drcBox != Rect() && !drcBox.intersects(bbox)) { continue; + } auto tech = getDesign()->getTech(); auto layer = tech->getLayer(marker->getLayerNum()); auto layerType = layer->getType(); @@ -1336,10 +1380,11 @@ void TritonRoute::reportDRC(const std::string& file_name, if (con) { std::string violName; if (con->typeId() == frConstraintTypeEnum::frcShortConstraint - && layerType == dbTechLayerType::CUT) + && layerType == dbTechLayerType::CUT) { violName = "Cut Short"; - else + } else { violName = con->getViolName(); + } drcRpt << violName; } else { drcRpt << "nullptr"; @@ -1398,3 +1443,5 @@ void TritonRoute::reportDRC(const std::string& file_name, std::cout << "Error: Fail to open DRC report file\n"; } } + +} // namespace drt diff --git a/src/drt/src/TritonRoute.i b/src/drt/src/TritonRoute.i index b319d759419..ed10006eb52 100644 --- a/src/drt/src/TritonRoute.i +++ b/src/drt/src/TritonRoute.i @@ -94,8 +94,7 @@ void detailed_route_cmd(const char* outputMazeFile, bool singleStepDR, int minAccessPoints, bool saveGuideUpdates, - const char* repairPDNLayerBeginName, - const char* repairPDNLayerEndName, + const char* repairPDNLayerName, int drcReportIterStep) { auto* router = ord::OpenRoad::openRoad()->getTritonRoute(); @@ -123,8 +122,7 @@ void detailed_route_cmd(const char* outputMazeFile, singleStepDR, minAccessPoints, saveGuideUpdates, - repairPDNLayerBeginName, - repairPDNLayerEndName}); + repairPDNLayerName}); router->main(); router->setDistributed(false); } @@ -136,7 +134,7 @@ void pin_access_cmd(const char* dbProcessNode, int minAccessPoints) { auto* router = ord::OpenRoad::openRoad()->getTritonRoute(); - triton_route::ParamStruct params; + drt::ParamStruct params; params.dbProcessNode = dbProcessNode; params.bottomRoutingLayer = bottomRoutingLayer; params.topRoutingLayer = topRoutingLayer; diff --git a/src/drt/src/TritonRoute.tcl b/src/drt/src/TritonRoute.tcl index 9b53251a350..7354dc66e90 100644 --- a/src/drt/src/TritonRoute.tcl +++ b/src/drt/src/TritonRoute.tcl @@ -45,7 +45,7 @@ sta::define_cmd_args "detailed_route" { [-via_in_pin_bottom_layer layer] [-via_in_pin_top_layer layer] [-or_seed seed] - [-or_k_ k] + [-or_k k] [-bottom_routing_layer layer] [-top_routing_layer layer] [-verbose level] @@ -58,7 +58,8 @@ sta::define_cmd_args "detailed_route" { [-no_pin_access] [-min_access_points count] [-save_guide_updates] - [-repair_pdn_vias begin_layer end_layer] + [-repair_pdn_vias layer] + [-single_step_dr] } proc detailed_route { args } { @@ -68,7 +69,8 @@ proc detailed_route { args } { -via_in_pin_top_layer -or_seed -or_k -bottom_routing_layer \ -top_routing_layer -verbose -remote_host -remote_port -shared_volume \ -cloud_size -min_access_points -repair_pdn_vias -drc_report_iter_step} \ - flags {-disable_via_gen -distributed -clean_patches -no_pin_access -single_step_dr -save_guide_updates} + flags {-disable_via_gen -distributed -clean_patches -no_pin_access \ + -single_step_dr -save_guide_updates} sta::check_argc_eq0 "detailed_route" $args set enable_via_gen [expr ![info exists flags(-disable_via_gen)]] @@ -76,21 +78,14 @@ proc detailed_route { args } { set no_pin_access [expr [info exists flags(-no_pin_access)]] # single_step_dr is not a user option but is intended for algorithm # development. It is not listed in the help string intentionally. - set single_step_dr [expr [info exists flags(-single_step_dr)]] - set save_guide_updates [expr [info exists flags(-save_guide_updates)]] + set single_step_dr [expr [info exists flags(-single_step_dr)]] + set save_guide_updates [expr [info exists flags(-save_guide_updates)]] - if {[info exists keys(-repair_pdn_vias)]} { - set repair_pdn_vias $keys(-repair_pdn_vias) - if {[llength $repair_pdn_vias] != 2} { - utl::error DRT 556 "-repair_pdn_vias should be a list of 2 layers; the begin via layer and end via layer" - } else { - lassign $keys(-repair_pdn_vias) repair_pdn_vias_begin repair_pdn_vias_end - } + if { [info exists keys(-repair_pdn_vias)] } { + set repair_pdn_vias $keys(-repair_pdn_vias) } else { - set repair_pdn_vias_begin "" - set repair_pdn_vias_end "" + set repair_pdn_vias "" } - if { [info exists keys(-output_maze)] } { set output_maze $keys(-output_maze) } else { @@ -202,7 +197,7 @@ proc detailed_route { args } { $via_in_pin_bottom_layer $via_in_pin_top_layer \ $or_seed $or_k $bottom_routing_layer $top_routing_layer $verbose \ $clean_patches $no_pin_access $single_step_dr $min_access_points \ - $save_guide_updates $repair_pdn_vias_begin $repair_pdn_vias_end $drc_report_iter_step + $save_guide_updates $repair_pdn_vias $drc_report_iter_step } proc detailed_route_num_drvs { args } { @@ -230,8 +225,9 @@ sta::define_cmd_args "detailed_route_debug" { proc detailed_route_debug { args } { sta::parse_key_args "detailed_route_debug" args \ - keys {-net -iter -pin -dump_dir -box} \ - flags {-dr -maze -pa -pa_markers -pa_edge -pa_commit -dump_dr -ta -write_net_tracks -dump_last_worker} + keys {-net -iter -pin -dump_dir -box} \ + flags {-dr -maze -pa -pa_markers -pa_edge -pa_commit -dump_dr -ta \ + -write_net_tracks -dump_last_worker} sta::check_argc_eq0 "detailed_route_debug" $args @@ -270,7 +266,7 @@ proc detailed_route_debug { args } { set box_y1 -1 set box_x2 -1 set box_y2 -1 - if [info exists keys(-box)] { + if {[info exists keys(-box)]} { set box $keys(-box) if { [llength $box] != 4 } { utl::error DRT 118 "-box is a list of 4 coordinates." @@ -287,7 +283,8 @@ proc detailed_route_debug { args } { } drt::set_detailed_route_debug_cmd $net_name $pin_name $dr $dump_dr $pa $maze \ - $box_x1 $box_y1 $box_x2 $box_y2 $iter $pa_markers $pa_edge $pa_commit $dump_dir $ta $write_net_tracks $dump_last_worker + $box_x1 $box_y1 $box_x2 $box_y2 $iter $pa_markers $pa_edge $pa_commit \ + $dump_dir $ta $write_net_tracks $dump_last_worker } sta::define_cmd_args "pin_access" { @@ -304,11 +301,11 @@ sta::define_cmd_args "pin_access" { } proc pin_access { args } { sta::parse_key_args "pin_access" args \ - keys {-db_process_node -bottom_routing_layer -top_routing_layer -verbose \ - -min_access_points -remote_host -remote_port -shared_volume -cloud_size } \ - flags {-distributed} + keys {-db_process_node -bottom_routing_layer -top_routing_layer -verbose \ + -min_access_points -remote_host -remote_port -shared_volume -cloud_size } \ + flags {-distributed} sta::check_argc_eq0 "detailed_route_debug" $args - if [info exists keys(-db_process_node)] { + if {[info exists keys(-db_process_node)]} { set db_process_node $keys(-db_process_node) } else { set db_process_node "" @@ -358,19 +355,20 @@ proc pin_access { args } { } drt::detailed_route_distributed $rhost $rport $vol $cloudsz } - drt::pin_access_cmd $db_process_node $bottom_routing_layer $top_routing_layer $verbose $min_access_points + drt::pin_access_cmd $db_process_node $bottom_routing_layer \ + $top_routing_layer $verbose $min_access_points } sta::define_cmd_args "detailed_route_run_worker" { [-dump_dir dir] [-worker_dir dir] [-drc_rpt drc] -} +};# checker off proc detailed_route_run_worker { args } { sta::parse_key_args "detailed_route_run_worker" args \ - keys {-dump_dir -worker_dir -drc_rpt} \ - flags {} + keys {-dump_dir -worker_dir -drc_rpt} \ + flags {};# checker off sta::check_argc_eq0 "detailed_route_run_worker" $args if { [info exists keys(-dump_dir)] } { set dump_dir $keys(-dump_dir) @@ -389,7 +387,7 @@ proc detailed_route_run_worker { args } { } else { set drc_rpt "" } - drt::run_worker_cmd $dump_dir $worker_dir $drc_rpt + drt::run_worker_cmd $dump_dir $worker_dir $drc_rpt } sta::define_cmd_args "detailed_route_worker_debug" { @@ -400,54 +398,56 @@ sta::define_cmd_args "detailed_route_worker_debug" { [-marker_decay m_decay] [-ripup_mode mode] [-follow_guide f_guide] -} +};# checker off proc detailed_route_worker_debug { args } { sta::parse_key_args "detailed_route_worker_debug" args \ - keys {-maze_end_iter -drc_cost -marker_cost -fixed_shape_cost -marker_decay -ripup_mode -follow_guide} \ - flags {} - if [info exists keys(-maze_end_iter)] { + keys {-maze_end_iter -drc_cost -marker_cost -fixed_shape_cost \ + -marker_decay -ripup_mode -follow_guide} \ + flags {};# checker off + if {[info exists keys(-maze_end_iter)]} { set maze_end_iter $keys(-maze_end_iter) } else { set maze_end_iter -1 } - if [info exists keys(-drc_cost)] { + if {[info exists keys(-drc_cost)]} { set drc_cost $keys(-drc_cost) } else { set drc_cost -1 } - if [info exists keys(-marker_cost)] { + if {[info exists keys(-marker_cost)]} { set marker_cost $keys(-marker_cost) } else { set marker_cost -1 } - if [info exists keys(-fixed_shape_cost)] { + if {[info exists keys(-fixed_shape_cost)]} { set fixed_shape_cost $keys(-fixed_shape_cost) } else { set fixed_shape_cost -1 } - if [info exists keys(-marker_decay)] { + if {[info exists keys(-marker_decay)]} { set marker_decay $keys(-marker_decay) } else { set marker_decay -1 } - if [info exists keys(-ripup_mode)] { + if {[info exists keys(-ripup_mode)]} { set ripup_mode $keys(-ripup_mode) } else { set ripup_mode -1 } - if [info exists keys(-follow_guide)] { + if {[info exists keys(-follow_guide)]} { set follow_guide $keys(-follow_guide) } else { set follow_guide -1 } - drt::set_worker_debug_params $maze_end_iter $drc_cost $marker_cost $fixed_shape_cost $marker_decay $ripup_mode $follow_guide + drt::set_worker_debug_params $maze_end_iter $drc_cost $marker_cost \ + $fixed_shape_cost $marker_decay $ripup_mode $follow_guide } proc detailed_route_set_default_via { args } { @@ -474,21 +474,21 @@ proc step_dr { args } { sta::define_cmd_args "check_drc" { [-box box] [-output_file filename] -} +};# checker off proc check_drc { args } { sta::parse_key_args "check_drc" args \ - keys { -box -output_file } \ - flags {} + keys { -box -output_file } \ + flags {};# checker off sta::check_argc_eq0 "check_drc" $args set box { 0 0 0 0 } - if [info exists keys(-box)] { + if {[info exists keys(-box)]} { set box $keys(-box) if { [llength $box] != 4 } { utl::error DRT 612 "-box is a list of 4 coordinates." - } + } } lassign $box x1 y1 x2 y2 - if { [info exists keys(-output_file)] } { + if { [info exists keys(-output_file)] } { set output_file $keys(-output_file) } else { utl::error DRT 613 "-output_file is required for check_drc command" diff --git a/src/drt/src/gc/FlexGC_cut.cpp b/src/drt/src/gc/FlexGC_cut.cpp index 9b250a02d3a..e4222e539dc 100644 --- a/src/drt/src/gc/FlexGC_cut.cpp +++ b/src/drt/src/gc/FlexGC_cut.cpp @@ -30,8 +30,8 @@ #include "gc/FlexGC_impl.h" #include "odb/db.h" -using namespace fr; -typedef odb::dbTechLayerCutSpacingTableDefRule::LOOKUP_STRATEGY LOOKUP_STRATEGY; +namespace drt { +using LOOKUP_STRATEGY = odb::dbTechLayerCutSpacingTableDefRule::LOOKUP_STRATEGY; inline frSquaredDistance getC2CDistSquare( const gtl::rectangle_data& rect1, @@ -47,8 +47,8 @@ bool FlexGCWorker::Impl::checkLef58CutSpacingTbl_prlValid( const gtl::rectangle_data& viaRect1, const gtl::rectangle_data& viaRect2, const gtl::rectangle_data& markerRect, - std::string cutClass1, - std::string cutClass2, + const std::string& cutClass1, + const std::string& cutClass2, frCoord& prl, odb::dbTechLayerCutSpacingTableDefRule* dbRule) { @@ -70,15 +70,15 @@ bool FlexGCWorker::Impl::checkLef58CutSpacingTbl_prlValid( if (prlX > reqPrl || prlY > reqPrl) { prl = std::max(prlX, prlY); return true; - } else - return false; + } + return false; } bool FlexGCWorker::Impl::checkLef58CutSpacingTbl_helper( gcRect* viaRect1, gcRect* viaRect2, - frString class1, - frString class2, + const frString& class1, + const frString& class2, const frDirEnum dir, frSquaredDistance distSquare, frSquaredDistance c2cSquare, @@ -110,25 +110,25 @@ bool FlexGCWorker::Impl::checkLef58CutSpacingTbl_helper( reqSpcSqr *= reqSpcSqr; if (c2cSquare < reqSpcSqr) { return true; - } else { - reqSpcSqr - = dbRule->getSpacing(class1, - isSide1, - class2, - isSide2, - odb::dbTechLayerCutSpacingTableDefRule::MIN); - reqSpcSqr *= reqSpcSqr; - if (distSquare < reqSpcSqr) - return true; + } + reqSpcSqr = dbRule->getSpacing(class1, + isSide1, + class2, + isSide2, + odb::dbTechLayerCutSpacingTableDefRule::MIN); + reqSpcSqr *= reqSpcSqr; + if (distSquare < reqSpcSqr) { + return true; } return false; } if (class1 == class2 && !dbRule->isLayerValid()) { bool exactlyAligned = false; - if (dir == frDirEnum::N || dir == frDirEnum::S) + if (dir == frDirEnum::N || dir == frDirEnum::S) { exactlyAligned = (prl == deltaH1) && !dbRule->isHorizontal(); - else + } else { exactlyAligned = (prl == deltaV1) && !dbRule->isVertical(); + } auto exAlSpc = dbRule->getExactAlignedSpacing(class1); if (exactlyAligned && exAlSpc != -1) { @@ -161,8 +161,9 @@ bool FlexGCWorker::Impl::checkLef58CutSpacingTbl_helper( auto& workerRegionQuery = getWorkerRegionQuery(); workerRegionQuery.queryPolygonEdge( qb, viaRect2->getLayerNum() + 1, results); - if (results.size() == 0) + if (results.empty()) { spcIdx = LOOKUP_STRATEGY::FIRST; + } } frCoord reqSpc = dbRule->getSpacing(class1, isSide1, class2, isSide2, spcIdx); @@ -175,8 +176,9 @@ bool FlexGCWorker::Impl::checkLef58CutSpacingTbl_helper( == dbRule->getSpacing( class1, isSide1, class2, isSide2, LOOKUP_STRATEGY::MAX)); if (useCenter) { - if (c2cSquare < reqSpcSqr) + if (c2cSquare < reqSpcSqr) { return true; + } } else if (distSquare < reqSpcSqr) { return true; } @@ -193,9 +195,11 @@ bool FlexGCWorker::Impl::checkLef58CutSpacingTbl_sameMetal(gcRect* viaRect1, workerRegionQuery.queryMaxRectangle(qb, viaRect1->getLayerNum() - 1, results); for (const auto& res : results) { auto metalRect = res.second; - if (gtl::intersects(*metalRect, *viaRect1, false)) - if (gtl::intersects(*metalRect, *viaRect2, false)) + if (gtl::intersects(*metalRect, *viaRect1, false)) { + if (gtl::intersects(*metalRect, *viaRect2, false)) { return true; + } + } } return false; } @@ -203,8 +207,9 @@ bool FlexGCWorker::Impl::checkLef58CutSpacingTbl_sameMetal(gcRect* viaRect1, bool FlexGCWorker::Impl::checkLef58CutSpacingTbl_stacked(gcRect* viaRect1, gcRect* viaRect2) { - if (*viaRect1 == *viaRect2) + if (*viaRect1 == *viaRect2) { return true; + } return gtl::contains(*viaRect1, *viaRect2) || gtl::contains(*viaRect2, *viaRect1); } @@ -222,16 +227,20 @@ void FlexGCWorker::Impl::checkLef58CutSpacingTbl_main( bool viol = false; if (dbRule->isLayerValid()) { if (dbRule->isSameNet()) { - if (viaRect1->getNet() != viaRect2->getNet()) + if (viaRect1->getNet() != viaRect2->getNet()) { return; + } if (layer1->hasLef58SameMetalInterCutSpcTblConstraint() - && checkLef58CutSpacingTbl_sameMetal(viaRect1, viaRect2)) + && checkLef58CutSpacingTbl_sameMetal(viaRect1, viaRect2)) { return; + } } else if (dbRule->isSameMetal()) { - if (viaRect1->getNet() != viaRect2->getNet()) + if (viaRect1->getNet() != viaRect2->getNet()) { return; - if (!checkLef58CutSpacingTbl_sameMetal(viaRect1, viaRect2)) + } + if (!checkLef58CutSpacingTbl_sameMetal(viaRect1, viaRect2)) { return; + } } else { if (viaRect1->getNet() == viaRect2->getNet()) { return; @@ -239,20 +248,25 @@ void FlexGCWorker::Impl::checkLef58CutSpacingTbl_main( } } else { if (dbRule->isSameNet()) { - if (viaRect1->getNet() != viaRect2->getNet()) + if (viaRect1->getNet() != viaRect2->getNet()) { return; + } } else if (dbRule->isSameMetal()) { - if (viaRect1->getNet() != viaRect2->getNet()) + if (viaRect1->getNet() != viaRect2->getNet()) { return; - if (!checkLef58CutSpacingTbl_sameMetal(viaRect1, viaRect2)) + } + if (!checkLef58CutSpacingTbl_sameMetal(viaRect1, viaRect2)) { return; + } } else { if (viaRect1->getNet() == viaRect2->getNet()) { - if (layer1->hasLef58SameNetCutSpcTblConstraint()) + if (layer1->hasLef58SameNetCutSpcTblConstraint()) { return; - else if (checkLef58CutSpacingTbl_sameMetal(viaRect1, viaRect2) - && layer1->hasLef58SameMetalCutSpcTblConstraint()) + } + if (checkLef58CutSpacingTbl_sameMetal(viaRect1, viaRect2) + && layer1->hasLef58SameMetalCutSpcTblConstraint()) { return; + } } } } @@ -260,26 +274,30 @@ void FlexGCWorker::Impl::checkLef58CutSpacingTbl_main( = layer1->getCutClassIdx(viaRect1->width(), viaRect1->length()); auto cutClassIdx2 = layer2->getCutClassIdx(viaRect2->width(), viaRect2->length()); - frString class1 = ""; - frString class2 = ""; - if (cutClassIdx1 != -1) + frString class1; + frString class2; + if (cutClassIdx1 != -1) { class1 = layer1->getCutClass(cutClassIdx1)->getName(); - if (cutClassIdx2 != -1) + } + if (cutClassIdx2 != -1) { class2 = layer2->getCutClass(cutClassIdx2)->getName(); + } gtl::rectangle_data markerRect(*viaRect1); gtl::generalized_intersect(markerRect, *viaRect2); frSquaredDistance distSquare = gtl::square_euclidean_distance(*viaRect1, *viaRect2); if (distSquare == 0) { - if (dbRule->getMaxSpacing(class1, class2) == 0) + if (dbRule->getMaxSpacing(class1, class2) == 0) { return; - if (!dbRule->isLayerValid()) + } + if (!dbRule->isLayerValid()) { checkCutSpacing_short(viaRect1, viaRect2, markerRect); - else if (dbRule->isNoStack()) + } else if (dbRule->isNoStack()) { viol = true; - else + } else { viol = !checkLef58CutSpacingTbl_stacked(viaRect1, viaRect2); + } } frSquaredDistance c2cSquare = getC2CDistSquare(*viaRect1, *viaRect2); @@ -354,14 +372,25 @@ void FlexGCWorker::Impl::checkLef58CutSpacingTbl_main( } } -bool FlexGCWorker::Impl::isSkipVia(gcRect* rect) +inline bool isSupplyVia(gcRect* rect) { - return rect->getLayerNum() >= GC_IGNORE_PDN_BEGIN_LAYER - && rect->getLayerNum() <= GC_IGNORE_PDN_END_LAYER && rect->isFixed() - && rect->hasNet() && rect->getNet()->getFrNet() + return rect->isFixed() && rect->hasNet() && rect->getNet()->getFrNet() && rect->getNet()->getFrNet()->getType().isSupply(); } +inline bool isSkipVia(gcRect* rect) +{ + return rect->getLayerNum() == GC_IGNORE_PDN_LAYER_NUM && isSupplyVia(rect); +} + +inline bool isFixedVia(gcRect* rect) +{ + if (rect->getLayerNum() == REPAIR_PDN_LAYER_NUM && isSupplyVia(rect)) { + return false; + } + return rect->isFixed(); +} + void FlexGCWorker::Impl::checkLef58CutSpacingTbl( gcRect* viaRect, frLef58CutSpacingTableConstraint* con) @@ -371,29 +400,34 @@ void FlexGCWorker::Impl::checkLef58CutSpacingTbl( auto width = viaRect->width(); auto length = viaRect->length(); auto cutClassIdx = layer1->getCutClassIdx(width, length); - frString cutClass = ""; - if (cutClassIdx != -1) + frString cutClass; + if (cutClassIdx != -1) { cutClass = layer1->getCutClass(cutClassIdx)->getName(); + } auto dbRule = con->getODBRule(); - if (isSkipVia(viaRect)) + if (isSkipVia(viaRect)) { return; + } bool isUpperVia = true; frLayerNum queryLayerNum; if (dbRule->isLayerValid()) { - if (dbRule->getSecondLayer()->getName() == layer1->getName()) + if (dbRule->getSecondLayer()->getName() == layer1->getName()) { isUpperVia = false; - if (isUpperVia) + } + if (isUpperVia) { queryLayerNum = getTech() ->getLayer(dbRule->getSecondLayer()->getName()) ->getLayerNum(); - else + } else { queryLayerNum = getTech() ->getLayer(dbRule->getTechLayer()->getName()) ->getLayerNum(); - } else + } + } else { queryLayerNum = layerNum1; + } frCoord maxSpc; if (width == length) { @@ -409,34 +443,37 @@ void FlexGCWorker::Impl::checkLef58CutSpacingTbl( auto& workerRegionQuery = getWorkerRegionQuery(); workerRegionQuery.queryMaxRectangle(queryBox, queryLayerNum, results); for (auto& [box, ptr] : results) { - if (ptr->isFixed() && viaRect->isFixed()) + if (isFixedVia(ptr) && isFixedVia(viaRect)) { continue; - if (ptr->getPin() == viaRect->getPin()) + } + if (ptr->getPin() == viaRect->getPin()) { continue; - if (isSkipVia(ptr)) + } + if (isSkipVia(ptr)) { continue; - queryLayerNum = layerNum1; - - if (isUpperVia) + } + if (isUpperVia) { checkLef58CutSpacingTbl_main(viaRect, ptr, con); - else + } else { checkLef58CutSpacingTbl_main(ptr, viaRect, con); + } } } - void FlexGCWorker::Impl::checKeepOutZone_main(gcRect* rect, frLef58KeepOutZoneConstraint* con) { auto layer = getTech()->getLayer(rect->getLayerNum()); - if (isSkipVia(rect)) + if (isSkipVia(rect)) { return; + } auto dbRule = con->getODBRule(); Rect viaBox(gtl::xl(*rect), gtl::yl(*rect), gtl::xh(*rect), gtl::yh(*rect)); Rect sideQueryBox(viaBox), endQueryBox(viaBox); auto viaCutClass = layer->getCutClass(rect->width(), rect->length()); if (viaCutClass == nullptr - || viaCutClass->getName() != dbRule->getFirstCutClass()) + || viaCutClass->getName() != dbRule->getFirstCutClass()) { return; + } if (viaBox.dx() > viaBox.dy()) { sideQueryBox = sideQueryBox.bloat(dbRule->getSideForwardExtension(), @@ -475,21 +512,26 @@ void FlexGCWorker::Impl::checKeepOutZone_main(gcRect* rect, allResults.insert(allResults.end(), results.begin(), results.end()); } for (auto& [box, ptr] : allResults) { - if (ptr->isFixed() && rect->isFixed()) + if (isFixedVia(ptr) && isFixedVia(rect)) { continue; - if (ptr->getPin() == rect->getPin()) + } + if (ptr->getPin() == rect->getPin()) { continue; - if (isSkipVia(ptr)) + } + if (isSkipVia(ptr)) { continue; + } auto via2CutClass = layer->getCutClass(ptr->width(), ptr->length()); if (!dbRule->getSecondCutClass().empty() && (via2CutClass == nullptr - || dbRule->getSecondCutClass() != via2CutClass->getName())) + || dbRule->getSecondCutClass() != via2CutClass->getName())) { continue; + } odb::Rect ptrBox( gtl::xl(*ptr), gtl::yl(*ptr), gtl::xh(*ptr), gtl::yh(*ptr)); - if (!sideQueryBox.overlaps(ptrBox) && !endQueryBox.overlaps(ptrBox)) + if (!sideQueryBox.overlaps(ptrBox) && !endQueryBox.overlaps(ptrBox)) { continue; + } gtl::rectangle_data markerRect(*rect); gtl::generalized_intersect(markerRect, *ptr); Rect markerBox(gtl::xl(markerRect), @@ -524,8 +566,9 @@ void FlexGCWorker::Impl::checkMetalWidthViaTable_main(gcRect* rect) auto required_viadef = getTech()->getVia(rule->getViaName()); frVia required_via(required_viadef); if (rect->width() == required_via.getCutBBox().minDXDY() - && rect->length() == required_via.getCutBBox().maxDXDY()) + && rect->length() == required_via.getCutBBox().maxDXDY()) { continue; + } auto checkEnclosure = [this](gcRect* rect, odb::dbMetalWidthViaMap* rule, bool above) { std::vector> results; @@ -535,16 +578,18 @@ void FlexGCWorker::Impl::checkMetalWidthViaTable_main(gcRect* rect) *rect, rect->getLayerNum() + ((above) ? 1 : -1), results); gcRect* chosen_rect = nullptr; for (auto& [box, obj] : results) { - if (!gtl::contains(*obj, *rect)) + if (!gtl::contains(*obj, *rect)) { continue; + } auto above_width = box.minDXDY(); if (above_width >= ((above) ? rule->getAboveLayerWidthLow() : rule->getBelowLayerWidthLow()) && above_width <= ((above) ? rule->getAboveLayerWidthHigh() : rule->getBelowLayerWidthHigh())) { chosen_rect = obj; - if (!obj->isFixed()) + if (!obj->isFixed()) { break; + } } } return chosen_rect; @@ -552,15 +597,18 @@ void FlexGCWorker::Impl::checkMetalWidthViaTable_main(gcRect* rect) // check above Metal Layer Width gcRect* above_rect = checkEnclosure(rect, rule, true); - if (above_rect == nullptr) + if (above_rect == nullptr) { continue; + } // check below Metal Layer Width gcRect* below_rect = checkEnclosure(rect, rule, true); - if (below_rect == nullptr) + if (below_rect == nullptr) { continue; - if (below_rect->isFixed() && above_rect->isFixed() && rect->isFixed()) + } + if (below_rect->isFixed() && above_rect->isFixed() && rect->isFixed()) { continue; + } Rect markerBox( gtl::xl(*rect), gtl::yl(*rect), gtl::xh(*rect), gtl::yh(*rect)); auto net1 = above_rect->getNet(); @@ -642,3 +690,102 @@ 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(); + 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> 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 diff --git a/src/drt/src/gc/FlexGC_impl.h b/src/drt/src/gc/FlexGC_impl.h index fb31423576d..af046f56e67 100644 --- a/src/drt/src/gc/FlexGC_impl.h +++ b/src/drt/src/gc/FlexGC_impl.h @@ -39,7 +39,7 @@ namespace odb { class dbTechLayerCutSpacingTableDefRule; } -namespace fr { +namespace drt { class FlexGCWorkerRegionQuery { public: @@ -49,28 +49,28 @@ class FlexGCWorkerRegionQuery void addPolygonEdge(gcSegment* edge); void addMaxRectangle(gcRect* rect); void addSpcRectangle(gcRect* rect); - void removePolygonEdge(gcSegment* connFig); - void removeMaxRectangle(gcRect* connFig); + void removePolygonEdge(gcSegment* edge); + void removeMaxRectangle(gcRect* rect); void removeSpcRectangle(gcRect* rect); void queryPolygonEdge( const box_t& box, - const frLayerNum layerNum, + frLayerNum layerNum, std::vector>& result) const; void queryPolygonEdge( const Rect& box, - const frLayerNum layerNum, + frLayerNum layerNum, std::vector>& result) const; void queryMaxRectangle(const box_t& box, - const frLayerNum layerNum, + frLayerNum layerNum, std::vector>& result) const; void querySpcRectangle(const box_t& box, - const frLayerNum layerNum, + frLayerNum layerNum, std::vector>& result) const; void queryMaxRectangle(const Rect& box, - const frLayerNum layerNum, + frLayerNum layerNum, std::vector>& result) const; void queryMaxRectangle(const gtl::rectangle_data& box, - const frLayerNum layerNum, + frLayerNum layerNum, std::vector>& result) const; void init(int numLayers); void addToRegionQuery(gcNet* net); @@ -225,14 +225,12 @@ class FlexGCWorker::Impl gcSegment* ptr, const gtl::orientation_2d& orient) const; void checkMetalSpacing_wrongDir(gcPin* pin, frLayer* layer); - void checkMetalSpacingRange(gcRect* rect); - void checkMetalSpacingRange(gcRect* rect, frSpacingRangeConstraint* con); - frCoord checkMetalSpacing_getMaxSpcVal(frLayerNum layerNum, bool checkNDRs = true); void myBloat(const gtl::rectangle_data& rect, frCoord val, box_t& box); + bool hasRoute(gcRect* rect, gtl::rectangle_data markerRect); void checkMetalSpacing_main(gcRect* rect, bool checkNDRs = true, bool isSpcRect = false); @@ -260,7 +258,8 @@ class FlexGCWorker::Impl const gtl::rectangle_data& markerRect); frCoord checkMetalSpacing_prl_getReqSpcVal(gcRect* rect1, gcRect* rect2, - frCoord prl); + frCoord prl, + bool& isSpcRange); bool checkMetalSpacing_prl_hasPolyEdge( gcRect* rect1, gcRect* rect2, @@ -275,6 +274,22 @@ class FlexGCWorker::Impl frCoord distY, bool checkNDRs = true, bool checkPolyEdge = true); + void checkForbiddenSpc_main(gcRect* rect1, + gcRect* rect2, + frLef58ForbiddenSpcConstraint* con, + bool isH); + Rect checkForbiddenSpc_queryBox(gcRect* rect, + frCoord minSpc, + frCoord maxSpc, + bool isH, + bool right); + bool checkForbiddenSpc_twoedges(gcRect* rect, + frLef58ForbiddenSpcConstraint* con, + bool isH); + void checkForbiddenSpc_main(gcRect* rect, frLef58ForbiddenSpcConstraint* con); + void checkTwoWiresForbiddenSpc_main( + gcRect* rect, + frLef58TwoWiresForbiddenSpcConstraint* con); box_t checkMetalCornerSpacing_getQueryBox(gcCorner* corner, frCoord& maxSpcValX, frCoord& maxSpcValY); @@ -332,10 +347,11 @@ class FlexGCWorker::Impl frLef58EolExtensionConstraint* constraint); void checkMetalEndOfLine_ext(gcSegment* edge, frLef58EolExtensionConstraint* constraint); - void checkMetalEOLkeepout_helper(gcSegment* edge, - gcRect* rect, - gtl::rectangle_data queryRect, - frLef58EolKeepOutConstraint* constraint); + void checkMetalEOLkeepout_helper( + gcSegment* edge, + gcRect* rect, + const gtl::rectangle_data& queryRect, + frLef58EolKeepOutConstraint* constraint); void checkMetalEOLkeepout_main(gcSegment* edge, frLef58EolKeepOutConstraint* constraint); void getEolKeepOutExceptWithinRects(gcSegment* edge, @@ -411,8 +427,8 @@ class FlexGCWorker::Impl const gtl::rectangle_data& viaRect1, const gtl::rectangle_data& viaRect2, const gtl::rectangle_data& markerRect, - std::string cutClass1, - std::string cutClass2, + const std::string& cutClass1, + const std::string& cutClass2, frCoord& prl, odb::dbTechLayerCutSpacingTableDefRule* dbRule); bool checkLef58CutSpacingTbl_sameMetal(gcRect* viaRect1, gcRect* viaRect2); @@ -423,9 +439,9 @@ class FlexGCWorker::Impl bool checkLef58CutSpacingTbl_helper( gcRect* viaRect1, gcRect* viaRect2, - frString cutClass1, - frString cutClass2, - const frDirEnum dir, + const frString& cutClass1, + const frString& cutClass2, + frDirEnum dir, frSquaredDistance distSquare, frSquaredDistance c2cSquare, bool prlValid, @@ -451,15 +467,12 @@ class FlexGCWorker::Impl gcRect* rect2, const gtl::rectangle_data& markerRect, frCutSpacingConstraint* con); - frCoord checkCutSpacing_spc_getReqSpcVal(gcRect* ptr1, - gcRect* ptr2, - frCutSpacingConstraint* con); // LEF58 void checkLef58CutSpacing_main(gcRect* rect); void checkLef58CutSpacing_main(gcRect* rect, frLef58CutSpacingConstraint* con, - bool skipSameNet = false); + bool skipDiffNet = false); void checkLef58CutSpacing_spc_parallelOverlap( gcRect* rect1, gcRect* rect2, @@ -486,10 +499,9 @@ class FlexGCWorker::Impl bool checkLef58CutSpacing_spc_hasTwoCuts_helper( gcRect* rect, frLef58CutSpacingConstraint* con); - frCoord checkLef58CutSpacing_spc_getReqSpcVal( - gcRect* ptr1, - gcRect* ptr2, - 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); @@ -497,16 +509,18 @@ class FlexGCWorker::Impl void checkMetalShape_lef58MinStep(gcPin* pin); void checkMetalShape_lef58MinStep_noBetweenEol(gcPin* pin, frLef58MinStepConstraint* con); + void checkMetalShape_lef58MinStep_minAdjLength(gcPin* pin, + frLef58MinStepConstraint* con); void checkMetalSpacingTableInfluence(); void checkPinMetSpcTblInf(gcPin*); void checkRectMetSpcTblInf(gcRect*, frSpacingTableInfluenceConstraint*); void checkOrthRectsMetSpcTblInf(const std::vector& rects, const gtl::rectangle_data& queryRect, - const frCoord spacing, - const gtl::orientation_2d orient); + frCoord spacing, + const gtl::orientation_2d& orient); void checkRectMetSpcTblInf_queryBox(const gtl::rectangle_data& rect, - const frCoord dist, - const frDirEnum dir, + frCoord dist, + frDirEnum dir, box_t& box); void checkMinimumCut_marker(gcRect* wideRect, gcRect* viaRect, @@ -537,6 +551,5 @@ class FlexGCWorker::Impl const gtl::rectangle_data& rect); bool isOppositeDir(gcCorner* corner, gcSegment* seg); bool isWrongDir(gcSegment* edge); - bool isSkipVia(gcRect* rect); }; -} // namespace fr +} // namespace drt diff --git a/src/drt/src/gc/FlexGC_main.cpp b/src/drt/src/gc/FlexGC_main.cpp index 24bac8921b5..c7718e0d200 100644 --- a/src/drt/src/gc/FlexGC_main.cpp +++ b/src/drt/src/gc/FlexGC_main.cpp @@ -32,9 +32,10 @@ #include "frProfileTask.h" #include "gc/FlexGC_impl.h" -using namespace fr; -typedef bg::model::polygon polygon_t; -typedef bg::model::multi_polygon mpolygon_t; +namespace drt { + +using polygon_t = bg::model::polygon; +using mpolygon_t = bg::model::multi_polygon; bool FlexGCWorker::Impl::isCornerOverlap(gcCorner* corner, const Rect& box) { @@ -108,6 +109,27 @@ void FlexGCWorker::Impl::myBloat(const gtl::rectangle_data& rect, bg::set(box, gtl::yh(rect) + val); } +bool FlexGCWorker::Impl::hasRoute(gcRect* rect, + gtl::rectangle_data markerRect) +{ + // marker enlarged by width + auto width = rect->width(); + gtl::bloat(markerRect, width); + // widthrect + gtl::polygon_90_set_data tmpPoly; + using boost::polygon::operators::operator+=; + using boost::polygon::operators::operator&=; + tmpPoly += markerRect; + tmpPoly &= *rect; // tmpPoly now is widthrect + auto targetArea = gtl::area(tmpPoly); + // get fixed shapes + tmpPoly &= rect->getNet()->getPolygons(rect->getLayerNum(), true); + if (gtl::area(tmpPoly) < targetArea) { + return true; + } + return false; +} + frCoord FlexGCWorker::Impl::checkMetalSpacing_getMaxSpcVal(frLayerNum layerNum, bool checkNDRs) { @@ -128,9 +150,10 @@ frCoord FlexGCWorker::Impl::checkMetalSpacing_getMaxSpcVal(frLayerNum layerNum, default: logger_->warn(DRT, 41, "Unsupported metSpc rule."); } - if (checkNDRs) + if (checkNDRs) { return std::max(maxSpcVal, getTech()->getMaxNondefaultSpacing(layerNum / 2 - 1)); + } } return maxSpcVal; } @@ -150,7 +173,6 @@ void FlexGCWorker::Impl::checkMetalCornerSpacing_getMaxSpcVal( maxSpcValY = std::max(maxSpcValY, con->findMax(false)); } } - return; } bool FlexGCWorker::Impl::isOppositeDir(gcCorner* corner, gcSegment* seg) @@ -166,9 +188,8 @@ bool FlexGCWorker::Impl::isOppositeDir(gcCorner* corner, gcSegment* seg) || (cornerDir == frCornerDirEnum::NW && (segDir == frDirEnum::N || segDir == frDirEnum::E))) { return true; - } else { - return false; } + return false; } box_t FlexGCWorker::Impl::checkMetalCornerSpacing_getQueryBox( @@ -232,11 +253,12 @@ bool isPG(frBlockObject* obj) } } -frCoord FlexGCWorker::Impl::checkMetalSpacing_prl_getReqSpcVal( - gcRect* rect1, - gcRect* rect2, - frCoord prl /*, bool &hasRoute*/) +frCoord FlexGCWorker::Impl::checkMetalSpacing_prl_getReqSpcVal(gcRect* rect1, + gcRect* rect2, + frCoord prl, + bool& isSpcRange) { + isSpcRange = false; auto layerNum = rect1->getLayerNum(); frCoord reqSpcVal = 0; auto currLayer = getTech()->getLayer(layerNum); @@ -288,10 +310,22 @@ frCoord FlexGCWorker::Impl::checkMetalSpacing_prl_getReqSpcVal( if (!isObs && rect1->getNet() == rect2->getNet()) { if (currLayer->hasSpacingSamenet()) { auto conSamenet = currLayer->getSpacingSamenet(); - if (!conSamenet->hasPGonly()) + if (!conSamenet->hasPGonly()) { reqSpcVal = std::max(conSamenet->getMinSpacing(), minSpcVal); - else if (isPG(rect1->getNet()->getOwner())) + } else if (isPG(rect1->getNet()->getOwner())) { reqSpcVal = std::max(conSamenet->getMinSpacing(), minSpcVal); + } + } + } + } + } + if (currLayer->hasSpacingRangeConstraints() + && rect2->getNet() != rect1->getNet()) { + for (const auto& con : currLayer->getSpacingRangeConstraints()) { + if (con->inRange(width1) || con->inRange(width2)) { + if (con->getMinSpacing() > reqSpcVal) { + isSpcRange = true; + reqSpcVal = con->getMinSpacing(); } } } @@ -378,11 +412,11 @@ bool FlexGCWorker::Impl::checkMetalSpacing_prl_hasPolyEdge( } if ((type == 0 || type == 2) && (flagB && flagT)) { return true; - } else if ((type == 1 || type == 2) && (flagL && flagR)) { + } + if ((type == 1 || type == 2) && (flagL && flagR)) { return true; - } else { - return false; } + return false; } std::string rectToString(gcRect& r) { @@ -409,17 +443,19 @@ void FlexGCWorker::Impl::checkMetalSpacing_prl( auto layerNum = rect1->getLayerNum(); auto net1 = rect1->getNet(); auto net2 = rect2->getNet(); - - auto reqSpcVal = checkMetalSpacing_prl_getReqSpcVal(rect1, rect2, prl); + bool isSpcRange = false; + auto reqSpcVal + = checkMetalSpacing_prl_getReqSpcVal(rect1, rect2, prl, isSpcRange); if (checkNDRs) { frCoord ndrSpc1 = 0, ndrSpc2 = 0; - if (!rect1->isFixed() && net1->isNondefault() && !rect1->isTapered()) + if (!rect1->isFixed() && net1->isNondefault() && !rect1->isTapered()) { ndrSpc1 = net1->getFrNet()->getNondefaultRule()->getSpacing(layerNum / 2 - 1); - if (!rect2->isFixed() && net2->isNondefault() && !rect2->isTapered()) + } + if (!rect2->isFixed() && net2->isNondefault() && !rect2->isTapered()) { ndrSpc2 = net2->getFrNet()->getNondefaultRule()->getSpacing(layerNum / 2 - 1); - + } reqSpcVal = std::max(reqSpcVal, std::max(ndrSpc1, ndrSpc2)); } @@ -445,46 +481,12 @@ void FlexGCWorker::Impl::checkMetalSpacing_prl( return; } // no violation if bloat width cannot find non-fixed route shapes - bool hasRoute = false; - if (!hasRoute) { - // marker enlarged by width - auto width = rect1->width(); - gtl::rectangle_data enlargedMarkerRect(markerRect); - gtl::bloat(enlargedMarkerRect, width); - // widthrect - gtl::polygon_90_set_data tmpPoly; - using namespace boost::polygon::operators; - tmpPoly += enlargedMarkerRect; - tmpPoly &= *rect1; // tmpPoly now is widthrect - auto targetArea = gtl::area(tmpPoly); - // get fixed shapes - tmpPoly &= net1->getPolygons(layerNum, true); - if (gtl::area(tmpPoly) < targetArea) { - hasRoute = true; - } - } - if (!hasRoute) { - // marker enlarged by width - auto width = rect2->width(); - gtl::rectangle_data enlargedMarkerRect(markerRect); - gtl::bloat(enlargedMarkerRect, width); - // widthrect - gtl::polygon_90_set_data tmpPoly; - using namespace boost::polygon::operators; - tmpPoly += enlargedMarkerRect; - tmpPoly &= *rect2; // tmpPoly now is widthrect - auto targetArea = gtl::area(tmpPoly); - // get fixed shapes - tmpPoly &= net2->getPolygons(layerNum, true); - if (gtl::area(tmpPoly) < targetArea) { - hasRoute = true; - } - } - if (!hasRoute) { + if (!hasRoute(rect1, markerRect) && !hasRoute(rect2, markerRect)) { return; } } else { - using namespace boost::polygon::operators; + using boost::polygon::operators::operator+=; + using boost::polygon::operators::operator-=; auto& netPoly = net1->getPolygons( layerNum, false); // consider net1 since spc rect is always rect1 gtl::polygon_90_set_data markerPoly; @@ -504,8 +506,9 @@ void FlexGCWorker::Impl::checkMetalSpacing_prl( } markerPoly += mRect; markerPoly -= netPoly; - if (markerPoly.size() == 0) + if (markerPoly.empty()) { return; + } // check if the edge related to the 0 width is within the net shape (this // is an indirect check) std::vector> rects; @@ -513,19 +516,22 @@ void FlexGCWorker::Impl::checkMetalSpacing_prl( if (rects.size() == 1) { if (isX) { if (gtl::xl(rects[0]) == gtl::xl(markerRect) - || gtl::xh(rects[0]) == gtl::xl(markerRect)) + || gtl::xh(rects[0]) == gtl::xl(markerRect)) { return; + } } else { if (gtl::yl(rects[0]) == gtl::yl(markerRect) - || gtl::yh(rects[0]) == gtl::yl(markerRect)) + || gtl::yh(rects[0]) == gtl::yl(markerRect)) { return; + } } } } else { markerPoly += mRect; markerPoly -= netPoly; - if (markerPoly.size() == 0) + if (markerPoly.empty()) { return; + } } } auto marker = std::make_unique(); @@ -535,7 +541,12 @@ void FlexGCWorker::Impl::checkMetalSpacing_prl( gtl::yh(markerRect)); marker->setBBox(box); marker->setLayerNum(layerNum); - marker->setConstraint(getTech()->getLayer(layerNum)->getMinSpacing()); + if (isSpcRange) { + marker->setConstraint( + getTech()->getLayer(layerNum)->getSpacingRangeConstraints().at(0)); + } else { + marker->setConstraint(getTech()->getLayer(layerNum)->getMinSpacing()); + } marker->addSrc(net1->getOwner()); marker->addVictim(net1->getOwner(), std::make_tuple(rect1->getLayerNum(), @@ -572,10 +583,10 @@ inline gtl::polygon_90_set_data bg2gtl(const polygon_t& p) gtl::polygon_90_data poly; std::vector> points; for (const auto& pt : p.outer()) { - points.push_back(gtl::point_data(pt.x(), pt.y())); + points.emplace_back(pt.x(), pt.y()); } poly.set(points.begin(), points.end()); - using namespace boost::polygon::operators; + using boost::polygon::operators::operator+=; set += poly; return set; } @@ -584,8 +595,9 @@ void FlexGCWorker::Impl::checkMetalSpacing_short_obs( gcRect* rect2, const gtl::rectangle_data& markerRect) { - if (rect1->isFixed() && rect2->isFixed()) + if (rect1->isFixed() && rect2->isFixed()) { return; + } bool isRect1Obs = rect1->getNet()->isBlockage(); bool isRect2Obs = rect2->getNet()->isBlockage(); if (isRect1Obs && isRect2Obs) { @@ -646,7 +658,7 @@ bool FlexGCWorker::Impl::checkMetalSpacing_short_skipFixed( if (gtl::delta(markerRect, gtl::VERTICAL) == 0) { gtl::bloat(bloatMarkerRect, gtl::VERTICAL, 1); } - using namespace boost::polygon::operators; + using boost::polygon::operators::operator&; auto& polys1 = net1->getPolygons(layerNum, false); auto intersection_polys1 = polys1 & bloatMarkerRect; auto& polys2 = net2->getPolygons(layerNum, false); @@ -733,15 +745,18 @@ void FlexGCWorker::Impl::checkMetalSpacing_short( auto layerNum = rect1->getLayerNum(); auto net1 = rect1->getNet(); auto net2 = rect2->getNet(); - if (rect1->isFixed() && rect2->isFixed()) + if (rect1->isFixed() && rect2->isFixed()) { return; + } // skip if marker area does not have route shape, must exclude touching - if (checkMetalSpacing_short_skipFixed(rect1, rect2, markerRect)) + if (checkMetalSpacing_short_skipFixed(rect1, rect2, markerRect)) { return; + } // skip same-net sufficient metal - if (checkMetalSpacing_short_skipSameNet(rect1, rect2, markerRect)) + if (checkMetalSpacing_short_skipSameNet(rect1, rect2, markerRect)) { return; + } auto marker = std::make_unique(); Rect box(gtl::xl(markerRect), @@ -775,24 +790,21 @@ void FlexGCWorker::Impl::checkMetalSpacing_short( addMarker(std::move(marker)); } -void FlexGCWorker::Impl::checkMetalSpacing_main(gcRect* ptr1, - gcRect* ptr2, +void FlexGCWorker::Impl::checkMetalSpacing_main(gcRect* rect1, + gcRect* rect2, bool checkNDRs, bool isSpcRect) { // NSMetal does not need self-intersection // Minimum width rule handled outside this function - if (ptr1 == ptr2) { - return; - } - if (isSkipVia(ptr1) || isSkipVia(ptr2)) { + if (rect1 == rect2) { return; } - gtl::rectangle_data markerRect(*ptr1); - auto distX = gtl::euclidean_distance(markerRect, *ptr2, gtl::HORIZONTAL); - auto distY = gtl::euclidean_distance(markerRect, *ptr2, gtl::VERTICAL); + gtl::rectangle_data markerRect(*rect1); + auto distX = gtl::euclidean_distance(markerRect, *rect2, gtl::HORIZONTAL); + auto distY = gtl::euclidean_distance(markerRect, *rect2, gtl::VERTICAL); - gtl::generalized_intersect(markerRect, *ptr2); + gtl::generalized_intersect(markerRect, *rect2); auto prlX = gtl::delta(markerRect, gtl::HORIZONTAL); auto prlY = gtl::delta(markerRect, gtl::VERTICAL); @@ -814,15 +826,15 @@ void FlexGCWorker::Impl::checkMetalSpacing_main(gcRect* ptr1, if (prlY == 0) { gtl::bloat(markerRect, gtl::VERTICAL, 1); } - if (ptr1->getNet()->isBlockage() || ptr2->getNet()->isBlockage()) { - checkMetalSpacing_short_obs(ptr1, ptr2, markerRect); + if (rect1->getNet()->isBlockage() || rect2->getNet()->isBlockage()) { + checkMetalSpacing_short_obs(rect1, rect2, markerRect); } else { - checkMetalSpacing_short(ptr1, ptr2, markerRect); + checkMetalSpacing_short(rect1, rect2, markerRect); } // prl } else { - checkMetalSpacing_prl(ptr1, - ptr2, + checkMetalSpacing_prl(rect1, + rect2, markerRect, std::max(prlX, prlY), distX, @@ -832,78 +844,18 @@ void FlexGCWorker::Impl::checkMetalSpacing_main(gcRect* ptr1, } } -void FlexGCWorker::Impl::checkMetalSpacingRange(gcRect* rect, - frSpacingRangeConstraint* con) -{ - auto minSpc = con->getMinSpacing(); - frSquaredDistance reqSpcValSquare = minSpc * (frSquaredDistance) minSpc; - box_t queryBox; - myBloat(*rect, minSpc, queryBox); - auto& workerRegionQuery = getWorkerRegionQuery(); - std::vector> result; - workerRegionQuery.queryMaxRectangle(queryBox, rect->getLayerNum(), result); - for (auto& [objBox, ptr] : result) { - if (ptr == rect) { - continue; - } - if (ptr->isFixed() && rect->isFixed()) { - continue; - } - if (!con->inRange(ptr->width())) { - continue; - } - frSquaredDistance distSquare = gtl::square_euclidean_distance(*rect, *ptr); - if (distSquare >= reqSpcValSquare) { - continue; - } - // Make marker - auto net1 = rect->getNet(); - auto net2 = ptr->getNet(); - gtl::rectangle_data markerRect(*rect); - gtl::generalized_intersect(markerRect, *ptr); - auto marker = std::make_unique(); - Rect box(gtl::xl(markerRect), - gtl::yl(markerRect), - gtl::xh(markerRect), - gtl::yh(markerRect)); - marker->setBBox(box); - marker->setLayerNum(rect->getLayerNum()); - marker->setConstraint(con); - marker->addSrc(net1->getOwner()); - marker->addVictim( - net1->getOwner(), - std::make_tuple( - rect->getLayerNum(), - Rect( - gtl::xl(*rect), gtl::yl(*rect), gtl::xh(*rect), gtl::yh(*rect)), - rect->isFixed())); - marker->addSrc(net2->getOwner()); - marker->addAggressor( - net2->getOwner(), - std::make_tuple( - ptr->getLayerNum(), - Rect(gtl::xl(*ptr), gtl::yl(*ptr), gtl::xh(*ptr), gtl::yh(*ptr)), - ptr->isFixed())); - addMarker(std::move(marker)); - } -} - -void FlexGCWorker::Impl::checkMetalSpacingRange(gcRect* rect) -{ - auto layer = getTech()->getLayer(rect->getLayerNum()); - for (auto con : layer->getSpacingRangeConstraints()) { - if (con->inRange(rect->width())) { - checkMetalSpacingRange(rect, con); - } - } -} - void FlexGCWorker::Impl::checkMetalSpacing_main(gcRect* rect, bool checkNDRs, bool isSpcRect) { auto layerNum = rect->getLayerNum(); auto maxSpcVal = checkMetalSpacing_getMaxSpcVal(layerNum, checkNDRs); + for (const auto& con : + getTech()->getLayer(layerNum)->getSpacingRangeConstraints()) { + if (con->inRange(rect->width())) { + maxSpcVal = std::max(maxSpcVal, con->getMinSpacing()); + } + } box_t queryBox; myBloat(*rect, maxSpcVal, queryBox); @@ -944,14 +896,23 @@ void FlexGCWorker::Impl::checkMetalSpacing() for (auto& maxrect : pin->getMaxRectangles()) { checkMetalSpacing_main(maxrect.get(), getDRWorker() || !AUTO_TAPER_NDR_NETS); - if (currLayer->hasSpacingRangeConstraints()) { - checkMetalSpacingRange(maxrect.get()); + if (currLayer->hasTwoWiresForbiddenSpacingConstraints()) { + for (auto con : + currLayer->getTwoWiresForbiddenSpacingConstraints()) { + checkTwoWiresForbiddenSpc_main(maxrect.get(), con); + } + } + if (currLayer->hasForbiddenSpacingConstraints()) { + for (auto con : currLayer->getForbiddenSpacingConstraints()) { + checkForbiddenSpc_main(maxrect.get(), con); + } } } } - for (auto& sr : targetNet_->getSpecialSpcRects()) + for (auto& sr : targetNet_->getSpecialSpcRects()) { checkMetalSpacing_main( sr.get(), getDRWorker() || !AUTO_TAPER_NDR_NETS, true); + } } } else { // layer --> net --> polygon --> maxrect @@ -973,14 +934,23 @@ void FlexGCWorker::Impl::checkMetalSpacing() // Short, NSMetal, metSpc checkMetalSpacing_main(maxrect.get(), getDRWorker() || !AUTO_TAPER_NDR_NETS); - if (currLayer->hasSpacingRangeConstraints()) { - checkMetalSpacingRange(maxrect.get()); + if (currLayer->hasTwoWiresForbiddenSpacingConstraints()) { + for (auto con : + currLayer->getTwoWiresForbiddenSpacingConstraints()) { + checkTwoWiresForbiddenSpc_main(maxrect.get(), con); + } + } + if (currLayer->hasForbiddenSpacingConstraints()) { + for (auto con : currLayer->getForbiddenSpacingConstraints()) { + checkForbiddenSpc_main(maxrect.get(), con); + } } } } - for (auto& sr : net->getSpecialSpcRects()) + for (auto& sr : net->getSpecialSpcRects()) { checkMetalSpacing_main( sr.get(), getDRWorker() || !AUTO_TAPER_NDR_NETS, true); + } } } } @@ -1180,29 +1150,38 @@ void FlexGCWorker::Impl::checkMetalCornerSpacing_main( if (con->getCornerType() == frCornerTypeEnum::CONVEX) { if (cornerX >= (candX = gtl::xh(*rect))) { if (cornerY >= (candY = gtl::yh(*rect))) { - if (corner->getDir() != frCornerDirEnum::SW) + if (corner->getDir() != frCornerDirEnum::SW) { return; + } } else if (cornerY <= (candY = gtl::yl(*rect))) { - if (corner->getDir() != frCornerDirEnum::NW) + if (corner->getDir() != frCornerDirEnum::NW) { return; - } else + } + } else { return; + } } else if (cornerX <= (candX = gtl::xl(*rect))) { if (cornerY >= (candY = gtl::yh(*rect))) { - if (corner->getDir() != frCornerDirEnum::SE) + if (corner->getDir() != frCornerDirEnum::SE) { return; + } } else if (cornerY <= (candY = gtl::yl(*rect))) { - if (corner->getDir() != frCornerDirEnum::NE) + if (corner->getDir() != frCornerDirEnum::NE) { return; - } else + } + } else { return; - } else + } + } else { return; + } // The corner of the rect has to be convex // TODO: detect concave corners if (rect->getNet() - && !rect->getNet()->hasPolyCornerAt(candX, candY, rect->getLayerNum())) + && !rect->getNet()->hasPolyCornerAt( + candX, candY, rect->getLayerNum())) { return; + } } // skip for EXCEPTEOL eolWidth if (con->hasExceptEol()) { @@ -1262,8 +1241,9 @@ void FlexGCWorker::Impl::checkMetalCornerSpacing_main( = gtl::square_euclidean_distance(*rect, point); frSquaredDistance reqSpcValSquare = reqSpcVal * (frSquaredDistance) reqSpcVal; - if (distSquare >= reqSpcValSquare) + if (distSquare >= reqSpcValSquare) { continue; + } } else if (maxXY >= reqSpcVal) { continue; } @@ -1282,7 +1262,8 @@ void FlexGCWorker::Impl::checkMetalCornerSpacing_main( gtl::bloat(enlargedMarkerRect, width); // widthrect gtl::polygon_90_set_data tmpPoly; - using namespace boost::polygon::operators; + using boost::polygon::operators::operator+=; + using boost::polygon::operators::operator&=; tmpPoly += enlargedMarkerRect; tmpPoly &= *objPtr; // tmpPoly now is widthrect auto targetArea = gtl::area(tmpPoly); @@ -1300,7 +1281,8 @@ void FlexGCWorker::Impl::checkMetalCornerSpacing_main( gtl::bloat(enlargedMarkerRect, width); // widthrect gtl::polygon_90_set_data tmpPoly; - using namespace boost::polygon::operators; + using boost::polygon::operators::operator+=; + using boost::polygon::operators::operator&=; tmpPoly += enlargedMarkerRect; tmpPoly &= *rect; // tmpPoly now is widthrect auto targetArea = gtl::area(tmpPoly); @@ -1341,8 +1323,6 @@ void FlexGCWorker::Impl::checkMetalCornerSpacing_main( rect->isFixed())); addMarker(std::move(marker)); return; - } else { - // TODO: implement others if necessary } } } @@ -1438,7 +1418,7 @@ void FlexGCWorker::Impl::checkMetalShape_minWidth( } // only show marker if fixed area < marker area { - using namespace boost::polygon::operators; + using boost::polygon::operators::operator&; auto& fixedPolys = net->getPolygons(layerNum, true); auto intersection_fixedPolys = fixedPolys & rect; if (gtl::area(intersection_fixedPolys) == gtl::area(rect)) { @@ -1522,12 +1502,15 @@ bool isConvex(gcSegment* s) } gcSegment* bestSuitable(gcSegment* a, gcSegment* b) { - if (isConvex(a) && !isConvex(b)) + if (isConvex(a) && !isConvex(b)) { return a; - if (isConvex(b) && !isConvex(a)) + } + if (isConvex(b) && !isConvex(a)) { return b; - if (gtl::length(*a) > gtl::length(*b)) + } + if (gtl::length(*a) > gtl::length(*b)) { return a; + } return b; } void FlexGCWorker::Impl::checkMetalShape_minArea(gcPin* pin) @@ -1553,12 +1536,14 @@ void FlexGCWorker::Impl::checkMetalShape_minArea(gcPin* pin) gtl::rectangle_data bbox; gtl::extents(bbox, *pin->getPolygon()); Rect bbox2(gtl::xl(bbox), gtl::yl(bbox), gtl::xh(bbox), gtl::yh(bbox)); - if (!drWorker_->getDrcBox().contains(bbox2)) + if (!drWorker_->getDrcBox().contains(bbox2)) { return; + } for (auto& edges : pin->getPolygonEdges()) { for (auto& edge : edges) { - if (edge->isFixed()) + if (edge->isFixed()) { return; + } } } @@ -1645,6 +1630,95 @@ void FlexGCWorker::Impl::checkMetalShape_lef58MinStep_noBetweenEol( } } +inline void joinSegmentCoords(gcSegment* seg, + frCoord& llx, + frCoord& lly, + frCoord& urx, + frCoord& ury) +{ + llx = std::min(llx, seg->low().x()); + lly = std::min(lly, seg->low().y()); + urx = std::max(urx, seg->low().x()); + ury = std::max(ury, seg->low().y()); + + llx = std::min(llx, seg->high().x()); + lly = std::min(lly, seg->high().y()); + urx = std::max(urx, seg->high().x()); + ury = std::max(ury, seg->high().y()); +} + +void FlexGCWorker::Impl::checkMetalShape_lef58MinStep_minAdjLength( + gcPin* pin, + frLef58MinStepConstraint* con) +{ + auto poly = pin->getPolygon(); + auto layerNum = poly->getLayerNum(); + auto net = poly->getNet(); + if (poly->size() == 4 && con->isExceptRectangle()) { + return; + } + + std::vector startEdges; + auto minStepLength = con->getMinStepLength(); + for (auto& edges : pin->getPolygonEdges()) { + // get the first edge that is >= minstep length + for (auto& e : edges) { + if (gtl::length(*e) < minStepLength) { + startEdges.push_back(e.get()); + } + } + } + for (auto startEdge : startEdges) { + bool violating = false; + auto nextEdge = startEdge->getNextEdge(); + auto prevEdge = startEdge->getPrevEdge(); + if (gtl::length(*(nextEdge)) < con->getMinAdjacentLength() + || gtl::length(*(prevEdge)) < con->getMinAdjacentLength()) { + violating = true; + } + if (con->getNoAdjEol() > -1) { + if (nextEdge->getLowCorner()->getType() == frCornerTypeEnum::CONVEX + && nextEdge->getHighCorner()->getType() == frCornerTypeEnum::CONVEX + && gtl::length(*(nextEdge)) < con->getNoAdjEol()) { + violating = true; + } + if (prevEdge->getLowCorner()->getType() == frCornerTypeEnum::CONVEX + && prevEdge->getHighCorner()->getType() == frCornerTypeEnum::CONVEX + && gtl::length(*(prevEdge)) < con->getNoAdjEol()) { + violating = true; + } + } + // skip if all edges are fixed + if (startEdge->isFixed() && nextEdge->isFixed() && prevEdge->isFixed()) { + continue; + } + if (!violating) { + continue; + } + + // real violation + frCoord llx = startEdge->low().x(); + frCoord lly = startEdge->low().y(); + frCoord urx = startEdge->low().x(); + frCoord ury = startEdge->low().y(); + + joinSegmentCoords(startEdge, llx, lly, urx, ury); + joinSegmentCoords(nextEdge, llx, lly, urx, ury); + joinSegmentCoords(prevEdge, llx, lly, urx, ury); + + auto marker = std::make_unique(); + Rect box(llx, lly, urx, ury); + marker->setBBox(box); + marker->setLayerNum(layerNum); + marker->setConstraint(con); + marker->addSrc(net->getOwner()); + marker->addVictim(net->getOwner(), std::make_tuple(layerNum, box, false)); + marker->addAggressor(net->getOwner(), + std::make_tuple(layerNum, box, false)); + addMarker(std::move(marker)); + } +} + // currently only support nobetweeneol void FlexGCWorker::Impl::checkMetalShape_lef58MinStep(gcPin* pin) { @@ -1653,10 +1727,12 @@ void FlexGCWorker::Impl::checkMetalShape_lef58MinStep(gcPin* pin) // auto net = poly->getNet(); for (auto con : getTech()->getLayer(layerNum)->getLef58MinStepConstraints()) { - if (!con->hasEolWidth()) { - continue; + if (con->hasEolWidth()) { + checkMetalShape_lef58MinStep_noBetweenEol(pin, con); + } + if (con->hasMinAdjacentLength()) { + checkMetalShape_lef58MinStep_minAdjLength(pin, con); } - checkMetalShape_lef58MinStep_noBetweenEol(pin, con); } } @@ -1773,7 +1849,7 @@ void FlexGCWorker::Impl::checkMetalShape_rectOnly(gcPin* pin) std::vector> rects; gtl::polygon_90_set_data polySet; { - using namespace boost::polygon::operators; + using boost::polygon::operators::operator+=; polySet += *poly; } gtl::get_max_rectangles(rects, polySet); @@ -1801,7 +1877,7 @@ void FlexGCWorker::Impl::checkMetalShape_rectOnly(gcPin* pin) gtl::x(corner) + layerMinWidth, gtl::y(corner) + layerMinWidth); { - using namespace boost::polygon::operators; + using boost::polygon::operators::operator&; auto intersectionPolySet = polySet & rect; auto intersectionFixedPolySet = intersectionPolySet & fixedPolys; if (gtl::area(intersectionFixedPolySet) @@ -1846,7 +1922,7 @@ void FlexGCWorker::Impl::checkMetalShape_offGrid(gcPin* pin) // continue if the marker area does not have route shape auto& polys = net->getPolygons(layerNum, false); gtl::rectangle_data markerRect(*maxRect); - using namespace boost::polygon::operators; + using boost::polygon::operators::operator&; auto intersection_polys = polys & markerRect; if (gtl::empty(intersection_polys)) { continue; @@ -1883,7 +1959,7 @@ void FlexGCWorker::Impl::checkMetalShape_minEnclosedArea(gcPin* pin) auto reqArea = con->getArea(); if (gtl::area(hole_poly) < reqArea) { auto& polys = net->getPolygons(layerNum, false); - using namespace boost::polygon::operators; + using boost::polygon::operators::operator&; auto intersection_polys = polys & (*poly); if (gtl::empty(intersection_polys)) { continue; @@ -1954,12 +2030,14 @@ void FlexGCWorker::Impl::checkMetalShape_lef58Area(gcPin* pin) gtl::rectangle_data bbox; gtl::extents(bbox, *pin->getPolygon()); Rect bbox2(gtl::xl(bbox), gtl::yl(bbox), gtl::xh(bbox), gtl::yh(bbox)); - if (!drWorker_->getDrcBox().contains(bbox2)) + if (!drWorker_->getDrcBox().contains(bbox2)) { continue; + } for (auto& edges : pin->getPolygonEdges()) { for (auto& edge : edges) { - if (edge->isFixed()) + if (edge->isFixed()) { continue; + } } } @@ -2010,16 +2088,15 @@ bool FlexGCWorker::Impl::checkMetalShape_lef58Area_exceptRectangle( std::vector> rects; gtl::polygon_90_set_data polySet; { - using namespace boost::polygon::operators; + using boost::polygon::operators::operator+=; polySet += *poly; } gtl::get_max_rectangles(rects, polySet); // rect only is true if (rects.size() == 1) { return false; - } else { - return true; } + return true; } return false; @@ -2034,7 +2111,7 @@ bool FlexGCWorker::Impl::checkMetalShape_lef58Area_rectWidth( std::vector> rects; gtl::polygon_90_set_data polySet; { - using namespace boost::polygon::operators; + using boost::polygon::operators::operator+=; polySet += *poly; } gtl::get_max_rectangles(rects, polySet); @@ -2047,9 +2124,8 @@ bool FlexGCWorker::Impl::checkMetalShape_lef58Area_rectWidth( apply_rect_width_area = std::min(xLen, yLen) <= min_width; check_rect_width = !apply_rect_width_area; return apply_rect_width_area; - } else { - return false; } + return false; } return false; @@ -2069,8 +2145,9 @@ void FlexGCWorker::Impl::checkMetalShape_addPatch(gcPin* pin, int min_area) for (auto& edges : pin->getPolygonEdges()) { for (auto& e : edges) { if (e->isVertical() != prefDirIsVert - && (!chosenEdg || bestSuitable(e.get(), chosenEdg) == e.get())) + && (!chosenEdg || bestSuitable(e.get(), chosenEdg) == e.get())) { chosenEdg = e.get(); + } } } frCoord length = ceil((float) gapArea / chosenEdg->length() @@ -2081,26 +2158,28 @@ void FlexGCWorker::Impl::checkMetalShape_addPatch(gcPin* pin, int min_area) if (prefDirIsVert) { patchBx.set_xlo(-chosenEdg->length() / 2); patchBx.set_xhi(chosenEdg->length() / 2); - patchBx.set_yhi(length); offset.setX((chosenEdg->low().x() + chosenEdg->high().x()) / 2); + offset.setY(chosenEdg->low().y()); if (chosenEdg->getOuterDir() == frDirEnum::N) { - offset.setY(chosenEdg->low().y()); + patchBx.set_yhi(length); } else if (chosenEdg->getOuterDir() == frDirEnum::S) { - offset.setY(chosenEdg->low().y() - length); - } else + patchBx.set_ylo(-length); + } else { logger_->error( DRT, 4500, "Edge outer dir should be either North or South"); + } } else { - patchBx.set_xhi(length); patchBx.set_ylo(-chosenEdg->length() / 2); patchBx.set_yhi(chosenEdg->length() / 2); + offset.setX(chosenEdg->low().x()); offset.setY((chosenEdg->low().y() + chosenEdg->high().y()) / 2); if (chosenEdg->getOuterDir() == frDirEnum::E) { - offset.setX(chosenEdg->low().x()); + patchBx.set_xhi(length); } else if (chosenEdg->getOuterDir() == frDirEnum::W) { - offset.setX(chosenEdg->low().x() - length); - } else + patchBx.set_xlo(-length); + } else { logger_->error(DRT, 4501, "Edge outer dir should be either East or West"); + } } auto patch = std::make_unique(); patch->setLayerNum(layer_idx); @@ -2125,11 +2204,10 @@ void FlexGCWorker::Impl::checkMetalShape_addPatch(gcPin* pin, int min_area) // detect what drNet has objects overlapping with the patch checkMetalShape_patchOwner_helper(patch.get(), dr_nets); } - if (!patch->hasNet()) + if (!patch->hasNet()) { return; + } - Rect shiftedPatch = patchBx; - shiftedPatch.moveTo(offset.x(), offset.y()); pwires_.push_back(std::move(patch)); } @@ -2171,7 +2249,7 @@ void FlexGCWorker::Impl::checkMetalShape_main(gcPin* pin, bool allow_patching) std::vector> rects; gtl::polygon_90_set_data polySet; { - using namespace boost::polygon::operators; + using boost::polygon::operators::operator+=; polySet += *poly; } polySet.get_rectangles(rects, gtl::HORIZONTAL); @@ -2185,8 +2263,9 @@ void FlexGCWorker::Impl::checkMetalShape_main(gcPin* pin, bool allow_patching) } // min area - if (allow_patching) + if (allow_patching) { checkMetalShape_minArea(pin); + } // min step checkMetalShape_minStep(pin); @@ -2204,8 +2283,9 @@ void FlexGCWorker::Impl::checkMetalShape_main(gcPin* pin, bool allow_patching) checkMetalShape_minEnclosedArea(pin); // lef58 area - if (allow_patching) + if (allow_patching) { checkMetalShape_lef58Area(pin); + } } void FlexGCWorker::Impl::checkMetalShape(bool allow_patching) @@ -2271,40 +2351,6 @@ frCoord FlexGCWorker::Impl::checkLef58CutSpacing_getMaxSpcVal( return maxSpcVal; } -frCoord FlexGCWorker::Impl::checkCutSpacing_spc_getReqSpcVal( - gcRect* ptr1, - gcRect* ptr2, - frCutSpacingConstraint* con) -{ - frCoord maxSpcVal = 0; - if (con) { - maxSpcVal = con->getCutSpacing(); - if (con->isAdjacentCuts()) { - auto ptr1LayerNum = ptr1->getLayerNum(); - auto ptr1Layer = getTech()->getLayer(ptr1LayerNum); - if (ptr1->getNet()->isBlockage()) { - frCoord width1 = ptr1->width(); - if (ptr1->getNet()->getDesignRuleWidth() != -1) { - width1 = ptr1->getNet()->getDesignRuleWidth(); - } - if (width1 > int(ptr1Layer->getWidth())) - maxSpcVal = con->getCutWithin(); - } - auto ptr2LayerNum = ptr2->getLayerNum(); - auto ptr2Layer = getTech()->getLayer(ptr2LayerNum); - if (ptr2->getNet()->isBlockage()) { - frCoord width2 = ptr2->width(); - if (ptr2->getNet()->getDesignRuleWidth() != -1) { - width2 = ptr2->getNet()->getDesignRuleWidth(); - } - if (width2 > int(ptr2Layer->getWidth())) - maxSpcVal = con->getCutWithin(); - } - } - } - return maxSpcVal; -} - void FlexGCWorker::Impl::checkCutSpacing_short( gcRect* rect1, gcRect* rect2, @@ -2393,31 +2439,30 @@ void FlexGCWorker::Impl::checkCutSpacing_spc( if (prl <= 0) { return; // skip if parallel overlap but shares the same above/below metal - } else { - box_t queryBox; - myBloat(markerRect, 0, queryBox); - auto& workerRegionQuery = getWorkerRegionQuery(); - std::vector> result; - auto secondLayerNum = rect1->getLayerNum() - 1; - if (secondLayerNum >= getTech()->getBottomLayerNum() - && secondLayerNum <= getTech()->getTopLayerNum()) { - workerRegionQuery.queryMaxRectangle(queryBox, secondLayerNum, result); - } - secondLayerNum = rect1->getLayerNum() + 1; - if (secondLayerNum >= getTech()->getBottomLayerNum() - && secondLayerNum <= getTech()->getTopLayerNum()) { - workerRegionQuery.queryMaxRectangle(queryBox, secondLayerNum, result); - } - for (auto& [objBox, objPtr] : result) { - // TODO why isn't this auto-converted from Rect to box_t? - Rect queryRect(queryBox.min_corner().get<0>(), - queryBox.min_corner().get<1>(), - queryBox.max_corner().get<0>(), - queryBox.max_corner().get<1>()); - if ((objPtr->getNet() == net1 || objPtr->getNet() == net2) - && objBox.contains(queryRect)) { - return; - } + } + box_t queryBox; + myBloat(markerRect, 0, queryBox); + auto& workerRegionQuery = getWorkerRegionQuery(); + std::vector> result; + auto secondLayerNum = rect1->getLayerNum() - 1; + if (secondLayerNum >= getTech()->getBottomLayerNum() + && secondLayerNum <= getTech()->getTopLayerNum()) { + workerRegionQuery.queryMaxRectangle(queryBox, secondLayerNum, result); + } + secondLayerNum = rect1->getLayerNum() + 1; + if (secondLayerNum >= getTech()->getBottomLayerNum() + && secondLayerNum <= getTech()->getTopLayerNum()) { + workerRegionQuery.queryMaxRectangle(queryBox, secondLayerNum, result); + } + for (auto& [objBox, objPtr] : result) { + // TODO why isn't this auto-converted from Rect to box_t? + Rect queryRect(queryBox.min_corner().get<0>(), + queryBox.min_corner().get<1>(), + queryBox.max_corner().get<0>(), + queryBox.max_corner().get<1>()); + if ((objPtr->getNet() == net1 || objPtr->getNet() == net2) + && objBox.contains(queryRect)) { + return; } } } @@ -2428,8 +2473,7 @@ void FlexGCWorker::Impl::checkCutSpacing_spc( } // no violation if spacing satisfied - frSquaredDistance reqSpcValSquare - = checkCutSpacing_spc_getReqSpcVal(rect1, rect2, con); + frSquaredDistance reqSpcValSquare = con->getCutSpacing(); reqSpcValSquare *= reqSpcValSquare; gtl::point_data center1, center2; @@ -2497,8 +2541,7 @@ void FlexGCWorker::Impl::checkCutSpacing_spc_diff_layer( } // no violation if spacing satisfied - frSquaredDistance reqSpcValSquare - = checkCutSpacing_spc_getReqSpcVal(rect1, rect2, con); + frSquaredDistance reqSpcValSquare = con->getCutSpacing(); reqSpcValSquare *= reqSpcValSquare; gtl::point_data center1, center2; @@ -2598,8 +2641,7 @@ void FlexGCWorker::Impl::checkLef58CutSpacing_spc_parallelOverlap( } // no violation if spacing satisfied - frSquaredDistance reqSpcValSquare - = checkLef58CutSpacing_spc_getReqSpcVal(rect1, rect2, con); + frSquaredDistance reqSpcValSquare = con->getCutSpacing(); reqSpcValSquare *= reqSpcValSquare; frSquaredDistance distSquare = 0; @@ -2719,15 +2761,15 @@ bool FlexGCWorker::Impl::checkLef58CutSpacing_spc_hasAdjCuts( if (no_prl || distSquare == 0) { cnt++; } - } else + } else { cnt++; + } } } if (cnt >= reqNumCut) { return true; - } else { - return false; } + return false; } bool FlexGCWorker::Impl::checkLef58CutSpacing_spc_hasTwoCuts( @@ -2738,9 +2780,8 @@ bool FlexGCWorker::Impl::checkLef58CutSpacing_spc_hasTwoCuts( if (checkLef58CutSpacing_spc_hasTwoCuts_helper(rect1, con) && checkLef58CutSpacing_spc_hasTwoCuts_helper(rect2, con)) { return true; - } else { - return false; } + return false; } bool FlexGCWorker::Impl::checkLef58CutSpacing_spc_hasTwoCuts_helper( @@ -2784,43 +2825,8 @@ bool FlexGCWorker::Impl::checkLef58CutSpacing_spc_hasTwoCuts_helper( if (cnt >= reqNumCut) { return true; - } else { - return false; } -} - -frCoord FlexGCWorker::Impl::checkLef58CutSpacing_spc_getReqSpcVal( - gcRect* ptr1, - gcRect* ptr2, - frLef58CutSpacingConstraint* con) -{ - frCoord maxSpcVal = 0; - if (con) { - maxSpcVal = con->getCutSpacing(); - if (con->hasAdjacentCuts()) { - auto ptr1LayerNum = ptr1->getLayerNum(); - auto ptr1Layer = getTech()->getLayer(ptr1LayerNum); - if (ptr1->getNet()->isBlockage()) { - frCoord width1 = ptr1->width(); - if (ptr1->getNet()->getDesignRuleWidth() != -1) { - width1 = ptr1->getNet()->getDesignRuleWidth(); - } - if (width1 > int(ptr1Layer->getWidth())) - maxSpcVal = con->getCutWithin(); - } - auto ptr2LayerNum = ptr2->getLayerNum(); - auto ptr2Layer = getTech()->getLayer(ptr2LayerNum); - if (ptr2->getNet()->isBlockage()) { - frCoord width2 = ptr2->width(); - if (ptr2->getNet()->getDesignRuleWidth() != -1) { - width2 = ptr2->getNet()->getDesignRuleWidth(); - } - if (width2 > int(ptr2Layer->getWidth())) - maxSpcVal = con->getCutWithin(); - } - } - } - return maxSpcVal; + return false; } // only works for GF14 syntax (i.e., TWOCUTS), not full rule support @@ -2917,8 +2923,7 @@ void FlexGCWorker::Impl::checkLef58CutSpacing_spc_adjCut( ; } - frSquaredDistance reqSpcValSquare - = checkLef58CutSpacing_spc_getReqSpcVal(rect1, rect2, con); + frSquaredDistance reqSpcValSquare = con->getCutSpacing(); reqSpcValSquare *= reqSpcValSquare; gtl::point_data center1, center2; @@ -2984,21 +2989,23 @@ void FlexGCWorker::Impl::checkLef58CutSpacing_spc_layer( logger_->warn( DRT, 54, "Unsupported branch STACK in checkLef58CutSpacing_spc_layer."); return; - } else if (con->hasOrthogonalSpacing()) { + } + if (con->hasOrthogonalSpacing()) { logger_->warn(DRT, 55, "Unsupported branch ORTHOGONALSPACING in " "checkLef58CutSpacing_spc_layer."); return; - } else if (con->hasCutClass()) { - ; + } + if (con->hasCutClass()) { if (con->isShortEdgeOnly()) { logger_->warn(DRT, 56, "Unsupported branch SHORTEDGEONLY in " "checkLef58CutSpacing_spc_layer."); return; - } else if (con->isConcaveCorner()) { + } + if (con->isConcaveCorner()) { if (con->hasWidth()) { logger_->warn( DRT, @@ -3358,11 +3365,7 @@ bool FlexGCWorker::Impl::checkCutSpacing_main_hasAdjCuts( cnt++; } } - if (cnt >= reqNumCut) { - return true; - } else { - return false; - } + return cnt >= reqNumCut; } void FlexGCWorker::Impl::checkLef58CutSpacing_main( @@ -3468,34 +3471,43 @@ void FlexGCWorker::Impl::checkCutSpacing_main(gcRect* rect) } // LEF58_SPACINGTABLE - if (layer->hasLef58SameMetalCutSpcTblConstraint()) + if (layer->hasLef58SameMetalCutSpcTblConstraint()) { checkLef58CutSpacingTbl(rect, layer->getLef58SameMetalCutSpcTblConstraint()); - if (layer->hasLef58SameNetCutSpcTblConstraint()) + } + if (layer->hasLef58SameNetCutSpcTblConstraint()) { checkLef58CutSpacingTbl(rect, layer->getLef58SameNetCutSpcTblConstraint()); - if (layer->hasLef58DiffNetCutSpcTblConstraint()) + } + if (layer->hasLef58DiffNetCutSpcTblConstraint()) { checkLef58CutSpacingTbl(rect, layer->getLef58DiffNetCutSpcTblConstraint()); - if (layer->hasLef58SameNetInterCutSpcTblConstraint()) + } + if (layer->hasLef58SameNetInterCutSpcTblConstraint()) { checkLef58CutSpacingTbl(rect, layer->getLef58SameNetInterCutSpcTblConstraint()); - if (layer->hasLef58SameMetalInterCutSpcTblConstraint()) + } + if (layer->hasLef58SameMetalInterCutSpcTblConstraint()) { checkLef58CutSpacingTbl(rect, layer->getLef58SameMetalInterCutSpcTblConstraint()); - if (layer->hasLef58DefaultInterCutSpcTblConstraint()) + } + if (layer->hasLef58DefaultInterCutSpcTblConstraint()) { checkLef58CutSpacingTbl(rect, layer->getLef58DefaultInterCutSpcTblConstraint()); + } if (layer->getLayerNum() + 2 < TOP_ROUTING_LAYER && layer->getLayerNum() + 2 < getTech()->getLayers().size()) { auto aboveLayer = getTech()->getLayer(layer->getLayerNum() + 2); - if (aboveLayer->hasLef58SameNetInterCutSpcTblConstraint()) + if (aboveLayer->hasLef58SameNetInterCutSpcTblConstraint()) { checkLef58CutSpacingTbl( rect, aboveLayer->getLef58SameNetInterCutSpcTblConstraint()); - if (aboveLayer->hasLef58SameMetalInterCutSpcTblConstraint()) + } + if (aboveLayer->hasLef58SameMetalInterCutSpcTblConstraint()) { checkLef58CutSpacingTbl( rect, aboveLayer->getLef58SameMetalInterCutSpcTblConstraint()); - if (aboveLayer->hasLef58DefaultInterCutSpcTblConstraint()) + } + if (aboveLayer->hasLef58DefaultInterCutSpcTblConstraint()) { checkLef58CutSpacingTbl( rect, aboveLayer->getLef58DefaultInterCutSpcTblConstraint()); + } } } @@ -3515,6 +3527,7 @@ void FlexGCWorker::Impl::checkCutSpacing() for (auto& pin : targetNet_->getPins(i)) { for (auto& maxrect : pin->getMaxRectangles()) { checkCutSpacing_main(maxrect.get()); + checkLef58Enclosure_main(maxrect.get()); } } } @@ -3533,6 +3546,7 @@ void FlexGCWorker::Impl::checkCutSpacing() for (auto& pin : net->getPins(i)) { for (auto& maxrect : pin->getMaxRectangles()) { checkCutSpacing_main(maxrect.get()); + checkLef58Enclosure_main(maxrect.get()); } } } @@ -3671,8 +3685,9 @@ void FlexGCWorker::Impl::patchMetalShape_minStep() drNet* net = nullptr; auto& workerRegionQuery = getDRWorker()->getWorkerRegionQuery(); Rect markerBBox = marker->getBBox(); - if ((int) markerBBox.maxDXDY() < (frCoord) layer->getWidth()) + if ((int) markerBBox.maxDXDY() < (frCoord) layer->getWidth()) { continue; + } workerRegionQuery.query(markerBBox, lNum, results); std::map> vias; for (auto& connFig : results) { @@ -3697,10 +3712,11 @@ void FlexGCWorker::Impl::patchMetalShape_minStep() bool downViaFound = false; for (auto obj : objs) { frLayerNum cutLayerNum = obj->getViaDef()->getCutLayerNum(); - if (cutLayerNum == lNum + 1) + if (cutLayerNum == lNum + 1) { upViaFound = true; - else + } else { downViaFound = true; + } if (upViaFound && downViaFound) { net = obj->getNet(); origin = tmpOrigin; @@ -3762,14 +3778,17 @@ void FlexGCWorker::Impl::checkMinimumCut_main(gcRect* rect) auto width = rect->width(); auto length = rect->length(); for (auto con : layer->getMinimumcutConstraints()) { - if (width < con->getWidth()) + if (width < con->getWidth()) { continue; - if (con->hasLength() && length < con->getLength()) + } + if (con->hasLength() && length < con->getLength()) { continue; + } auto& workerRegionQuery = getWorkerRegionQuery(); gtl::rectangle_data queryBox = *rect; - if (con->hasLength()) + if (con->hasLength()) { gtl::bloat(queryBox, con->getDistance()); + } std::vector> result; if (con->getConnection() != frMinimumcutConnectionEnum::FROMABOVE && layerNum > getTech()->getBottomLayerNum()) { @@ -3787,12 +3806,15 @@ void FlexGCWorker::Impl::checkMinimumCut_main(gcRect* rect) Rect wideRect( gtl::xl(*rect), gtl::yl(*rect), gtl::xh(*rect), gtl::yh(*rect)); for (auto [viaBox, via] : result) { - if (via->getNet() != rect->getNet()) + if (via->getNet() != rect->getNet()) { continue; - if (via->isFixed() && rect->isFixed()) + } + if (via->isFixed() && rect->isFixed()) { continue; - if (con->hasLength() && wideRect.contains(viaBox)) + } + if (con->hasLength() && wideRect.contains(viaBox)) { continue; + } if (!con->hasLength()) { checkMinimumCut_marker(rect, via, con); continue; @@ -3802,16 +3824,18 @@ void FlexGCWorker::Impl::checkMinimumCut_main(gcRect* rect) bool viol = false; for (auto [encBox, encObj] : encResult) { - if (encObj->getNet() != via->getNet()) + if (encObj->getNet() != via->getNet()) { continue; + } if (encBox.intersects(viaBox) && encBox.intersects(wideRect)) { viol = true; break; } } - if (viol) + if (viol) { checkMinimumCut_marker(rect, via, con); + } } } } @@ -3826,10 +3850,12 @@ void FlexGCWorker::Impl::checkMinimumCut() <= std::min((frLayerNum) (getTech()->getTopLayerNum()), maxLayerNum_); i++) { auto currLayer = getTech()->getLayer(i); - if (currLayer->getType() != dbTechLayerType::ROUTING) + if (currLayer->getType() != dbTechLayerType::ROUTING) { continue; - if (!currLayer->hasMinimumcut()) + } + if (!currLayer->hasMinimumcut()) { continue; + } for (auto& pin : targetNet_->getPins(i)) { for (auto& maxrect : pin->getMaxRectangles()) { checkMinimumCut_main(maxrect.get()); @@ -3844,10 +3870,12 @@ void FlexGCWorker::Impl::checkMinimumCut() <= std::min((frLayerNum) (getTech()->getTopLayerNum()), maxLayerNum_); i++) { auto currLayer = getTech()->getLayer(i); - if (currLayer->getType() != dbTechLayerType::ROUTING) + if (currLayer->getType() != dbTechLayerType::ROUTING) { continue; - if (!currLayer->hasMinimumcut()) + } + if (!currLayer->hasMinimumcut()) { continue; + } for (auto& net : getNets()) { for (auto& pin : net->getPins(i)) { for (auto& maxrect : pin->getMaxRectangles()) { @@ -3859,13 +3887,115 @@ void FlexGCWorker::Impl::checkMinimumCut() } } +void FlexGCWorker::Impl::checkTwoWiresForbiddenSpc_main( + gcRect* rect, + frLef58TwoWiresForbiddenSpcConstraint* con) +{ + bool isH = getTech()->getLayer(rect->getLayerNum())->getDir() + == odb::dbTechLayerDir::HORIZONTAL; + auto width1 = rect->width(); + bool validMinSpanLength1 = con->isValidForMinSpanLength(width1); + bool validMaxSpanLength1 = con->isValidForMaxSpanLength(width1); + if (!validMinSpanLength1 && !validMaxSpanLength1) { + return; + } + box_t queryBox; + myBloat(*rect, con->getODBRule()->getMaxSpacing(), queryBox); + auto& workerRegionQuery = getWorkerRegionQuery(); + std::vector> result; + workerRegionQuery.queryMaxRectangle(queryBox, rect->getLayerNum(), result); + for (auto& [objBox, ptr] : result) { + if (rect == ptr) { + continue; + } + if (rect->isFixed() && ptr->isFixed()) { + continue; + } + auto width2 = ptr->width(); + bool validMinSpanLength2 = con->isValidForMinSpanLength(width2); + bool validMaxSpanLength2 = con->isValidForMaxSpanLength(width2); + if (!(validMinSpanLength1 && validMaxSpanLength2) + && !(validMaxSpanLength1 && validMinSpanLength2)) { + continue; + } + gtl::rectangle_data markerRect(*rect); + gtl::generalized_intersect(markerRect, *ptr); + auto prlX = gtl::delta(markerRect, gtl::HORIZONTAL); + auto prlY = gtl::delta(markerRect, gtl::VERTICAL); + auto distX = gtl::euclidean_distance(*rect, *ptr, gtl::HORIZONTAL); + auto distY = gtl::euclidean_distance(*rect, *ptr, gtl::VERTICAL); + // skip short violations + if (distX == 0 && distY == 0) { + continue; + } + if (distX) { + prlX = -prlX; + } + if (distY) { + prlY = -prlY; + } + if (!con->isValidPrl(isH ? prlX : prlY)) { + continue; + } + if (!con->isForbiddenSpacing(isH ? distY : distX)) { + continue; + } + + int type = 0; + if (std::max(prlX, prlY) <= 0) { + type = 2; + } else { + if (distX == 0) { + type = 0; + } else if (distY == 0) { + type = 1; + } + } + if (!checkMetalSpacing_prl_hasPolyEdge( + rect, ptr, markerRect, type, std::max(prlX, prlY))) { + continue; + ; + } + if (!hasRoute(rect, markerRect) && !hasRoute(ptr, markerRect)) { + continue; + } + // add violation + auto marker = std::make_unique(); + Rect box(gtl::xl(markerRect), + gtl::yl(markerRect), + gtl::xh(markerRect), + gtl::yh(markerRect)); + marker->setBBox(box); + marker->setLayerNum(rect->getLayerNum()); + marker->setConstraint(con); + marker->addSrc(rect->getNet()->getOwner()); + marker->addVictim( + rect->getNet()->getOwner(), + std::make_tuple( + rect->getLayerNum(), + Rect( + gtl::xl(*rect), gtl::yl(*rect), gtl::xh(*rect), gtl::yh(*rect)), + rect->isFixed())); + marker->addSrc(ptr->getNet()->getOwner()); + marker->addAggressor( + ptr->getNet()->getOwner(), + std::make_tuple( + ptr->getLayerNum(), + Rect(gtl::xl(*ptr), gtl::yl(*ptr), gtl::xh(*ptr), gtl::yh(*ptr)), + ptr->isFixed())); + addMarker(std::move(marker)); + } +} + void FlexGCWorker::Impl::modifyMarkers() { - if (!surgicalFixEnabled_ || pwires_.empty()) + if (!surgicalFixEnabled_ || pwires_.empty()) { return; + } for (auto& pwire : pwires_) { - if (!pwire->hasNet()) + if (!pwire->hasNet()) { continue; + } Point origin = pwire->getOrigin(); auto net = pwire->getNet()->getFrNet(); for (auto& marker : markers_) { @@ -3899,10 +4029,12 @@ int FlexGCWorker::Impl::main() if (surgicalFixEnabled_ && getDRWorker()) { checkMetalShape(true); // minStep patching for GF14 - if (tech_->hasVia2ViaMinStep() || tech_->hasCornerSpacingConstraint()) + if (tech_->hasVia2ViaMinStep() || tech_->hasCornerSpacingConstraint()) { patchMetalShape(); - if (!pwires_.empty()) + } + if (!pwires_.empty()) { updateGCWorker(); + } } // clear existing markers clearMarkers(); @@ -3914,7 +4046,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(); @@ -3926,3 +4058,5 @@ int FlexGCWorker::Impl::main() modifyMarkers(); return 0; } + +} // namespace drt diff --git a/src/drt/src/global.cpp b/src/drt/src/global.cpp index d40cf88fe11..14b4578f084 100644 --- a/src/drt/src/global.cpp +++ b/src/drt/src/global.cpp @@ -38,7 +38,7 @@ #include "db/obj/frMaster.h" #include "frDesign.h" -using namespace fr; +namespace drt { std::string OUT_MAZE_FILE; std::string DRC_RPT_FILE; @@ -50,7 +50,7 @@ std::string GUIDE_REPORT_FILE; int OR_SEED = -1; double OR_K = 0; -std::string DBPROCESSNODE = ""; +std::string DBPROCESSNODE; int MAX_THREADS = 1; int BATCHSIZE = 1024; int BATCHSIZETA = 8; @@ -93,7 +93,6 @@ int CLOCK_NETS_LEAF_RIPUP_HARDINESS = 10; bool AUTO_TAPER_NDR_NETS = true; int TAPERBOX_RADIUS = 3; -frUInt4 TAVIACOST = 1; frUInt4 TAPINCOST = 4; frUInt4 TAALIGNCOST = 4; frUInt4 TADRCCOST = 32; @@ -108,15 +107,12 @@ frUInt4 MARKERBLOATWIDTH = 1; frUInt4 BLOCKCOST = 32; frUInt4 GUIDECOST = 1; // disabled change getNextPathCost to enable float SHAPEBLOATWIDTH = 3; -int MISALIGNMENTCOST = 8; int CONGCOST = 8; int HISTCOST = 32; -std::string REPAIR_PDN_LAYER_BEGIN_NAME; -std::string REPAIR_PDN_LAYER_END_NAME; -frLayerNum GC_IGNORE_PDN_BEGIN_LAYER = -1; -frLayerNum GC_IGNORE_PDN_END_LAYER = -1; -namespace fr { +std::string REPAIR_PDN_LAYER_NAME; +frLayerNum REPAIR_PDN_LAYER_NUM = -1; +frLayerNum GC_IGNORE_PDN_LAYER_NUM = -1; std::ostream& operator<<(std::ostream& os, const frRect& pinFigIn) { @@ -246,7 +242,7 @@ std::ostream& operator<<(std::ostream& os, const frInst& instIn) { Point tmpPoint = instIn.getOrigin(); auto tmpOrient = instIn.getOrient(); - frString tmpName = instIn.getName(); + const frString& tmpName = instIn.getName(); frString tmpString = instIn.getMaster()->getName(); os << "- " << tmpName << " " << tmpString << " + STATUS + ( " << tmpPoint.x() << " " << tmpPoint.y() << " ) " << tmpOrient.getString() << std::endl; @@ -496,4 +492,4 @@ std::ostream& operator<<(std::ostream& os, const frMarker& m) } } -} // end namespace fr +} // end namespace drt diff --git a/src/drt/src/global.h b/src/drt/src/global.h index aa5beb5b615..180af0eb830 100644 --- a/src/drt/src/global.h +++ b/src/drt/src/global.h @@ -37,6 +37,13 @@ #include "db/obj/frMarker.h" #include "frBaseTypes.h" +namespace odb { +class Point; +class Rect; +} // namespace odb + +namespace drt { + extern std::string DBPROCESSNODE; extern std::string OUT_MAZE_FILE; extern std::string DRC_RPT_FILE; @@ -66,13 +73,12 @@ extern bool CLEAN_PATCHES; extern bool DO_PA; extern bool SINGLE_STEP_DR; extern bool SAVE_GUIDE_UPDATES; -// extern int TEST; extern std::string VIAINPIN_BOTTOMLAYER_NAME; extern std::string VIAINPIN_TOPLAYER_NAME; -extern fr::frLayerNum VIAINPIN_BOTTOMLAYERNUM; -extern fr::frLayerNum VIAINPIN_TOPLAYERNUM; +extern frLayerNum VIAINPIN_BOTTOMLAYERNUM; +extern frLayerNum VIAINPIN_TOPLAYERNUM; -extern fr::frLayerNum VIA_ACCESS_LAYERNUM; +extern frLayerNum VIA_ACCESS_LAYERNUM; extern int MINNUMACCESSPOINT_MACROCELLPIN; extern int MINNUMACCESSPOINT_STDCELLPIN; @@ -90,95 +96,81 @@ extern int TAPERBOX_RADIUS; extern int NDR_NETS_ABS_PRIORITY; extern int CLOCK_NETS_ABS_PRIORITY; -extern fr::frUInt4 TAVIACOST; -extern fr::frUInt4 TAPINCOST; -extern fr::frUInt4 TAALIGNCOST; -extern fr::frUInt4 TADRCCOST; +extern frUInt4 TAPINCOST; +extern frUInt4 TAALIGNCOST; +extern frUInt4 TADRCCOST; extern float TASHAPEBLOATWIDTH; -extern fr::frUInt4 VIACOST; +extern frUInt4 VIACOST; -extern fr::frUInt4 GRIDCOST; -extern fr::frUInt4 ROUTESHAPECOST; -extern fr::frUInt4 MARKERCOST; -extern fr::frUInt4 MARKERBLOATWIDTH; -extern fr::frUInt4 BLOCKCOST; -extern fr::frUInt4 GUIDECOST; +extern frUInt4 GRIDCOST; +extern frUInt4 ROUTESHAPECOST; +extern frUInt4 MARKERCOST; +extern frUInt4 MARKERBLOATWIDTH; +extern frUInt4 BLOCKCOST; +extern frUInt4 GUIDECOST; extern float SHAPEBLOATWIDTH; -extern int MISALIGNMENTCOST; // GR extern int HISTCOST; extern int CONGCOST; -extern std::string REPAIR_PDN_LAYER_BEGIN_NAME; -extern std::string REPAIR_PDN_LAYER_END_NAME; -extern fr::frLayerNum GC_IGNORE_PDN_BEGIN_LAYER; -extern fr::frLayerNum GC_IGNORE_PDN_END_LAYER; +extern std::string REPAIR_PDN_LAYER_NAME; +extern frLayerNum REPAIR_PDN_LAYER_NUM; +extern frLayerNum GC_IGNORE_PDN_LAYER_NUM; -#define DIRBITSIZE 3 -#define WAVEFRONTBUFFERSIZE 2 -#define WAVEFRONTBITSIZE (WAVEFRONTBUFFERSIZE * DIRBITSIZE) -#define WAVEFRONTBUFFERHIGHMASK \ - (111 << ((WAVEFRONTBUFFERSIZE - 1) * DIRBITSIZE)) +constexpr int DIRBITSIZE = 3; +constexpr int WAVEFRONTBUFFERSIZE = 2; +constexpr int WAVEFRONTBITSIZE = (WAVEFRONTBUFFERSIZE * DIRBITSIZE); +constexpr int WAVEFRONTBUFFERHIGHMASK + = (111 << ((WAVEFRONTBUFFERSIZE - 1) * DIRBITSIZE)); // GR -#define GRWAVEFRONTBUFFERSIZE 2 -#define GRWAVEFRONTBITSIZE (GRWAVEFRONTBUFFERSIZE * DIRBITSIZE) -#define GRWAVEFRONTBUFFERHIGHMASK \ - (111 << ((GRWAVEFRONTBUFFERSIZE - 1) * DIRBITSIZE)) +constexpr int GRWAVEFRONTBUFFERSIZE = 2; +constexpr int GRWAVEFRONTBITSIZE = (GRWAVEFRONTBUFFERSIZE * DIRBITSIZE); +constexpr int GRWAVEFRONTBUFFERHIGHMASK + = (111 << ((GRWAVEFRONTBUFFERSIZE - 1) * DIRBITSIZE)); -namespace odb { -class Point; -class Rect; -} // namespace odb - -namespace fr { -frCoord getGCELLGRIDX(); -frCoord getGCELLGRIDY(); -frCoord getGCELLOFFSETX(); -frCoord getGCELLOFFSETY(); - -class frViaDef; +class drConnFig; +class drNet; +class frBPin; +class frBTerm; class frBlock; -class frMaster; +class frBlockObject; +class frConnFig; +class frGuide; class frInst; class frInstTerm; -class frTerm; -class frBTerm; class frMTerm; +class frMaster; +class frNet; +class frPathSeg; class frPin; -class frBPin; -class frRect; class frPolygon; -class frNet; -class drNet; -class drConnFig; +class frRect; class frShape; -class frConnFig; -class frPathSeg; -class frGuide; -class frBlockObject; +class frTerm; +class frViaDef; // These need to be in the fr namespace to support argument-dependent // lookup -std::ostream& operator<<(std::ostream& os, const fr::frViaDef& viaDefIn); -std::ostream& operator<<(std::ostream& os, const fr::frBlock& blockIn); -std::ostream& operator<<(std::ostream& os, const fr::frInst& instIn); -std::ostream& operator<<(std::ostream& os, const fr::frInstTerm& instTermIn); -std::ostream& operator<<(std::ostream& os, const fr::frBTerm& termIn); -std::ostream& operator<<(std::ostream& os, const fr::frRect& pinFig); -std::ostream& operator<<(std::ostream& os, const fr::frPolygon& pinFig); -std::ostream& operator<<(std::ostream& os, const fr::drConnFig& fig); +std::ostream& operator<<(std::ostream& os, const frViaDef& viaDefIn); +std::ostream& operator<<(std::ostream& os, const frBlock& blockIn); +std::ostream& operator<<(std::ostream& os, const frInst& instIn); +std::ostream& operator<<(std::ostream& os, const frInstTerm& instTermIn); +std::ostream& operator<<(std::ostream& os, const frBTerm& termIn); +std::ostream& operator<<(std::ostream& os, const frRect& pinFig); +std::ostream& operator<<(std::ostream& os, const frPolygon& pinFig); +std::ostream& operator<<(std::ostream& os, const drConnFig& fig); std::ostream& operator<<(std::ostream& os, const frShape& fig); std::ostream& operator<<(std::ostream& os, const frConnFig& fig); -std::ostream& operator<<(std::ostream& os, const frPathSeg& fig); +std::ostream& operator<<(std::ostream& os, const frPathSeg& p); std::ostream& operator<<(std::ostream& os, const frGuide& p); std::ostream& operator<<(std::ostream& os, const frBlockObject& fig); -std::ostream& operator<<(std::ostream& os, const frNet& fig); +std::ostream& operator<<(std::ostream& os, const frNet& n); std::ostream& operator<<(std::ostream& os, const drNet& n); std::ostream& operator<<(std::ostream& os, const frMarker& m); using utl::format_as; -} // namespace fr +} // namespace drt From e0f76b6061e35c9265ffaacff905409e7d4224e1 Mon Sep 17 00:00:00 2001 From: osamahammad21 Date: Mon, 22 Jul 2024 13:00:03 +0300 Subject: [PATCH 4/4] drt: clang-tidy Signed-off-by: osamahammad21 --- src/drt/src/dr/FlexDR_init.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/drt/src/dr/FlexDR_init.cpp b/src/drt/src/dr/FlexDR_init.cpp index 459b6298f50..4da00ce4537 100644 --- a/src/drt/src/dr/FlexDR_init.cpp +++ b/src/drt/src/dr/FlexDR_init.cpp @@ -3472,8 +3472,9 @@ void FlexDRWorker::initMazeCost_planarTerm(const frDesign* design) for (int i = 0; i < pin->getNumPinAccess(); i++) { const auto& pa = pin->getPinAccess(i); for (const auto& ap : pa->getAccessPoints()) { - if (ap->getLayerNum() != layerNum) + if (ap->getLayerNum() != layerNum) { continue; + } hasVerticalAccess |= ap->hasAccess(frDirEnum::N); hasVerticalAccess |= ap->hasAccess(frDirEnum::S); hasHorizontalAccess |= ap->hasAccess(frDirEnum::W);