Skip to content

Commit

Permalink
Merge pull request #6075 from gadfort/rdl-route-bumps-only
Browse files Browse the repository at this point in the history
pad: correct handling of bump to bump routing
  • Loading branch information
maliberty authored Oct 31, 2024
2 parents d3654fe + 2cff365 commit 901913f
Show file tree
Hide file tree
Showing 12 changed files with 1,807 additions and 190 deletions.
233 changes: 127 additions & 106 deletions src/pad/src/RDLRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,15 @@ int RDLRouter::getRoutingInstanceCount() const
{
std::set<odb::dbInst*> insts;
for (const auto& route : routes_) {
insts.insert(route->getTerminal()->getInst());
if (route->isRouted()) {
insts.insert(route->getRouteTargetSource()->terminal->getInst());
insts.insert(route->getRouteTargetDestination()->terminal->getInst());
} else {
insts.insert(route->getTerminal()->getInst());
for (const auto* iterm : route->getTerminals()) {
insts.insert(iterm->getInst());
}
}
}
return insts.size();
}
Expand All @@ -245,7 +253,8 @@ std::set<odb::dbInst*> RDLRouter::getRoutedInstances() const
std::set<odb::dbInst*> insts;
for (const auto& route : routes_) {
if (route->isRouted()) {
insts.insert(route->getTerminal()->getInst());
insts.insert(route->getRouteTargetSource()->terminal->getInst());
insts.insert(route->getRouteTargetDestination()->terminal->getInst());
}
}
return insts;
Expand All @@ -257,7 +266,14 @@ std::vector<RDLRouter::RDLRoutePtr> RDLRouter::getFailedRoutes() const
std::set<odb::dbInst*> success_covers;
for (auto& route : routes_) {
if (route->isRouted()) {
success_covers.insert(route->getTerminal()->getInst());
if (isCoverTerm(route->getRouteTargetSource()->terminal)) {
success_covers.insert(
route->getRouteTargetSource()->terminal->getInst());
}
if (isCoverTerm(route->getRouteTargetDestination()->terminal)) {
success_covers.insert(
route->getRouteTargetDestination()->terminal->getInst());
}
}
}

Expand Down Expand Up @@ -368,13 +384,12 @@ void RDLRouter::route(const std::vector<odb::dbNet*>& nets)

logger_->info(utl::PAD, 5, "Routing {} nets", nets.size());

// track destinations routed to, so we don't attempt to route to the same
// iterm more than once.
std::set<odb::dbITerm*> dst_items_routed;
// track sets of routes, so we don't route the reverse by accident
std::map<odb::dbITerm*, odb::dbITerm*> routed_pairs;
// track cover instances we dont route the same one twice
std::set<odb::dbInst*> routed_covers;
// track non-cover iterms we dont route the same one twice
std::set<odb::dbITerm*> routed_non_covers;
// track iteration information
int iteration_count = 0;
std::set<odb::dbInst*> last_itr_routed;
Expand All @@ -401,107 +416,115 @@ void RDLRouter::route(const std::vector<odb::dbNet*>& nets)

routed_pairs[src] = nullptr;
route->moveNextTerminalToEnd();
continue;
}

// get the next destination
odb::dbITerm* dst = nullptr;
do {
if (!route->hasNextTerminal()) {
dst = nullptr;
break;
}
dst = route->getNextTerminal();
} while (dst_items_routed.find(dst) != dst_items_routed.end()
|| routed_pairs[src] == dst);

