Skip to content

Commit f576dda

Browse files
authored
Merge pull request #10044 from The-OpenROAD-Project-staging/grt_fill_via
grt: fix missing via for co-located pins on different layers
2 parents ee85037 + 0e2d771 commit f576dda

12 files changed

Lines changed: 453 additions & 64 deletions

src/grt/src/GlobalRouter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3181,8 +3181,7 @@ bool GlobalRouter::isCoveringPin(Net* net, GSegment& segment)
31813181
int seg_x = segment.final_x;
31823182
int seg_y = segment.final_y;
31833183
if (pin.getConnectionLayer() == seg_top_layer
3184-
&& pin.getOnGridPosition() == odb::Point(seg_x, seg_y)
3185-
&& (pin.isPort() || pin.isConnectedToPadOrMacro())) {
3184+
&& pin.getOnGridPosition() == odb::Point(seg_x, seg_y)) {
31863185
return true;
31873186
}
31883187
}

src/grt/src/fastroute/include/FastRoute.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <string>
1010
#include <tuple>
1111
#include <unordered_map>
12+
#include <unordered_set>
1213
#include <utility>
1314
#include <vector>
1415

@@ -294,6 +295,11 @@ class FastRouteCore
294295
void writeCongestionMap(const std::string& filename);
295296

296297
private:
298+
void convertGridsToSegments(
299+
const std::vector<GPoint3D>& grids,
300+
int grid_count,
301+
std::unordered_set<GSegment, GSegmentHash>& net_segs,
302+
GRoute& route);
297303
int getEdgeCapacity(FrNet* net, int x1, int y1, EdgeDirection direction);
298304
void getNetId(odb::dbNet* db_net, int& net_id, bool& exists);
299305
void clearNetRoute(int netID);

src/grt/src/fastroute/src/FastRoute.cpp

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,40 @@ void FastRouteCore::getPlanarRoute(odb::dbNet* db_net, GRoute& route)
11151115
}
11161116
}
11171117

1118+
void FastRouteCore::convertGridsToSegments(
1119+
const std::vector<GPoint3D>& grids,
1120+
int grid_count,
1121+
std::unordered_set<GSegment, GSegmentHash>& net_segs,
1122+
GRoute& route)
1123+
{
1124+
int lastX = (tile_size_ * (grids[0].x + 0.5)) + x_corner_;
1125+
int lastY = (tile_size_ * (grids[0].y + 0.5)) + y_corner_;
1126+
int lastL = grids[0].layer;
1127+
1128+
for (int i = 1; i <= grid_count; i++) {
1129+
const int xreal = (tile_size_ * (grids[i].x + 0.5)) + x_corner_;
1130+
const int yreal = (tile_size_ * (grids[i].y + 0.5)) + y_corner_;
1131+
const int currentL = grids[i].layer;
1132+
1133+
if (lastX == xreal && lastY == yreal && lastL == currentL) {
1134+
continue;
1135+
}
1136+
1137+
GSegment segment
1138+
= GSegment(lastX, lastY, lastL + 1, xreal, yreal, currentL + 1);
1139+
segment.setIs3DRoute(true);
1140+
1141+
if (net_segs.find(segment) == net_segs.end()) {
1142+
net_segs.insert(segment);
1143+
route.push_back(segment);
1144+
}
1145+
1146+
lastX = xreal;
1147+
lastY = yreal;
1148+
lastL = currentL;
1149+
}
1150+
}
1151+
11181152
void FastRouteCore::get3DRoute(odb::dbNet* db_net, GRoute& route)
11191153
{
11201154
int netID;
@@ -1206,39 +1240,23 @@ void FastRouteCore::get3DRoute(odb::dbNet* db_net, GRoute& route)
12061240
}
12071241
}
12081242

