summaryrefslogtreecommitdiff
path: root/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'node.c')
-rw-r--r--node.c382
1 files changed, 327 insertions, 55 deletions
diff --git a/node.c b/node.c
index 7de614d..8662e38 100644
--- a/node.c
+++ b/node.c
@@ -17,6 +17,7 @@
#include "node.h"
#include "qconfig.h"
#include "lef.h"
+#include "def.h"
#include "output.h"
/*--------------------------------------------------------------*/
@@ -94,10 +95,18 @@ FreeNodeinfo(int gridx, int gridy, int layer)
/* also, it should check for tap points that are routable */
/* by a wire and not a tap. However, those conditions are */
/* rare and are left unhandled for now. */
+/* */
+/* If "unblock_all" is 1, then unblock all grid points that */
+/* are cleanly routable by being completely inside a pin with */
+/* available margins for placing a via, regardless of whether */
+/* or not the pin has other available tap points. This should */
+/* only be used if obstructions are drawn in the style where */
+/* they can abut pins (e.g., part of the pin has been marked */
+/* as an obstruction). */
/*--------------------------------------------------------------*/
void
-count_reachable_taps()
+count_reachable_taps(u_char unblock_all)
{
NODE node;
NODEINFO lnode;
@@ -130,7 +139,7 @@ count_reachable_taps()
node = g->noderec[i];
if (node == NULL) continue;
if (node->numnodes == 0) continue; // e.g., vdd or gnd bus
- if (node->numtaps == 0) {
+ if ((node->numtaps == 0) || (unblock_all == TRUE)) {
/* Will try more than one via if available */
for (orient = 0; orient < 4; orient += 2) {
@@ -139,6 +148,7 @@ count_reachable_taps()
deltay = 0.5 * LefGetXYViaWidth(ds->layer, ds->layer, 1, orient);
gridx = (int)((ds->x1 - Xlowerbound) / PitchX) - 1;
+ if (gridx < 0) gridx = 0;
while (1) {
dx = (gridx * PitchX) + Xlowerbound;
if (dx > ds->x2 || gridx >= NumChannelsX) break;
@@ -147,6 +157,7 @@ count_reachable_taps()
((ds->x2 - dx + EPS) > deltax)) {
gridy = (int)((ds->y1 - Ylowerbound)
/ PitchY) - 1;
+ if (gridy < 0) gridy = 0;
while (1) {
dy = (gridy * PitchY) + Ylowerbound;
if (dy > ds->y2 || gridy >= NumChannelsY)
@@ -219,6 +230,7 @@ count_reachable_taps()
deltay = 0.5 * LefGetXYViaWidth(ds->layer, ds->layer, 1, orient);
gridx = (int)((ds->x1 - Xlowerbound) / PitchX) - 1;
+ if (gridx < 0) gridx = 0;
while (1) {
dx = (gridx * PitchX) + Xlowerbound;
if (dx > ds->x2 || gridx >= NumChannelsX) break;
@@ -226,6 +238,7 @@ count_reachable_taps()
if (((dx - ds->x1 + EPS) > -deltax) &&
((ds->x2 - dx + EPS) > -deltax)) {
gridy = (int)((ds->y1 - Ylowerbound) / PitchY) - 1;
+ if (gridy < 0) gridy = 0;
while (1) {
dy = (gridy * PitchY) + Ylowerbound;
@@ -233,13 +246,20 @@ count_reachable_taps()
break;
// Check that the grid position is inside the
- // tap rectangle. However, if the point above
- // the grid is blocked, then a via cannot be
- // placed here, so skip it.
+ // tap rectangle.
+
+ // NOTE: If the point above the grid is blocked,
+ // then a via cannot be placed here, so skip it.
+ // This currently looks only for completely
+ // obstructed positions. To do: For directionally
+ // obstructed positions, see if the obstruction
+ // is in the opposite direction of the via's
+ // offset and at least the same distance.
+ // Otherwise, it won't clear.
if (((ds->layer == Num_layers - 1) ||
!(OBSVAL(gridx, gridy, ds->layer + 1)
- & NO_NET)) &&
+ & (NO_NET || OBSTRUCT_MASK))) &&
((dy - ds->y1 + EPS) > -deltay) &&
((ds->y2 - dy + EPS) > -deltay)) {
@@ -371,6 +391,66 @@ count_reachable_taps()
print_node_name(node), node->netname);
Fprintf(stderr, "Qrouter will not be able to completely"
" route this net.\n");
+ if (Verbose > 1) {
+ int found_inside, found_inrange;
+ Fprintf(stderr, "Tap position blockage analysis:\n");
+
+ /* Unreachable taps are the most common problem with */
+ /* new processes or buggy code, so make a detailed */
+ /* report of blockages affecting routing for debugging. */
+
+ found_inside = found_inrange = 0;
+ for (ds = g->taps[i]; ds; ds = ds->next) {
+ unsigned char is_inside, is_inrange;
+
+ deltax = 0.5 * LefGetXYViaWidth(ds->layer, ds->layer, 0, 0);
+ deltay = 0.5 * LefGetXYViaWidth(ds->layer, ds->layer, 1, 0);
+
+ Fprintf(stderr, "Tap geometry (%g %g) to (%g %g):\n",
+ ds->x1, ds->y1, ds->x2, ds->y2);
+
+ gridx = (int)(((ds->x1 - 1) - Xlowerbound) / PitchX) - 1;
+ if (gridx < 0) gridx = 0;
+ while (1) {
+ dx = (gridx * PitchX) + Xlowerbound;
+ if (dx > (ds->x2 + 1) || gridx >= NumChannelsX) break;
+ gridy = (int)(((ds->y1 - 1) - Ylowerbound) / PitchY) - 1;
+ if (gridy < 0) gridy = 0;
+ while (1) {
+ dy = (gridy * PitchY) + Ylowerbound;
+ if (dy > (ds->y2 + 1) || gridy >= NumChannelsY)
+ break;
+
+ is_inside = (dx >= ds->x1 && dx <= ds->x2 &&
+ dy >= ds->y1 && dy <= ds->y2) ? 1 : 0;
+
+ is_inrange = (dx > ds->x1 - deltax &&
+ dx < ds->x2 + deltax &&
+ dy > ds->y1 - deltay &&
+ dy < ds->y2 + deltay) ? 1 : 0;
+
+ if (is_inrange) {
+ Fprintf(stderr, "Grid position (%d %d) at (%g %g) "
+ "layer %d is %s tap geometry.\n",
+ gridx, gridy, dx, dy, ds->layer,
+ (is_inside == 1) ? "inside" : "outside");
+ print_grid_information(gridx, gridy, ds->layer);
+ found_inrange++;
+ if (is_inside) found_inside++;
+ }
+ gridy++;
+ }
+ gridx++;
+ }
+ }
+ if (found_inrange == 0) Fprintf(stderr, "No positions analyzed.\n");
+ Fprintf(stderr, "%d grid position%s found "
+ "inside tap geometry\n", found_inside,
+ ((found_inside == 1) ? " was" : "s were"));
+ Fprintf(stderr, "%d grid position%s found "
+ "nearby tap geometry\n", found_inrange,
+ ((found_inrange == 1) ? " was" : "s were"));
+ }
}
}
}
@@ -427,16 +507,15 @@ void check_variable_pitch(int l, int *hptr, int *vptr)
vpitch = 0.5 * (LefGetRouteWidth(l) + wvia) + LefGetRouteSpacing(l);
}
- vnum = 1;
- while (vpitch > PitchY + EPS) {
- vpitch /= 2.0;
- vnum++;
- }
- hnum = 1;
- while (hpitch > PitchX + EPS) {
- hpitch /= 2.0;
- hnum++;
- }
+ vnum = (int)((vpitch / PitchY) - EPS) + 1;
+ hnum = (int)((hpitch / PitchX) - EPS) + 1;
+
+ // To mark blockages, either none of (hnum & vnum) should be
+ // larger than 1, or both of them should be. Further info in
+ // create_obstructions_from_variable_pitch(), below.
+
+ if (vnum > 1 && hnum == 1) hnum++;
+ if (hnum > 1 && vnum == 1) vnum++;
*vptr = vnum;
*hptr = hnum;
@@ -458,13 +537,56 @@ void check_variable_pitch(int l, int *hptr, int *vptr)
void create_obstructions_from_variable_pitch(void)
{
- int l, vnum, hnum, x, y;
+ int l, vnum, hnum, hoff, voff, x, y;
NODEINFO lnode;
+ TRACKS tracksinfo, tracksinfoother;
for (l = 0; l < Num_layers; l++) {
+ // check_variable_pitch() guarantees that either hnum
+ // and vnum are both one, or both are larger than 1.
+
check_variable_pitch(l, &hnum, &vnum);
+ if (hnum == 1 && vnum == 1) continue; // No obstructions needed
+
+ // Compute the offset of the tracks to mark obstructions
+ tracksinfo = DefGetTracks(l);
+ if (tracksinfo == NULL) {
+ // Should look at standard cell placement and LEF offset
+ // to determine offset here. For now, just use 0.
+ hoff = voff = 0;
+ }
+ else {
+ // Use the start position relative to lowerbound to determine
+ // the offset. use the offset of the higher or lower layer
+ // for determining the offset in the opposite direction of
+ // the current layer orientation.
+ if (l < Num_layers - 1) {
+ // If not the top layer, then use the upper layer as the other layer
+ tracksinfoother = DefGetTracks(l + 1);
+ }
+ else if (l > 0) {
+ // Otherwise, use the lower layer
+ tracksinfoother = DefGetTracks(l - 1);
+ }
+ else {
+ // Should not happen, as it means routing is done with one layer. . .
+ tracksinfoother = (TRACKS)NULL;
+ }
+
+ if (Vert[l]) {
+ hoff = (int)((tracksinfo->start - Xlowerbound) / PitchX + 0.5);
+ voff = (tracksinfoother == (TRACKS)NULL) ?
+ 0 : (int)((tracksinfoother->start - Ylowerbound) / PitchY + 0.5);
+ }
+ else {
+ voff = (int)((tracksinfo->start - Ylowerbound) / PitchY + 0.5);
+ hoff = (tracksinfoother == (TRACKS)NULL) ?
+ 0 : (int)((tracksinfoother->start - Xlowerbound) / PitchX + 0.5);
+ }
+ }
+
// This could be better handled by restricting
// access from specific directions rather than
// marking a position as NO_NET. Since the
@@ -473,14 +595,11 @@ void create_obstructions_from_variable_pitch(void)
// the other value, then we force both values to
// be at least 2.
- if (vnum > 1 && hnum == 1) hnum++;
- if (hnum > 1 && vnum == 1) vnum++;
-
if (vnum > 1 || hnum > 1) {
for (x = 0; x < NumChannelsX; x++) {
- if (x % hnum == 0) continue;
+ if ((x - hoff) % hnum == 0) continue;
for (y = 0; y < NumChannelsY; y++) {
- if (y % vnum == 0) continue;
+ if ((y - voff) % vnum == 0) continue;
// If the grid position itself is a node, don't restrict
// routing based on variable pitch.
@@ -808,8 +927,11 @@ void create_obstructions_from_gates(void)
}
else edist = 0;
- if ((edist + EPS) < (s * s))
+ if ((edist + EPS) < (s * s)) {
check_obstruct(gridx, gridy, ds, dx, dy, s);
+ if (is_testpoint(gridx, gridy, g, -1, ds) != NULL)
+ Fprintf(stderr, " Position blocked by gate obstruction.\n");
+ }
else
edist = 0; // diagnostic break
}
@@ -876,8 +998,12 @@ void create_obstructions_from_gates(void)
}
else edist = 0;
- if ((edist + EPS) < (s * s))
+ if ((edist + EPS) < (s * s)) {
check_obstruct(gridx, gridy, ds, dx, dy, s);
+ if (is_testpoint(gridx, gridy, g, i, ds) != NULL)
+ Fprintf(stderr, " Position blocked by unused"
+ " gate pin.\n");
+ }
}
gridy++;
}
@@ -912,8 +1038,11 @@ void create_obstructions_from_gates(void)
dy = (gridy * PitchY) + Ylowerbound;
if (dy > (ds->y2 + delta[ds->layer])
|| gridy >= NumChannelsY) break;
- if (dy >= (ds->y1 - delta[ds->layer]) && gridy >= 0)
+ if (dy >= (ds->y1 - delta[ds->layer]) && gridy >= 0) {
check_obstruct(gridx, gridy, ds, dx, dy, delta[i]);
+ if (is_testpoint(gridx, gridy, NULL, -1, ds) != NULL)
+ Fprintf(stderr, " Position blocked by defined obstruction.\n");
+ }
gridy++;
}
@@ -1000,6 +1129,79 @@ void expand_tap_geometry(void)
}
/*--------------------------------------------------------------*/
+/* is_testpoint() */
+/* */
+/* Check if a grid position is on the testpoint list. If so, */
+/* return the pointer to the testpoint structure. */
+/*--------------------------------------------------------------*/
+
+DPOINT
+is_testpoint(int gridx, int gridy, GATE g, int nidx, DSEG ds)
+{
+ int layer;
+ DPOINT trypoint;
+ NODE node = NULL, onode;
+ NODEINFO lnode;
+
+ layer = ds->layer;
+ for (trypoint = testpoint; trypoint; trypoint = trypoint->next) {
+ if (trypoint->gridx == gridx && trypoint->gridy == gridy &&
+ trypoint->layer == layer) {
+ Fprintf(stderr, "Watchpoint (%g, %g) layer %d"
+ " grid (%d, %d):\n",
+ trypoint->x, trypoint->y, trypoint->layer,
+ trypoint->gridx, trypoint->gridy);
+ if (g != NULL) {
+ Fprintf(stderr, " Gate instance = \"%s\"\n", g->gatename);
+ if (g->gatetype)
+ Fprintf(stderr, " Gate cell = \"%s\"\n", g->gatetype->gatename);
+
+ if (nidx >= 0) {
+ Fprintf(stderr, " Gate pin = \"%s\"\n", g->node[nidx]);
+ Fprintf(stderr, " Pin geometry = (%g, %g) to (%g, %g)\n",
+ ds->x1, ds->y1, ds->x2, ds->y2);
+ node = g->noderec[nidx];
+ Fprintf(stderr, " Connects to net \"%s\"\n", node->netname);
+ }
+ }
+ if (nidx < 0) {
+ Fprintf(stderr, " Obstruction geometry = (%g, %g) to (%g, %g)\n",
+ ds->x1, ds->y1, ds->x2, ds->y2);
+ }
+ lnode = NODEIPTR(gridx, gridy, layer);
+ if (lnode != NULL) {
+ onode = lnode->nodesav;
+ if (onode != NULL) {
+ if (node && (onode->netnum != node->netnum)) {
+ if (onode->netname)
+ Fprintf(stderr, " Position was previously assigned"
+ " to node %s on net %s\n", print_node_name(onode),
+ onode->netname);
+ else
+ Fprintf(stderr, " Position was previously assigned"
+ " to node %s on different net\n",
+ print_node_name(onode));
+ }
+ else {
+ Fprintf(stderr, " Position was previously assigned"
+ " to node %s on the same net\n",
+ print_node_name(onode));
+ }
+ }
+ else Fprintf(stderr, " Position was previously assigned"
+ " to a node that has been disabled.\n");
+ }
+ else Fprintf(stderr, " Position was not previously assigned"
+ " to a node\n");
+
+ Fprintf(stderr, "Disabled position because:\n");
+ return trypoint;
+ }
+ }
+ return NULL;
+}
+
+/*--------------------------------------------------------------*/
/* create_obstructions_inside_nodes() */
/* */
/* Fills in the Obs[][] grid from the position of each node */
@@ -1028,6 +1230,7 @@ void create_obstructions_inside_nodes(void)
NODEINFO lnode;
GATE g;
DSEG ds;
+ DPOINT tpoint;
u_int dir, mask, k;
int i, gridx, gridy;
double dx, dy, xdist, vwx, vwy;
@@ -1055,11 +1258,13 @@ void create_obstructions_inside_nodes(void)
for (ds = g->taps[i]; ds; ds = ds->next) {
gridx = (int)((ds->x1 - Xlowerbound) / PitchX) - 1;
+ if (gridx < 0) gridx = 0;
while (1) {
dx = (gridx * PitchX) + Xlowerbound;
if (dx > ds->x2 || gridx >= NumChannelsX) break;
else if (dx >= ds->x1 && gridx >= 0) {
gridy = (int)((ds->y1 - Ylowerbound) / PitchY) - 1;
+ if (gridy < 0) gridy = 0;
while (1) {
dy = (gridy * PitchY) + Ylowerbound;
if (dy > ds->y2 || gridy >= NumChannelsY) break;
@@ -1097,6 +1302,9 @@ void create_obstructions_inside_nodes(void)
// that it falls through on all subsequent
// processing.
+ if (is_testpoint(gridx, gridy, g, i, ds) != NULL)
+ Fprintf(stderr, " Position is inside pin but cannot "
+ "be routed without causing violation.\n");
disable_gridpos(gridx, gridy, ds->layer);
gridy++;
continue;
@@ -1287,6 +1495,7 @@ void create_obstructions_outside_nodes(void)
NODEINFO lnode;
GATE g;
DSEG ds;
+ DPOINT tpoint;
u_int dir, mask, k;
int i, gridx, gridy, orient;
double dx, dy, xdist, deltax, deltay;
@@ -1331,6 +1540,7 @@ void create_obstructions_outside_nodes(void)
deltax = get_via_clear(ds->layer, 1, orient, ds);
gridx = (int)((ds->x1 - Xlowerbound - deltax) / PitchX) - 1;
+ if (gridx < 0) gridx = 0;
while (1) {
dx = (gridx * PitchX) + Xlowerbound;
@@ -1347,6 +1557,7 @@ void create_obstructions_outside_nodes(void)
else if ((dx - EPS) > (ds->x1 - deltax) && gridx >= 0) {
deltay = get_via_clear(ds->layer, 0, orient, ds);
gridy = (int)((ds->y1 - Ylowerbound - deltay) / PitchY) - 1;
+ if (gridy < 0) gridy = 0;
while (1) {
dy = (gridy * PitchY) + Ylowerbound;
@@ -1437,8 +1648,9 @@ void create_obstructions_outside_nodes(void)
if ((ds->layer < Num_layers - 1) &&
(gridy > 0) &&
(OBSVAL(gridx, gridy - 1,
- ds->layer + 1) & OBSTRUCT_MASK))
+ ds->layer + 1) & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
}
@@ -1461,8 +1673,9 @@ void create_obstructions_outside_nodes(void)
if ((ds->layer < Num_layers - 1) &&
(gridy < NumChannelsY - 1) &&
(OBSVAL(gridx, gridy + 1,
- ds->layer + 1) & OBSTRUCT_MASK))
+ ds->layer + 1) & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
}
@@ -1485,8 +1698,9 @@ void create_obstructions_outside_nodes(void)
if ((ds->layer < Num_layers - 1) &&
(gridx > 0) &&
(OBSVAL(gridx - 1, gridy,
- ds->layer + 1) & OBSTRUCT_MASK))
+ ds->layer + 1) & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
}
@@ -1509,15 +1723,22 @@ void create_obstructions_outside_nodes(void)
if ((ds->layer < Num_layers - 1) &&
(gridx < NumChannelsX - 1) &&
(OBSVAL(gridx + 1, gridy,
- ds->layer + 1) & OBSTRUCT_MASK))
+ ds->layer + 1) & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
}
}
- if (maxerr == 1)
- disable_gridpos(gridx, gridy, ds->layer);
+ if (maxerr == 1) {
+ if (is_testpoint(gridx, gridy, g, i, ds) != NULL)
+ Fprintf(stderr,
+ "Attempted to clear obstruction with"
+ " offset, but offset is more than 1/2"
+ " route pitch.\n");
+ disable_gridpos(gridx, gridy, ds->layer);
+ }
// Diagnostic
else if (Verbose > 3)
@@ -1630,8 +1851,9 @@ void create_obstructions_outside_nodes(void)
(gridx > 0) &&
(OBSVAL(gridx - 1, gridy,
ds->layer + 1)
- & OBSTRUCT_MASK))
+ & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
else if ((dx <= ds->x1) &&
@@ -1646,8 +1868,9 @@ void create_obstructions_outside_nodes(void)
(NumChannelsX - 1)
&& (OBSVAL(gridx + 1, gridy,
ds->layer + 1)
- & OBSTRUCT_MASK))
+ & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
}
@@ -1665,8 +1888,9 @@ void create_obstructions_outside_nodes(void)
(NumChannelsY - 1)
&& (OBSVAL(gridx, gridy - 1,
ds->layer + 1)
- & OBSTRUCT_MASK))
+ & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
else if ((dy <= ds->y1) &&
@@ -1680,8 +1904,9 @@ void create_obstructions_outside_nodes(void)
(gridy > 0) &&
(OBSVAL(gridx, gridy + 1,
ds->layer + 1)
- & OBSTRUCT_MASK))
+ & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
}
@@ -1955,7 +2180,11 @@ void create_obstructions_outside_nodes(void)
// called STUBROUTE_X).
if (dir == NI_STUB_MASK) {
- disable_gridpos(gridx, gridy, ds->layer);
+ if (is_testpoint(gridx, gridy, g, i, ds) != NULL)
+ Fprintf(stderr, "Tap point is blocked in "
+ "and cannot be routed without causing "
+ "DRC violations.\n");
+ disable_gridpos(gridx, gridy, ds->layer);
}
}
else if (epass == 0) {
@@ -1993,8 +2222,17 @@ void create_obstructions_outside_nodes(void)
// node record. This will probably need
// revisiting.
- if ((k & PINOBSTRUCTMASK) != 0)
+ if ((k & PINOBSTRUCTMASK) != 0) {
+ if (is_testpoint(gridx, gridy, g, i, ds) != NULL) {
+ if (k & STUBROUTE)
+ Fprintf(stderr, "Position marked as a "
+ "stub route for the net.\n");
+ else
+ Fprintf(stderr, "Position marked as a "
+ "tap offset for the net.\n");
+ }
disable_gridpos(gridx, gridy, ds->layer);
+ }
else if ((lnode = NODEIPTR(gridx, gridy, ds->layer))
!= NULL && (lnode->nodesav != NULL)) {
@@ -2030,12 +2268,14 @@ void create_obstructions_outside_nodes(void)
if ((ds->layer < Num_layers - 1) &&
(gridx > 0) &&
(OBSVAL(gridx + 1, gridy,
- ds->layer + 1) & OBSTRUCT_MASK))
+ ds->layer + 1) & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
else if ((ds->layer < Num_layers - 1) &&
(gridx > 0) &&
- (dist > PitchX / 2))
+ (dist > PitchX / 2)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
}
@@ -2062,13 +2302,15 @@ void create_obstructions_outside_nodes(void)
if ((ds->layer < Num_layers - 1) && gridx <
(NumChannelsX - 1) &&
(OBSVAL(gridx - 1, gridy,
- ds->layer + 1) & OBSTRUCT_MASK))
+ ds->layer + 1) & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
else if ((ds->layer < Num_layers - 1) &&
gridx <
(NumChannelsX - 1) &&
- (dist < -PitchX / 2))
+ (dist < -PitchX / 2)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
}
@@ -2096,12 +2338,14 @@ void create_obstructions_outside_nodes(void)
if ((ds->layer < Num_layers - 1) &&
(gridy > 0) && (OBSVAL(gridx,
gridy + 1, ds->layer + 1)
- & OBSTRUCT_MASK))
+ & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
else if ((ds->layer < Num_layers - 1) &&
(gridy > 0) &&
- (dist > PitchY / 2))
+ (dist > PitchY / 2)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
}
@@ -2129,13 +2373,15 @@ void create_obstructions_outside_nodes(void)
gridx <
(NumChannelsX - 1) &&
(OBSVAL(gridx, gridy - 1,
- ds->layer + 1) & OBSTRUCT_MASK))
+ ds->layer + 1) & OBSTRUCT_MASK)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
else if ((ds->layer < Num_layers - 1) &&
gridx <
(NumChannelsX - 1) &&
- (dist < -PitchY / 2))
+ (dist < -PitchY / 2)) {
block_route(gridx, gridy, ds->layer, UP);
+ }
}
}
}
@@ -2149,14 +2395,24 @@ void create_obstructions_outside_nodes(void)
if (orient == 2) {
// Maybe no need to revert the flag?
lnode->flags &= ~NI_NO_VIAX;
+ if (is_testpoint(gridx, gridy,
+ g, i, ds) != NULL)
+ Fprintf(stderr, "Unable to find "
+ "a viable offset for a tap.\n");
disable_gridpos(gridx, gridy, ds->layer);
}
else
lnode->flags |= NI_NO_VIAX;
}
}
- else
+ else {
+ if (is_testpoint(gridx, gridy,
+ g, i, ds) != NULL)
+ Fprintf(stderr, "Tap point is too "
+ "close to two different nodes "
+ "and no offsets are possible.\n");
disable_gridpos(gridx, gridy, ds->layer);
+ }
}
/* If we are on a layer > 0, then this geometry */
@@ -2280,6 +2536,7 @@ void tap_to_tap_interactions(void)
NODEINFO lnode;
GATE g;
DSEG ds;
+ DPOINT tpoint;
struct dseg_ de;
int mingridx, mingridy, maxgridx, maxgridy;
int i, gridx, gridy, net, orignet;
@@ -2360,8 +2617,13 @@ void tap_to_tap_interactions(void)
/* the tap geometry? */
if ((de.x1 < ds->x2) && (ds->x1 < de.x2) &&
- (de.y1 < ds->y2) && (ds->y1 < de.y2))
+ (de.y1 < ds->y2) && (ds->y1 < de.y2)) {
+ if (is_testpoint(gridx, gridy,
+ g, i, ds) != NULL)
+ Fprintf(stderr, "Offset tap interferes "
+ "with position.\n");
disable_gridpos(gridx, gridy, ds->layer);
+ }
}
}
@@ -2472,11 +2734,13 @@ make_routable(NODE node)
if (g->noderec[i] == node) {
for (ds = g->taps[i]; ds; ds = ds->next) {
gridx = (int)((ds->x1 - Xlowerbound) / PitchX) - 1;
+ if (gridx < 0) gridx = 0;
while (1) {
dx = (gridx * PitchX) + Xlowerbound;
if (dx > ds->x2 || gridx >= NumChannelsX) break;
else if (dx >= ds->x1 && gridx >= 0) {
gridy = (int)((ds->y1 - Ylowerbound) / PitchY) - 1;
+ if (gridy < 0) gridy = 0;
while (1) {
dy = (gridy * PitchY) + Ylowerbound;
if (dy > ds->y2 || gridy >= NumChannelsY) break;
@@ -3164,10 +3428,12 @@ find_route_blocks()
lnode = NODEIPTR(gridx, gridy, lds.layer);
u = ((OBSVAL(gridx, gridy, lds.layer) & STUBROUTE)
&& (lnode->flags & NI_STUB_EW)) ? v : w;
- if (dy + EPS < lds.y2 - u)
+ if (dy + EPS < lds.y2 - u) {
block_route(gridx, gridy, lds.layer, NORTH);
- if (dy - EPS > lds.y1 + u)
+ }
+ if (dy - EPS > lds.y1 + u) {
block_route(gridx, gridy, lds.layer, SOUTH);
+ }
dy += PitchY;
gridy++;
}
@@ -3197,10 +3463,12 @@ find_route_blocks()
lnode = NODEIPTR(gridx, gridy, lds.layer);
u = ((OBSVAL(gridx, gridy, lds.layer) & STUBROUTE)
&& (lnode->flags & NI_STUB_EW)) ? v : w;
- if (dy + EPS < lds.y2 - u)
+ if (dy + EPS < lds.y2 - u) {
block_route(gridx, gridy, lds.layer, NORTH);
- if (dy - EPS > lds.y1 + u)
+ }
+ if (dy - EPS > lds.y1 + u) {
block_route(gridx, gridy, lds.layer, SOUTH);
+ }
dy += PitchY;
gridy++;
}
@@ -3230,10 +3498,12 @@ find_route_blocks()
lnode = NODEIPTR(gridx, gridy, lds.layer);
u = ((OBSVAL(gridx, gridy, lds.layer) & STUBROUTE)
&& (lnode->flags & NI_STUB_NS)) ? v : w;
- if (dx + EPS < lds.x2 - u)
+ if (dx + EPS < lds.x2 - u) {
block_route(gridx, gridy, lds.layer, EAST);
- if (dx - EPS > lds.x1 + u)
+ }
+ if (dx - EPS > lds.x1 + u) {
block_route(gridx, gridy, lds.layer, WEST);
+ }
dx += PitchX;
gridx++;
}
@@ -3263,10 +3533,12 @@ find_route_blocks()
lnode = NODEIPTR(gridx, gridy, lds.layer);
u = ((OBSVAL(gridx, gridy, lds.layer) & STUBROUTE)
&& (lnode->flags & NI_STUB_NS)) ? v : w;
- if (dx + EPS < lds.x2 - u)
+ if (dx + EPS < lds.x2 - u) {
block_route(gridx, gridy, lds.layer, EAST);
- if (dx - EPS > lds.x1 + u)
+ }
+ if (dx - EPS > lds.x1 + u) {
block_route(gridx, gridy, lds.layer, WEST);
+ }
dx += PitchX;
gridx++;
}