diff --git a/src/drt/src/ta/FlexTA.cpp b/src/drt/src/ta/FlexTA.cpp index 1210564261d..d38bb30c8c0 100644 --- a/src/drt/src/ta/FlexTA.cpp +++ b/src/drt/src/ta/FlexTA.cpp @@ -28,6 +28,37 @@ using odb::dbTechLayerType; namespace drt { +namespace { + +constexpr int kMaxTaThreads = 8; + +bool isBottomRoutingLayerHorizontal(frDesign* design) +{ + frLayerNum bottom_layer_num = design->getTech()->getBottomLayerNum(); + auto* bottom_layer = design->getTech()->getLayer(bottom_layer_num); + if (bottom_layer->getType() != dbTechLayerType::ROUTING) { + bottom_layer_num++; + bottom_layer = design->getTech()->getLayer(bottom_layer_num); + } + return bottom_layer->getDir() == dbTechLayerDir::HORIZONTAL; +} + +std::string getOrdinalSuffix(int iter) +{ + if (iter == 1 || (iter > 20 && iter % 10 == 1)) { + return "st"; + } + if (iter == 2 || (iter > 20 && iter % 10 == 2)) { + return "nd"; + } + if (iter == 3 || (iter > 20 && iter % 10 == 3)) { + return "rd"; + } + return "th"; +} + +} // namespace + int FlexTAWorker::main_mt() { ProfileTask profile("TA:main_mt"); @@ -100,91 +131,94 @@ FlexTA::~FlexTA() = default; int FlexTA::initTA_helper(int iter, int size, int offset, - bool isH, - int& numPanels) + bool is_horizontal, + int& num_panels) { - auto gCellPatterns = getDesign()->getTopBlock()->getGCellPatterns(); - auto& xgp = gCellPatterns.at(0); - auto& ygp = gCellPatterns.at(1); - int sol = 0; - numPanels = 0; - std::vector>> workers; - if (isH) { - for (int i = offset; i < (int) ygp.getCount(); i += size) { - auto uworker = std::make_unique( + const auto g_cell_patterns = getDesign()->getTopBlock()->getGCellPatterns(); + const auto& x_gp = g_cell_patterns.at(0); + const auto& y_gp = g_cell_patterns.at(1); + int num_assigned = 0; + num_panels = 0; + std::vector>> worker_batches; + if (is_horizontal) { + for (int i = offset; i < static_cast(y_gp.getCount()); i += size) { + auto worker_uptr = std::make_unique( getDesign(), logger_, router_cfg_, save_updates_); - auto& worker = *(uworker.get()); - odb::Rect beginBox + auto& worker = *worker_uptr; + const odb::Rect begin_box = getDesign()->getTopBlock()->getGCellBox(odb::Point(0, i)); - odb::Rect endBox = getDesign()->getTopBlock()->getGCellBox( - odb::Point((int) xgp.getCount() - 1, - std::min(i + size - 1, (int) ygp.getCount() - 1))); - odb::Rect routeBox( - beginBox.xMin(), beginBox.yMin(), endBox.xMax(), endBox.yMax()); - odb::Rect extBox; - routeBox.bloat(ygp.getSpacing() / 2, extBox); - worker.setRouteBox(routeBox); - worker.setExtBox(extBox); + const odb::Rect end_box + = getDesign()->getTopBlock()->getGCellBox(odb::Point( + static_cast(x_gp.getCount()) - 1, + std::min(i + size - 1, static_cast(y_gp.getCount()) - 1))); + const odb::Rect route_box( + begin_box.xMin(), begin_box.yMin(), end_box.xMax(), end_box.yMax()); + odb::Rect ext_box; + route_box.bloat(y_gp.getSpacing() / 2, ext_box); + worker.setRouteBox(route_box); + worker.setExtBox(ext_box); worker.setDir(dbTechLayerDir::HORIZONTAL); worker.setTAIter(iter); - if (workers.empty() - || (int) workers.back().size() >= router_cfg_->BATCHSIZETA) { - workers.emplace_back(std::vector>()); + if (worker_batches.empty() + || static_cast(worker_batches.back().size()) + >= router_cfg_->BATCHSIZETA) { + worker_batches.emplace_back(); } - workers.back().emplace_back(std::move(uworker)); + worker_batches.back().emplace_back(std::move(worker_uptr)); } } else { - for (int i = offset; i < (int) xgp.getCount(); i += size) { - auto uworker = std::make_unique( + for (int i = offset; i < static_cast(x_gp.getCount()); i += size) { + auto worker_uptr = std::make_unique( getDesign(), logger_, router_cfg_, save_updates_); - auto& worker = *(uworker.get()); - odb::Rect beginBox + auto& worker = *worker_uptr; + const odb::Rect begin_box = getDesign()->getTopBlock()->getGCellBox(odb::Point(i, 0)); - odb::Rect endBox = getDesign()->getTopBlock()->getGCellBox( - odb::Point(std::min(i + size - 1, (int) xgp.getCount() - 1), - (int) ygp.getCount() - 1)); - odb::Rect routeBox( - beginBox.xMin(), beginBox.yMin(), endBox.xMax(), endBox.yMax()); - odb::Rect extBox; - routeBox.bloat(xgp.getSpacing() / 2, extBox); - worker.setRouteBox(routeBox); - worker.setExtBox(extBox); + const odb::Rect end_box + = getDesign()->getTopBlock()->getGCellBox(odb::Point( + std::min(i + size - 1, static_cast(x_gp.getCount()) - 1), + static_cast(y_gp.getCount()) - 1)); + const odb::Rect route_box( + begin_box.xMin(), begin_box.yMin(), end_box.xMax(), end_box.yMax()); + odb::Rect ext_box; + route_box.bloat(x_gp.getSpacing() / 2, ext_box); + worker.setRouteBox(route_box); + worker.setExtBox(ext_box); worker.setDir(dbTechLayerDir::VERTICAL); worker.setTAIter(iter); - if (workers.empty() - || (int) workers.back().size() >= router_cfg_->BATCHSIZETA) { - workers.emplace_back(std::vector>()); + if (worker_batches.empty() + || static_cast(worker_batches.back().size()) + >= router_cfg_->BATCHSIZETA) { + worker_batches.emplace_back(); } - workers.back().push_back(std::move(uworker)); + worker_batches.back().emplace_back(std::move(worker_uptr)); } } - omp_set_num_threads(std::min(8, router_cfg_->MAX_THREADS)); - // parallel execution - // multi thread - for (auto& workerBatch : workers) { + omp_set_num_threads(std::min(kMaxTaThreads, router_cfg_->MAX_THREADS)); + // Execute each worker batch in parallel and merge assignment counts. + for (auto& worker_batch : worker_batches) { ProfileTask profile("TA:batch"); utl::ThreadException exception; #pragma omp parallel for schedule(dynamic) - for (int i = 0; i < (int) workerBatch.size(); i++) { + for (int i = 0; i < static_cast(worker_batch.size()); i++) { try { - workerBatch[i]->main_mt(); + worker_batch[i]->main_mt(); #pragma omp critical { - sol += workerBatch[i]->getNumAssigned(); - numPanels++; + num_assigned += worker_batch[i]->getNumAssigned(); + num_panels++; } } catch (...) { exception.capture(); } } exception.rethrow(); - for (auto& worker : workerBatch) { + for (auto& worker : worker_batch) { worker->end(); } - workerBatch.clear(); + worker_batch.clear(); } - return sol; + return num_assigned; } void FlexTA::initTA(int size) @@ -196,49 +230,43 @@ void FlexTA::initTA(int size) std::cout << std::endl << "start initial track assignment ..." << std::endl; } - auto bottomLNum = getDesign()->getTech()->getBottomLayerNum(); - auto bottomLayer = getDesign()->getTech()->getLayer(bottomLNum); - if (bottomLayer->getType() != dbTechLayerType::ROUTING) { - bottomLNum++; - bottomLayer = getDesign()->getTech()->getLayer(bottomLNum); - } - bool isBottomLayerH = (bottomLayer->isHorizontal()); + const bool is_bottom_layer_h = isBottomRoutingLayerHorizontal(getDesign()); // H first - if (isBottomLayerH) { - int numPanelsH; - int numAssignedH = initTA_helper(0, size, 0, true, numPanelsH); + if (is_bottom_layer_h) { + int num_panels_h; + int num_assigned_h = initTA_helper(0, size, 0, true, num_panels_h); - int numPanelsV; - int numAssignedV = initTA_helper(0, size, 0, false, numPanelsV); + int num_panels_v; + int num_assigned_v = initTA_helper(0, size, 0, false, num_panels_v); if (router_cfg_->VERBOSE > 0) { logger_->info(DRT, 183, "Done with {} horizontal wires in {} frboxes and " "{} vertical wires in {} frboxes.", - numAssignedH, - numPanelsH, - numAssignedV, - numPanelsV); + num_assigned_h, + num_panels_h, + num_assigned_v, + num_panels_v); } // V first } else { - int numPanelsV; - int numAssignedV = initTA_helper(0, size, 0, false, numPanelsV); + int num_panels_v; + int num_assigned_v = initTA_helper(0, size, 0, false, num_panels_v); - int numPanelsH; - int numAssignedH = initTA_helper(0, size, 0, true, numPanelsH); + int num_panels_h; + int num_assigned_h = initTA_helper(0, size, 0, true, num_panels_h); if (router_cfg_->VERBOSE > 0) { logger_->info(DRT, 184, "Done with {} vertical wires in {} frboxes and " "{} horizontal wires in {} frboxes.", - numAssignedV, - numPanelsV, - numAssignedH, - numPanelsH); + num_assigned_v, + num_panels_v, + num_assigned_h, + num_panels_h); } } } @@ -250,61 +278,46 @@ void FlexTA::searchRepair(int iter, int size, int offset) if (router_cfg_->VERBOSE > 1) { std::cout << std::endl << "start " << iter; - std::string suffix; - if (iter == 1 || (iter > 20 && iter % 10 == 1)) { - suffix = "st"; - } else if (iter == 2 || (iter > 20 && iter % 10 == 2)) { - suffix = "nd"; - } else if (iter == 3 || (iter > 20 && iter % 10 == 3)) { - suffix = "rd"; - } else { - suffix = "th"; - } - std::cout << suffix << " optimization iteration ..." << std::endl; - } - auto bottomLNum = getDesign()->getTech()->getBottomLayerNum(); - auto bottomLayer = getDesign()->getTech()->getLayer(bottomLNum); - if (bottomLayer->getType() != dbTechLayerType::ROUTING) { - bottomLNum++; - bottomLayer = getDesign()->getTech()->getLayer(bottomLNum); + std::cout << getOrdinalSuffix(iter) << " optimization iteration ..." + << std::endl; } - bool isBottomLayerH = (bottomLayer->isHorizontal()); + const bool is_bottom_layer_h = isBottomRoutingLayerHorizontal(getDesign()); // H first - if (isBottomLayerH) { - int numPanelsH; - int numAssignedH = initTA_helper(iter, size, offset, true, numPanelsH); + if (is_bottom_layer_h) { + int num_panels_h; + int num_assigned_h = initTA_helper(iter, size, offset, true, num_panels_h); - int numPanelsV; - int numAssignedV = initTA_helper(iter, size, offset, false, numPanelsV); + int num_panels_v; + int num_assigned_v = initTA_helper(iter, size, offset, false, num_panels_v); if (router_cfg_->VERBOSE > 0) { logger_->info(DRT, 268, "Done with {} horizontal wires in {} frboxes and " "{} vertical wires in {} frboxes.", - numAssignedH, - numPanelsH, - numAssignedV, - numPanelsV); + num_assigned_h, + num_panels_h, + num_assigned_v, + num_panels_v); } // V first } else { - int numPanelsV; - int numAssignedV = initTA_helper(iter, size, offset, false, numPanelsV); + int num_panels_v; + int num_assigned_v = initTA_helper(iter, size, offset, false, num_panels_v); - int numPanelsH; - int numAssignedH = initTA_helper(iter, size, offset, true, numPanelsH); + int num_panels_h; + int num_assigned_h = initTA_helper(iter, size, offset, true, num_panels_h); if (router_cfg_->VERBOSE > 0) { logger_->info(DRT, 186, "Done with {} vertical wires in {} frboxes and " "{} horizontal wires in {} frboxes.", - numAssignedV, - numPanelsV, - numAssignedH, - numPanelsH); + num_assigned_v, + num_panels_v, + num_assigned_h, + num_panels_h); } } } diff --git a/src/drt/src/ta/FlexTA.h b/src/drt/src/ta/FlexTA.h index a9bda2b0e46..c2859696a82 100644 --- a/src/drt/src/ta/FlexTA.h +++ b/src/drt/src/ta/FlexTA.h @@ -53,7 +53,11 @@ class FlexTA void main_helper(frLayerNum lNum, int maxOffsetIter, int panelWidth); void initTA(int size); void searchRepair(int iter, int size, int offset); - int initTA_helper(int iter, int size, int offset, bool isH, int& numPanels); + int initTA_helper(int iter, + int size, + int offset, + bool is_horizontal, + int& num_panels); }; class FlexTAWorker; @@ -68,33 +72,33 @@ class FlexTAWorkerRegionQuery void add(taPinFig* fig); void remove(taPinFig* fig); void query(const odb::Rect& box, - frLayerNum layerNum, + frLayerNum layer_num, frOrderedIdSet& result) const; void addCost(const odb::Rect& box, - frLayerNum layerNum, + frLayerNum layer_num, frBlockObject* obj, frConstraint* con); void removeCost(const odb::Rect& box, - frLayerNum layerNum, + frLayerNum layer_num, frBlockObject* obj, frConstraint* con); void queryCost( const odb::Rect& box, - frLayerNum layerNum, + frLayerNum layer_num, std::vector>>& result) const; void addViaCost(const odb::Rect& box, - frLayerNum layerNum, + frLayerNum layer_num, frBlockObject* obj, frConstraint* con); void removeViaCost(const odb::Rect& box, - frLayerNum layerNum, + frLayerNum layer_num, frBlockObject* obj, frConstraint* con); void queryViaCost( const odb::Rect& box, - frLayerNum layerNum, + frLayerNum layer_num, std::vector>>& result) const; @@ -164,16 +168,18 @@ class FlexTAWorker frRegionQuery* getRegionQuery() const { return design_->getRegionQuery(); } void getTrackIdx(frCoord loc1, frCoord loc2, - frLayerNum lNum, + frLayerNum layer_num, int& idx1, int& idx2) const { - idx1 = int( - std::lower_bound(trackLocs_[lNum].begin(), trackLocs_[lNum].end(), loc1) - - trackLocs_[lNum].begin()); - idx2 = int(std::upper_bound( - trackLocs_[lNum].begin(), trackLocs_[lNum].end(), loc2) - - trackLocs_[lNum].begin()) + idx1 = int(std::lower_bound(trackLocs_[layer_num].begin(), + trackLocs_[layer_num].end(), + loc1) + - trackLocs_[layer_num].begin()); + idx2 = int(std::upper_bound(trackLocs_[layer_num].begin(), + trackLocs_[layer_num].end(), + loc2) + - trackLocs_[layer_num].begin()) - 1; } const std::vector& getTrackLocs(frLayerNum in) const @@ -211,15 +217,15 @@ class FlexTAWorker void init(); void initFixedObjs(); frCoord initFixedObjs_calcBloatDist(frBlockObject* obj, - frLayerNum lNum, + frLayerNum layer_num, const odb::Rect& box); frCoord initFixedObjs_calcOBSBloatDistVia(const frViaDef* viaDef, - frLayerNum lNum, + frLayerNum layer_num, const odb::Rect& box, bool isOBS = true); void initFixedObjs_helper(const odb::Rect& box, frCoord bloatDist, - frLayerNum lNum, + frLayerNum layer_num, frNet* net, bool isViaCost = false); void initTracks(); @@ -239,6 +245,18 @@ class FlexTAWorker std::set& upViaCoordSet, int& nextIrouteDir, frCoord& pinCoord); + void initIroute_helper_generic_endpoint(frGuide* guide, + const odb::Point& cp, + bool is_begin, + frLayerNum layer_num, + bool is_horizontal, + frCoord& min_begin, + frCoord& max_end, + bool& has_min_begin, + bool& has_max_end, + std::set& down_via_coord_set, + std::set& up_via_coord_set, + int& next_iroute_dir); void initIroute_helper_generic_helper(frGuide* guide, frCoord& pinCoord); bool initIroute_helper_pin(frGuide* guide, frCoord& maxBegin, @@ -247,6 +265,51 @@ class FlexTAWorker std::set& upViaCoordSet, int& nextIrouteDir, frCoord& pinCoord); + bool initIroute_helper_pin_iterm(frInstTerm* iterm, + frNet* net, + frLayerNum layer_num, + bool is_horizontal, + bool has_down, + bool has_up, + frCoord& max_begin, + frCoord& min_end, + std::set& down_via_coord_set, + std::set& up_via_coord_set, + int& next_iroute_dir, + frCoord& pin_coord); + bool initIroute_helper_pin_bterm(frBTerm* bterm, + frNet* net, + frLayerNum layer_num, + bool is_horizontal, + bool has_down, + bool has_up, + frCoord& max_begin, + frCoord& min_end, + std::set& down_via_coord_set, + std::set& up_via_coord_set, + int& next_iroute_dir, + frCoord& pin_coord); + void initFixedObjs_processTerm(frBlockObject* obj, + frLayerNum layer_num, + const odb::Rect& bounds, + odb::Rect& box, + frCoord width); + void initFixedObjs_processRouting(frBlockObject* obj, + frLayerNum layer_num, + const odb::Rect& bounds, + odb::Rect& box, + frCoord width); + void initFixedObjs_processVia(frBlockObject* obj, + frLayerNum layer_num, + const odb::Rect& bounds, + odb::Rect& box, + frCoord width, + frNet* net_ptr); + void initFixedObjs_applyBorderViaCosts( + frLayerNum layer_num, + frCoord width, + bool upper, + const frRegionQuery::Objects& result); void initCosts(); void sortIroutes(); bool outOfDieVia(frLayerNum layer_num, @@ -264,19 +327,68 @@ class FlexTAWorker bool isAddCost, frOrderedIdSet* pinS = nullptr); void modMinSpacingCostPlanar(const odb::Rect& box, - frLayerNum lNum, + frLayerNum layer_num, taPinFig* fig, bool isAddCost, frOrderedIdSet* pinS = nullptr); void modMinSpacingCostVia(const odb::Rect& box, - frLayerNum lNum, + frLayerNum layer_num, taPinFig* fig, bool isAddCost, bool isUpperVia, bool isCurrPs, frOrderedIdSet* pinS = nullptr); + bool getFollowTrackLayerNum(frLayerNum cut_layer_num, + frLayerNum& follow_track_layer_num) const; + void getViaTrackRange(const odb::Rect& box, + const odb::Rect& via_box, + frCoord bloat_dist, + bool is_horizontal, + frLayerNum follow_track_layer_num, + int& idx_1, + int& idx_2) const; + frCoord getViaParallelRunLength(const odb::Rect& box, + const odb::Rect& via_box, + frCoord dx, + frCoord dy, + bool is_horizontal, + bool is_curr_ps) const; + bool buildViaBlockBox(const odb::Rect& box, + const odb::Rect& via_box, + frCoord dx, + frCoord dy, + frCoord req_dist, + bool is_horizontal, + bool is_center_to_center, + frCoord track_loc, + const odb::Point& box_center, + odb::Rect& block_box) const; + void updateViaCost(const odb::Rect& block_box, + frLayerNum layer_num, + taPinFig* fig, + frConstraint* con, + bool is_add_cost, + frOrderedIdSet* pin_set, + bool is_cut_cost); + bool adjustParallelOverlapBlockBox(const odb::Rect& box, + const odb::Rect& via_box, + frCoord dx, + frCoord dy, + bool is_horizontal, + frCoord track_loc, + odb::Rect& block_box) const; + bool isCutSpacingConstraintViolated(const frCutSpacingConstraint* con, + const odb::Rect& box, + const odb::Rect& transformed_via_box, + frCoord dx, + frCoord dy, + bool is_horizontal, + frCoord track_loc, + const odb::Point& box_center, + const odb::Rect& via_box, + odb::Rect& block_box) const; void modCutSpacingCost(const odb::Rect& box, - frLayerNum lNum, + frLayerNum layer_num, taPinFig* fig, bool isAddCost, frOrderedIdSet* pinS = nullptr); @@ -286,15 +398,44 @@ class FlexTAWorker void assignIroute(taPin* iroute); void assignIroute_init(taPin* iroute, frOrderedIdSet* pinS); void assignIroute_availTracks(taPin* iroute, - frLayerNum& lNum, - int& idx1, - int& idx2); + frLayerNum& layer_num, + int& idx_1, + int& idx_2); int assignIroute_bestTrack(taPin* iroute, - frLayerNum lNum, - int idx1, - int idx2); + frLayerNum layer_num, + int idx_1, + int idx_2); + int assignIroute_clampStartTrackIdx(frLayerNum layer_num, + frCoord pin_coord, + int idx_1, + int idx_2) const; + bool assignIroute_scanAscending(taPin* iroute, + frLayerNum layer_num, + int start_idx, + int end_idx, + frUInt4& best_cost, + frCoord& best_track_loc, + int& best_track_idx, + frUInt4& drc_cost); + bool assignIroute_scanDescending(taPin* iroute, + frLayerNum layer_num, + int start_idx, + int end_idx, + frUInt4& best_cost, + frCoord& best_track_loc, + int& best_track_idx, + frUInt4& drc_cost); + bool assignIroute_scanAlternating(taPin* iroute, + frLayerNum layer_num, + int start_idx, + int idx_1, + int idx_2, + frUInt4& best_cost, + frCoord& best_track_loc, + int& best_track_idx, + frUInt4& drc_cost); void assignIroute_bestTrack_helper(taPin* iroute, - frLayerNum lNum, + frLayerNum layer_num, int trackIdx, frUInt4& bestCost, frCoord& bestTrackLoc, @@ -309,7 +450,7 @@ class FlexTAWorker frUInt4 assignIroute_getDRCCost(taPin* iroute, frCoord trackLoc); frUInt4 assignIroute_getDRCCost_helper(taPin* iroute, odb::Rect& box, - frLayerNum lNum); + frLayerNum layer_num); void assignIroute_updateIroute(taPin* iroute, frCoord bestTrackLoc, frOrderedIdSet* pinS); diff --git a/src/drt/src/ta/FlexTA_assign.cpp b/src/drt/src/ta/FlexTA_assign.cpp index ade3ba0a4a9..d5c4e99b415 100644 --- a/src/drt/src/ta/FlexTA_assign.cpp +++ b/src/drt/src/ta/FlexTA_assign.cpp @@ -29,6 +29,11 @@ using odb::dbTechLayerType; namespace drt { +namespace { +constexpr int kWarnViaLayerNonRoutingMinSpacingMsgId = 414; +constexpr int kWarnViaLayerNonRoutingCutSpacingMsgId = 415; +} // namespace + frSquaredDistance FlexTAWorker::box2boxDistSquare(const odb::Rect& box1, const odb::Rect& box2, frCoord& dx, @@ -47,8 +52,8 @@ frSquaredDistance FlexTAWorker::box2boxDistSquare(const odb::Rect& box1, void FlexTAWorker::modMinSpacingCostPlanar(const odb::Rect& box, frLayerNum lNum, taPinFig* fig, - bool isAddCost, - frOrderedIdSet* pinS) + bool is_add_cost, + frOrderedIdSet* pin_set) { // obj1 = curr obj frCoord width1 = box.minDXDY(); @@ -77,18 +82,18 @@ void FlexTAWorker::modMinSpacingCostPlanar(const odb::Rect& box, frCoord boxRight = isH ? box.xMax() : box.yMax(); odb::Rect box1(boxLeft, boxLow, boxRight, boxHigh); - int idx1, idx2; + int idx_1, idx_2; getTrackIdx(boxLow - bloatDist - halfwidth2 + 1, boxHigh + bloatDist + halfwidth2 - 1, lNum, - idx1, - idx2); + idx_1, + idx_2); odb::Rect box2(-halfwidth2, -halfwidth2, halfwidth2, halfwidth2); frCoord dx, dy; auto& trackLocs = getTrackLocs(lNum); auto& workerRegionQuery = getWorkerRegionQuery(); - for (int i = idx1; i <= idx2; i++) { + for (int i = idx_1; i <= idx_2; i++) { auto trackLoc = trackLocs[i]; odb::dbTransform xform(odb::Point(boxLeft, trackLoc)); xform.apply(box2); @@ -111,426 +116,445 @@ void FlexTAWorker::modMinSpacingCostPlanar(const odb::Rect& box, tmpBox.init(trackLoc, blockLeft, trackLoc, blockRight); } auto con = layer->getMinSpacing(); - if (isAddCost) { + if (is_add_cost) { workerRegionQuery.addCost(tmpBox, lNum, fig, con); - if (pinS) { - workerRegionQuery.query(tmpBox, lNum, *pinS); + if (pin_set) { + workerRegionQuery.query(tmpBox, lNum, *pin_set); } } else { workerRegionQuery.removeCost(tmpBox, lNum, fig, con); - if (pinS) { - workerRegionQuery.query(tmpBox, lNum, *pinS); + if (pin_set) { + workerRegionQuery.query(tmpBox, lNum, *pin_set); } } } } -// given a shape on any routing layer n, block via @(n+1) if isUpperVia is true +bool FlexTAWorker::getFollowTrackLayerNum( + frLayerNum cut_layer_num, + frLayerNum& follow_track_layer_num) const +{ + if (cut_layer_num - 1 >= getDesign()->getTech()->getBottomLayerNum() + && getDesign()->getTech()->getLayer(cut_layer_num - 1)->getType() + == dbTechLayerType::ROUTING + && getDesign()->getTech()->getLayer(cut_layer_num - 1)->getDir() + == getDir()) { + follow_track_layer_num = cut_layer_num - 1; + return true; + } + if (cut_layer_num + 1 <= getDesign()->getTech()->getTopLayerNum() + && getDesign()->getTech()->getLayer(cut_layer_num + 1)->getType() + == dbTechLayerType::ROUTING + && getDesign()->getTech()->getLayer(cut_layer_num + 1)->getDir() + == getDir()) { + follow_track_layer_num = cut_layer_num + 1; + return true; + } + return false; +} + +void FlexTAWorker::getViaTrackRange(const odb::Rect& box, + const odb::Rect& via_box, + frCoord bloat_dist, + bool is_horizontal, + frLayerNum follow_track_layer_num, + int& idx_1, + int& idx_2) const +{ + if (is_horizontal) { + getTrackIdx(box.yMin() - bloat_dist - via_box.yMax() + 1, + box.yMax() + bloat_dist - via_box.yMin() - 1, + follow_track_layer_num, + idx_1, + idx_2); + } else { + getTrackIdx(box.xMin() - bloat_dist - via_box.xMax() + 1, + box.xMax() + bloat_dist - via_box.xMin() - 1, + follow_track_layer_num, + idx_1, + idx_2); + } +} + +frCoord FlexTAWorker::getViaParallelRunLength(const odb::Rect& box, + const odb::Rect& via_box, + frCoord dx, + frCoord dy, + bool is_horizontal, + bool is_curr_ps) const +{ + if (is_horizontal) { + if (dy > 0) { + return is_curr_ps ? via_box.dx() : std::min(box.dx(), via_box.dx()); + } + return is_curr_ps ? via_box.dy() : std::min(box.dy(), via_box.dy()); + } + + if (dx > 0) { + return is_curr_ps ? via_box.dy() : std::min(box.dy(), via_box.dy()); + } + return is_curr_ps ? via_box.dx() : std::min(box.dx(), via_box.dx()); +} + +bool FlexTAWorker::buildViaBlockBox(const odb::Rect& box, + const odb::Rect& via_box, + frCoord dx, + frCoord dy, + frCoord req_dist, + bool is_horizontal, + bool is_center_to_center, + frCoord track_loc, + const odb::Point& box_center, + odb::Rect& block_box) const +{ + frCoord distance = is_horizontal ? dy : dx; + if (is_center_to_center) { + distance = is_horizontal ? std::abs(box_center.y() - track_loc) + : std::abs(box_center.x() - track_loc); + } + if (distance >= req_dist) { + return false; + } + + frCoord max_delta = (frCoord) std::sqrt(1.0 * req_dist * req_dist + - 1.0 * distance * distance); + if (max_delta * max_delta + distance * distance == req_dist * req_dist) { + max_delta = std::max(0, max_delta - 1); + } + + frCoord block_left = 0; + frCoord block_right = 0; + if (is_center_to_center) { + block_left = is_horizontal ? box_center.x() - max_delta + : box_center.y() - max_delta; + block_right = is_horizontal ? box_center.x() + max_delta + : box_center.y() + max_delta; + } else if (is_horizontal) { + block_left = box.xMin() - max_delta - via_box.xMax(); + block_right = box.xMax() + max_delta - via_box.xMin(); + } else { + block_left = box.yMin() - max_delta - via_box.yMax(); + block_right = box.yMax() + max_delta - via_box.yMin(); + } + + if (is_horizontal) { + block_box.init(block_left, track_loc, block_right, track_loc); + } else { + block_box.init(track_loc, block_left, track_loc, block_right); + } + return true; +} + +void FlexTAWorker::updateViaCost(const odb::Rect& block_box, + frLayerNum layer_num, + taPinFig* fig, + frConstraint* con, + bool is_add_cost, + frOrderedIdSet* pin_set, + bool is_cut_cost) +{ + auto& worker_region_query = getWorkerRegionQuery(); + if (is_add_cost) { + if (is_cut_cost) { + worker_region_query.addViaCost(block_box, layer_num, fig, con); + } else { + worker_region_query.addCost(block_box, layer_num, fig, con); + } + } else if (is_cut_cost) { + worker_region_query.removeViaCost(block_box, layer_num, fig, con); + } else { + worker_region_query.removeCost(block_box, layer_num, fig, con); + } + if (pin_set) { + worker_region_query.query(block_box, layer_num, *pin_set); + } +} + +bool FlexTAWorker::adjustParallelOverlapBlockBox(const odb::Rect& box, + const odb::Rect& via_box, + frCoord dx, + frCoord dy, + bool is_horizontal, + frCoord track_loc, + odb::Rect& block_box) const +{ + if (is_horizontal) { + if (dy <= 0) { + return false; + } + block_box.init(std::max(box.xMin() - via_box.xMax() + 1, block_box.xMin()), + track_loc, + std::min(box.xMax() - via_box.xMin() - 1, block_box.xMax()), + track_loc); + } else { + if (dx <= 0) { + return false; + } + block_box.init(track_loc, + std::max(box.yMin() - via_box.yMax() + 1, block_box.yMin()), + track_loc, + std::min(box.yMax() - via_box.yMin() - 1, block_box.yMax())); + } + return block_box.xMin() <= block_box.xMax() + && block_box.yMin() <= block_box.yMax(); +} + +bool FlexTAWorker::isCutSpacingConstraintViolated( + const frCutSpacingConstraint* con, + const odb::Rect& box, + const odb::Rect& transformed_via_box, + frCoord dx, + frCoord dy, + bool is_horizontal, + frCoord track_loc, + const odb::Point& box_center, + const odb::Rect& via_box, + odb::Rect& block_box) const +{ + if (con->hasSameNet()) { + return false; + } + + if (!buildViaBlockBox(box, + via_box, + dx, + dy, + con->getCutSpacing(), + is_horizontal, + con->hasCenterToCenter(), + track_loc, + box_center, + block_box)) { + return false; + } + + if (con->isLayer()) { + return false; + } + if (con->isAdjacentCuts()) { + return true; + } + if (con->isParallelOverlap()) { + return adjustParallelOverlapBlockBox( + box, via_box, dx, dy, is_horizontal, track_loc, block_box); + } + if (con->isArea()) { + return std::max(box.area(), transformed_via_box.area()) + >= con->getCutArea(); + } + return true; +} + +// given a shape on any routing layer n, block via @(n+1) if is_upper_via is +// true void FlexTAWorker::modMinSpacingCostVia(const odb::Rect& box, frLayerNum lNum, taPinFig* fig, - bool isAddCost, - bool isUpperVia, - bool isCurrPs, - frOrderedIdSet* pinS) + bool is_add_cost, + bool is_upper_via, + bool is_curr_ps, + frOrderedIdSet* pin_set) { - // obj1 = curr obj - frCoord width1 = box.minDXDY(); - frCoord length1 = box.maxDXDY(); - // obj2 = other obj - // default via dimension - const frViaDef* viaDef = nullptr; - frLayerNum cutLNum = 0; - if (isUpperVia) { - viaDef + const frViaDef* via_def = nullptr; + frLayerNum cut_layer_num = 0; + if (is_upper_via) { + via_def = (lNum < getDesign()->getTech()->getTopLayerNum()) ? getDesign()->getTech()->getLayer(lNum + 1)->getDefaultViaDef() : nullptr; - cutLNum = lNum + 1; + cut_layer_num = lNum + 1; } else { - viaDef + via_def = (lNum > getDesign()->getTech()->getBottomLayerNum()) ? getDesign()->getTech()->getLayer(lNum - 1)->getDefaultViaDef() : nullptr; - cutLNum = lNum - 1; + cut_layer_num = lNum - 1; } - if (viaDef == nullptr) { + if (via_def == nullptr) { return; } - frVia via(viaDef); - odb::Rect viaBox(0, 0, 0, 0); - if (isUpperVia) { - viaBox = via.getLayer1BBox(); - } else { - viaBox = via.getLayer2BBox(); - } - frCoord width2 = viaBox.minDXDY(); - frCoord length2 = viaBox.maxDXDY(); - bool isH = (getDir() == dbTechLayerDir::HORIZONTAL); - frLayerNum followTrackLNum; - if (cutLNum - 1 >= getDesign()->getTech()->getBottomLayerNum() - && getDesign()->getTech()->getLayer(cutLNum - 1)->getType() - == dbTechLayerType::ROUTING - && getDesign()->getTech()->getLayer(cutLNum - 1)->getDir() == getDir()) { - followTrackLNum = cutLNum - 1; - } else if (cutLNum + 1 <= getDesign()->getTech()->getTopLayerNum() - && getDesign()->getTech()->getLayer(cutLNum + 1)->getType() - == dbTechLayerType::ROUTING - && getDesign()->getTech()->getLayer(cutLNum + 1)->getDir() - == getDir()) { - followTrackLNum = cutLNum + 1; - } else { - std::cout - << "Warning: via layer connected to non-routing layer, skipped in " - "modMinSpacingCostVia\n"; + frLayerNum follow_track_layer_num = 0; + if (!getFollowTrackLayerNum(cut_layer_num, follow_track_layer_num)) { + logger_->warn(DRT, + kWarnViaLayerNonRoutingMinSpacingMsgId, + "Via layer connected to non-routing layer, skipped in " + "modMinSpacingCostVia."); return; } - // spacing value needed - auto layer = getTech()->getLayer(lNum); - frCoord bloatDist = layer->getMinSpacingValue( - width1, width2, isCurrPs ? length2 : std::min(length1, length2), false); + frVia via(via_def); + odb::Rect via_box = is_upper_via ? via.getLayer1BBox() : via.getLayer2BBox(); + const frCoord width1 = box.minDXDY(); + const frCoord length1 = box.maxDXDY(); + const frCoord width2 = via_box.minDXDY(); + const frCoord length2 = via_box.maxDXDY(); + const bool is_horizontal = (getDir() == dbTechLayerDir::HORIZONTAL); + + auto* layer = getTech()->getLayer(lNum); + frCoord bloat_dist = layer->getMinSpacingValue( + width1, width2, is_curr_ps ? length2 : std::min(length1, length2), false); if (fig->getNet()->getNondefaultRule()) { - bloatDist = std::max( - bloatDist, + bloat_dist = std::max( + bloat_dist, fig->getNet()->getNondefaultRule()->getSpacing(lNum / 2 - 1)); } - int idx1, idx2; - if (isH) { - getTrackIdx(box.yMin() - bloatDist - (viaBox.yMax() - 0) + 1, - box.yMax() + bloatDist + (0 - viaBox.yMin()) - 1, - followTrackLNum, - idx1, - idx2); - } else { - getTrackIdx(box.xMin() - bloatDist - (viaBox.xMax() - 0) + 1, - box.xMax() + bloatDist + (0 - viaBox.xMin()) - 1, - followTrackLNum, - idx1, - idx2); - } - auto& trackLocs = getTrackLocs(followTrackLNum); - auto& workerRegionQuery = getWorkerRegionQuery(); - odb::Rect tmpBx; + int idx_1 = 0; + int idx_2 = -1; + getViaTrackRange(box, + via_box, + bloat_dist, + is_horizontal, + follow_track_layer_num, + idx_1, + idx_2); + auto& track_locs = getTrackLocs(follow_track_layer_num); + + odb::Rect transformed_via_box; odb::dbTransform xform; - frCoord dx, dy, prl; - frCoord maxX, blockLeft, blockRight; - odb::Rect blockBox; - for (int i = idx1; i <= idx2; i++) { - auto trackLoc = trackLocs[i]; - if (isH) { - xform.setOffset(odb::Point(box.xMin(), trackLoc)); - } else { - xform.setOffset(odb::Point(trackLoc, box.yMin())); - } - tmpBx = viaBox; - xform.apply(tmpBx); - box2boxDistSquare(box, tmpBx, dx, dy); - if (isH) { // track is horizontal - if (dy > 0) { // via at the bottom of box - if (isCurrPs) { // prl maxed out to be viaBox - prl = viaBox.dx(); - } else { // prl maxed out to be smaller of box and viaBox - prl = std::min(box.dx(), viaBox.dx()); - } - // via at the side of box - } else { - if (isCurrPs) { // prl maxed out to be viaBox - prl = viaBox.dy(); - } else { // prl maxed out to be smaller of box and viaBox - prl = std::min(box.dy(), viaBox.dy()); - } - } - } else { // track is vertical - if (dx > 0) { // via at the bottom of box - if (isCurrPs) { // prl maxed out to be viaBox - prl = viaBox.dy(); - } else { // prl maxed out to be smaller of box and viaBox - prl = std::min(box.dy(), viaBox.dy()); - } - // via at the side of box - } else { - if (isCurrPs) { // prl maxed out to be viaBox - prl = viaBox.dx(); - } else { // prl maxed out to be smaller of box and viaBox - prl = std::min(box.dx(), viaBox.dx()); - } - } - } + for (int i = idx_1; i <= idx_2; i++) { + const frCoord track_loc = track_locs[i]; + xform.setOffset(is_horizontal ? odb::Point(box.xMin(), track_loc) + : odb::Point(track_loc, box.yMin())); + transformed_via_box = via_box; + xform.apply(transformed_via_box); + + frCoord dx = 0; + frCoord dy = 0; + box2boxDistSquare(box, transformed_via_box, dx, dy); + const frCoord prl = getViaParallelRunLength( + box, via_box, dx, dy, is_horizontal, is_curr_ps); - frCoord reqDist = layer->getMinSpacingValue(width1, width2, prl, false); + frCoord req_dist = layer->getMinSpacingValue(width1, width2, prl, false); if (fig->getNet()->getNondefaultRule()) { - reqDist = std::max( - reqDist, + req_dist = std::max( + req_dist, fig->getNet()->getNondefaultRule()->getSpacing(lNum / 2 - 1)); } - if (isH) { - if (dy >= reqDist) { - continue; - } - maxX = (frCoord) (sqrt(1.0 * reqDist * reqDist - 1.0 * dy * dy)); - if (maxX * maxX + dy * dy == reqDist * reqDist) { - maxX = std::max(0, maxX - 1); - } - blockLeft = box.xMin() - maxX - (viaBox.xMax() - 0); - blockRight = box.xMax() + maxX + (0 - viaBox.xMin()); - - blockBox.init(blockLeft, trackLoc, blockRight, trackLoc); - } else { - if (dx >= reqDist) { - continue; - } - maxX = (frCoord) (sqrt(1.0 * reqDist * reqDist - 1.0 * dx * dx)); - if (maxX * maxX + dx * dx == reqDist * reqDist) { - maxX = std::max(0, maxX - 1); - } - blockLeft = box.yMin() - maxX - (viaBox.yMax() - 0); - blockRight = box.yMax() + maxX + (0 - viaBox.yMin()); - - blockBox.init(trackLoc, blockLeft, trackLoc, blockRight); - } - - auto con = layer->getMinSpacing(); - if (isAddCost) { - workerRegionQuery.addViaCost(blockBox, cutLNum, fig, con); - if (pinS) { - workerRegionQuery.query(blockBox, cutLNum, *pinS); - } - } else { - workerRegionQuery.removeViaCost(blockBox, cutLNum, fig, con); - if (pinS) { - workerRegionQuery.query(blockBox, cutLNum, *pinS); - } + odb::Rect block_box; + if (!buildViaBlockBox(box, + via_box, + dx, + dy, + req_dist, + is_horizontal, + false, + track_loc, + odb::Point(), + block_box)) { + continue; } + updateViaCost(block_box, + cut_layer_num, + fig, + layer->getMinSpacing(), + is_add_cost, + pin_set, + true); } } void FlexTAWorker::modCutSpacingCost(const odb::Rect& box, frLayerNum lNum, taPinFig* fig, - bool isAddCost, - frOrderedIdSet* pinS) + bool is_add_cost, + frOrderedIdSet* pin_set) { - if (!getDesign()->getTech()->getLayer(lNum)->hasCutSpacing()) { + auto* layer = getDesign()->getTech()->getLayer(lNum); + if (!layer->hasCutSpacing()) { return; } - // obj1 = curr obj - // obj2 = other obj - // default via dimension - const frViaDef* viaDef - = getDesign()->getTech()->getLayer(lNum)->getDefaultViaDef(); - frVia via(viaDef); - odb::Rect viaBox = via.getCutBBox(); - bool isH = (getDir() == dbTechLayerDir::HORIZONTAL); - frLayerNum followTrackLNum; - if (lNum - 1 >= getDesign()->getTech()->getBottomLayerNum() - && getDesign()->getTech()->getLayer(lNum - 1)->getType() - == dbTechLayerType::ROUTING - && getDesign()->getTech()->getLayer(lNum - 1)->getDir() == getDir()) { - followTrackLNum = lNum - 1; - } else if (lNum + 1 <= getDesign()->getTech()->getTopLayerNum() - && getDesign()->getTech()->getLayer(lNum + 1)->getType() - == dbTechLayerType::ROUTING - && getDesign()->getTech()->getLayer(lNum + 1)->getDir() - == getDir()) { - followTrackLNum = lNum + 1; - } else { - std::cout - << "Warning: via layer connected to non-routing layer, skipped in " - "modMinSpacingCostVia\n"; + const frViaDef* via_def = layer->getDefaultViaDef(); + if (via_def == nullptr) { return; } + frVia via(via_def); + odb::Rect via_box = via.getCutBBox(); - // spacing value needed - frCoord bloatDist = 0; - for (auto con : getDesign()->getTech()->getLayer(lNum)->getCutSpacing()) { - bloatDist = std::max(bloatDist, con->getCutSpacing()); + frLayerNum follow_track_layer_num = 0; + if (!getFollowTrackLayerNum(lNum, follow_track_layer_num)) { + logger_->warn(DRT, + kWarnViaLayerNonRoutingCutSpacingMsgId, + "Via layer connected to non-routing layer, skipped in " + "modCutSpacingCost."); + return; } - int idx1, idx2; - if (isH) { - getTrackIdx(box.yMin() - bloatDist - (viaBox.yMax() - 0) + 1, - box.yMax() + bloatDist + (0 - viaBox.yMin()) - 1, - followTrackLNum, - idx1, - idx2); - } else { - getTrackIdx(box.xMin() - bloatDist - (viaBox.xMax() - 0) + 1, - box.xMax() + bloatDist + (0 - viaBox.xMin()) - 1, - followTrackLNum, - idx1, - idx2); + frCoord bloat_dist = 0; + for (const auto* con : layer->getCutSpacing()) { + bloat_dist = std::max(bloat_dist, con->getCutSpacing()); } - auto& trackLocs = getTrackLocs(followTrackLNum); - auto& workerRegionQuery = getWorkerRegionQuery(); - odb::Rect tmpBx; + const bool is_horizontal = (getDir() == dbTechLayerDir::HORIZONTAL); + int idx_1 = 0; + int idx_2 = -1; + getViaTrackRange(box, + via_box, + bloat_dist, + is_horizontal, + follow_track_layer_num, + idx_1, + idx_2); + auto& track_locs = getTrackLocs(follow_track_layer_num); + const odb::Point box_center((box.xMin() + box.xMax()) / 2, + (box.yMin() + box.yMax()) / 2); + odb::dbTransform xform; - frCoord dx, dy, c2ctrackdist; - frCoord reqDist = 0; - frCoord maxX, blockLeft, blockRight; - odb::Rect blockBox; - odb::Point boxCenter; - boxCenter = {(box.xMin() + box.xMax()) / 2, (box.yMin() + box.yMax()) / 2}; - bool hasViol = false; - for (int i = idx1; i <= idx2; i++) { - auto trackLoc = trackLocs[i]; - if (isH) { - xform.setOffset(odb::Point(box.xMin(), trackLoc)); - } else { - xform.setOffset(odb::Point(trackLoc, box.yMin())); - } - tmpBx = viaBox; - xform.apply(tmpBx); - box2boxDistSquare(box, tmpBx, dx, dy); - - for (auto con : getDesign()->getTech()->getLayer(lNum)->getCutSpacing()) { - hasViol = false; - reqDist = con->getCutSpacing(); - bool isC2C = con->hasCenterToCenter(); - if (isH) { - c2ctrackdist = abs(boxCenter.y() - trackLoc); - } else { - c2ctrackdist = abs(boxCenter.x() - trackLoc); - } + for (int i = idx_1; i <= idx_2; i++) { + const frCoord track_loc = track_locs[i]; + xform.setOffset(is_horizontal ? odb::Point(box.xMin(), track_loc) + : odb::Point(track_loc, box.yMin())); + odb::Rect transformed_via_box = via_box; + xform.apply(transformed_via_box); - if (isH) { - if (isC2C) { - if (c2ctrackdist >= reqDist) { - continue; - } - } else { - if (dy >= reqDist) { - continue; - } - } - if (isC2C) { - maxX = (frCoord) (sqrt(1.0 * reqDist * reqDist - - 1.0 * c2ctrackdist * c2ctrackdist)); - } else { - maxX = (frCoord) (sqrt(1.0 * reqDist * reqDist - 1.0 * dy * dy)); - } - if (maxX * maxX + dy * dy == reqDist * reqDist) { - maxX = std::max(0, maxX - 1); - } - if (isC2C) { - blockLeft = boxCenter.x() - maxX; - blockRight = boxCenter.x() + maxX; - } else { - blockLeft = box.xMin() - maxX - (viaBox.xMax() - 0); - blockRight = box.xMax() + maxX + (0 - viaBox.xMin()); - } - blockBox.init(blockLeft, trackLoc, blockRight, trackLoc); - } else { - if (isC2C) { - if (c2ctrackdist >= reqDist) { - continue; - } - } else { - if (dx >= reqDist) { - continue; - } - } - if (isC2C) { - maxX = (frCoord) (sqrt(1.0 * reqDist * reqDist - - 1.0 * c2ctrackdist * c2ctrackdist)); - } else { - maxX = (frCoord) (sqrt(1.0 * reqDist * reqDist - 1.0 * dx * dx)); - } - if (maxX * maxX + dx * dx == reqDist * reqDist) { - maxX = std::max(0, maxX - 1); - } - if (isC2C) { - blockLeft = boxCenter.y() - maxX; - blockRight = boxCenter.y() + maxX; - } else { - blockLeft = box.yMin() - maxX - (viaBox.yMax() - 0); - blockRight = box.yMax() + maxX + (0 - viaBox.yMin()); - } + frCoord dx = 0; + frCoord dy = 0; + box2boxDistSquare(box, transformed_via_box, dx, dy); - blockBox.init(trackLoc, blockLeft, trackLoc, blockRight); - } - if (con->hasSameNet()) { + for (auto* con : layer->getCutSpacing()) { + odb::Rect block_box; + if (!isCutSpacingConstraintViolated(con, + box, + transformed_via_box, + dx, + dy, + is_horizontal, + track_loc, + box_center, + via_box, + block_box)) { continue; } - if (con->isLayer()) { - ; - } else if (con->isAdjacentCuts()) { - hasViol = true; - // should disable hasViol and modify this part to new grid graph - } else if (con->isParallelOverlap()) { - if (isH) { - if (dy > 0) { - blockBox.init( - std::max(box.xMin() - (viaBox.xMax() - 0) + 1, blockLeft), - trackLoc, - std::min(box.xMax() + (0 - viaBox.xMin()) - 1, blockRight), - trackLoc); - } - } else { - if (dx > 0) { - blockBox.init( - trackLoc, - std::max(box.yMin() - (viaBox.yMax() - 0) + 1, blockLeft), - trackLoc, - std::min(box.yMax() + (0 - viaBox.yMin()) - 1, blockRight)); - } - } - if (blockBox.xMin() <= blockBox.xMax() - && blockBox.yMin() <= blockBox.yMax()) { - hasViol = true; - } - } else if (con->isArea()) { - auto currArea = std::max(box.area(), tmpBx.area()); - if (currArea >= con->getCutArea()) { - hasViol = true; - } - } else { - hasViol = true; - } - if (hasViol) { - if (isAddCost) { - workerRegionQuery.addViaCost(blockBox, lNum, fig, con); - if (pinS) { - workerRegionQuery.query(blockBox, lNum, *pinS); - } - } else { - workerRegionQuery.removeViaCost(blockBox, lNum, fig, con); - if (pinS) { - workerRegionQuery.query(blockBox, lNum, *pinS); - } - } - } + updateViaCost(block_box, lNum, fig, con, is_add_cost, pin_set, true); } } } -void FlexTAWorker::addCost(taPinFig* fig, frOrderedIdSet* pinS) +void FlexTAWorker::addCost(taPinFig* fig, frOrderedIdSet* pin_set) { - modCost(fig, true, pinS); + modCost(fig, true, pin_set); } -void FlexTAWorker::subCost(taPinFig* fig, frOrderedIdSet* pinS) +void FlexTAWorker::subCost(taPinFig* fig, frOrderedIdSet* pin_set) { - modCost(fig, false, pinS); + modCost(fig, false, pin_set); } void FlexTAWorker::modCost(taPinFig* fig, - bool isAddCost, - frOrderedIdSet* pinS) + bool is_add_cost, + frOrderedIdSet* pin_set) { if (fig->typeId() == tacPathSeg) { auto obj = static_cast(fig); auto layerNum = obj->getLayerNum(); odb::Rect box = obj->getBBox(); modMinSpacingCostPlanar( - box, layerNum, obj, isAddCost, pinS); // must be current TA layer - modMinSpacingCostVia(box, layerNum, obj, isAddCost, true, true, pinS); - modMinSpacingCostVia(box, layerNum, obj, isAddCost, false, true, pinS); + box, layerNum, obj, is_add_cost, pin_set); // must be current TA layer + modMinSpacingCostVia(box, layerNum, obj, is_add_cost, true, true, pin_set); + modMinSpacingCostVia(box, layerNum, obj, is_add_cost, false, true, pin_set); } else if (fig->typeId() == tacVia) { auto obj = static_cast(fig); // assumes enclosure for via is always rectangle @@ -538,20 +562,22 @@ void FlexTAWorker::modCost(taPinFig* fig, auto layerNum = obj->getViaDef()->getLayer1Num(); // current TA layer if (getDir() == getDesign()->getTech()->getLayer(layerNum)->getDir()) { - modMinSpacingCostPlanar(box, layerNum, obj, isAddCost, pinS); + modMinSpacingCostPlanar(box, layerNum, obj, is_add_cost, pin_set); } - modMinSpacingCostVia(box, layerNum, obj, isAddCost, true, false, pinS); - modMinSpacingCostVia(box, layerNum, obj, isAddCost, false, false, pinS); + modMinSpacingCostVia(box, layerNum, obj, is_add_cost, true, false, pin_set); + modMinSpacingCostVia( + box, layerNum, obj, is_add_cost, false, false, pin_set); // assumes enclosure for via is always rectangle box = obj->getLayer2BBox(); layerNum = obj->getViaDef()->getLayer2Num(); // current TA layer if (getDir() == getDesign()->getTech()->getLayer(layerNum)->getDir()) { - modMinSpacingCostPlanar(box, layerNum, obj, isAddCost, pinS); + modMinSpacingCostPlanar(box, layerNum, obj, is_add_cost, pin_set); } - modMinSpacingCostVia(box, layerNum, obj, isAddCost, true, false, pinS); - modMinSpacingCostVia(box, layerNum, obj, isAddCost, false, false, pinS); + modMinSpacingCostVia(box, layerNum, obj, is_add_cost, true, false, pin_set); + modMinSpacingCostVia( + box, layerNum, obj, is_add_cost, false, false, pin_set); odb::Point pt = obj->getOrigin(); odb::dbTransform xform(pt); @@ -560,7 +586,7 @@ void FlexTAWorker::modCost(taPinFig* fig, box = rect->getBBox(); xform.apply(box); layerNum = obj->getViaDef()->getCutLayerNum(); - modCutSpacingCost(box, layerNum, obj, isAddCost, pinS); + modCutSpacingCost(box, layerNum, obj, is_add_cost, pin_set); } } else { std::cout << "Error: unsupported region query add\n"; @@ -568,33 +594,33 @@ void FlexTAWorker::modCost(taPinFig* fig, } void FlexTAWorker::assignIroute_availTracks(taPin* iroute, - frLayerNum& lNum, - int& idx1, - int& idx2) + frLayerNum& layer_num, + int& idx_1, + int& idx_2) { - lNum = iroute->getGuide()->getBeginLayerNum(); + layer_num = iroute->getGuide()->getBeginLayerNum(); auto [gbp, gep] = iroute->getGuide()->getPoints(); odb::Point gIdx = getDesign()->getTopBlock()->getGCellIdx(gbp); odb::Rect gBox = getDesign()->getTopBlock()->getGCellBox(gIdx); - bool isH = (getDir() == dbTechLayerDir::HORIZONTAL); - frCoord coordLow = isH ? gBox.yMin() : gBox.xMin(); - frCoord coordHigh = isH ? gBox.yMax() : gBox.xMax(); + bool is_horizontal = (getDir() == dbTechLayerDir::HORIZONTAL); + frCoord coordLow = is_horizontal ? gBox.yMin() : gBox.xMin(); + frCoord coordHigh = is_horizontal ? gBox.yMax() : gBox.xMax(); coordHigh--; // to avoid higher track == guide top/right - if (getTech()->getLayer(lNum)->isUnidirectional()) { + if (getTech()->getLayer(layer_num)->isUnidirectional()) { const odb::Rect& dieBx = design_->getTopBlock()->getDieBox(); const frViaDef* via = nullptr; odb::Rect testBox; - if (lNum + 1 <= getTech()->getTopLayerNum()) { - via = getTech()->getLayer(lNum + 1)->getDefaultViaDef(); + if (layer_num + 1 <= getTech()->getTopLayerNum()) { + via = getTech()->getLayer(layer_num + 1)->getDefaultViaDef(); testBox = via->getLayer1ShapeBox(); testBox.merge(via->getLayer2ShapeBox()); } else { - via = getTech()->getLayer(lNum - 1)->getDefaultViaDef(); + via = getTech()->getLayer(layer_num - 1)->getDefaultViaDef(); testBox = via->getLayer1ShapeBox(); testBox.merge(via->getLayer2ShapeBox()); } int diffLow, diffHigh; - if (isH) { + if (is_horizontal) { diffLow = dieBx.yMin() - (coordLow - testBox.dy() / 2); diffHigh = coordHigh + testBox.dy() / 2 - dieBx.yMax(); } else { @@ -608,16 +634,16 @@ void FlexTAWorker::assignIroute_availTracks(taPin* iroute, coordHigh -= diffHigh; } } - getTrackIdx(coordLow, coordHigh, lNum, idx1, idx2); - if (idx2 < idx1) { + getTrackIdx(coordLow, coordHigh, layer_num, idx_1, idx_2); + if (idx_2 < idx_1) { const double dbu = getDesign()->getTopBlock()->getDBUPerUU(); logger_->error(DRT, 406, "No {} tracks found in ({}, {}) for layer {}", - isH ? "horizontal" : "vertical", + is_horizontal ? "horizontal" : "vertical", coordLow / dbu, coordHigh / dbu, - getTech()->getLayer(lNum)->getName()); + getTech()->getLayer(layer_num)->getName()); } } @@ -942,176 +968,262 @@ frUInt4 FlexTAWorker::assignIroute_getCost(taPin* iroute, } void FlexTAWorker::assignIroute_bestTrack_helper(taPin* iroute, - frLayerNum lNum, - int trackIdx, - frUInt4& bestCost, - frCoord& bestTrackLoc, - int& bestTrackIdx, - frUInt4& drcCost) + frLayerNum layer_num, + int track_idx, + frUInt4& best_cost, + frCoord& best_track_loc, + int& best_track_idx, + frUInt4& drc_cost) { - auto trackLoc = getTrackLocs(lNum)[trackIdx]; - auto currCost = assignIroute_getCost(iroute, trackLoc, drcCost); + auto trackLoc = getTrackLocs(layer_num)[track_idx]; + auto currCost = assignIroute_getCost(iroute, trackLoc, drc_cost); if (isInitTA()) { - if (currCost < bestCost) { - bestCost = currCost; - bestTrackLoc = trackLoc; - bestTrackIdx = trackIdx; + if (currCost < best_cost) { + best_cost = currCost; + best_track_loc = trackLoc; + best_track_idx = track_idx; } } else { - if (drcCost < bestCost) { - bestCost = drcCost; - bestTrackLoc = trackLoc; - bestTrackIdx = trackIdx; + if (drc_cost < best_cost) { + best_cost = drc_cost; + best_track_loc = trackLoc; + best_track_idx = track_idx; } } } -int FlexTAWorker::assignIroute_bestTrack(taPin* iroute, - frLayerNum lNum, - int idx1, - int idx2) +int FlexTAWorker::assignIroute_clampStartTrackIdx(frLayerNum layer_num, + frCoord pin_coord, + int idx_1, + int idx_2) const { - double dbu = getDesign()->getTopBlock()->getDBUPerUU(); - frCoord bestTrackLoc = 0; - int bestTrackIdx = -1; - frUInt4 bestCost = std::numeric_limits::max(); - frUInt4 drcCost = 0; - if (iroute->hasPinCoord()) { - // std::cout <<"if" <getPinCoord(); - if (iroute->getNextIrouteDir() > 0) { - int startTrackIdx - = int(std::lower_bound( - trackLocs_[lNum].begin(), trackLocs_[lNum].end(), pinCoord) - - trackLocs_[lNum].begin()); - startTrackIdx = std::min(startTrackIdx, idx2); - startTrackIdx = std::max(startTrackIdx, idx1); - for (int i = startTrackIdx; i <= idx2; i++) { - assignIroute_bestTrack_helper( - iroute, lNum, i, bestCost, bestTrackLoc, bestTrackIdx, drcCost); - if (!drcCost) { - break; - } - } - if (drcCost) { - for (int i = startTrackIdx - 1; i >= idx1; i--) { - assignIroute_bestTrack_helper( - iroute, lNum, i, bestCost, bestTrackLoc, bestTrackIdx, drcCost); - if (!drcCost) { - break; - } - } - } - } else if (iroute->getNextIrouteDir() == 0) { - int startTrackIdx - = int(std::lower_bound( - trackLocs_[lNum].begin(), trackLocs_[lNum].end(), pinCoord) - - trackLocs_[lNum].begin()); - startTrackIdx = std::min(startTrackIdx, idx2); - startTrackIdx = std::max(startTrackIdx, idx1); - // std::cout <<"startTrackIdx " <= idx1 && currTrackIdx <= idx2) { - assignIroute_bestTrack_helper(iroute, - lNum, - currTrackIdx, - bestCost, - bestTrackLoc, - bestTrackIdx, - drcCost); - } - if (!drcCost) { - break; - } - currTrackIdx = startTrackIdx - i - 1; - if (currTrackIdx >= idx1 && currTrackIdx <= idx2) { - assignIroute_bestTrack_helper(iroute, - lNum, - currTrackIdx, - bestCost, - bestTrackLoc, - bestTrackIdx, - drcCost); - } - if (!drcCost) { - break; - } - } - } else { - int startTrackIdx - = int(std::lower_bound( - trackLocs_[lNum].begin(), trackLocs_[lNum].end(), pinCoord) - - trackLocs_[lNum].begin()); - startTrackIdx = std::min(startTrackIdx, idx2); - startTrackIdx = std::max(startTrackIdx, idx1); - for (int i = startTrackIdx; i >= idx1; i--) { - assignIroute_bestTrack_helper( - iroute, lNum, i, bestCost, bestTrackLoc, bestTrackIdx, drcCost); - if (!drcCost) { - break; - } - } - if (drcCost) { - for (int i = startTrackIdx + 1; i <= idx2; i++) { - assignIroute_bestTrack_helper( - iroute, lNum, i, bestCost, bestTrackLoc, bestTrackIdx, drcCost); - if (!drcCost) { - break; - } - } - } + const auto& track_locs = getTrackLocs(layer_num); + int start_track_idx = static_cast( + std::ranges::lower_bound(track_locs, pin_coord) - track_locs.begin()); + start_track_idx = std::min(start_track_idx, idx_2); + start_track_idx = std::max(start_track_idx, idx_1); + return start_track_idx; +} + +bool FlexTAWorker::assignIroute_scanAscending(taPin* iroute, + frLayerNum layer_num, + int start_idx, + int end_idx, + frUInt4& best_cost, + frCoord& best_track_loc, + int& best_track_idx, + frUInt4& drc_cost) +{ + if (start_idx > end_idx) { + return false; + } + for (int i = start_idx; i <= end_idx; i++) { + assignIroute_bestTrack_helper(iroute, + layer_num, + i, + best_cost, + best_track_loc, + best_track_idx, + drc_cost); + if (!drc_cost) { + return true; } - } else { - if (iroute->getNextIrouteDir() > 0) { - for (int i = idx2; i >= idx1; i--) { - assignIroute_bestTrack_helper( - iroute, lNum, i, bestCost, bestTrackLoc, bestTrackIdx, drcCost); - if (!drcCost) { - break; - } + } + return false; +} + +bool FlexTAWorker::assignIroute_scanDescending(taPin* iroute, + frLayerNum layer_num, + int start_idx, + int end_idx, + frUInt4& best_cost, + frCoord& best_track_loc, + int& best_track_idx, + frUInt4& drc_cost) +{ + if (start_idx < end_idx) { + return false; + } + for (int i = start_idx; i >= end_idx; i--) { + assignIroute_bestTrack_helper(iroute, + layer_num, + i, + best_cost, + best_track_loc, + best_track_idx, + drc_cost); + if (!drc_cost) { + return true; + } + } + return false; +} + +bool FlexTAWorker::assignIroute_scanAlternating(taPin* iroute, + frLayerNum layer_num, + int start_idx, + int idx_1, + int idx_2, + frUInt4& best_cost, + frCoord& best_track_loc, + int& best_track_idx, + frUInt4& drc_cost) +{ + const int track_count = idx_2 - idx_1 + 1; + for (int offset = 0; offset < track_count; offset++) { + int curr_track_idx = start_idx + offset; + if (curr_track_idx >= idx_1 && curr_track_idx <= idx_2) { + assignIroute_bestTrack_helper(iroute, + layer_num, + curr_track_idx, + best_cost, + best_track_loc, + best_track_idx, + drc_cost); + if (!drc_cost) { + return true; } - } else if (iroute->getNextIrouteDir() == 0) { - for (int i = (idx1 + idx2) / 2; i <= idx2; i++) { - assignIroute_bestTrack_helper( - iroute, lNum, i, bestCost, bestTrackLoc, bestTrackIdx, drcCost); - if (!drcCost) { - break; - } + } + + curr_track_idx = start_idx - offset - 1; + if (curr_track_idx >= idx_1 && curr_track_idx <= idx_2) { + assignIroute_bestTrack_helper(iroute, + layer_num, + curr_track_idx, + best_cost, + best_track_loc, + best_track_idx, + drc_cost); + if (!drc_cost) { + return true; } - if (drcCost) { - for (int i = (idx1 + idx2) / 2 - 1; i >= idx1; i--) { - assignIroute_bestTrack_helper( - iroute, lNum, i, bestCost, bestTrackLoc, bestTrackIdx, drcCost); - if (!drcCost) { - break; - } - } + } + } + return false; +} + +int FlexTAWorker::assignIroute_bestTrack(taPin* iroute, + frLayerNum layer_num, + int idx_1, + int idx_2) +{ + const double dbu = getDesign()->getTopBlock()->getDBUPerUU(); + frCoord best_track_loc = 0; + int best_track_idx = -1; + frUInt4 best_cost = std::numeric_limits::max(); + frUInt4 drc_cost = 0; + const int next_iroute_dir = iroute->getNextIrouteDir(); + + if (iroute->hasPinCoord()) { + const int start_track_idx = assignIroute_clampStartTrackIdx( + layer_num, iroute->getPinCoord(), idx_1, idx_2); + if (next_iroute_dir > 0) { + if (!assignIroute_scanAscending(iroute, + layer_num, + start_track_idx, + idx_2, + best_cost, + best_track_loc, + best_track_idx, + drc_cost)) { + assignIroute_scanDescending(iroute, + layer_num, + start_track_idx - 1, + idx_1, + best_cost, + best_track_loc, + best_track_idx, + drc_cost); } + } else if (next_iroute_dir == 0) { + assignIroute_scanAlternating(iroute, + layer_num, + start_track_idx, + idx_1, + idx_2, + best_cost, + best_track_loc, + best_track_idx, + drc_cost); } else { - for (int i = idx1; i <= idx2; i++) { - assignIroute_bestTrack_helper( - iroute, lNum, i, bestCost, bestTrackLoc, bestTrackIdx, drcCost); - if (!drcCost) { - break; - } + if (!assignIroute_scanDescending(iroute, + layer_num, + start_track_idx, + idx_1, + best_cost, + best_track_loc, + best_track_idx, + drc_cost)) { + assignIroute_scanAscending(iroute, + layer_num, + start_track_idx + 1, + idx_2, + best_cost, + best_track_loc, + best_track_idx, + drc_cost); } } + } else if (next_iroute_dir > 0) { + assignIroute_scanDescending(iroute, + layer_num, + idx_2, + idx_1, + best_cost, + best_track_loc, + best_track_idx, + drc_cost); + } else if (next_iroute_dir == 0) { + const int middle_track_idx = (idx_1 + idx_2) / 2; + if (!assignIroute_scanAscending(iroute, + layer_num, + middle_track_idx, + idx_2, + best_cost, + best_track_loc, + best_track_idx, + drc_cost)) { + assignIroute_scanDescending(iroute, + layer_num, + middle_track_idx - 1, + idx_1, + best_cost, + best_track_loc, + best_track_idx, + drc_cost); + } + } else { + assignIroute_scanAscending(iroute, + layer_num, + idx_1, + idx_2, + best_cost, + best_track_loc, + best_track_idx, + drc_cost); } - if (bestTrackIdx == -1) { - auto guide = iroute->getGuide(); - odb::Rect box = guide->getBBox(); - std::cout << "Error: assignIroute_bestTrack select no track for " - << guide->getNet()->getName() << " @(" << box.xMin() / dbu << ", " - << box.yMin() / dbu << ") (" << box.xMax() / dbu << ", " - << box.yMax() / dbu << " " - << getDesign()->getTech()->getLayer(lNum)->getName() - << " idx1/2=" << idx1 << "/" << idx2 << '\n'; - exit(1); + + if (best_track_idx == -1) { + auto* guide = iroute->getGuide(); + const odb::Rect box = guide->getBBox(); + constexpr int kAssignBestTrackNoTrackMsgId = 413; + logger_->error( + DRT, + kAssignBestTrackNoTrackMsgId, + "assignIroute_bestTrack could not select a track for net {} in box " + "({}, {}) ({}, {}) on layer {} with track indices ({}, {}).", + guide->getNet()->getName(), + box.xMin() / dbu, + box.yMin() / dbu, + box.xMax() / dbu, + box.yMax() / dbu, + getDesign()->getTech()->getLayer(layer_num)->getName(), + idx_1, + idx_2); } - totCost_ += drcCost; - iroute->setCost(drcCost); - return bestTrackLoc; + totCost_ += drc_cost; + iroute->setCost(drc_cost); + return best_track_loc; } void FlexTAWorker::assignIroute_updateIroute(taPin* iroute, @@ -1217,12 +1329,12 @@ void FlexTAWorker::assignIroute(taPin* iroute) { frOrderedIdSet pinS; assignIroute_init(iroute, &pinS); - frLayerNum lNum; - int idx1, idx2; - assignIroute_availTracks(iroute, lNum, idx1, idx2); - auto bestTrackLoc = assignIroute_bestTrack(iroute, lNum, idx1, idx2); + frLayerNum layer_num; + int idx_1, idx_2; + assignIroute_availTracks(iroute, layer_num, idx_1, idx_2); + auto best_track_loc = assignIroute_bestTrack(iroute, layer_num, idx_1, idx_2); - assignIroute_updateIroute(iroute, bestTrackLoc, &pinS); + assignIroute_updateIroute(iroute, best_track_loc, &pinS); assignIroute_updateOthers(pinS); } diff --git a/src/drt/src/ta/FlexTA_end.cpp b/src/drt/src/ta/FlexTA_end.cpp index 7f809ee9064..d7a6b87bcb5 100644 --- a/src/drt/src/ta/FlexTA_end.cpp +++ b/src/drt/src/ta/FlexTA_end.cpp @@ -16,25 +16,23 @@ namespace drt { void FlexTAWorker::saveToGuides() { for (auto& iroute : iroutes_) { - for (auto& uPinFig : iroute->getFigs()) { - if (uPinFig->typeId() == tacPathSeg) { - std::unique_ptr pathSeg = std::make_unique( - *static_cast(uPinFig.get())); + auto* guide = iroute->getGuide(); + for (auto& pin_fig : iroute->getFigs()) { + if (pin_fig->typeId() == tacPathSeg) { + auto path_seg = std::make_unique( + *static_cast(pin_fig.get())); if (save_updates_) { drUpdate update(drUpdate::ADD_GUIDE); - update.setPathSeg(*pathSeg); - update.setIndexInOwner(iroute->getGuide()->getIndexInOwner()); - update.setNet(iroute->getGuide()->getNet()); + update.setPathSeg(*path_seg); + update.setIndexInOwner(guide->getIndexInOwner()); + update.setNet(guide->getNet()); design_->addUpdate(update); } - pathSeg->addToNet(iroute->getGuide()->getNet()); - auto guide = iroute->getGuide(); - std::vector> tmp; - tmp.push_back(std::move(pathSeg)); - guide->setRoutes(tmp); + path_seg->addToNet(guide->getNet()); + std::vector> routes; + routes.push_back(std::move(path_seg)); + guide->setRoutes(routes); } - // modify upper/lower segs - // upper/lower seg will have longest wirelength } } } diff --git a/src/drt/src/ta/FlexTA_graphics.cpp b/src/drt/src/ta/FlexTA_graphics.cpp index 4daf2ab7316..b478f3a304b 100644 --- a/src/drt/src/ta/FlexTA_graphics.cpp +++ b/src/drt/src/ta/FlexTA_graphics.cpp @@ -40,19 +40,17 @@ void FlexTAGraphics::drawIrouteGuide(frNet* net, odb::dbTechLayer* layer, gui::Painter& painter) { - frLayerNum layerNum; - - layerNum = layer_map_.at(layer->getNumber()); - if (layerNum < 0) { + const frLayerNum layer_num = layer_map_.at(layer->getNumber()); + if (layer_num < 0) { return; } for (auto& guide : net->getGuides()) { - for (auto& uConnFig : guide->getRoutes()) { - auto connFig = uConnFig.get(); - if (connFig->typeId() == frcPathSeg) { - auto seg = static_cast(connFig); - if (seg->getLayerNum() == layerNum) { + for (auto& conn_fig_ptr : guide->getRoutes()) { + auto conn_fig = conn_fig_ptr.get(); + if (conn_fig->typeId() == frcPathSeg) { + auto seg = static_cast(conn_fig); + if (seg->getLayerNum() == layer_num) { painter.drawRect(seg->getBBox()); } } diff --git a/src/drt/src/ta/FlexTA_init.cpp b/src/drt/src/ta/FlexTA_init.cpp index 5280d07e6ba..582b309f96e 100644 --- a/src/drt/src/ta/FlexTA_init.cpp +++ b/src/drt/src/ta/FlexTA_init.cpp @@ -18,6 +18,7 @@ #include "db/obj/frInstBlockage.h" #include "db/obj/frInstTerm.h" #include "db/obj/frShape.h" +#include "db/obj/frVia.h" #include "db/taObj/taFig.h" #include "db/taObj/taPin.h" #include "db/taObj/taVia.h" @@ -73,68 +74,166 @@ bool FlexTAWorker::outOfDieVia(frLayerNum layer_num, void FlexTAWorker::initTracks() { trackLocs_.clear(); - const int numLayers = getDesign()->getTech()->getLayers().size(); - trackLocs_.resize(numLayers); - std::vector> trackCoordSets(numLayers); + const int num_layers = getDesign()->getTech()->getLayers().size(); + trackLocs_.resize(num_layers); + std::vector> track_coord_sets(num_layers); // uPtr for tp auto die_box = getDesign()->getTopBlock()->getDieBox(); auto die_center = die_box.center(); - for (int lNum = 0; lNum < (int) numLayers; lNum++) { - auto layer = getDesign()->getTech()->getLayer(lNum); + for (int layer_num = 0; layer_num < (int) num_layers; layer_num++) { + auto layer = getDesign()->getTech()->getLayer(layer_num); if (layer->getType() != dbTechLayerType::ROUTING) { continue; } if (layer->getDir() != getDir()) { continue; } - for (auto& tp : getDesign()->getTopBlock()->getTrackPatterns(lNum)) { - if ((getDir() == dbTechLayerDir::HORIZONTAL && !tp->isHorizontal()) - || (getDir() == dbTechLayerDir::VERTICAL && tp->isHorizontal())) { - bool isH = (getDir() == dbTechLayerDir::HORIZONTAL); - frCoord lowCoord = (isH ? getRouteBox().yMin() : getRouteBox().xMin()); - frCoord highCoord = (isH ? getRouteBox().yMax() : getRouteBox().xMax()); - int trackNum - = (lowCoord - tp->getStartCoord()) / (int) tp->getTrackSpacing(); - trackNum = std::max(trackNum, 0); - if (trackNum * (int) tp->getTrackSpacing() + tp->getStartCoord() - < lowCoord) { - trackNum++; + for (auto& tp : getDesign()->getTopBlock()->getTrackPatterns(layer_num)) { + if ((getDir() == dbTechLayerDir::HORIZONTAL + && tp->isHorizontal() == false) + || (getDir() == dbTechLayerDir::VERTICAL + && tp->isHorizontal() == true)) { + bool is_horizontal = (getDir() == dbTechLayerDir::HORIZONTAL); + frCoord low_coord + = (is_horizontal ? getRouteBox().yMin() : getRouteBox().xMin()); + frCoord high_coord + = (is_horizontal ? getRouteBox().yMax() : getRouteBox().xMax()); + int track_num + = (low_coord - tp->getStartCoord()) / (int) tp->getTrackSpacing(); + track_num = std::max(track_num, 0); + if (track_num * (int) tp->getTrackSpacing() + tp->getStartCoord() + < low_coord) { + track_num++; } - for (; trackNum < (int) tp->getNumTracks() - && trackNum * (int) tp->getTrackSpacing() + tp->getStartCoord() - < highCoord; - trackNum++) { + for (; track_num < (int) tp->getNumTracks() + && track_num * (int) tp->getTrackSpacing() + tp->getStartCoord() + < high_coord; + track_num++) { frCoord trackCoord - = trackNum * tp->getTrackSpacing() + tp->getStartCoord(); + = track_num * tp->getTrackSpacing() + tp->getStartCoord(); odb::Point via_pt(die_center); - if (isH) { + if (is_horizontal) { via_pt.setY(trackCoord); } else { via_pt.setX(trackCoord); } - if (outOfDieVia(lNum, via_pt, die_box)) { + if (outOfDieVia(layer_num, via_pt, die_box)) { continue; } - trackCoordSets[lNum].insert(trackCoord); + track_coord_sets[layer_num].insert(trackCoord); } } } } - for (int i = 0; i < (int) trackCoordSets.size(); i++) { - for (auto coord : trackCoordSets[i]) { + for (int i = 0; i < (int) track_coord_sets.size(); i++) { + for (auto coord : track_coord_sets[i]) { trackLocs_[i].push_back(coord); } } } +bool FlexTAWorker::initIroute_helper_pin_iterm( + frInstTerm* iterm, + frNet* net, + frLayerNum layer_num, + bool is_horizontal, + bool has_down, + bool has_up, + frCoord& max_begin, + frCoord& min_end, + std::set& down_via_coord_set, + std::set& up_via_coord_set, + int& next_iroute_dir, + frCoord& pin_coord) +{ + if (iterm->getNet() != net) { + return false; + } + frInst* inst = iterm->getInst(); + odb::dbTransform shiftXform = inst->getNoRotationTransform(); + frMTerm* mterm = iterm->getTerm(); + int pinIdx = 0; + for (auto& pin : mterm->getPins()) { + if (!pin->hasPinAccess()) { + pinIdx++; + continue; + } + frAccessPoint* ap = (iterm->getAccessPoints())[pinIdx]; + if (ap == nullptr) { + pinIdx++; + continue; + } + odb::Point bp = ap->getPoint(); + auto bNum = ap->getLayerNum(); + shiftXform.apply(bp); + if (layer_num == bNum && getRouteBox().intersects(bp)) { + pin_coord = is_horizontal ? bp.y() : bp.x(); + max_begin = is_horizontal ? bp.x() : bp.y(); + min_end = is_horizontal ? bp.x() : bp.y(); + next_iroute_dir = 0; + if (has_down) { + down_via_coord_set.insert(max_begin); + } + if (has_up) { + up_via_coord_set.insert(max_begin); + } + return true; + } + pinIdx++; + } + return false; +} + +bool FlexTAWorker::initIroute_helper_pin_bterm( + frBTerm* bterm, + frNet* net, + frLayerNum layer_num, + bool is_horizontal, + bool has_down, + bool has_up, + frCoord& max_begin, + frCoord& min_end, + std::set& down_via_coord_set, + std::set& up_via_coord_set, + int& next_iroute_dir, + frCoord& pin_coord) +{ + if (bterm->getNet() != net) { + return false; + } + for (auto& pin : bterm->getPins()) { + if (!pin->hasPinAccess()) { + continue; + } + for (auto& ap : pin->getPinAccess(0)->getAccessPoints()) { + odb::Point bp = ap->getPoint(); + auto bNum = ap->getLayerNum(); + if (layer_num == bNum && getRouteBox().intersects(bp)) { + pin_coord = is_horizontal ? bp.y() : bp.x(); + max_begin = is_horizontal ? bp.x() : bp.y(); + min_end = is_horizontal ? bp.x() : bp.y(); + next_iroute_dir = 0; + if (has_down) { + down_via_coord_set.insert(max_begin); + } + if (has_up) { + up_via_coord_set.insert(max_begin); + } + return true; + } + } + } + return false; +} + // use prefAp, otherwise return false bool FlexTAWorker::initIroute_helper_pin(frGuide* guide, - frCoord& maxBegin, - frCoord& minEnd, - std::set& downViaCoordSet, - std::set& upViaCoordSet, - int& nextIrouteDir, - frCoord& pinCoord) + frCoord& max_begin, + frCoord& min_end, + std::set& down_via_coord_set, + std::set& up_via_coord_set, + int& next_iroute_dir, + frCoord& pin_coord) { auto [bp, ep] = guide->getPoints(); if (bp != ep) { @@ -142,31 +241,31 @@ bool FlexTAWorker::initIroute_helper_pin(frGuide* guide, } auto net = guide->getNet(); - auto layerNum = guide->getBeginLayerNum(); - bool isH = (getDir() == dbTechLayerDir::HORIZONTAL); - bool hasDown = false; - bool hasUp = false; + auto layer_num = guide->getBeginLayerNum(); + bool is_horizontal = (getDir() == dbTechLayerDir::HORIZONTAL); + bool has_down = false; + bool has_up = false; - std::vector nbrGuides; + std::vector nbr_guides; auto rq = getRegionQuery(); odb::Rect box; box = odb::Rect(bp, bp); - nbrGuides.clear(); - if (layerNum - 2 >= router_cfg_->BOTTOM_ROUTING_LAYER) { - rq->queryGuide(box, layerNum - 2, nbrGuides); - for (auto& nbrGuide : nbrGuides) { + nbr_guides.clear(); + if (layer_num - 2 >= router_cfg_->BOTTOM_ROUTING_LAYER) { + rq->queryGuide(box, layer_num - 2, nbr_guides); + for (auto& nbrGuide : nbr_guides) { if (nbrGuide->getNet() == net) { - hasDown = true; + has_down = true; break; } } } - nbrGuides.clear(); - if (layerNum + 2 < (int) design_->getTech()->getLayers().size()) { - rq->queryGuide(box, layerNum + 2, nbrGuides); - for (auto& nbrGuide : nbrGuides) { + nbr_guides.clear(); + if (layer_num + 2 < (int) design_->getTech()->getLayers().size()) { + rq->queryGuide(box, layer_num + 2, nbr_guides); + for (auto& nbrGuide : nbr_guides) { if (nbrGuide->getNet() == net) { - hasUp = true; + has_up = true; break; } } @@ -180,70 +279,37 @@ bool FlexTAWorker::initIroute_helper_pin(frGuide* guide, switch (term->typeId()) { case frcInstTerm: { auto iterm = static_cast(term); - if (iterm->getNet() != net) { - continue; - } - frInst* inst = iterm->getInst(); - odb::dbTransform shiftXform = inst->getNoRotationTransform(); - frMTerm* mterm = iterm->getTerm(); - int pinIdx = 0; - for (auto& pin : mterm->getPins()) { - if (!pin->hasPinAccess()) { - pinIdx++; - continue; - } - frAccessPoint* ap - = (static_cast(term)->getAccessPoints())[pinIdx]; - if (ap == nullptr) { - pinIdx++; - continue; - } - odb::Point bp = ap->getPoint(); - auto bNum = ap->getLayerNum(); - shiftXform.apply(bp); - if (layerNum == bNum && getRouteBox().intersects(bp)) { - pinCoord = isH ? bp.y() : bp.x(); - maxBegin = isH ? bp.x() : bp.y(); - minEnd = isH ? bp.x() : bp.y(); - nextIrouteDir = 0; - if (hasDown) { - downViaCoordSet.insert(maxBegin); - } - if (hasUp) { - upViaCoordSet.insert(maxBegin); - } - return true; - } - pinIdx++; + if (initIroute_helper_pin_iterm(iterm, + net, + layer_num, + is_horizontal, + has_down, + has_up, + max_begin, + min_end, + down_via_coord_set, + up_via_coord_set, + next_iroute_dir, + pin_coord)) { + return true; } break; } case frcBTerm: { auto bterm = static_cast(term); - if (bterm->getNet() != net) { - continue; - } - for (auto& pin : bterm->getPins()) { - if (!pin->hasPinAccess()) { - continue; - } - for (auto& ap : pin->getPinAccess(0)->getAccessPoints()) { - odb::Point bp = ap->getPoint(); - auto bNum = ap->getLayerNum(); - if (layerNum == bNum && getRouteBox().intersects(bp)) { - pinCoord = isH ? bp.y() : bp.x(); - maxBegin = isH ? bp.x() : bp.y(); - minEnd = isH ? bp.x() : bp.y(); - nextIrouteDir = 0; - if (hasDown) { - downViaCoordSet.insert(maxBegin); - } - if (hasUp) { - upViaCoordSet.insert(maxBegin); - } - return true; - } - } + if (initIroute_helper_pin_bterm(bterm, + net, + layer_num, + is_horizontal, + has_down, + has_up, + max_begin, + min_end, + down_via_coord_set, + up_via_coord_set, + next_iroute_dir, + pin_coord)) { + return true; } break; } @@ -256,36 +322,36 @@ bool FlexTAWorker::initIroute_helper_pin(frGuide* guide, } void FlexTAWorker::initIroute_helper(frGuide* guide, - frCoord& maxBegin, - frCoord& minEnd, - std::set& downViaCoordSet, - std::set& upViaCoordSet, - int& nextIrouteDir, - frCoord& pinCoord) + frCoord& max_begin, + frCoord& min_end, + std::set& down_via_coord_set, + std::set& up_via_coord_set, + int& next_iroute_dir, + frCoord& pin_coord) { if (!initIroute_helper_pin(guide, - maxBegin, - minEnd, - downViaCoordSet, - upViaCoordSet, - nextIrouteDir, - pinCoord)) { + max_begin, + min_end, + down_via_coord_set, + up_via_coord_set, + next_iroute_dir, + pin_coord)) { initIroute_helper_generic(guide, - maxBegin, - minEnd, - downViaCoordSet, - upViaCoordSet, - nextIrouteDir, - pinCoord); + max_begin, + min_end, + down_via_coord_set, + up_via_coord_set, + next_iroute_dir, + pin_coord); } } void FlexTAWorker::initIroute_helper_generic_helper(frGuide* guide, - frCoord& pinCoord) + frCoord& pin_coord) { auto [bp, ep] = guide->getPoints(); auto net = guide->getNet(); - bool isH = (getDir() == dbTechLayerDir::HORIZONTAL); + bool is_horizontal = (getDir() == dbTechLayerDir::HORIZONTAL); auto rq = getRegionQuery(); std::vector result; @@ -320,7 +386,8 @@ void FlexTAWorker::initIroute_helper_generic_helper(frGuide* guide, frPinAccess* pa = pin->getPinAccess(0); if (pa != nullptr) { if (pa->getNumAccessPoints() > 0) { - // use first ap of frMPin's pin access to set pinCoord of iroute + // use first ap of frMPin's pin access to set pin_coord of + // iroute ap = pa->getAccessPoint(0); } else { pinIdx++; @@ -334,7 +401,7 @@ void FlexTAWorker::initIroute_helper_generic_helper(frGuide* guide, odb::Point bp = ap->getPoint(); shiftXform.apply(bp); if (getRouteBox().intersects(bp)) { - pinCoord = isH ? bp.y() : bp.x(); + pin_coord = is_horizontal ? bp.y() : bp.x(); return; } pinIdx++; @@ -353,7 +420,7 @@ void FlexTAWorker::initIroute_helper_generic_helper(frGuide* guide, for (auto& ap : pin->getPinAccess(0)->getAccessPoints()) { odb::Point bp = ap->getPoint(); if (getRouteBox().intersects(bp)) { - pinCoord = isH ? bp.y() : bp.x(); + pin_coord = is_horizontal ? bp.y() : bp.x(); return; } } @@ -366,215 +433,251 @@ void FlexTAWorker::initIroute_helper_generic_helper(frGuide* guide, } } -void FlexTAWorker::initIroute_helper_generic(frGuide* guide, - frCoord& minBegin, - frCoord& maxEnd, - std::set& downViaCoordSet, - std::set& upViaCoordSet, - int& nextIrouteDir, - frCoord& pinCoord) +void FlexTAWorker::initIroute_helper_generic_endpoint( + frGuide* guide, + const odb::Point& cp, + bool is_begin, + frLayerNum layer_num, + bool is_horizontal, + frCoord& min_begin, + frCoord& max_end, + bool& has_min_begin, + bool& has_max_end, + std::set& down_via_coord_set, + std::set& up_via_coord_set, + int& next_iroute_dir) { auto net = guide->getNet(); - auto layerNum = guide->getBeginLayerNum(); - bool hasMinBegin = false; - bool hasMaxEnd = false; - minBegin = std::numeric_limits::max(); - maxEnd = std::numeric_limits::min(); - nextIrouteDir = 0; - // pinCoord = std::numeric_limits::max(); - bool isH = (getDir() == dbTechLayerDir::HORIZONTAL); - downViaCoordSet.clear(); - upViaCoordSet.clear(); - - auto [bp, ep] = guide->getPoints(); - odb::Point cp; - // layerNum in FlexTAWorker - std::vector nbrGuides; + std::vector nbr_guides; + odb::Rect box(cp, cp); auto rq = getRegionQuery(); - odb::Rect box; - for (int i = 0; i < 2; i++) { - nbrGuides.clear(); - // check left - if (i == 0) { - box = odb::Rect(bp, bp); - cp = bp; - // check right - } else { - box = odb::Rect(ep, ep); - cp = ep; - } - if (layerNum - 2 >= router_cfg_->BOTTOM_ROUTING_LAYER) { - rq->queryGuide(box, layerNum - 2, nbrGuides); - } - if (layerNum + 2 < (int) design_->getTech()->getLayers().size()) { - rq->queryGuide(box, layerNum + 2, nbrGuides); + + if (layer_num - 2 >= router_cfg_->BOTTOM_ROUTING_LAYER) { + rq->queryGuide(box, layer_num - 2, nbr_guides); + } + if (layer_num + 2 < (int) design_->getTech()->getLayers().size()) { + rq->queryGuide(box, layer_num + 2, nbr_guides); + } + + for (auto* nbr_guide : nbr_guides) { + if (nbr_guide->getNet() != net) { + continue; } - for (auto& nbrGuide : nbrGuides) { - if (nbrGuide->getNet() == net) { - auto [nbrBp, nbrEp] = nbrGuide->getPoints(); - if (!nbrGuide->hasRoutes()) { - // via location assumed in center - auto psLNum = nbrGuide->getBeginLayerNum(); - if (psLNum == layerNum - 2) { - downViaCoordSet.insert((isH ? nbrBp.x() : nbrBp.y())); - } else { - upViaCoordSet.insert((isH ? nbrBp.x() : nbrBp.y())); - } - } else { - for (auto& connFig : nbrGuide->getRoutes()) { - if (connFig->typeId() == frcPathSeg) { - auto obj = static_cast(connFig.get()); - auto [nbrSegBegin, ignored] = obj->getPoints(); - auto psLNum = obj->getLayerNum(); - if (i == 0) { - minBegin = std::min(minBegin, - (isH ? nbrSegBegin.x() : nbrSegBegin.y())); - hasMinBegin = true; - } else { - maxEnd = std::max(maxEnd, - (isH ? nbrSegBegin.x() : nbrSegBegin.y())); - hasMaxEnd = true; - } - if (psLNum == layerNum - 2) { - downViaCoordSet.insert( - (isH ? nbrSegBegin.x() : nbrSegBegin.y())); - } else { - upViaCoordSet.insert((isH ? nbrSegBegin.x() : nbrSegBegin.y())); - } - } - } + + auto [nbr_begin, nbr_end] = nbr_guide->getPoints(); + if (!nbr_guide->hasRoutes()) { + const auto ps_layer_num = nbr_guide->getBeginLayerNum(); + const frCoord coord = is_horizontal ? nbr_begin.x() : nbr_begin.y(); + if (ps_layer_num == layer_num - 2) { + down_via_coord_set.insert(coord); + } else { + up_via_coord_set.insert(coord); + } + } else { + for (auto& conn_fig : nbr_guide->getRoutes()) { + if (conn_fig->typeId() != frcPathSeg) { + continue; } - if (cp == nbrEp) { - nextIrouteDir -= 1; + + auto* path_seg = static_cast(conn_fig.get()); + auto [nbr_seg_begin, ignored] = path_seg->getPoints(); + const auto ps_layer_num = path_seg->getLayerNum(); + const frCoord coord + = is_horizontal ? nbr_seg_begin.x() : nbr_seg_begin.y(); + + if (is_begin) { + min_begin = std::min(min_begin, coord); + has_min_begin = true; + } else { + max_end = std::max(max_end, coord); + has_max_end = true; } - if (cp == nbrBp) { - nextIrouteDir += 1; + + if (ps_layer_num == layer_num - 2) { + down_via_coord_set.insert(coord); + } else { + up_via_coord_set.insert(coord); } } } + + if (cp == nbr_end) { + next_iroute_dir -= 1; + } + if (cp == nbr_begin) { + next_iroute_dir += 1; + } } +} + +void FlexTAWorker::initIroute_helper_generic( + frGuide* guide, + frCoord& min_begin, + frCoord& max_end, + std::set& down_via_coord_set, + std::set& up_via_coord_set, + int& next_iroute_dir, + frCoord& pin_coord) +{ + auto layer_num = guide->getBeginLayerNum(); + bool has_min_begin = false; + bool has_max_end = false; + min_begin = std::numeric_limits::max(); + max_end = std::numeric_limits::min(); + next_iroute_dir = 0; + // pin_coord = std::numeric_limits::max(); + bool is_horizontal = (getDir() == dbTechLayerDir::HORIZONTAL); + down_via_coord_set.clear(); + up_via_coord_set.clear(); + + auto [bp, ep] = guide->getPoints(); + initIroute_helper_generic_endpoint(guide, + bp, + true, + layer_num, + is_horizontal, + min_begin, + max_end, + has_min_begin, + has_max_end, + down_via_coord_set, + up_via_coord_set, + next_iroute_dir); + initIroute_helper_generic_endpoint(guide, + ep, + false, + layer_num, + is_horizontal, + min_begin, + max_end, + has_min_begin, + has_max_end, + down_via_coord_set, + up_via_coord_set, + next_iroute_dir); - if (!hasMinBegin) { - minBegin = (isH ? bp.x() : bp.y()); + if (!has_min_begin) { + min_begin = (is_horizontal ? bp.x() : bp.y()); } - if (!hasMaxEnd) { - maxEnd = (isH ? ep.x() : ep.y()); + if (!has_max_end) { + max_end = (is_horizontal ? ep.x() : ep.y()); } - if (minBegin > maxEnd) { - std::swap(minBegin, maxEnd); + if (min_begin > max_end) { + std::swap(min_begin, max_end); } - if (minBegin == maxEnd) { - maxEnd += 1; + if (min_begin == max_end) { + max_end += 1; } - // pinCoord purely depends on ap regardless of track - initIroute_helper_generic_helper(guide, pinCoord); + // pin_coord purely depends on ap regardless of track + initIroute_helper_generic_helper(guide, pin_coord); } void FlexTAWorker::initIroute(frGuide* guide) { auto iroute = std::make_unique(); iroute->setGuide(guide); - odb::Rect guideBox = guide->getBBox(); - auto layerNum = guide->getBeginLayerNum(); - bool isExt = !(getRouteBox().contains(guideBox)); - if (isExt) { + odb::Rect guide_box = guide->getBBox(); + auto layer_num = guide->getBeginLayerNum(); + bool is_ext = !(getRouteBox().contains(guide_box)); + if (is_ext) { // extIroute empty, skip if (guide->getRoutes().empty()) { return; } } - frCoord maxBegin, minEnd; - std::set downViaCoordSet, upViaCoordSet; - int nextIrouteDir = 0; - frCoord pinCoord = std::numeric_limits::max(); + frCoord max_begin, min_end; + std::set down_via_coord_set, up_via_coord_set; + int next_iroute_dir = 0; + frCoord pin_coord = std::numeric_limits::max(); initIroute_helper(guide, - maxBegin, - minEnd, - downViaCoordSet, - upViaCoordSet, - nextIrouteDir, - pinCoord); - - frCoord trackLoc = 0; - bool isH = (getDir() == dbTechLayerDir::HORIZONTAL); + max_begin, + min_end, + down_via_coord_set, + up_via_coord_set, + next_iroute_dir, + pin_coord); + + frCoord track_loc = 0; + bool is_horizontal = (getDir() == dbTechLayerDir::HORIZONTAL); // set trackIdx if (!isInitTA()) { for (auto& connFig : guide->getRoutes()) { if (connFig->typeId() == frcPathSeg) { auto obj = static_cast(connFig.get()); auto [segBegin, ignored] = obj->getPoints(); - trackLoc = (isH ? segBegin.y() : segBegin.x()); + track_loc = (is_horizontal ? segBegin.y() : segBegin.x()); } } } else { - trackLoc = 0; + track_loc = 0; } std::unique_ptr ps = std::make_unique(); ps->setNet(guide->getNet()); - auto rptr = static_cast(ps.get()); - if (isH) { - rptr->setPoints(odb::Point(maxBegin, trackLoc), - odb::Point(minEnd, trackLoc)); + auto r_ptr = static_cast(ps.get()); + if (is_horizontal) { + r_ptr->setPoints(odb::Point(max_begin, track_loc), + odb::Point(min_end, track_loc)); } else { - rptr->setPoints(odb::Point(trackLoc, maxBegin), - odb::Point(trackLoc, minEnd)); + r_ptr->setPoints(odb::Point(track_loc, max_begin), + odb::Point(track_loc, min_end)); } - rptr->setLayerNum(layerNum); + r_ptr->setLayerNum(layer_num); if (guide->getNet() && guide->getNet()->getNondefaultRule()) { frNonDefaultRule* ndr = guide->getNet()->getNondefaultRule(); auto style - = getDesign()->getTech()->getLayer(layerNum)->getDefaultSegStyle(); + = getDesign()->getTech()->getLayer(layer_num)->getDefaultSegStyle(); style.setWidth( - std::max((int) style.getWidth(), ndr->getWidth(layerNum / 2 - 1))); - rptr->setStyle(style); + std::max((int) style.getWidth(), ndr->getWidth(layer_num / 2 - 1))); + r_ptr->setStyle(style); } else { - rptr->setStyle( - getDesign()->getTech()->getLayer(layerNum)->getDefaultSegStyle()); + r_ptr->setStyle( + getDesign()->getTech()->getLayer(layer_num)->getDefaultSegStyle()); } // owner set when add to taPin iroute->addPinFig(std::move(ps)); const frViaDef* viaDef; - for (auto coord : upViaCoordSet) { + for (auto coord : up_via_coord_set) { if (guide->getNet()->getNondefaultRule() - && guide->getNet()->getNondefaultRule()->getPrefVia(layerNum / 2 - 1)) { + && guide->getNet()->getNondefaultRule()->getPrefVia(layer_num / 2 + - 1)) { viaDef - = guide->getNet()->getNondefaultRule()->getPrefVia(layerNum / 2 - 1); + = guide->getNet()->getNondefaultRule()->getPrefVia(layer_num / 2 - 1); } else { viaDef - = getDesign()->getTech()->getLayer(layerNum + 1)->getDefaultViaDef(); + = getDesign()->getTech()->getLayer(layer_num + 1)->getDefaultViaDef(); } std::unique_ptr via = std::make_unique(viaDef); via->setNet(guide->getNet()); - auto rViaPtr = static_cast(via.get()); - rViaPtr->setOrigin(isH ? odb::Point(coord, trackLoc) - : odb::Point(trackLoc, coord)); + auto r_via_ptr = static_cast(via.get()); + r_via_ptr->setOrigin(is_horizontal ? odb::Point(coord, track_loc) + : odb::Point(track_loc, coord)); iroute->addPinFig(std::move(via)); } - for (auto coord : downViaCoordSet) { + for (auto coord : down_via_coord_set) { if (guide->getNet()->getNondefaultRule() - && guide->getNet()->getNondefaultRule()->getPrefVia((layerNum - 2) / 2 + && guide->getNet()->getNondefaultRule()->getPrefVia((layer_num - 2) / 2 - 1)) { viaDef = guide->getNet()->getNondefaultRule()->getPrefVia( - (layerNum - 2) / 2 - 1); + (layer_num - 2) / 2 - 1); } else { viaDef - = getDesign()->getTech()->getLayer(layerNum - 1)->getDefaultViaDef(); + = getDesign()->getTech()->getLayer(layer_num - 1)->getDefaultViaDef(); } std::unique_ptr via = std::make_unique(viaDef); via->setNet(guide->getNet()); - auto rViaPtr = static_cast(via.get()); - rViaPtr->setOrigin(isH ? odb::Point(coord, trackLoc) - : odb::Point(trackLoc, coord)); + auto r_via_ptr = static_cast(via.get()); + r_via_ptr->setOrigin(is_horizontal ? odb::Point(coord, track_loc) + : odb::Point(track_loc, coord)); iroute->addPinFig(std::move(via)); } - iroute->setNextIrouteDir(nextIrouteDir); - if (pinCoord < std::numeric_limits::max()) { - iroute->setPinCoord(pinCoord); + iroute->setNextIrouteDir(next_iroute_dir); + if (pin_coord < std::numeric_limits::max()) { + iroute->setPinCoord(pin_coord); } - addIroute(std::move(iroute), isExt); + addIroute(std::move(iroute), is_ext); } void FlexTAWorker::initIroutes() @@ -682,30 +785,30 @@ void FlexTAWorker::sortIroutes() } void FlexTAWorker::initFixedObjs_helper(const odb::Rect& box, - frCoord bloatDist, - frLayerNum lNum, - frNet* net, + frCoord bloat_dist, + frLayerNum layer_num, + frNet* net_ptr, bool isViaCost) { odb::Rect bloatBox; - box.bloat(bloatDist, bloatBox); - auto con = getDesign()->getTech()->getLayer(lNum)->getShortConstraint(); + box.bloat(bloat_dist, bloatBox); + auto con = getDesign()->getTech()->getLayer(layer_num)->getShortConstraint(); bool isH = (getDir() == dbTechLayerDir::HORIZONTAL); int idx1, idx2; // frCoord x1, x2; if (isH) { - getTrackIdx(bloatBox.yMin(), bloatBox.yMax(), lNum, idx1, idx2); + getTrackIdx(bloatBox.yMin(), bloatBox.yMax(), layer_num, idx1, idx2); } else { - getTrackIdx(bloatBox.xMin(), bloatBox.xMax(), lNum, idx1, idx2); + getTrackIdx(bloatBox.xMin(), bloatBox.xMax(), layer_num, idx1, idx2); } - auto& trackLocs = getTrackLocs(lNum); + auto& trackLocs = getTrackLocs(layer_num); auto& workerRegionQuery = getWorkerRegionQuery(); for (int i = idx1; i <= idx2; i++) { // new // auto &track = tracks[i]; - // track.addToCost(net, x1, x2, 0); - // track.addToCost(net, x1, x2, 1); - // track.addToCost(net, x1, x2, 2); + // track.addToCost(net_ptr, x1, x2, 0); + // track.addToCost(net_ptr, x1, x2, 1); + // track.addToCost(net_ptr, x1, x2, 2); // old auto trackLoc = trackLocs[i]; odb::Rect tmpBox; @@ -715,10 +818,131 @@ void FlexTAWorker::initFixedObjs_helper(const odb::Rect& box, tmpBox.init(trackLoc, bloatBox.yMin(), trackLoc, bloatBox.yMax()); } if (isViaCost) { - workerRegionQuery.addViaCost(tmpBox, lNum, net, con); + workerRegionQuery.addViaCost(tmpBox, layer_num, net_ptr, con); } else { - workerRegionQuery.addCost(tmpBox, lNum, net, con); + workerRegionQuery.addCost(tmpBox, layer_num, net_ptr, con); + } + } +} + +void FlexTAWorker::initFixedObjs_processTerm(frBlockObject* obj, + frLayerNum layer_num, + const odb::Rect& bounds, + odb::Rect& box, + frCoord width) +{ + frCoord bloat_dist = router_cfg_->TASHAPEBLOATWIDTH * width; + frNet* net_ptr = nullptr; + if (obj->typeId() == frcBTerm) { + net_ptr = static_cast(obj)->getNet(); + } else { + net_ptr = static_cast(obj)->getNet(); + } + initFixedObjs_helper(box, bloat_dist, layer_num, net_ptr); +} + +void FlexTAWorker::initFixedObjs_processVia(frBlockObject* obj, + frLayerNum layer_num, + const odb::Rect& bounds, + odb::Rect& box, + frCoord width, + frNet* net_ptr) +{ + frCoord bloat_dist = 0; + // down-via + if (layer_num - 2 >= getDesign()->getTech()->getBottomLayerNum() + && getTech()->getLayer(layer_num - 2)->getType() + == dbTechLayerType::ROUTING) { + auto cut_layer = getTech()->getLayer(layer_num - 1); + auto via = std::make_unique(cut_layer->getDefaultViaDef()); + odb::Rect via_box = via->getLayer2BBox(); + frCoord via_width = via_box.minDXDY(); + // only add for fat via + if (via_width > width) { + bloat_dist = initFixedObjs_calcOBSBloatDistVia( + cut_layer->getDefaultViaDef(), layer_num, bounds, false); + initFixedObjs_helper(box, bloat_dist, layer_num, net_ptr, true); + } + } + // up-via + if (layer_num + 2 < (int) design_->getTech()->getLayers().size() + && getTech()->getLayer(layer_num + 2)->getType() + == dbTechLayerType::ROUTING) { + auto cut_layer = getTech()->getLayer(layer_num + 1); + auto via = std::make_unique(cut_layer->getDefaultViaDef()); + odb::Rect via_box = via->getLayer1BBox(); + frCoord via_width = via_box.minDXDY(); + // only add for fat via + if (via_width > width) { + bloat_dist = initFixedObjs_calcOBSBloatDistVia( + cut_layer->getDefaultViaDef(), layer_num, bounds, false); + initFixedObjs_helper(box, bloat_dist, layer_num, net_ptr, true); + } + } +} + +void FlexTAWorker::initFixedObjs_processRouting(frBlockObject* obj, + frLayerNum layer_num, + const odb::Rect& bounds, + odb::Rect& box, + frCoord width) +{ + frCoord bloat_dist = initFixedObjs_calcBloatDist(obj, layer_num, bounds); + frNet* net_ptr = nullptr; + if (obj->typeId() == frcPathSeg) { + net_ptr = static_cast(obj)->getNet(); + } else { + net_ptr = static_cast(obj)->getNet(); + } + initFixedObjs_helper(box, bloat_dist, layer_num, net_ptr); + if (getTech()->getLayer(layer_num)->getType() == dbTechLayerType::ROUTING) { + initFixedObjs_processVia(obj, layer_num, bounds, box, width, net_ptr); + } +} + +void FlexTAWorker::initFixedObjs_applyBorderViaCosts( + frLayerNum layer_num, + frCoord width, + bool upper, + const frRegionQuery::Objects& result) +{ + for (auto& [bounds, obj] : result) { + odb::Rect box; + bounds.bloat(-1, box); + if (obj->typeId() != frcInstBlockage) { + continue; + } + + auto* inst_blkg = static_cast(obj); + auto* inst = inst_blkg->getInst(); + const odb::dbMasterType master_type = inst->getMaster()->getMasterType(); + if (!master_type.isBlock() && !master_type.isPad() + && master_type != odb::dbMasterType::RING) { + continue; + } + if (bounds.minDXDY() <= 2 * width) { + continue; } + + auto* cut_layer + = getTech()->getLayer(upper ? layer_num + 1 : layer_num - 1); + const auto bloat_dist = initFixedObjs_calcOBSBloatDistVia( + cut_layer->getDefaultViaDef(), layer_num, bounds); + odb::Rect bloat_box; + box.bloat(bloat_dist, bloat_box); + + odb::Rect border_box( + bloat_box.xMin(), bloat_box.yMin(), box.xMin(), bloat_box.yMax()); + initFixedObjs_helper(border_box, 0, layer_num, nullptr, true); + border_box.init( + bloat_box.xMin(), box.yMax(), bloat_box.xMax(), bloat_box.yMax()); + initFixedObjs_helper(border_box, 0, layer_num, nullptr, true); + border_box.init( + box.xMax(), bloat_box.yMin(), bloat_box.xMax(), bloat_box.yMax()); + initFixedObjs_helper(border_box, 0, layer_num, nullptr, true); + border_box.init( + bloat_box.xMin(), bloat_box.yMin(), bloat_box.xMax(), box.yMin()); + initFixedObjs_helper(border_box, 0, layer_num, nullptr, true); } } @@ -727,7 +951,7 @@ void FlexTAWorker::initFixedObjs() frRegionQuery::Objects result; odb::Rect box; frCoord width = 0; - frCoord bloatDist = 0; + frCoord bloat_dist = 0; for (auto layerNum = getTech()->getBottomLayerNum(); layerNum <= getTech()->getTopLayerNum(); ++layerNum) { @@ -744,125 +968,31 @@ void FlexTAWorker::initFixedObjs() auto type = obj->typeId(); // instterm term if (type == frcInstTerm || type == frcBTerm) { - bloatDist = router_cfg_->TASHAPEBLOATWIDTH * width; - frNet* netPtr = nullptr; - if (type == frcBTerm) { - netPtr = static_cast(obj)->getNet(); - } else { - netPtr = static_cast(obj)->getNet(); - } - initFixedObjs_helper(box, bloatDist, layerNum, netPtr); + initFixedObjs_processTerm(obj, layerNum, bounds, box, width); // snet } else if (type == frcPathSeg || type == frcVia) { - bloatDist = initFixedObjs_calcBloatDist(obj, layerNum, bounds); - frNet* netPtr = nullptr; - if (type == frcPathSeg) { - netPtr = static_cast(obj)->getNet(); - } else { - netPtr = static_cast(obj)->getNet(); - } - initFixedObjs_helper(box, bloatDist, layerNum, netPtr); - if (getTech()->getLayer(layerNum)->getType() - == dbTechLayerType::ROUTING) { - // down-via - if (layerNum - 2 >= getDesign()->getTech()->getBottomLayerNum() - && getTech()->getLayer(layerNum - 2)->getType() - == dbTechLayerType::ROUTING) { - auto cutLayer = getTech()->getLayer(layerNum - 1); - auto via = std::make_unique(cutLayer->getDefaultViaDef()); - odb::Rect viaBox = via->getLayer2BBox(); - frCoord viaWidth = viaBox.minDXDY(); - // only add for fat via - if (viaWidth > width) { - bloatDist = initFixedObjs_calcOBSBloatDistVia( - cutLayer->getDefaultViaDef(), layerNum, bounds, false); - initFixedObjs_helper(box, bloatDist, layerNum, netPtr, true); - } - } - // up-via - if (layerNum + 2 < (int) design_->getTech()->getLayers().size() - && getTech()->getLayer(layerNum + 2)->getType() - == dbTechLayerType::ROUTING) { - auto cutLayer = getTech()->getLayer(layerNum + 1); - auto via = std::make_unique(cutLayer->getDefaultViaDef()); - odb::Rect viaBox = via->getLayer1BBox(); - frCoord viaWidth = viaBox.minDXDY(); - // only add for fat via - if (viaWidth > width) { - bloatDist = initFixedObjs_calcOBSBloatDistVia( - cutLayer->getDefaultViaDef(), layerNum, bounds, false); - initFixedObjs_helper(box, bloatDist, layerNum, netPtr, true); - } - } - } + initFixedObjs_processRouting(obj, layerNum, bounds, box, width); } else if (type == frcBlockage || type == frcInstBlockage) { - bloatDist = initFixedObjs_calcBloatDist(obj, layerNum, bounds); - initFixedObjs_helper(box, bloatDist, layerNum, nullptr); + bloat_dist = initFixedObjs_calcBloatDist(obj, layerNum, bounds); + initFixedObjs_helper(box, bloat_dist, layerNum, nullptr); } else { std::cout << "Warning: unsupported type in initFixedObjs\n"; } } - auto costResults = [this, layerNum, width]( - bool upper, - const frRegionQuery::Objects& - result) { - odb::Rect box; - for (auto& [bounds, obj] : result) { - bounds.bloat(-1, box); - auto type = obj->typeId(); - switch (type) { - case frcInstBlockage: { - auto instBlkg = (static_cast(obj)); - auto inst = instBlkg->getInst(); - odb::dbMasterType masterType = inst->getMaster()->getMasterType(); - if (!masterType.isBlock() && !masterType.isPad() - && masterType != odb::dbMasterType::RING) { - continue; - } - if (bounds.minDXDY() <= 2 * width) { - continue; - } - auto cutLayer - = getTech()->getLayer(upper ? layerNum + 1 : layerNum - 1); - auto bloatDist = initFixedObjs_calcOBSBloatDistVia( - cutLayer->getDefaultViaDef(), layerNum, bounds); - odb::Rect bloatBox; - box.bloat(bloatDist, bloatBox); - - odb::Rect borderBox( - bloatBox.xMin(), bloatBox.yMin(), box.xMin(), bloatBox.yMax()); - initFixedObjs_helper(borderBox, 0, layerNum, nullptr, true); - borderBox.init( - bloatBox.xMin(), box.yMax(), bloatBox.xMax(), bloatBox.yMax()); - initFixedObjs_helper(borderBox, 0, layerNum, nullptr, true); - borderBox.init( - box.xMax(), bloatBox.yMin(), bloatBox.xMax(), bloatBox.yMax()); - initFixedObjs_helper(borderBox, 0, layerNum, nullptr, true); - borderBox.init( - bloatBox.xMin(), bloatBox.yMin(), bloatBox.xMax(), box.yMin()); - initFixedObjs_helper(borderBox, 0, layerNum, nullptr, true); - break; - } - default: - break; - } - } - }; - result.clear(); if (layerNum - 2 >= getDesign()->getTech()->getBottomLayerNum() && getTech()->getLayer(layerNum - 2)->getType() == dbTechLayerType::ROUTING) { getRegionQuery()->query(getExtBox(), layerNum - 2, result); } - costResults(false, result); + initFixedObjs_applyBorderViaCosts(layerNum, width, false, result); result.clear(); if (layerNum + 2 < getDesign()->getTech()->getLayers().size() && getTech()->getLayer(layerNum + 2)->getType() == dbTechLayerType::ROUTING) { getRegionQuery()->query(getExtBox(), layerNum + 2, result); } - costResults(true, result); + initFixedObjs_applyBorderViaCosts(layerNum, width, true, result); } } @@ -887,25 +1017,25 @@ frCoord FlexTAWorker::initFixedObjs_calcOBSBloatDistVia(const frViaDef* viaDef, obsWidth = layer->getWidth(); } - frCoord bloatDist + frCoord bloat_dist = layer->getMinSpacingValue(obsWidth, viaWidth, viaWidth, false); - if (bloatDist < 0) { + if (bloat_dist < 0) { logger_->error( DRT, 140, "Layer {} has negative min spacing value.", layer->getName()); } auto& eol = layer->getDrEolSpacingConstraint(); if (viaBox.minDXDY() < eol.eolWidth) { - bloatDist = std::max(bloatDist, eol.eolSpace); + bloat_dist = std::max(bloat_dist, eol.eolSpace); } // at least via enclosure should not short with obs (OBS has issue with // wrongway and PG has issue with prefDir) // TODO: generalize the following if (isOBS) { - bloatDist += viaLength / 2; + bloat_dist += viaLength / 2; } else { - bloatDist += viaWidth / 2; + bloat_dist += viaWidth / 2; } - return bloatDist; + return bloat_dist; } frCoord FlexTAWorker::initFixedObjs_calcBloatDist(frBlockObject* obj, @@ -924,10 +1054,10 @@ frCoord FlexTAWorker::initFixedObjs_calcBloatDist(frBlockObject* obj, } // use width if minSpc does not exist - frCoord bloatDist = width; + frCoord bloat_dist = width; if (layer->hasMinSpacing()) { - bloatDist = layer->getMinSpacingValue(objWidth, width, prl, false); - if (bloatDist < 0) { + bloat_dist = layer->getMinSpacingValue(objWidth, width, prl, false); + if (bloat_dist < 0) { logger_->error(DRT, 144, "Layer {} has negative min spacing value.", @@ -935,8 +1065,8 @@ frCoord FlexTAWorker::initFixedObjs_calcBloatDist(frBlockObject* obj, } } // assuming the wire width is width - bloatDist += width / 2; - return bloatDist; + bloat_dist += width / 2; + return bloat_dist; } void FlexTAWorker::init() diff --git a/src/drt/src/ta/FlexTA_rq.cpp b/src/drt/src/ta/FlexTA_rq.cpp index dfaa5e1da45..08e914f6fa6 100644 --- a/src/drt/src/ta/FlexTA_rq.cpp +++ b/src/drt/src/ta/FlexTA_rq.cpp @@ -23,9 +23,34 @@ namespace drt { +namespace { + +bool getTaPinFigBoxAndLayer(taPinFig* fig, + odb::Rect& box, + frLayerNum& layer_num) +{ + if (fig->typeId() == tacPathSeg) { + auto* obj = static_cast(fig); + auto [begin, end] = obj->getPoints(); + box = odb::Rect(begin, end); + layer_num = obj->getLayerNum(); + return true; + } + if (fig->typeId() == tacVia) { + auto* obj = static_cast(fig); + const auto origin = obj->getOrigin(); + box = odb::Rect(origin, origin); + layer_num = obj->getViaDef()->getCutLayerNum(); + return true; + } + return false; +} + +} // namespace + struct FlexTAWorkerRegionQuery::Impl { - FlexTAWorker* taWorker; + FlexTAWorker* ta_worker; std::vector> shapes; // resource map // fixed objs, owner:: nullptr or net, con = short std::vector>> route_costs; @@ -35,65 +60,48 @@ struct FlexTAWorkerRegionQuery::Impl FlexTAWorkerRegionQuery::FlexTAWorkerRegionQuery(FlexTAWorker* in) : impl_(std::make_unique()) { - impl_->taWorker = in; + impl_->ta_worker = in; } FlexTAWorkerRegionQuery::~FlexTAWorkerRegionQuery() = default; FlexTAWorker* FlexTAWorkerRegionQuery::getTAWorker() const { - return impl_->taWorker; + return impl_->ta_worker; } frDesign* FlexTAWorkerRegionQuery::getDesign() const { - return impl_->taWorker->getDesign(); + return impl_->ta_worker->getDesign(); } void FlexTAWorkerRegionQuery::add(taPinFig* fig) { odb::Rect box; - if (fig->typeId() == tacPathSeg) { - auto obj = static_cast(fig); - auto [bp, ep] = obj->getPoints(); - box = odb::Rect(bp, ep); - impl_->shapes.at(obj->getLayerNum()).insert(std::make_pair(box, obj)); - } else if (fig->typeId() == tacVia) { - auto obj = static_cast(fig); - auto bp = obj->getOrigin(); - box = odb::Rect(bp, bp); - impl_->shapes.at(obj->getViaDef()->getCutLayerNum()) - .insert(std::make_pair(box, obj)); - } else { + frLayerNum layer_num = 0; + if (!getTaPinFigBoxAndLayer(fig, box, layer_num)) { std::cout << "Error: unsupported region query add\n"; + return; } + impl_->shapes.at(layer_num).insert(std::make_pair(box, fig)); } void FlexTAWorkerRegionQuery::remove(taPinFig* fig) { odb::Rect box; - if (fig->typeId() == tacPathSeg) { - auto obj = static_cast(fig); - auto [bp, ep] = obj->getPoints(); - box = odb::Rect(bp, ep); - impl_->shapes.at(obj->getLayerNum()).remove(std::make_pair(box, obj)); - } else if (fig->typeId() == tacVia) { - auto obj = static_cast(fig); - auto bp = obj->getOrigin(); - box = odb::Rect(bp, bp); - impl_->shapes.at(obj->getViaDef()->getCutLayerNum()) - .remove(std::make_pair(box, obj)); - } else { + frLayerNum layer_num = 0; + if (!getTaPinFigBoxAndLayer(fig, box, layer_num)) { std::cout << "Error: unsupported region query add\n"; + return; } + impl_->shapes.at(layer_num).remove(std::make_pair(box, fig)); } void FlexTAWorkerRegionQuery::query(const odb::Rect& box, - const frLayerNum layerNum, + const frLayerNum layer_num, frOrderedIdSet& result) const { - std::vector> temp; - auto& tree = impl_->shapes.at(layerNum); + auto& tree = impl_->shapes.at(layer_num); transform(tree.qbegin(bgi::intersects(box)), tree.qend(), inserter(result, result.end()), @@ -102,69 +110,69 @@ void FlexTAWorkerRegionQuery::query(const odb::Rect& box, void FlexTAWorkerRegionQuery::init() { - int numLayers = getDesign()->getTech()->getLayers().size(); + int num_layers = getDesign()->getTech()->getLayers().size(); impl_->shapes.clear(); - impl_->shapes.resize(numLayers); + impl_->shapes.resize(num_layers); impl_->route_costs.clear(); - impl_->route_costs.resize(numLayers); + impl_->route_costs.resize(num_layers); impl_->via_costs.clear(); - impl_->via_costs.resize(numLayers); + impl_->via_costs.resize(num_layers); } void FlexTAWorkerRegionQuery::addCost(const odb::Rect& box, - const frLayerNum layerNum, + const frLayerNum layer_num, frBlockObject* obj, frConstraint* con) { - impl_->route_costs.at(layerNum).insert( + impl_->route_costs.at(layer_num).insert( std::make_pair(box, std::make_pair(obj, con))); } void FlexTAWorkerRegionQuery::removeCost(const odb::Rect& box, - const frLayerNum layerNum, + const frLayerNum layer_num, frBlockObject* obj, frConstraint* con) { - impl_->route_costs.at(layerNum).remove( + impl_->route_costs.at(layer_num).remove( std::make_pair(box, std::make_pair(obj, con))); } void FlexTAWorkerRegionQuery::queryCost( const odb::Rect& box, - const frLayerNum layerNum, + const frLayerNum layer_num, std::vector>>& result) const { - impl_->route_costs.at(layerNum).query(bgi::intersects(box), - back_inserter(result)); + impl_->route_costs.at(layer_num).query(bgi::intersects(box), + back_inserter(result)); } void FlexTAWorkerRegionQuery::addViaCost(const odb::Rect& box, - const frLayerNum layerNum, + const frLayerNum layer_num, frBlockObject* obj, frConstraint* con) { - impl_->via_costs.at(layerNum).insert( + impl_->via_costs.at(layer_num).insert( std::make_pair(box, std::make_pair(obj, con))); } void FlexTAWorkerRegionQuery::removeViaCost(const odb::Rect& box, - const frLayerNum layerNum, + const frLayerNum layer_num, frBlockObject* obj, frConstraint* con) { - impl_->via_costs.at(layerNum).remove( + impl_->via_costs.at(layer_num).remove( std::make_pair(box, std::make_pair(obj, con))); } void FlexTAWorkerRegionQuery::queryViaCost( const odb::Rect& box, - const frLayerNum layerNum, + const frLayerNum layer_num, std::vector>>& result) const { - impl_->via_costs.at(layerNum).query(bgi::intersects(box), - back_inserter(result)); + impl_->via_costs.at(layer_num).query(bgi::intersects(box), + back_inserter(result)); } } // namespace drt