From f89d52dbcc6f21eafff2479d94a44e944bd0b767 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 6 Jan 2022 13:29:43 -0500 Subject: [PATCH] Modified the short selection routine (again) to avoid issues when tracing the short path back through stacked contacts. Discovered a problem with the connectivity search routine (which has been in the code for a very long time) which will fail to copy contacts to the selection cell if it has already drawn one of the metal layers in the same place. This has now been fixed. --- VERSION | 2 +- database/DBconnect.c | 10 ++- select/selOps.c | 141 ++++++++++++++++++++++++++----------------- 3 files changed, 93 insertions(+), 60 deletions(-) diff --git a/VERSION b/VERSION index d166a16e..96aff2f6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.251 +8.3.253 diff --git a/database/DBconnect.c b/database/DBconnect.c index 2ffbffee..7be8e222 100644 --- a/database/DBconnect.c +++ b/database/DBconnect.c @@ -792,7 +792,7 @@ dbcConnectFunc(tile, cx) SearchContext scx2; TileType loctype = TiGetTypeExact(tile); TileType dinfo = 0; - int i, pNum = cx->tc_plane; + int retval, i, pNum = cx->tc_plane; CellDef *def; TiToRect(tile, &tileArea); @@ -860,20 +860,24 @@ dbcConnectFunc(tile, cx) /* which have not already been painted. */ def = csa2->csa2_use->cu_def; + retval = 1; if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum], dinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc, (ClientData) NULL) == 0) - return 0; + retval = 0; /* Paint this tile into the destination cell. This * marks its area has having been processed. Then recycle * the storage for the current list element. */ - DBNMPaintPlane(def->cd_planes[pNum], dinfo, + if ((retval == 1) || DBIsContact(loctype)) + DBNMPaintPlane(def->cd_planes[pNum], dinfo, &newarea, DBStdPaintTbl(loctype, pNum), (PaintUndoInfo *) NULL); + if (retval == 0) return 0; + /* Since the whole area of this tile hasn't been recorded, * we must process its area to find any other tiles that * connect to it. Add each of them to the list of things diff --git a/select/selOps.c b/select/selOps.c index 82499c11..6774745e 100644 --- a/select/selOps.c +++ b/select/selOps.c @@ -311,6 +311,38 @@ SelectFlat() } +/* Structure used by selShortTileProc() below to save a cost and Tile pointer */ + +typedef struct _shortsearchdata { + int cost; + Tile *tile; +} ShortSearchData; + +/* + * ---------------------------------------------------------------------------- + * + * selShortTileProc -- + * + * Callback function for DBSrPaintArea in selShortFindReverse(). When + * checking connected types on other planes, record the tile with the + * minimum cost. + * + * ---------------------------------------------------------------------------- + */ + +int +selShortTileProc(tile, ssd) + Tile *tile; + ShortSearchData *ssd; +{ + if ((int)tile->ti_client < ssd->cost) + { + ssd->cost = (int)tile->ti_client; + ssd->tile = tile; + } + return 0; +} + /* * ---------------------------------------------------------------------------- * @@ -342,11 +374,13 @@ selShortFindReverse(rlist, tile, pnum, fdir) int fdir; { Tile *tp, *mintp; - int mincost = INT_MAX; ExtRectList *newrrec; - int minp, p, mindir; + int mincost, minp, p, mindir; TileType ttype; + mindir = fdir; + mincost = (int)tile->ti_client; + while (TRUE) { newrrec = mallocMagic(sizeof(ExtRectList)); @@ -393,6 +427,7 @@ selShortFindReverse(rlist, tile, pnum, fdir) *rlist = newrrec; if ((int)tile->ti_client == 0) return 0; /* We're done */ + minp = pnum; /* Search top */ @@ -478,21 +513,24 @@ rightside: donesides: if (DBIsContact(ttype)) { + ShortSearchData ssd; PlaneMask pmask; pmask = DBConnPlanes[ttype]; + + ssd.cost = mincost; + ssd.tile = (Tile *)NULL; for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) { if (PlaneMaskHasPlane(pmask, p) && (p != pnum)) { - tp = SelectDef->cd_planes[p]->pl_hint; - GOTOPOINT(tp, &tile->ti_ll); - SelectDef->cd_planes[p]->pl_hint = tp; - if (tp->ti_client == (ClientData)CLIENTDEFAULT) continue; - if ((int)tp->ti_client < mincost) + DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[p], + &newrrec->r_r, &DBAllButSpaceAndDRCBits, + selShortTileProc, &ssd); + if (ssd.cost < mincost) { - mincost = (int)tp->ti_client; - mintp = tp; + mincost = ssd.cost; + mintp = ssd.tile; minp = p; mindir = GEO_CENTER; } @@ -503,17 +541,23 @@ donesides: /* If mincost is still set to INT_MAX we have a real serious problem! */ if (mincost == INT_MAX) return 1; - /* Stopgap measure: Error should not happen, but it does! */ - /* Remove client data of current tile and take minimum. */ - if (mincost == (int)tile->ti_client) TiSetClient(tile, CLIENTDEFAULT); + /* Failsafe: Avoid infinite recursion */ + if ((tile == mintp) || (tile->ti_client == CLIENTDEFAULT)) + { + TxError("Failed to trace back shorting path.\n"); + break; + } /* Now we have the minimum cost neighboring tile; continue search with it */ tile = mintp; pnum = minp; fdir = mindir; - } - /* Not reached */ + /* WIP Diagnostic */ + // TxPrintf("Cost = %d Tile @ %d %d plane %d dir %d\n", + // mincost, tile->ti_ll.p_x, tile->ti_ll.p_y, pnum, fdir); + } + return 1; } /* Data structure used by selShortFindForward() to store a tile and */ @@ -813,11 +857,35 @@ SelectShort(char *lab1, char *lab2) PlaneMask pmask; ExtRectList *rlist; - /* Step one: find the tiles containing the labels. If not found, */ - /* return NULL. */ + CellUse *use; + TileType ttype; + Rect rect; + SearchContext scx; + MagWindow *window; + DBWclientRec *crec; + int windowMask; + + window = ToolGetBoxWindow(&rect, &windowMask); + if (!window) return NULL; + use = (CellUse *)window->w_surfaceID; + + /* Run the equivalent of "goto lab1 ; select net" */ + /* Make sure the selection is clear before starting */ + + SelectClear(); + ttype = CmdFindNetProc(lab1, use, &rect, FALSE); + if (ttype == TT_SPACE) return NULL; + + bzero(&scx, sizeof(SearchContext)); + scx.scx_use = use; + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = rect; + crec = (DBWclientRec *)window->w_clientData; + + SelectNet(&scx, ttype, crec->dbw_bitmask, (Rect *)NULL, FALSE); for (selLabel = SelectDef->cd_labels; selLabel != NULL; selLabel = - selLabel->lab_next) + selLabel->lab_next) { if ((srclab == NULL) && Match(lab1, selLabel->lab_text)) srclab = selLabel; @@ -826,45 +894,6 @@ SelectShort(char *lab1, char *lab2) destlab = selLabel; } - /* If both labels were not in the existing selection, run the equivalent - * of "goto lab1 ; select net" - */ - if ((srclab == NULL) || (destlab == NULL)) - { - CellUse *use; - TileType ttype; - Rect rect; - SearchContext scx; - MagWindow *window; - DBWclientRec *crec; - int windowMask; - - window = ToolGetBoxWindow(&rect, &windowMask); - if (!window) return NULL; - - use = (CellUse *)window->w_surfaceID; - ttype = CmdFindNetProc(lab1, use, &rect, FALSE); - if (ttype == TT_SPACE) return NULL; - - bzero(&scx, sizeof(SearchContext)); - scx.scx_use = use; - scx.scx_trans = GeoIdentityTransform; - scx.scx_area = rect; - crec = (DBWclientRec *)window->w_clientData; - - SelectNet(&scx, ttype, crec->dbw_bitmask, (Rect *)NULL, FALSE); - - for (selLabel = SelectDef->cd_labels; selLabel != NULL; selLabel = - selLabel->lab_next) - { - if ((srclab == NULL) && Match(lab1, selLabel->lab_text)) - srclab = selLabel; - - if ((destlab == NULL) && Match(lab2, selLabel->lab_text)) - destlab = selLabel; - } - } - /* Must be able to find both labels */ if ((srclab == NULL) || (destlab == NULL)) return NULL;