@@ -1407,17 +1407,59 @@ void FastRouteCore::updateRouteGridsLayer(int x1,
14071407 TreeEdge* treeedge = &(treeedges[edgeID]);
14081408 // Only process edges that have actual routing
14091409 if (treeedge->len > 0 || treeedge->route .routelen > 0 ) {
1410- int routeLen = treeedge->route .routelen ;
1411- std::vector<GPoint3D>& grids = treeedge->route .grids ;
1410+ const int routeLen = treeedge->route .routelen ;
1411+ const std::vector<GPoint3D>& grids = treeedge->route .grids ;
1412+
1413+ std::vector<GPoint3D> new_grids;
1414+ new_grids.reserve (grids.size () + 4 );
1415+ bool modified = false ;
14121416
1413- // If the point is within the specified rectangular region AND on the
1414- // original layer
14151417 for (int i = 0 ; i <= routeLen; i++) {
1416- if (grids[i].x >= x1 && grids[i].x <= x2 && grids[i].y >= y1
1417- && grids[i].y <= y2 && grids[i].layer == layer) {
1418- // Update to the new layer
1419- grids[i].layer = new_layer;
1418+ const bool in_region = grids[i].x >= x1 && grids[i].x <= x2
1419+ && grids[i].y >= y1 && grids[i].y <= y2
1420+ && grids[i].layer == layer;
1421+ if (!in_region) {
1422+ new_grids.push_back (grids[i]);
1423+ continue ;
14201424 }
1425+ modified = true ;
1426+ // Check whether the previous/next grid point is outside the promoted
1427+ // region. When the first (or last) promoted point is adjacent to an
1428+ // unpromoted point we insert a via-transition copy on the old layer so
1429+ // that releaseNetResources sees a layer change (via) rather than a
1430+ // same-layer horizontal/vertical edge at the boundary. Without this,
1431+ // two back-to-back jumpers whose promoted endpoints are adjacent
1432+ // (e.g. right endpoint of jumper A at x=107 and left endpoint of
1433+ // jumper B at x=108) merge into a single same-layer chain and
1434+ // releaseNetResources under-decrements the edge that was never
1435+ // incremented.
1436+ const bool prev_outside = (i == 0 ) || grids[i - 1 ].x < x1
1437+ || grids[i - 1 ].x > x2 || grids[i - 1 ].y < y1
1438+ || grids[i - 1 ].y > y2
1439+ || grids[i - 1 ].layer != layer;
1440+ const bool next_outside = (i == routeLen) || grids[i + 1 ].x < x1
1441+ || grids[i + 1 ].x > x2 || grids[i + 1 ].y < y1
1442+ || grids[i + 1 ].y > y2
1443+ || grids[i + 1 ].layer != layer;
1444+
1445+ // Insert old-layer via point before the first promoted point
1446+ if (prev_outside && i > 0 ) {
1447+ new_grids.push_back (
1448+ {grids[i].x , grids[i].y , static_cast <int16_t >(layer)});
1449+ }
1450+ GPoint3D promoted = grids[i];
1451+ promoted.layer = new_layer;
1452+ new_grids.push_back (promoted);
1453+ // Insert old-layer via point after the last promoted point
1454+ if (next_outside && i < routeLen) {
1455+ new_grids.push_back (
1456+ {grids[i].x , grids[i].y , static_cast <int16_t >(layer)});
1457+ }
1458+ }
1459+
1460+ if (modified) {
1461+ treeedge->route .routelen = static_cast <int >(new_grids.size ()) - 1 ;
1462+ treeedge->route .grids = std::move (new_grids);
14211463 }
14221464 }
14231465 }
0 commit comments