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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 134 additions & 31 deletions src/drt/src/dr/FlexDR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ std::unique_ptr<FlexDRWorker> 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)) {
Expand All @@ -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,
Expand Down Expand Up @@ -1063,23 +1058,15 @@ std::vector<std::vector<int>> getWorkerBatchesBoxes(
return {};
}
std::vector<odb::Rect> 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<std::vector<int>> batches;
batches.push_back({0});
Expand Down Expand Up @@ -1114,15 +1101,37 @@ 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<odb::Rect> drv_boxes;
for (const auto& marker : getDesign()->getTopBlock()->getMarkers()) {
auto box = marker->getBBox();
drv_boxes.push_back(getDRVBBox(box));
}
auto merged_boxes = stub_tiles::mergeBoxes(drv_boxes);
auto expanded_boxes = stub_tiles::expandBoxes(merged_boxes);

// Convert gcell indices to actual coordinates
std::vector<std::set<odb::Rect>> 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<odb::Rect> 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<frUInt4> drc_costs
= {args.workerDRCCost, args.workerDRCCost / 2, args.workerDRCCost * 2};
std::vector<frUInt4> marker_costs = {args.workerMarkerCost,
Expand All @@ -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;
Expand Down Expand Up @@ -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<odb::Rect> workers;
for (const auto& marker : getDesign()->getTopBlock()->getMarkers()) {
for (auto src : marker->getSrcs()) {
if (src->typeId() == frcNet) {
auto net = static_cast<frNet*>(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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be itr1 or itr1+1 as in the loop initialization?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be itr1. Once the loop finishes an iteration and goes back to the for statement, the increment step will advance it to itr1+1.

}
}
}
Comment on lines +1218 to +1226
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The nested loop for merging worker rectangles is functionally correct, but its implementation using itr2 = itr1; to restart the inner loop is a non-standard pattern which can be confusing for future maintenance.

A goto statement, while often discouraged, can make the intent of restarting the loop scan much clearer in this specific case. This change improves readability without altering the logic. The inefficiency of std::vector::erase in a loop remains, but this is a separate concern from code clarity.

  for (auto itr1 = workers.begin(); itr1 != workers.end(); ++itr1) {
  restart_inner_loop:
    for (auto itr2 = itr1 + 1; itr2 != workers.end(); ++itr2) {
      if (itr1->getDir() == itr2->getDir() && itr1->intersects(*itr2)) {
        itr1->merge(*itr2);
        workers.erase(itr2);
        goto restart_inner_loop;
      }
    }
  }

std::vector<std::set<odb::Rect>> 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<std::vector<std::unique_ptr<FlexDRWorker>>> 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<int, FlexDRWorker*>
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)
{
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/drt/src/dr/FlexDR.h
Original file line number Diff line number Diff line change
Expand Up @@ -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};
};
Expand Down Expand Up @@ -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);
};
Expand Down