1209-
int lastX = (tile_size_ * (filled_grids[0].x + 0.5)) + x_corner_;
1210-
int lastY = (tile_size_ * (filled_grids[0].y + 0.5)) + y_corner_;
1211-
int lastL = filled_grids[0].layer;
1212-
1213-
for (int i = 1; i < filled_grids.size(); i++) {
1214-
const int xreal = (tile_size_ * (filled_grids[i].x + 0.5)) + x_corner_;
1215-
const int yreal = (tile_size_ * (filled_grids[i].y + 0.5)) + y_corner_;
1216-
const int currentL = filled_grids[i].layer;
1217-
1218-
// Prevent adding segments that are effectively zero-length vias on the
1219-
// same layer
1220-
if (lastX == xreal && lastY == yreal && lastL == currentL) {
1221-
// Skip this segment as it's a redundant via on the same layer
1222-
lastX = xreal;
1223-
lastY = yreal;
1224-
lastL = currentL;
1225-
continue;
1226-
}
1227-
1228-
GSegment segment
1229-
= GSegment(lastX, lastY, lastL + 1, xreal, yreal, currentL + 1);
1230-
segment.setIs3DRoute(true);
1231-
1232-
// Only add segment if it's not a duplicate
1233-
if (net_segs.find(segment) == net_segs.end()) {
1234-
net_segs.insert(segment);
1235-
route.push_back(segment);
1236-
}
1237-
1238-
lastX = xreal;
1239-
lastY = yreal;
1240-
lastL = currentL;
1241-
}
1243+
convertGridsToSegments(
1244+
filled_grids, filled_grids.size() - 1, net_segs, route);
1245+
} else if (treeedge->route.routelen > 0) {
1246+
// Handle zero-length edges (len == 0) that carry via route grids.
1247+
// These arise in two situations:
1248+
// (a) fillVIA created a via stack for co-located terminal pins on
1249+
// different layers (e.g. two pins in the same gcell on layers 2
1250+
// and 3).
1251+
// (b) ensurePinCoverage appended a new TreeEdge with a via route to
1252+
// reach an uncovered pin.
1253+
// In both cases len is 0 and n1a/n2a are not set by layerAssignment
1254+
// (which only processes len>0 edges), so the grids are converted
1255+
// directly to GSegments without the pin-via-stack logic used above.
1256+
// Without this branch the via is silently dropped, leaving RSZ unable
1257+
// to build a connected tree (RSZ-0074).
1258+
convertGridsToSegments(
1259+
treeedge->route.grids, treeedge->route.routelen, net_segs, route);
12421260
}
12431261
}
12441262
}

