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
3 changes: 1 addition & 2 deletions src/grt/src/GlobalRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3181,8 +3181,7 @@ bool GlobalRouter::isCoveringPin(Net* net, GSegment& segment)
int seg_x = segment.final_x;
int seg_y = segment.final_y;
if (pin.getConnectionLayer() == seg_top_layer
&& pin.getOnGridPosition() == odb::Point(seg_x, seg_y)
&& (pin.isPort() || pin.isConnectedToPadOrMacro())) {
&& pin.getOnGridPosition() == odb::Point(seg_x, seg_y)) {
return true;
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/grt/src/fastroute/include/FastRoute.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

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

private:
void convertGridsToSegments(
const std::vector<GPoint3D>& grids,
int grid_count,
std::unordered_set<GSegment, GSegmentHash>& net_segs,
GRoute& route);
int getEdgeCapacity(FrNet* net, int x1, int y1, EdgeDirection direction);
void getNetId(odb::dbNet* db_net, int& net_id, bool& exists);
void clearNetRoute(int netID);
Expand Down
84 changes: 51 additions & 33 deletions src/grt/src/fastroute/src/FastRoute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,40 @@ void FastRouteCore::getPlanarRoute(odb::dbNet* db_net, GRoute& route)
}
}

void FastRouteCore::convertGridsToSegments(
const std::vector<GPoint3D>& grids,
int grid_count,
std::unordered_set<GSegment, GSegmentHash>& net_segs,
GRoute& route)
{
int lastX = (tile_size_ * (grids[0].x + 0.5)) + x_corner_;
int lastY = (tile_size_ * (grids[0].y + 0.5)) + y_corner_;
int lastL = grids[0].layer;

for (int i = 1; i <= grid_count; i++) {
const int xreal = (tile_size_ * (grids[i].x + 0.5)) + x_corner_;
const int yreal = (tile_size_ * (grids[i].y + 0.5)) + y_corner_;
const int currentL = grids[i].layer;

if (lastX == xreal && lastY == yreal && lastL == currentL) {
continue;
}

GSegment segment
= GSegment(lastX, lastY, lastL + 1, xreal, yreal, currentL + 1);
segment.setIs3DRoute(true);

if (net_segs.find(segment) == net_segs.end()) {
net_segs.insert(segment);
route.push_back(segment);
}

lastX = xreal;
lastY = yreal;
lastL = currentL;
}
}

void FastRouteCore::get3DRoute(odb::dbNet* db_net, GRoute& route)
{
int netID;
Expand Down Expand Up @@ -1206,39 +1240,23 @@ void FastRouteCore::get3DRoute(odb::dbNet* db_net, GRoute& route)
}
}

int lastX = (tile_size_ * (filled_grids[0].x + 0.5)) + x_corner_;
int lastY = (tile_size_ * (filled_grids[0].y + 0.5)) + y_corner_;
int lastL = filled_grids[0].layer;

