diff --git a/src/drt/src/dr/FlexDR.cpp b/src/drt/src/dr/FlexDR.cpp index b9a5983a57..c9ff5ffc7c 100644 --- a/src/drt/src/dr/FlexDR.cpp +++ b/src/drt/src/dr/FlexDR.cpp @@ -608,7 +608,7 @@ std::unique_ptr FlexDR::createWorker(const int x_offset, namespace { void printIteration(utl::Logger* logger, const int iter, - const bool stubborn_flow) + const std::string& flow_name) { std::string suffix; if (iter == 1 || (iter > 20 && iter % 10 == 1)) { @@ -620,12 +620,7 @@ void printIteration(utl::Logger* logger, } else { suffix = "th"; } - logger->info(DRT, - 195, - "Start {}{} {} iteration.", - iter, - suffix, - stubborn_flow ? "stubborn tiles" : "optimization"); + logger->info(DRT, 195, "Start {}{} {} iteration.", iter, suffix, flow_name); } void printIterationProgress(utl::Logger* logger, @@ -1063,23 +1058,15 @@ std::vector> getWorkerBatchesBoxes( return {}; } std::vector boxes_max; + boxes_max.resize(expanded_boxes.size()); int id = 0; for (auto& boxes : expanded_boxes) { - bool first = true; - for (auto& box : boxes) { - auto min_idx = box.ll(); - auto max_idx = box.ur(); - odb::Rect rect(design->getTopBlock()->getGCellBox(min_idx).ll(), - design->getTopBlock()->getGCellBox(max_idx).ur()); + boxes_max[id].mergeInit(); + for (auto rect : boxes) { rect.bloat(bloating_dist, rect); - if (first) { - boxes_max.emplace_back(rect); - first = false; - continue; - } boxes_max[id].merge(rect); } - id++; + ++id; } std::vector> batches; batches.push_back({0}); @@ -1114,6 +1101,8 @@ void FlexDR::stubbornTilesFlow(const SearchRepairArgs& args, if (graphics_) { graphics_->startIter(iter_, router_cfg_); } + control_.skip_till_changed = false; + control_.tried_guide_flow = false; std::vector drv_boxes; for (const auto& marker : getDesign()->getTopBlock()->getMarkers()) { auto box = marker->getBBox(); @@ -1121,8 +1110,28 @@ void FlexDR::stubbornTilesFlow(const SearchRepairArgs& args, } auto merged_boxes = stub_tiles::mergeBoxes(drv_boxes); auto expanded_boxes = stub_tiles::expandBoxes(merged_boxes); + + // Convert gcell indices to actual coordinates + std::vector> expanded_boxes_coords; + expanded_boxes_coords.reserve(expanded_boxes.size()); + std::ranges::transform( + expanded_boxes, + std::back_inserter(expanded_boxes_coords), + [this](const auto& box_set) { + std::set coord_set; + std::ranges::transform( + box_set, + std::inserter(coord_set, coord_set.end()), + [this](const auto& gcell_box) { + return odb::Rect( + getDesign()->getTopBlock()->getGCellBox(gcell_box.ll()).ll(), + getDesign()->getTopBlock()->getGCellBox(gcell_box.ur()).ur()); + }); + return coord_set; + }); + auto route_boxes_batches = stub_tiles::getWorkerBatchesBoxes( - getDesign(), expanded_boxes, router_cfg_->MTSAFEDIST); + getDesign(), expanded_boxes_coords, router_cfg_->MTSAFEDIST); std::vector drc_costs = {args.workerDRCCost, args.workerDRCCost / 2, args.workerDRCCost * 2}; std::vector marker_costs = {args.workerMarkerCost, @@ -1134,12 +1143,7 @@ void FlexDR::stubbornTilesFlow(const SearchRepairArgs& args, for (int batch_id = 0; batch_id < route_boxes_batches.size(); batch_id++) { auto& batch = route_boxes_batches[batch_id]; for (const auto worker_id : batch) { - for (auto gcell_box : expanded_boxes[worker_id]) { - auto min_idx = gcell_box.ll(); - auto max_idx = gcell_box.ur(); - odb::Rect route_box( - getDesign()->getTopBlock()->getGCellBox(min_idx).ll(), - getDesign()->getTopBlock()->getGCellBox(max_idx).ur()); + for (const auto& route_box : expanded_boxes_coords[worker_id]) { for (auto drc_cost : drc_costs) { for (auto marker_cost : marker_costs) { auto worker_args = args; @@ -1181,6 +1185,88 @@ void FlexDR::stubbornTilesFlow(const SearchRepairArgs& args, } } +void FlexDR::guideTilesFlow(const SearchRepairArgs& args, + IterationProgress& iter_prog) +{ + if (graphics_) { + graphics_->startIter(iter_, router_cfg_); + } + control_.tried_guide_flow = true; + std::vector workers; + for (const auto& marker : getDesign()->getTopBlock()->getMarkers()) { + for (auto src : marker->getSrcs()) { + if (src->typeId() == frcNet) { + auto net = static_cast(src); + if (net->getOrigGuides().empty()) { + continue; + } + for (const auto& guide : net->getOrigGuides()) { + if (!guide.getBBox().intersects(marker->getBBox())) { + continue; + } + workers.push_back(guide.getBBox()); + } + } + } + } + if (workers.empty()) { + iter_prog.total_num_workers = 1; + iter_prog.cnt_done_workers = 1; + return; + } + + for (auto itr1 = workers.begin(); itr1 != workers.end(); ++itr1) { + for (auto itr2 = itr1 + 1; itr2 != workers.end(); ++itr2) { + if (itr1->getDir() == itr2->getDir() && itr1->intersects(*itr2)) { + itr1->merge(*itr2); + workers.erase(itr2); + itr2 = itr1; + } + } + } + std::vector> boxes_set; + boxes_set.reserve(workers.size()); + for (auto& worker : workers) { + boxes_set.push_back({worker}); + } + auto route_boxes_batches = stub_tiles::getWorkerBatchesBoxes( + getDesign(), boxes_set, router_cfg_->MTSAFEDIST); + std::vector>> workers_batches( + route_boxes_batches.size()); + iter_prog.total_num_workers = 0; + for (int batch_id = 0; batch_id < route_boxes_batches.size(); batch_id++) { + auto& batch = route_boxes_batches[batch_id]; + for (const auto worker_id : batch) { + for (auto route_box : boxes_set[worker_id]) { + workers_batches[batch_id].emplace_back( + createWorker(0, 0, args, route_box)); + workers_batches[batch_id].back()->setWorkerId(worker_id); + iter_prog.total_num_workers++; + } + } + } + bool changed = false; + omp_set_num_threads(router_cfg_->MAX_THREADS); + for (auto& batch : workers_batches) { + processWorkersBatch(batch, iter_prog); + std::map + worker_best_result; // holds the best worker in results + for (auto& worker : batch) { + const int worker_id = worker->getWorkerId(); + if (worker_best_result.find(worker_id) == worker_best_result.end() + || worker->getBestNumMarkers() + < worker_best_result[worker_id]->getBestNumMarkers()) { + worker_best_result[worker_id] = worker.get(); + } + } + for (auto [_, worker] : worker_best_result) { + changed + |= (worker->end(getDesign()) + && worker->getBestNumMarkers() != worker->getInitNumMarkers()); + } + batch.clear(); + } +} void FlexDR::optimizationFlow(const SearchRepairArgs& args, IterationProgress& iter_prog) { @@ -1275,11 +1361,28 @@ void FlexDR::searchRepair(const SearchRepairArgs& args) const bool stubborn_flow = num_drvs <= 11 && ripupMode != RipUpMode::ALL && ripupMode != RipUpMode::INCR && !control_.fixing_max_spacing; + const bool skip_stubborn_flow + = stubborn_flow && control_.skip_till_changed + && args.isEqualIgnoringSizeAndOffset(control_.last_args); + const bool guides_flow = skip_stubborn_flow && !control_.tried_guide_flow; + if (router_cfg_->VERBOSE > 0) { - printIteration(logger_, iter_, stubborn_flow); + std::string flow_name; + if (guides_flow) { + flow_name = "guides tiles"; + } else if (stubborn_flow) { + flow_name = "stubborn tiles"; + } else { + flow_name = "optimization"; + } + printIteration(logger_, iter_, flow_name); } - if (stubborn_flow) { - stubbornTilesFlow(args, iter_prog); + if (guides_flow) { + guideTilesFlow(args, iter_prog); + } else if (stubborn_flow) { + if (!skip_stubborn_flow) { + stubbornTilesFlow(args, iter_prog); + } } else { optimizationFlow(args, iter_prog); } @@ -1890,14 +1993,14 @@ int FlexDR::main() } } if (control_.skip_till_changed - && args.isEqualIgnoringSizeAndOffset(control_.last_args)) { + && args.isEqualIgnoringSizeAndOffset(control_.last_args) + && control_.tried_guide_flow) { if (router_cfg_->VERBOSE > 0) { logger_->info(DRT, 200, "Skipping iteration {}", iter_); } ++iter_; continue; } - control_.skip_till_changed = false; searchRepair(args); if (getDesign()->getTopBlock()->getNumMarkers() == 0) { break; diff --git a/src/drt/src/dr/FlexDR.h b/src/drt/src/dr/FlexDR.h index 0d6350860e..0c22ca0690 100644 --- a/src/drt/src/dr/FlexDR.h +++ b/src/drt/src/dr/FlexDR.h @@ -96,6 +96,7 @@ class FlexDR struct IterationsControl { bool skip_till_changed{false}; + bool tried_guide_flow{false}; SearchRepairArgs last_args; bool fixing_max_spacing{false}; }; @@ -206,6 +207,8 @@ class FlexDR odb::Rect getDRVBBox(const odb::Rect& drv_rect) const; void stubbornTilesFlow(const SearchRepairArgs& args, IterationProgress& iter_prog); + void guideTilesFlow(const SearchRepairArgs& args, + IterationProgress& iter_prog); void optimizationFlow(const SearchRepairArgs& args, IterationProgress& iter_prog); };