/* grouteTile.c - * * Global signal router code for tile and channel related things. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #ifndef lint static char sccsid[] = "@(#)grouteTile.c 4.3 MAGIC (Berkeley) 10/31/85"; #endif /* not lint */ #include #include "utils/magic.h" #include "utils/geometry.h" #include "utils/hash.h" #include "utils/heap.h" #include "tiles/tile.h" #include "database/database.h" #include "debug/debug.h" #include "gcr/gcr.h" #include "windows/windows.h" #include "graphics/graphics.h" #include "utils/main.h" #include "dbwind/dbwind.h" #include "utils/signals.h" #include "router/router.h" #include "grouter/grouter.h" #include "utils/styles.h" #include "textio/textio.h" bool GlDebugCrossings = FALSE; #define isSpaceTile(tile) (TiGetBody(tile) == NULL) /* * ---------------------------------------------------------------------------- * * glAdjacentChannel -- * * Figure out which channel borders the given channel at the given * point. If the given channel is NULL, then assume the point is at * the edge of a cell, and return the channel adjacent to the cell. * * Results: * Pointer to the adjacent channel, or NULL if none exists. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ GCRChannel * glAdjacentChannel(ch, point) GCRChannel *ch; /* The tile corresponding to a channel */ Point *point; /* A point somewhere on the channel edge */ { Point p; int side; ASSERT(ch!=(GCRChannel *) NULL, "Null channel in glAdjacentChannel"); side = glPointToSide(ch, point); p = * point; switch(side) { case GEO_NORTH: case GEO_EAST: break; case GEO_SOUTH: p.p_y--; break; case GEO_WEST: p.p_x--; break; default: ASSERT(FALSE, "glAdjacentChannel point not on channel"); return((GCRChannel *) NULL); break; } return (glTileToChannel(TiSrPointNoHint(RtrChannelPlane, &p))); } /* * ---------------------------------------------------------------------------- * * glBadChannel -- * * Decide if a prospective channel is okay to use in global routing * propagation. If it creates a loop for the particular path under * investigation, then forget it. If it doesn't exist, then forget it. * * Results: * FALSE if the channel is okay to use, otherwise TRUE. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ bool glBadChannel(oldCh, newCh, entryPt) GCRChannel *oldCh; /* The current channel */ GCRChannel *newCh; /* See if this new one is okay to use */ GlPoint *entryPt; /* List of previously used points */ { GlPoint *temp; /* Reject a null channel */ if ((oldCh == (GCRChannel *) NULL) || (newCh == (GCRChannel *) NULL)) return (TRUE); /* Reject the channel if using it creates a loop in the routing path */ for (temp = entryPt; temp != (GlPoint *) NULL; temp = temp->gl_parent) if (temp->gl_ch == newCh) return (TRUE); return (FALSE); } /* * ---------------------------------------------------------------------------- * * glDebug -- * * Code to display crossing points on the screen. * * Results: * None. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ void glDebug(point, text, value, size) Point *point; /* Location to be marked */ char *text; /* Text to associate with error paint */ int value; /* An integer value to go into the text */ int size; /* How big to make the error paint box */ { char buffer1[1024], buffer2[1024]; Rect area; if (!GlDebugCrossings) return; (void) strcpy(buffer1, text); (void) sprintf(buffer2, "(value = %d)", value); (void) strcat(buffer1, buffer2); area.r_ll.p_x = point->p_x - size; area.r_ur.p_x = point->p_x + size; area.r_ll.p_y = point->p_y - size; area.r_ur.p_y = point->p_y + size; DBWFeedbackAdd(&area, buffer1, EditCellUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); GrFlush(); (void) sprintf(buffer2, "%s --more--", buffer1); (void) TxGetLinePrompt(buffer1, sizeof buffer1, buffer2); if (buffer1[0] == 'q') GlDebugCrossings = FALSE; TxPrintf("\n"); } /* * ---------------------------------------------------------------------------- * * glPointToChannel -- * * Given a point and a direction, return a pointer to the channel * adjacent to the given point, in the given direction. The point * must be on the edge of a channel. If on the edge of a cell, the * point location must be the modified location returned by RtrStemTip. * * Results: * Pointer to the channel. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ GCRChannel * glPointToChannel(point, dir) Point *point; /* The point from which the channel is found */ int dir; /* The direction in which the search goes */ { Point p; p = *point; switch (dir) { case GEO_NORTH: case GEO_EAST: break; case GEO_SOUTH: p.p_y--; break; case GEO_WEST: p.p_x--; break; default: ASSERT(FALSE, "glPointToChannel: bad direction argument"); return ((GCRChannel *) NULL); } return (glTileToChannel(TiSrPointNoHint(RtrChannelPlane, &p))); } /* * ---------------------------------------------------------------------------- * * glPointToSide -- * * Given a point somewhere on the perimeter of a channel, determine * which side it is on. The channel is given to prevent ambiguity, * since the point may fall on a border between two channels. * * Results: * The compass direction corresponding to the side of the channel on * which the point lies. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ int glPointToSide(ch, pt) GCRChannel * ch; /* Channel containing the given point */ Point * pt; /* The point on some side of the channel*/ { /* The point is on the left */ if (ch->gcr_area->r_xbot == pt->p_x) return (GEO_WEST); /* The point is on the bottom */ if (ch->gcr_area->r_ybot == pt->p_y) return (GEO_SOUTH); /* The point is on the right */ if (ch->gcr_area->r_xtop == pt->p_x) return (GEO_EAST); /* The point is on the top */ if (ch->gcr_area->r_ytop == pt->p_y) return (GEO_NORTH); ASSERT(FALSE, "glPointToSide point not on edge"); return (GEO_CENTER); } /* * ---------------------------------------------------------------------------- * * glSide -- * * Determine which side of a cell a terminal label is on by looking on * the channel plane for channel tiles in each of the quadrants. A * terminal label must not fall on space or on a corner. It must lie * on a flat edge of a cell tile. * * Are all these calls to TiSrPoint really necessary? I think so, * because a label might fall on the edge of a particular tile but * still appear over contiguous cell tiles. * * Results: * A direction GEO_NORTH, SOUTH, EAST, WEST, or CENTER if internal or * a corner. This indicates the side of the cell on which the terminal * lies. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ int glSide(point) Point *point; /* The lower left point of the label rectangle */ { int glSrFunc(); Tile *t; Point p; p = *point; t = TiSrPoint((Tile *) NULL, RtrChannelPlane, &p); if(TiGetBody(t) != NULL) /* _?|X_ */ { /* ?|? */ p.p_x--; t = TiSrPoint(t, RtrChannelPlane, &p); if(TiGetBody(t) != NULL) /* _X|X_ */ { /* ?|? */ p.p_y--; t = TiSrPoint(t, RtrChannelPlane, &p); if(TiGetBody(t) != NULL) /* _X|X_ */ return(GEO_CENTER); /* X|? */ p.p_x++; t = TiSrPoint(t, RtrChannelPlane, &p); if(TiGetBody(t) != NULL) /* _X|X_ */ return(GEO_CENTER); /* |X */ else return(GEO_SOUTH); } else /* __|X_ */ { /* ?|? */ p.p_y--; t = TiSrPoint(t, RtrChannelPlane, &p); if(TiGetBody(t) != NULL) /* __|X_ */ return(GEO_CENTER); /* X|? */ p.p_x++; t = TiSrPoint(t, RtrChannelPlane, &p); if(TiGetBody(t) != NULL) /* __|X_ */ return(GEO_WEST); /* |X */ } } else /* Forget about S or W */ { p.p_x--; t = TiSrPoint(t, RtrChannelPlane, &p); if(TiGetBody(t) != NULL) /* _X|__ */ { /* ?|? */ p.p_y--; t = TiSrPoint(t, RtrChannelPlane, &p); if(TiGetBody(t) == NULL) /* _X|__ */ return(GEO_CENTER); /* |? */ p.p_x++; t = TiSrPoint(t, RtrChannelPlane, &p); if(TiGetBody(t) != NULL) /* _X|__ */ return(GEO_CENTER); /* X|X */ else return(GEO_EAST); } else /* __|__ */ { /* ?|? */ p.p_y--; t = TiSrPoint(t, RtrChannelPlane, &p); if(TiGetBody(t) == NULL) /* __|__ */ return(GEO_CENTER); /* |? */ p.p_x++; t = TiSrPoint(t, RtrChannelPlane, &p); if(TiGetBody(t) != NULL) /* __|__ */ return(GEO_NORTH); /* X|X */ } } return(GEO_CENTER); } /* * ---------------------------------------------------------------------------- * * glTileToChannel -- * * Figure out which channel corresponds to the given tile. * * Results: * Pointer to the channel. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ GCRChannel * glTileToChannel(tile) Tile *tile; /* Should point to a channel (space) tile */ { HashEntry *he; if (!isSpaceTile(tile)) return ((GCRChannel *) NULL); he = HashLookOnly(&RtrTileToChannel, (char *) tile); if (he == (HashEntry *) NULL) return ((GCRChannel *) NULL); return (GCRChannel *) HashGetValue(he); }