src/grt/src/fastroute/src/utility.cpp

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -288,29 +288,48 @@ void FastRouteCore::fillVIA()
288288
treeedge.route.type = RouteType::MazeRoute;
289289
treeedge.route.routelen = newCNT - 1;
290290
}
291-
} else if ((treenodes[treeedge.n1].hID == BIG_INT
292-
&& treenodes[treeedge.n1].lID == BIG_INT)
293-
|| (treenodes[treeedge.n2].hID == BIG_INT
294-
&& treenodes[treeedge.n2].lID == BIG_INT)) {
291+
} else {
292+
// Handle zero-length edges (len == 0) that may need via grids.
293+
// These arise when two pins share the same gcell (x,y) but sit on
294+
// different layers. STT creates zero-length Steiner edges between
295+
// them (directly or through a Steiner node at the same position).
296+
//
297+
// For Steiner nodes co-located with terminals, layerAssignment
298+
// updates botL/topL on the stackAlias (a terminal), not on the
299+
// Steiner node itself. Resolve through stackAlias to obtain
300+
// meaningful layer information.
295301
int node1 = treeedge.n1;
296302
int node2 = treeedge.n2;
297-
if ((treenodes[node1].botL == num_layers_
298-
&& treenodes[node1].topL == -1)
299-
|| (treenodes[node2].botL == num_layers_
300-
&& treenodes[node2].topL == -1)) {
303+
int effective_node1 = (treenodes[node1].botL == num_layers_
304+
&& treenodes[node1].topL == -1)
305+
? treenodes[node1].stackAlias
306+
: node1;
307+
int effective_node2 = (treenodes[node2].botL == num_layers_
308+
&& treenodes[node2].topL == -1)
309+
? treenodes[node2].stackAlias
310+
: node2;
311+
312+
// Skip if both resolved nodes still lack layer information.
313+
if ((treenodes[effective_node1].botL == num_layers_
314+
&& treenodes[effective_node1].topL == -1)
315+
&& (treenodes[effective_node2].botL == num_layers_
316+
&& treenodes[effective_node2].topL == -1)) {
301317
continue;
302318
}
303319

304-
int16_t l1 = treenodes[node1].botL;
305-
int16_t l2 = treenodes[node2].botL;
306-
int16_t bottom_layer = std::min(l1, l2);
307-
int16_t top_layer = std::max(l1, l2);
308-
if (node1 < num_terminals) {
309-
extendLayerRange(node1, bottom_layer, top_layer);
320+
int16_t bottom_layer = std::min(treenodes[effective_node1].botL,
321+
treenodes[effective_node2].botL);
322+
int16_t top_layer = std::max(treenodes[effective_node1].botL,
323+
treenodes[effective_node2].botL);
324+
if (effective_node1 < num_terminals) {
325+
extendLayerRange(effective_node1, bottom_layer, top_layer);
326+
}
327+
if (effective_node2 < num_terminals) {
328+
extendLayerRange(effective_node2, bottom_layer, top_layer);
310329
}
311330

312-
if (node2 < num_terminals) {
313-
extendLayerRange(node2, bottom_layer, top_layer);
331+
if (top_layer <= bottom_layer) {
332+
continue;
314333
}
315334

316335
treeedge.route.grids.resize(top_layer - bottom_layer + 1);

src/grt/test/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ TESTS = [
1111
"clock_route_alpha",
1212
"clock_route_error1",
1313
"clock_route_error2",
14+
"colocated_pins",
1415
"congestion1",
1516
"congestion2",
1617
"congestion3",

src/grt/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ or_integration_tests(
88
clock_route_alpha
99
clock_route_error1
1010
clock_route_error2
11+
colocated_pins
1112
congestion1
1213
congestion2
1314
congestion3

src/grt/test/colocated_pins.def

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
VERSION 5.8 ;
2+
NAMESCASESENSITIVE ON ;
3+
DIVIDERCHAR "/" ;
4+
BUSBITCHARS "[]" ;
5+
DESIGN colocated_pins ;
6+
UNITS DISTANCE MICRONS 2000 ;
7+
DIEAREA ( 0 0 ) ( 60000 60000 ) ;
8+
ROW ROW_0 FreePDK45_38x28_10R_NP_162NW_34O 3800 2800 FS DO 137 BY 1 STEP 380 0 ;
9+
ROW ROW_1 FreePDK45_38x28_10R_NP_162NW_34O 3800 5600 N DO 137 BY 1 STEP 380 0 ;
10+
ROW ROW_2 FreePDK45_38x28_10R_NP_162NW_34O 3800 8400 FS DO 137 BY 1 STEP 380 0 ;
11+
ROW ROW_3 FreePDK45_38x28_10R_NP_162NW_34O 3800 11200 N DO 137 BY 1 STEP 380 0 ;
12+
ROW ROW_4 FreePDK45_38x28_10R_NP_162NW_34O 3800 14000 FS DO 137 BY 1 STEP 380 0 ;
13+
ROW ROW_5 FreePDK45_38x28_10R_NP_162NW_34O 3800 16800 N DO 137 BY 1 STEP 380 0 ;
14+
ROW ROW_6 FreePDK45_38x28_10R_NP_162NW_34O 3800 19600 FS DO 137 BY 1 STEP 380 0 ;
15+
ROW ROW_7 FreePDK45_38x28_10R_NP_162NW_34O 3800 22400 N DO 137 BY 1 STEP 380 0 ;
16+
ROW ROW_8 FreePDK45_38x28_10R_NP_162NW_34O 3800 25200 FS DO 137 BY 1 STEP 380 0 ;
17+
ROW ROW_9 FreePDK45_38x28_10R_NP_162NW_34O 3800 28000 N DO 137 BY 1 STEP 380 0 ;
18+
ROW ROW_10 FreePDK45_38x28_10R_NP_162NW_34O 3800 30800 FS DO 137 BY 1 STEP 380 0 ;
19+
ROW ROW_11 FreePDK45_38x28_10R_NP_162NW_34O 3800 33600 N DO 137 BY 1 STEP 380 0 ;
20+
ROW ROW_12 FreePDK45_38x28_10R_NP_162NW_34O 3800 36400 FS DO 137 BY 1 STEP 380 0 ;
21+
ROW ROW_13 FreePDK45_38x28_10R_NP_162NW_34O 3800 39200 N DO 137 BY 1 STEP 380 0 ;
22+
ROW ROW_14 FreePDK45_38x28_10R_NP_162NW_34O 3800 42000 FS DO 137 BY 1 STEP 380 0 ;
23+
ROW ROW_15 FreePDK45_38x28_10R_NP_162NW_34O 3800 44800 N DO 137 BY 1 STEP 380 0 ;
24+
ROW ROW_16 FreePDK45_38x28_10R_NP_162NW_34O 3800 47600 FS DO 137 BY 1 STEP 380 0 ;
25+
ROW ROW_17 FreePDK45_38x28_10R_NP_162NW_34O 3800 50400 N DO 137 BY 1 STEP 380 0 ;
26+
ROW ROW_18 FreePDK45_38x28_10R_NP_162NW_34O 3800 53200 FS DO 137 BY 1 STEP 380 0 ;
27+
TRACKS X 190 DO 158 STEP 380 LAYER metal1 ;
28+
TRACKS Y 140 DO 214 STEP 280 LAYER metal1 ;
29+
TRACKS X 190 DO 158 STEP 380 LAYER metal2 ;
30+
TRACKS Y 140 DO 214 STEP 280 LAYER metal2 ;
31+
TRACKS X 190 DO 158 STEP 380 LAYER metal3 ;
32+
TRACKS Y 140 DO 214 STEP 280 LAYER metal3 ;
33+
TRACKS X 190 DO 107 STEP 560 LAYER metal4 ;
34+
TRACKS Y 140 DO 107 STEP 560 LAYER metal4 ;
35+
TRACKS X 190 DO 107 STEP 560 LAYER metal5 ;
36+
TRACKS Y 140 DO 107 STEP 560 LAYER metal5 ;
37+
TRACKS X 190 DO 107 STEP 560 LAYER metal6 ;
38+
TRACKS Y 140 DO 107 STEP 560 LAYER metal6 ;
39+
TRACKS X 190 DO 38 STEP 1600 LAYER metal7 ;
40+
TRACKS Y 140 DO 38 STEP 1600 LAYER metal7 ;
41+
TRACKS X 190 DO 38 STEP 1600 LAYER metal8 ;
42+
TRACKS Y 140 DO 38 STEP 1600 LAYER metal8 ;
43+
TRACKS X 190 DO 19 STEP 3200 LAYER metal9 ;
44+
TRACKS Y 140 DO 19 STEP 3200 LAYER metal9 ;
45+
TRACKS X 190 DO 19 STEP 3200 LAYER metal10 ;
46+
TRACKS Y 140 DO 19 STEP 3200 LAYER metal10 ;
47+
COMPONENTS 6 ;
48+
- load_tl BUF_X1 + PLACED ( 3800 53200 ) N ;
49+
- load_tr BUF_X1 + PLACED ( 52060 53200 ) N ;
50+
- load_bl BUF_X1 + PLACED ( 3800 2800 ) N ;
51+
- load_br BUF_X1 + PLACED ( 52060 2800 ) N ;
52+
- u_m4 CELL_M4_PIN + PLACED ( 28500 25200 ) N ;
53+
- u_m3 CELL_M3_PIN + PLACED ( 30020 25200 ) N ;
54+
END COMPONENTS
55+
PINS 0 ;
56+
END PINS
57+
NETS 1 ;
58+
- test_net ( load_tl A ) ( load_tr A ) ( load_bl A ) ( load_br A ) ( u_m4 A ) ( u_m3 Z ) + USE SIGNAL ;
59+
END NETS
60+
END DESIGN
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
test_net
2+
(
3+
0 22800 5700 60000 metal2
4+
0 51300 5700 60000 metal1
5+
28500 22800 60000 28500 metal3
6+
51300 22800 60000 28500 metal2
7+
51300 22800 60000 60000 metal2
8+
51300 51300 60000 60000 metal1
9+
0 0 5700 28500 metal2
10+
0 0 5700 5700 metal1
11+
28500 22800 34200 28500 metal3
12+
28500 22800 34200 28500 metal4
13+
51300 0 60000 28500 metal2
14+
51300 0 60000 5700 metal1
15+
0 22800 5700 28500 metal2
16+
0 22800 34200 28500 metal3
17+
)

src/grt/test/colocated_pins.lef

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
VERSION 5.6 ;
2+
BUSBITCHARS "[]" ;
3+
DIVIDERCHAR "/" ;
4+
5+
# Cells with signal pins on metal4 and metal3 respectively.
6+
# Used to test that fillVIA creates a via stack when two pins from
7+
# different cells land in the same gcell on different routing layers.
8+
9+
MACRO CELL_M4_PIN
10+
CLASS CORE ;
11+
ORIGIN 0 0 ;
12+
FOREIGN CELL_M4_PIN 0 0 ;
13+
SIZE 0.76 BY 1.4 ;
14+
SYMMETRY X Y ;
15+
SITE FreePDK45_38x28_10R_NP_162NW_34O ;
16+
PIN A
17+
DIRECTION INPUT ;
18+
USE SIGNAL ;
19+
PORT
20+
LAYER metal4 ;
21+
RECT 0.28 0.525 0.42 0.875 ;
22+
END
23+
END A
24+
PIN VDD
25+
DIRECTION INOUT ;
26+
USE POWER ;
27+
SHAPE ABUTMENT ;
28+
PORT
29+
LAYER metal1 ;
30+
RECT 0 1.315 0.76 1.485 ;
31+
END
32+
END VDD
33+
PIN VSS
34+
DIRECTION INOUT ;
35+
USE GROUND ;
36+
SHAPE ABUTMENT ;
37+
PORT
38+
LAYER metal1 ;
39+
RECT 0 -0.085 0.76 0.085 ;
40+
END
41+
END VSS
42+
END CELL_M4_PIN
43+
44+
MACRO CELL_M3_PIN
45+
CLASS CORE ;
46+
ORIGIN 0 0 ;
47+
FOREIGN CELL_M3_PIN 0 0 ;
48+
SIZE 0.76 BY 1.4 ;
49+
SYMMETRY X Y ;
50+
SITE FreePDK45_38x28_10R_NP_162NW_34O ;
51+
PIN Z
52+
DIRECTION OUTPUT ;
53+
USE SIGNAL ;
54+
PORT
55+
LAYER metal3 ;
56+
RECT 0.28 0.525 0.42 0.875 ;
57+
END
58+
END Z
59+
PIN VDD
60+
DIRECTION INOUT ;
61+
USE POWER ;
62+
SHAPE ABUTMENT ;
63+
PORT
64+
LAYER metal1 ;
65+
RECT 0 1.315 0.76 1.485 ;
66+
END
67+
END VDD
68+
PIN VSS
69+
DIRECTION INOUT ;
70+
USE GROUND ;
71+
SHAPE ABUTMENT ;
72+
PORT
73+
LAYER metal1 ;
74+
RECT 0 -0.085 0.76 0.085 ;
75+
END
76+
END VSS
77+
END CELL_M3_PIN
78+
79+
END LIBRARY

0 commit comments

Comments
 (0)