diff options
Diffstat (limited to 'node.c')
-rw-r--r-- | node.c | 382 |
1 files changed, 327 insertions, 55 deletions
@@ -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++; } |