if (dst != nullptr) {
// create ordered set of iterm targets
std::vector<TargetPair> targets;
for (const auto& src_target : net_targets[src]) {
for (const auto& dst_target : net_targets[dst]) {
targets.push_back(TargetPair{&src_target, &dst_target});
} else {
// get the next destination
odb::dbITerm* dst = nullptr;
do {
if (!route->hasNextTerminal()) {
dst = nullptr;
break;
}
}

std::stable_sort(
targets.begin(), targets.end(), [](const auto& lhs, const auto& rhs) {
return distance(lhs) < distance(rhs);
});

debugPrint(
logger_,
utl::PAD,
"Router",
2,
"Routing {} -> {} : ({:.3f}um) / {} target pairs / {} priority",
src->getName(),
dst->getName(),
distance(src->getBBox().center(), dst->getBBox().center()) / dbus,
targets.size(),
route->getPriority());

for (auto& points : targets) {
debugPrint(logger_,
utl::PAD,
"Router",
3,
"Routing {} ({:.3f}um, {:.3f}um) -> ({:.3f}um, {:.3f}um) : "
"({:.3f}um)",
net->getName(),
points.target0->center.x() / dbus,
points.target0->center.y() / dbus,
points.target1->center.x() / dbus,
points.target1->center.y() / dbus,
distance(points) / dbus);

const auto added_edges0
= insertTerminalVertex(*points.target0, *points.target1);
const auto added_edges1
= insertTerminalVertex(*points.target1, *points.target0);

auto route_vextex = run(points.target0->center, points.target1->center);

if (!route_vextex.empty()) {
debugPrint(logger_,
utl::PAD,
"Router",
3,
"Route segments {}",
route_vextex.size());
const auto route_edges = commitRoute(route_vextex);
route->setRoute(
route_vextex, route_edges, points.target0, points.target1);

// record destination to avoid picking it again as a destination
dst_items_routed.insert(dst);

// record cover instance
routed_covers.insert(src->getInst());

// record routed pair (forward and reverse) to avoid routing this
// segment again
routed_pairs[src] = dst;
routed_pairs[dst] = src;
dst = route->getNextTerminal();
} while (routed_non_covers.find(dst) != routed_non_covers.end()
|| routed_pairs[src] == dst);

if (dst != nullptr) {
// create ordered set of iterm targets
std::vector<TargetPair> targets;
for (const auto& src_target : net_targets[src]) {
for (const auto& dst_target : net_targets[dst]) {
targets.push_back(TargetPair{&src_target, &dst_target});
}
}

removeTerminalEdges(added_edges0);
removeTerminalEdges(added_edges1);
std::stable_sort(targets.begin(),
targets.end(),
[](const auto& lhs, const auto& rhs) {
return distance(lhs) < distance(rhs);
});

debugPrint(
logger_,
utl::PAD,
"Router",
2,
"Routing {} -> {} : ({:.3f}um) / {} target pairs / {} priority",
src->getName(),
dst->getName(),
distance(src->getBBox().center(), dst->getBBox().center()) / dbus,
targets.size(),
route->getPriority());

for (auto& points : targets) {
debugPrint(
logger_,
utl::PAD,
"Router",
3,
"Routing {} ({:.3f}um, {:.3f}um) -> ({:.3f}um, {:.3f}um) : "
"({:.3f}um)",
net->getName(),
points.target0->center.x() / dbus,
points.target0->center.y() / dbus,
points.target1->center.x() / dbus,
points.target1->center.y() / dbus,
distance(points) / dbus);

const auto added_edges0
= insertTerminalVertex(*points.target0, *points.target1);
const auto added_edges1
= insertTerminalVertex(*points.target1, *points.target0);

auto route_vextex
= run(points.target0->center, points.target1->center);

if (!route_vextex.empty()) {
debugPrint(logger_,
utl::PAD,
"Router",
3,
"Route segments {}",
route_vextex.size());
const auto route_edges = commitRoute(route_vextex);
route->setRoute(
route_vextex, route_edges, points.target0, points.target1);

// record cover instance
if (isCoverTerm(src)) {
routed_covers.insert(src->getInst());
} else {
routed_non_covers.insert(src);
}
if (isCoverTerm(dst)) {
routed_covers.insert(dst->getInst());
} else {
routed_non_covers.insert(dst);
}

if (route->isRouted()) {
break;
// record routed pair (forward and reverse) to avoid routing this
// segment again
routed_pairs[src] = dst;
routed_pairs[dst] = src;
}

removeTerminalEdges(added_edges0);
removeTerminalEdges(added_edges1);

if (route->isRouted()) {
break;
}
}
}
}

if (!route->isRouted()) {
if (route->hasNextTerminal()) {
route_queue.push(route);
if (!route->isRouted()) {
if (route->hasNextTerminal()) {
route_queue.push(route);
}
}
}

if (gui_ != nullptr && logger_->debugCheck(utl::PAD, "Router", 3)) {
gui_->pause(route->isRouted());
if (gui_ != nullptr && logger_->debugCheck(utl::PAD, "Router", 3)) {
gui_->pause(route->isRouted());
}
}

if (route_queue.empty() && iteration_count < max_router_iterations_) {
Expand All @@ -521,12 +544,7 @@ void RDLRouter::route(const std::vector<odb::dbNet*>& nets)
}
last_itr_routed = routed_insts;

std::vector<RDLRoutePtr> failed;
for (auto& route : routes_) {
if (route->isFailed()) {
failed.push_back(route);
}
}
std::vector<RDLRoutePtr> failed = getFailedRoutes();

if (failed.empty()) {
continue;
Expand Down Expand Up @@ -579,10 +597,13 @@ void RDLRouter::route(const std::vector<odb::dbNet*>& nets)
// ripup routing
for (auto& ripup_route : ripup) {
uncommitRoute(ripup_route->getRouteEdges());
dst_items_routed.erase(
ripup_route->getRouteTargetDestination()->terminal);
routed_covers.erase(
ripup_route->getRouteTargetSource()->terminal->getInst());
routed_covers.erase(
ripup_route->getRouteTargetDestination()->terminal->getInst());
routed_non_covers.erase(ripup_route->getRouteTargetSource()->terminal);
routed_non_covers.erase(
ripup_route->getRouteTargetDestination()->terminal);
routed_pairs.erase(ripup_route->getRouteTargetSource()->terminal);
routed_pairs.erase(ripup_route->getRouteTargetDestination()->terminal);
ripup_route->resetRoute();
Expand Down
1 change: 1 addition & 0 deletions src/pad/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ set(TEST_NAMES
rdl_route_45_with_2port_bump
rdl_route_45_with_oct_bump
rdl_route_single_target
rdl_route_bump_to_bump_only
skywater130_overlapping_filler
skywater130_caravel
skywater130_coyote_tc
Expand Down
39 changes: 39 additions & 0 deletions src/pad/test/passive_tech/bumps.lef
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
VERSION 5.7 ;
NAMESCASESENSITIVE ON ;
BUSBITCHARS "[]" ;
DIVIDERCHAR "/" ;

PROPERTYDEFINITIONS
END PROPERTYDEFINITIONS


MACRO BUMP10
CLASS COVER BUMP ;
ORIGIN 5 5 ;
SIZE 10 BY 10 ;
SYMMETRY X Y ;
PIN PAD
DIRECTION INOUT ;
USE SIGNAL ;
PORT
LAYER topmetal ;
POLYGON 2 -5 -2 -5 -5 -2 -5 2 -2 5 2 5 5 2 5 -2 2 -5 ;
END
END PAD
END BUMP10

MACRO BUMP45
CLASS COVER BUMP ;
ORIGIN 14 14 ;
SIZE 28 BY 28 ;
SYMMETRY X Y ;
PIN PAD
DIRECTION INOUT ;
USE SIGNAL ;
PORT
LAYER topmetal ;
POLYGON 6 -14 -6 -14 -14 -6 -14 6 -6 14 6 14 14 6 14 -6 6 -14 ;
END
END PAD
END BUMP45
END LIBRARY
Loading

0 comments on commit 901913f

Please sign in to comment.