From f11f92229c3a872534d9b4996a7c1c783ab54f57 Mon Sep 17 00:00:00 2001 From: Eder Monteiro Date: Wed, 10 Jun 2026 17:53:33 -0300 Subject: [PATCH 1/2] pad: add custom comparator for GridGraphEdge set to prevent non-determinism Signed-off-by: Eder Monteiro --- src/pad/src/RDLRouter.cpp | 13 ++++++------- src/pad/src/RDLRouter.h | 25 ++++++++++++++++++++++--- src/pad/test/rdl_route_failed.ok | 3 ++- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/pad/src/RDLRouter.cpp b/src/pad/src/RDLRouter.cpp index 076308e8a09..aa0037a0b82 100644 --- a/src/pad/src/RDLRouter.cpp +++ b/src/pad/src/RDLRouter.cpp @@ -381,7 +381,7 @@ void RDLRouter::route(const std::vector& nets) makeGraph(); // Determine access points - std::unordered_map> remove_edges; + std::unordered_map remove_edges; for (auto& [net, iterm_targets] : routing_targets_) { for (auto& [iterm, targets] : iterm_targets) { for (auto& target : targets) { @@ -797,7 +797,7 @@ static odb::Point getValidGridPoint( } void RDLRouter::cleanupGraphEdges( - const std::unordered_map>& edges) + const std::unordered_map& edges) { if (edges.empty()) { return; @@ -824,7 +824,7 @@ void RDLRouter::cleanupGraphEdges( void RDLRouter::populateTerminalAccessPoints( RouteTarget& target, - std::unordered_map>& edges) const + std::unordered_map& edges) const { // determine new access point in graph std::set snap_pts; @@ -1181,10 +1181,9 @@ bool RDLRouter::is45DegreeEdge(const odb::Point& pt0, return RDLRoute::is45DegreeEdge(pt0, pt1); } -std::set RDLRouter::getVertexEdges( - const GridGraphVertex& vertex) const +GridGraphEdgeSet RDLRouter::getVertexEdges(const GridGraphVertex& vertex) const { - std::set edges; + GridGraphEdgeSet edges; GridGraph::out_edge_iterator oit, oend; std::tie(oit, oend) = boost::out_edges(vertex, graph_); @@ -1203,7 +1202,7 @@ std::set RDLRouter::getVertexEdges( std::vector RDLRouter::commitRoute( const std::vector& route) { - std::set edges; + GridGraphEdgeSet edges; for (const auto& v : route) { const auto v_edges = getVertexEdges(v); edges.insert(v_edges.begin(), v_edges.end()); diff --git a/src/pad/src/RDLRouter.h b/src/pad/src/RDLRouter.h index 2973571ec76..5e45cfc221a 100644 --- a/src/pad/src/RDLRouter.h +++ b/src/pad/src/RDLRouter.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include #include @@ -67,6 +68,24 @@ using GridWeightMap using GridGraphVertex = GridGraph::vertex_descriptor; using GridGraphEdge = GridGraph::edge_descriptor; +// Order edges by (source, target) vertex indices; the descriptor's default +// operator< compares a heap pointer, giving build-dependent iteration. +struct GridGraphEdgeLess +{ + bool operator()(const GridGraphEdge& lhs, const GridGraphEdge& rhs) const + { + const auto lhs_lo = std::min(lhs.m_source, lhs.m_target); + const auto lhs_hi = std::max(lhs.m_source, lhs.m_target); + const auto rhs_lo = std::min(rhs.m_source, rhs.m_target); + const auto rhs_hi = std::max(rhs.m_source, rhs.m_target); + if (lhs_lo != rhs_lo) { + return lhs_lo < rhs_lo; + } + return lhs_hi < rhs_hi; + } +}; +using GridGraphEdgeSet = std::set; + struct RouteTarget { // center point of the target shape @@ -213,11 +232,11 @@ class RDLRouter void populateTerminalAccessPoints( RouteTarget& target, - std::unordered_map>& edges) const; + std::unordered_map& edges) const; void cleanupTerminalAccessPoints(odb::dbITerm* iterm, std::vector& targets) const; void cleanupGraphEdges( - const std::unordered_map>& edges); + const std::unordered_map& edges); std::set generateTerminalAccessPoints(const odb::Point& pt, bool do_x) const; TerminalAccess insertTerminalAccess(const RouteTarget& target, @@ -227,7 +246,7 @@ class RDLRouter odb::PtrMap> generateRoutingTargets( odb::dbNet* net) const; odb::dbTechLayer* getOtherLayer(odb::dbTechVia* via) const; - std::set getVertexEdges(const GridGraphVertex& vertex) const; + GridGraphEdgeSet getVertexEdges(const GridGraphVertex& vertex) const; void buildIntialRouteSet(); int reportFailedRoutes( diff --git a/src/pad/test/rdl_route_failed.ok b/src/pad/test/rdl_route_failed.ok index 9c40bdf3997..d028e5be0b9 100644 --- a/src/pad/test/rdl_route_failed.ok +++ b/src/pad/test/rdl_route_failed.ok @@ -15,7 +15,7 @@ [INFO PAD-0037] End of routing iteration 7: 89.5% complete [INFO PAD-0037] End of routing iteration 8: 89.0% complete [INFO PAD-0037] End of routing iteration 9: 88.8% complete -[INFO PAD-0037] End of routing iteration 10: 88.8% complete +[INFO PAD-0037] End of routing iteration 10: 88.4% complete [WARNING PAD-0006] Failed to route the following 17 nets: DVDD BUMP_11_3/PAD -> u_v18_6/DVDD, u_v18_7/DVDD, u_v18_5/DVDD, u_v18_4/DVDD, u_v18_8/DVDD, ... (67 possible terminals) @@ -27,6 +27,7 @@ BUMP_15_11/PAD -> u_vzz_15/DVSS, u_vzz_16/DVSS, u_vzz_14/DVSS, u_vzz_13/DVSS, u_vzz_12/DVSS, ... (67 possible terminals) BUMP_15_7/PAD -> u_vzz_12/DVSS, u_vzz_13/DVSS, u_vzz_11/DVSS, u_vzz_14/DVSS, u_vzz_10/DVSS, ... (67 possible terminals) BUMP_1_9/PAD -> u_vzz_29/DVSS, u_vzz_30/DVSS, u_vzz_28/DVSS, u_vzz_31/DVSS, u_vzz_27/DVSS, ... (67 possible terminals) + BUMP_8_15/PAD -> u_vzz_21/DVSS, u_vzz_22/DVSS, u_vzz_20/DVSS, u_vzz_23/DVSS, u_vzz_24/DVSS, ... (67 possible terminals) VSS BUMP_14_9/PAD -> u_vss_6/VSS, u_vss_5/VSS, u_vss_7/VSS, u_vss_4/VSS, u_vss_8/VSS, ... (33 possible terminals) BUMP_16_6/PAD -> u_vss_5/VSS, u_vss_6/VSS, u_vss_4/VSS, u_vss_7/VSS, u_vss_3/VSS, ... (33 possible terminals) From f2ae0d84f70ba9db997cd50b95861f30c731d230 Mon Sep 17 00:00:00 2001 From: Eder Monteiro Date: Wed, 10 Jun 2026 18:38:04 -0300 Subject: [PATCH 2/2] pad: gemini reviews Signed-off-by: Eder Monteiro --- src/pad/src/RDLRouter.cpp | 19 ++++++---- src/pad/src/RDLRouter.h | 10 ++---- src/pad/test/rdl_route_failed.ok | 45 ++++++++++-------------- src/pad/test/rdl_route_max_iterations.ok | 1 - 4 files changed, 33 insertions(+), 42 deletions(-) diff --git a/src/pad/src/RDLRouter.cpp b/src/pad/src/RDLRouter.cpp index aa0037a0b82..a397768a690 100644 --- a/src/pad/src/RDLRouter.cpp +++ b/src/pad/src/RDLRouter.cpp @@ -41,6 +41,17 @@ namespace pad { namespace { +// Order routes by their source terminal id so ripup iteration (and the edge +// re-add order it drives) is deterministic, not heap-address dependent. +struct RDLRoutePtrLess +{ + bool operator()(const std::shared_ptr& lhs, + const std::shared_ptr& rhs) const + { + return lhs->getTerminal()->getId() < rhs->getTerminal()->getId(); + } +}; + bool compareRouteTargets(const RouteTarget& lhs, const RouteTarget& rhs) { if (lhs.center.x() != rhs.center.x()) { @@ -649,7 +660,7 @@ void RDLRouter::route(const std::vector& nets) } // find routes to ripup - std::set ripup; + std::set ripup; for (const auto& failed_route : failed) { for (const auto& route : routes_) { if (!route->isRouted()) { @@ -1185,16 +1196,12 @@ GridGraphEdgeSet RDLRouter::getVertexEdges(const GridGraphVertex& vertex) const { GridGraphEdgeSet edges; + // The graph is undirected, so out_edges already yields every incident edge. GridGraph::out_edge_iterator oit, oend; std::tie(oit, oend) = boost::out_edges(vertex, graph_); for (; oit != oend; oit++) { edges.insert(*oit); } - GridGraph::in_edge_iterator iit, iend; - std::tie(iit, iend) = boost::in_edges(vertex, graph_); - for (; iit != iend; iit++) { - edges.insert(*iit); - } return edges; } diff --git a/src/pad/src/RDLRouter.h b/src/pad/src/RDLRouter.h index 5e45cfc221a..46d338975e6 100644 --- a/src/pad/src/RDLRouter.h +++ b/src/pad/src/RDLRouter.h @@ -74,14 +74,8 @@ struct GridGraphEdgeLess { bool operator()(const GridGraphEdge& lhs, const GridGraphEdge& rhs) const { - const auto lhs_lo = std::min(lhs.m_source, lhs.m_target); - const auto lhs_hi = std::max(lhs.m_source, lhs.m_target); - const auto rhs_lo = std::min(rhs.m_source, rhs.m_target); - const auto rhs_hi = std::max(rhs.m_source, rhs.m_target); - if (lhs_lo != rhs_lo) { - return lhs_lo < rhs_lo; - } - return lhs_hi < rhs_hi; + return std::minmax(lhs.m_source, lhs.m_target) + < std::minmax(rhs.m_source, rhs.m_target); } }; using GridGraphEdgeSet = std::set; diff --git a/src/pad/test/rdl_route_failed.ok b/src/pad/test/rdl_route_failed.ok index d028e5be0b9..a7136f4307e 100644 --- a/src/pad/test/rdl_route_failed.ok +++ b/src/pad/test/rdl_route_failed.ok @@ -10,54 +10,45 @@ [INFO PAD-0037] End of routing iteration 2: 85.4% complete [INFO PAD-0037] End of routing iteration 3: 81.9% complete [INFO PAD-0037] End of routing iteration 4: 84.4% complete -[INFO PAD-0037] End of routing iteration 5: 89.0% complete -[INFO PAD-0037] End of routing iteration 6: 89.9% complete -[INFO PAD-0037] End of routing iteration 7: 89.5% complete -[INFO PAD-0037] End of routing iteration 8: 89.0% complete -[INFO PAD-0037] End of routing iteration 9: 88.8% complete -[INFO PAD-0037] End of routing iteration 10: 88.4% complete -[WARNING PAD-0006] Failed to route the following 17 nets: +[INFO PAD-0037] End of routing iteration 5: 89.2% complete +[INFO PAD-0037] End of routing iteration 6: 90.1% complete +[INFO PAD-0037] End of routing iteration 7: 90.3% complete +[INFO PAD-0037] End of routing iteration 8: 90.3% complete +[INFO PAD-0037] End of routing iteration 9: 89.2% complete +[INFO PAD-0037] End of routing iteration 10: 90.3% complete +[WARNING PAD-0006] Failed to route the following 13 nets: DVDD BUMP_11_3/PAD -> u_v18_6/DVDD, u_v18_7/DVDD, u_v18_5/DVDD, u_v18_4/DVDD, u_v18_8/DVDD, ... (67 possible terminals) BUMP_16_11/PAD -> u_v18_15/DVDD, u_v18_16/DVDD, u_v18_14/DVDD, u_v18_13/DVDD, u_v18_12/DVDD, ... (67 possible terminals) BUMP_1_13/PAD -> u_v18_26/DVDD, u_v18_27/DVDD, u_v18_28/DVDD, u_v18_25/DVDD, u_v18_29/DVDD, ... (67 possible terminals) - BUMP_4_1/PAD -> u_v18_1/DVDD, u_v18_2/DVDD, u_v18_0/DVDD, u_v18_3/DVDD, u_v18_4/DVDD, ... (67 possible terminals) DVSS - BUMP_0_8/PAD -> u_vzz_30/DVSS, u_vzz_29/DVSS, u_vzz_31/DVSS, u_vzz_32/DVSS, u_vzz_28/DVSS, ... (67 possible terminals) BUMP_15_11/PAD -> u_vzz_15/DVSS, u_vzz_16/DVSS, u_vzz_14/DVSS, u_vzz_13/DVSS, u_vzz_12/DVSS, ... (67 possible terminals) BUMP_15_7/PAD -> u_vzz_12/DVSS, u_vzz_13/DVSS, u_vzz_11/DVSS, u_vzz_14/DVSS, u_vzz_10/DVSS, ... (67 possible terminals) BUMP_1_9/PAD -> u_vzz_29/DVSS, u_vzz_30/DVSS, u_vzz_28/DVSS, u_vzz_31/DVSS, u_vzz_27/DVSS, ... (67 possible terminals) - BUMP_8_15/PAD -> u_vzz_21/DVSS, u_vzz_22/DVSS, u_vzz_20/DVSS, u_vzz_23/DVSS, u_vzz_24/DVSS, ... (67 possible terminals) + VDD + BUMP_11_12/PAD -> u_vdd_9/VDD, u_vdd_pll/VDD, u_vdd_8/VDD, u_vdd_7/VDD, u_vdd_10/VDD, ... (33 possible terminals) + BUMP_1_10/PAD -> u_vdd_13/VDD, u_vdd_14/VDD, u_vdd_12/VDD, u_vdd_15/VDD, u_vdd_11/VDD, ... (33 possible terminals) VSS + BUMP_0_10/PAD -> u_vss_13/VSS, u_vss_14/VSS, u_vss_12/VSS, u_vss_15/VSS, u_vss_11/VSS, ... (33 possible terminals) BUMP_14_9/PAD -> u_vss_6/VSS, u_vss_5/VSS, u_vss_7/VSS, u_vss_4/VSS, u_vss_8/VSS, ... (33 possible terminals) BUMP_16_6/PAD -> u_vss_5/VSS, u_vss_6/VSS, u_vss_4/VSS, u_vss_7/VSS, u_vss_3/VSS, ... (33 possible terminals) + p_bsg_tag_data_o + BUMP_2_10/PAD -> u_bsg_tag_data_o/PAD p_clk_A_i BUMP_7_13/PAD -> u_clk_A_i/PAD - p_clk_async_reset_i - BUMP_9_14/PAD -> u_clk_async_reset_i/PAD p_co2_v_o BUMP_0_13/PAD -> u_co2_v_o/PAD - p_ddr_addr_15_o - BUMP_4_0/PAD -> u_ddr_addr_15_o/PAD p_ddr_addr_2_o BUMP_8_2/PAD -> u_ddr_addr_2_o/PAD - p_ddr_addr_6_o - BUMP_7_0/PAD -> u_ddr_addr_6_o/PAD - p_ddr_addr_7_o - BUMP_7_1/PAD -> u_ddr_addr_7_o/PAD + p_ddr_addr_4_o + BUMP_7_4/PAD -> u_ddr_addr_4_o/PAD p_ddr_ck_n_o BUMP_11_4/PAD -> u_ddr_ck_n_o/PAD - p_ddr_dq_0_io - BUMP_3_7/PAD -> u_ddr_dq_0_io/PAD - p_ddr_dq_11_io - BUMP_4_5/PAD -> u_ddr_dq_11_io/PAD - p_ddr_dq_13_io - BUMP_3_5/PAD -> u_ddr_dq_13_io/PAD - p_ddr_dq_2_io - BUMP_1_8/PAD -> u_ddr_dq_2_io/PAD + p_ddr_dq_7_io + BUMP_4_10/PAD -> u_ddr_dq_7_io/PAD p_ddr_dq_8_io BUMP_0_4/PAD -> u_ddr_dq_8_io/PAD p_ddr_dq_9_io BUMP_1_4/PAD -> u_ddr_dq_9_io/PAD -[ERROR PAD-0007] Failed to route 17 nets. +[ERROR PAD-0007] Failed to route 13 nets. pass diff --git a/src/pad/test/rdl_route_max_iterations.ok b/src/pad/test/rdl_route_max_iterations.ok index b73dbca8530..e608b2f478b 100644 --- a/src/pad/test/rdl_route_max_iterations.ok +++ b/src/pad/test/rdl_route_max_iterations.ok @@ -13,7 +13,6 @@ [WARNING PAD-0006] Failed to route the following 18 nets: DVDD BUMP_11_13/PAD -> u_v18_19/DVDD, u_v18_20/DVDD, u_v18_18/DVDD, u_v18_21/DVDD, u_v18_17/DVDD, ... (67 possible terminals) - BUMP_7_3/PAD -> u_v18_3/DVDD, u_v18_4/DVDD, u_v18_2/DVDD, u_v18_5/DVDD, u_v18_1/DVDD, ... (67 possible terminals) VSS BUMP_0_7/PAD -> u_vss_14/VSS, u_vss_13/VSS, u_vss_15/VSS, u_vss_12/VSS, u_vss_0/VSS, ... (33 possible terminals) BUMP_10_13/PAD -> u_vss_9/VSS, u_vss_pll/VSS, u_vss_10/VSS, u_vss_8/VSS, u_vss_7/VSS, ... (33 possible terminals)