for (int i = 1; i < filled_grids.size(); i++) {
const int xreal = (tile_size_ * (filled_grids[i].x + 0.5)) + x_corner_;
const int yreal = (tile_size_ * (filled_grids[i].y + 0.5)) + y_corner_;
const int currentL = filled_grids[i].layer;

// Prevent adding segments that are effectively zero-length vias on the
// same layer
if (lastX == xreal && lastY == yreal && lastL == currentL) {
// Skip this segment as it's a redundant via on the same layer
lastX = xreal;
lastY = yreal;
lastL = currentL;
continue;
}

GSegment segment
= GSegment(lastX, lastY, lastL + 1, xreal, yreal, currentL + 1);
segment.setIs3DRoute(true);

// Only add segment if it's not a duplicate
if (net_segs.find(segment) == net_segs.end()) {
net_segs.insert(segment);
route.push_back(segment);
}

lastX = xreal;
lastY = yreal;
lastL = currentL;
}
convertGridsToSegments(
filled_grids, filled_grids.size() - 1, net_segs, route);
} else if (treeedge->route.routelen > 0) {
// Handle zero-length edges (len == 0) that carry via route grids.
// These arise in two situations:
// (a) fillVIA created a via stack for co-located terminal pins on
// different layers (e.g. two pins in the same gcell on layers 2
// and 3).
// (b) ensurePinCoverage appended a new TreeEdge with a via route to
// reach an uncovered pin.
// In both cases len is 0 and n1a/n2a are not set by layerAssignment
// (which only processes len>0 edges), so the grids are converted
// directly to GSegments without the pin-via-stack logic used above.
// Without this branch the via is silently dropped, leaving RSZ unable
// to build a connected tree (RSZ-0074).
convertGridsToSegments(
treeedge->route.grids, treeedge->route.routelen, net_segs, route);
}
}
}
Expand Down
51 changes: 35 additions & 16 deletions src/grt/src/fastroute/src/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,29 +288,48 @@ void FastRouteCore::fillVIA()
treeedge.route.type = RouteType::MazeRoute;
treeedge.route.routelen = newCNT - 1;
}
} else if ((treenodes[treeedge.n1].hID == BIG_INT
&& treenodes[treeedge.n1].lID == BIG_INT)
|| (treenodes[treeedge.n2].hID == BIG_INT
&& treenodes[treeedge.n2].lID == BIG_INT)) {
} else {
// Handle zero-length edges (len == 0) that may need via grids.
// These arise when two pins share the same gcell (x,y) but sit on
// different layers. STT creates zero-length Steiner edges between
// them (directly or through a Steiner node at the same position).
//
// For Steiner nodes co-located with terminals, layerAssignment
// updates botL/topL on the stackAlias (a terminal), not on the
// Steiner node itself. Resolve through stackAlias to obtain
// meaningful layer information.
int node1 = treeedge.n1;
int node2 = treeedge.n2;
if ((treenodes[node1].botL == num_layers_
&& treenodes[node1].topL == -1)
|| (treenodes[node2].botL == num_layers_
&& treenodes[node2].topL == -1)) {
int effective_node1 = (treenodes[node1].botL == num_layers_
&& treenodes[node1].topL == -1)
? treenodes[node1].stackAlias
: node1;
int effective_node2 = (treenodes[node2].botL == num_layers_
&& treenodes[node2].topL == -1)
? treenodes[node2].stackAlias
: node2;

// Skip if both resolved nodes still lack layer information.
if ((treenodes[effective_node1].botL == num_layers_
&& treenodes[effective_node1].topL == -1)
&& (treenodes[effective_node2].botL == num_layers_
&& treenodes[effective_node2].topL == -1)) {
continue;
}

int16_t l1 = treenodes[node1].botL;
int16_t l2 = treenodes[node2].botL;
int16_t bottom_layer = std::min(l1, l2);
int16_t top_layer = std::max(l1, l2);
if (node1 < num_terminals) {
extendLayerRange(node1, bottom_layer, top_layer);
int16_t bottom_layer = std::min(treenodes[effective_node1].botL,
treenodes[effective_node2].botL);
int16_t top_layer = std::max(treenodes[effective_node1].botL,
treenodes[effective_node2].botL);
if (effective_node1 < num_terminals) {
extendLayerRange(effective_node1, bottom_layer, top_layer);
}
if (effective_node2 < num_terminals) {
extendLayerRange(effective_node2, bottom_layer, top_layer);
}

if (node2 < num_terminals) {
extendLayerRange(node2, bottom_layer, top_layer);
if (top_layer <= bottom_layer) {
continue;
}

treeedge.route.grids.resize(top_layer - bottom_layer + 1);
Expand Down
1 change: 1 addition & 0 deletions src/grt/test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ TESTS = [
"clock_route_alpha",
"clock_route_error1",
"clock_route_error2",
"colocated_pins",
"congestion1",
"congestion2",
"congestion3",
Expand Down
1 change: 1 addition & 0 deletions src/grt/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ or_integration_tests(
clock_route_alpha
clock_route_error1
clock_route_error2
colocated_pins
congestion1
congestion2
congestion3
Expand Down
60 changes: 60 additions & 0 deletions src/grt/test/colocated_pins.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
VERSION 5.8 ;
NAMESCASESENSITIVE ON ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN colocated_pins ;
UNITS DISTANCE MICRONS 2000 ;
DIEAREA ( 0 0 ) ( 60000 60000 ) ;
ROW ROW_0 FreePDK45_38x28_10R_NP_162NW_34O 3800 2800 FS DO 137 BY 1 STEP 380 0 ;
ROW ROW_1 FreePDK45_38x28_10R_NP_162NW_34O 3800 5600 N DO 137 BY 1 STEP 380 0 ;
ROW ROW_2 FreePDK45_38x28_10R_NP_162NW_34O 3800 8400 FS DO 137 BY 1 STEP 380 0 ;
ROW ROW_3 FreePDK45_38x28_10R_NP_162NW_34O 3800 11200 N DO 137 BY 1 STEP 380 0 ;
ROW ROW_4 FreePDK45_38x28_10R_NP_162NW_34O 3800 14000 FS DO 137 BY 1 STEP 380 0 ;
ROW ROW_5 FreePDK45_38x28_10R_NP_162NW_34O 3800 16800 N DO 137 BY 1 STEP 380 0 ;
ROW ROW_6 FreePDK45_38x28_10R_NP_162NW_34O 3800 19600 FS DO 137 BY 1 STEP 380 0 ;
ROW ROW_7 FreePDK45_38x28_10R_NP_162NW_34O 3800 22400 N DO 137 BY 1 STEP 380 0 ;
ROW ROW_8 FreePDK45_38x28_10R_NP_162NW_34O 3800 25200 FS DO 137 BY 1 STEP 380 0 ;
ROW ROW_9 FreePDK45_38x28_10R_NP_162NW_34O 3800 28000 N DO 137 BY 1 STEP 380 0 ;
ROW ROW_10 FreePDK45_38x28_10R_NP_162NW_34O 3800 30800 FS DO 137 BY 1 STEP 380 0 ;
ROW ROW_11 FreePDK45_38x28_10R_NP_162NW_34O 3800 33600 N DO 137 BY 1 STEP 380 0 ;
ROW ROW_12 FreePDK45_38x28_10R_NP_162NW_34O 3800 36400 FS DO 137 BY 1 STEP 380 0 ;
ROW ROW_13 FreePDK45_38x28_10R_NP_162NW_34O 3800 39200 N DO 137 BY 1 STEP 380 0 ;
ROW ROW_14 FreePDK45_38x28_10R_NP_162NW_34O 3800 42000 FS DO 137 BY 1 STEP 380 0 ;
ROW ROW_15 FreePDK45_38x28_10R_NP_162NW_34O 3800 44800 N DO 137 BY 1 STEP 380 0 ;
ROW ROW_16 FreePDK45_38x28_10R_NP_162NW_34O 3800 47600 FS DO 137 BY 1 STEP 380 0 ;
ROW ROW_17 FreePDK45_38x28_10R_NP_162NW_34O 3800 50400 N DO 137 BY 1 STEP 380 0 ;
ROW ROW_18 FreePDK45_38x28_10R_NP_162NW_34O 3800 53200 FS DO 137 BY 1 STEP 380 0 ;
TRACKS X 190 DO 158 STEP 380 LAYER metal1 ;
TRACKS Y 140 DO 214 STEP 280 LAYER metal1 ;
TRACKS X 190 DO 158 STEP 380 LAYER metal2 ;
TRACKS Y 140 DO 214 STEP 280 LAYER metal2 ;
TRACKS X 190 DO 158 STEP 380 LAYER metal3 ;
TRACKS Y 140 DO 214 STEP 280 LAYER metal3 ;
TRACKS X 190 DO 107 STEP 560 LAYER metal4 ;
TRACKS Y 140 DO 107 STEP 560 LAYER metal4 ;
TRACKS X 190 DO 107 STEP 560 LAYER metal5 ;
TRACKS Y 140 DO 107 STEP 560 LAYER metal5 ;
TRACKS X 190 DO 107 STEP 560 LAYER metal6 ;
TRACKS Y 140 DO 107 STEP 560 LAYER metal6 ;
TRACKS X 190 DO 38 STEP 1600 LAYER metal7 ;
TRACKS Y 140 DO 38 STEP 1600 LAYER metal7 ;
TRACKS X 190 DO 38 STEP 1600 LAYER metal8 ;
TRACKS Y 140 DO 38 STEP 1600 LAYER metal8 ;
TRACKS X 190 DO 19 STEP 3200 LAYER metal9 ;
TRACKS Y 140 DO 19 STEP 3200 LAYER metal9 ;
TRACKS X 190 DO 19 STEP 3200 LAYER metal10 ;
TRACKS Y 140 DO 19 STEP 3200 LAYER metal10 ;
COMPONENTS 6 ;
- load_tl BUF_X1 + PLACED ( 3800 53200 ) N ;
- load_tr BUF_X1 + PLACED ( 52060 53200 ) N ;
- load_bl BUF_X1 + PLACED ( 3800 2800 ) N ;
- load_br BUF_X1 + PLACED ( 52060 2800 ) N ;
- u_m4 CELL_M4_PIN + PLACED ( 28500 25200 ) N ;
- u_m3 CELL_M3_PIN + PLACED ( 30020 25200 ) N ;
END COMPONENTS
PINS 0 ;
END PINS
NETS 1 ;
- test_net ( load_tl A ) ( load_tr A ) ( load_bl A ) ( load_br A ) ( u_m4 A ) ( u_m3 Z ) + USE SIGNAL ;
END NETS
END DESIGN
17 changes: 17 additions & 0 deletions src/grt/test/colocated_pins.guideok
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
test_net
(
0 22800 5700 60000 metal2
0 51300 5700 60000 metal1
28500 22800 60000 28500 metal3
51300 22800 60000 28500 metal2
51300 22800 60000 60000 metal2
51300 51300 60000 60000 metal1
0 0 5700 28500 metal2
0 0 5700 5700 metal1
28500 22800 34200 28500 metal3
28500 22800 34200 28500 metal4
51300 0 60000 28500 metal2
51300 0 60000 5700 metal1
0 22800 5700 28500 metal2
0 22800 34200 28500 metal3
)
79 changes: 79 additions & 0 deletions src/grt/test/colocated_pins.lef
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
VERSION 5.6 ;
BUSBITCHARS "[]" ;
DIVIDERCHAR "/" ;

# Cells with signal pins on metal4 and metal3 respectively.
# Used to test that fillVIA creates a via stack when two pins from
# different cells land in the same gcell on different routing layers.

MACRO CELL_M4_PIN
CLASS CORE ;
ORIGIN 0 0 ;
FOREIGN CELL_M4_PIN 0 0 ;
SIZE 0.76 BY 1.4 ;
SYMMETRY X Y ;
SITE FreePDK45_38x28_10R_NP_162NW_34O ;
PIN A
DIRECTION INPUT ;
USE SIGNAL ;
PORT
LAYER metal4 ;
RECT 0.28 0.525 0.42 0.875 ;
END
END A
PIN VDD
DIRECTION INOUT ;
USE POWER ;
SHAPE ABUTMENT ;
PORT
LAYER metal1 ;
RECT 0 1.315 0.76 1.485 ;
END
END VDD
PIN VSS
DIRECTION INOUT ;
USE GROUND ;
SHAPE ABUTMENT ;
PORT
LAYER metal1 ;
RECT 0 -0.085 0.76 0.085 ;
END
END VSS
END CELL_M4_PIN

MACRO CELL_M3_PIN
CLASS CORE ;
ORIGIN 0 0 ;
FOREIGN CELL_M3_PIN 0 0 ;
SIZE 0.76 BY 1.4 ;
SYMMETRY X Y ;
SITE FreePDK45_38x28_10R_NP_162NW_34O ;
PIN Z
DIRECTION OUTPUT ;
USE SIGNAL ;
PORT
LAYER metal3 ;
RECT 0.28 0.525 0.42 0.875 ;
END
END Z
PIN VDD
DIRECTION INOUT ;
USE POWER ;
SHAPE ABUTMENT ;
PORT
LAYER metal1 ;
RECT 0 1.315 0.76 1.485 ;
END
END VDD
PIN VSS
DIRECTION INOUT ;
USE GROUND ;
SHAPE ABUTMENT ;
PORT
LAYER metal1 ;
RECT 0 -0.085 0.76 0.085 ;
END
END VSS
END CELL_M3_PIN

END LIBRARY
Loading
Loading