From 814fb6f18dc0af889a63347072ea4981e6c647c8 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sun, 18 Feb 2024 14:04:21 -0500 Subject: [PATCH] Corrected two separate issues with R-C extraction: (1) There was a method that failed to work on devices with complex shapes on the device recognition layer, such as snake-geometry resistors. (2) The use of contact type "xpc" in the sky130 tech file as its own contact residue caused the contact tracing in extresist to fail. I opted to keep the unorthodox contact description in the tech file and wrote an extension to a routine in extresist to handle the case. --- VERSION | 2 +- resis/ResMain.c | 207 ++++++++++++++++++++++++++++++++++++++++++++--- resis/ResUtils.c | 43 ++++++++++ resis/resis.h | 6 +- 4 files changed, 246 insertions(+), 12 deletions(-) diff --git a/VERSION b/VERSION index 31fd3361..c0cbfb0d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.460 +8.3.461 diff --git a/resis/ResMain.c b/resis/ResMain.c index 02ef74c4..1652a30a 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -66,23 +66,31 @@ extern HashTable ResNodeTable; void ResInitializeConn() { - TileType dev, diff; + TileType dev, ttype; char *dev_name; + int i; ExtDevice *devptr; for (dev = TT_TECHDEPBASE; dev < TT_MAXTYPES; dev++) { - devptr = ExtCurStyle->exts_device[dev]; - if ((devptr != NULL) && ((dev_name = devptr->exts_deviceName) != NULL) - && (strcmp(dev_name, "None"))) + for (devptr = ExtCurStyle->exts_device[dev]; devptr; devptr = devptr->exts_next) { - for (diff = TT_TECHDEPBASE; diff < TT_MAXTYPES; diff++) + if ((devptr != NULL) && ((dev_name = devptr->exts_deviceName) != NULL) + && (strcmp(dev_name, "None"))) { - if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), diff) - TTMaskSetType(&ResConnectWithSD[diff], dev); + for (ttype = TT_TECHDEPBASE; ttype < TT_MAXTYPES; ttype++) + { + for (i = 0; ; i++) + { + if (TTMaskIsZero(&(devptr->exts_deviceSDTypes[i]))) + break; + if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), ttype) + TTMaskSetType(&ResConnectWithSD[ttype], dev); + } - if TTMaskHasType(&(devptr->exts_deviceSubstrateTypes), diff) - TTMaskSetType(&ResConnectWithSD[diff], dev); + if TTMaskHasType(&(devptr->exts_deviceSubstrateTypes), ttype) + TTMaskSetType(&ResConnectWithSD[ttype], dev); + } } } TTMaskSetMask(&ResConnectWithSD[dev], &DBConnectTbl[dev]); @@ -410,6 +418,7 @@ ResFindNewContactTiles(contacts) TxError("Error: setting contact tile to null\n"); } #endif + if ((IsSplit(tile) && TTMaskHasType(&mask, TiGetRightType(tile))) || TTMaskHasType(&mask, TiGetType(tile))) { @@ -423,6 +432,30 @@ ResFindNewContactTiles(contacts) (contacts->cp_currentcontact) += 1; j->contactList = ce; } + else + { + TileType ttype = TiGetTypeExact(tile); + if (DBIsContact(ttype)) + { + /* Handle the exceptional case in which a contact + * type is its own residue. This can be used for + * devices whose terminals are always a contact + * and for which a non-contact type cannot be drawn. + */ + if (TTMaskIntersect(DBResidueMask(ttype), &mask)) + { + tileJunk *j = (tileJunk *)tile->ti_client; + cElement *ce; + + ce = (cElement *) mallocMagic((unsigned) (sizeof(cElement))); + contacts->cp_tile[contacts->cp_currentcontact] = tile; + ce->ce_thisc = contacts; + ce->ce_nextc = j->contactList; + (contacts->cp_currentcontact) += 1; + j->contactList = ce; + } + } + } } #ifdef PARANOID if (contacts->cp_currentcontact >= LAYERS_PER_CONTACT) @@ -1289,6 +1322,8 @@ FindStartTile(goodies, SourcePoint) int pnum, t1, t2, i; ExtDevice *devptr; Rect r; + bool complex; + static Stack *devStack = NULL; /* If the drive point is on a contact, check for the contact residues */ /* first, then the contact type itself. */ @@ -1391,6 +1426,8 @@ FindStartTile(goodies, SourcePoint) { for (i = 0; i < devptr->exts_deviceSDCount; i++) { + complex = FALSE; /* Assume device is a single tile */ + /* left */ for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) { @@ -1403,6 +1440,9 @@ FindStartTile(goodies, SourcePoint) MAX(BOTTOM(tile), BOTTOM(tp))) >> 1; return(tp); } + else if (tp->ti_client != CLIENTDEFAULT) + if (((tileJunk *)tp->ti_client)->tj_status & RES_TILE_DEV) + complex = TRUE; } /* right */ @@ -1417,6 +1457,9 @@ FindStartTile(goodies, SourcePoint) MAX(BOTTOM(tile), BOTTOM(tp))) >> 1; return(tp); } + else if (tp->ti_client != CLIENTDEFAULT) + if (((tileJunk *)tp->ti_client)->tj_status & RES_TILE_DEV) + complex = TRUE; } /* top */ @@ -1431,6 +1474,9 @@ FindStartTile(goodies, SourcePoint) MAX(LEFT(tile), LEFT(tp))) >> 1; return(tp); } + else if (tp->ti_client != CLIENTDEFAULT) + if (((tileJunk *)tp->ti_client)->tj_status & RES_TILE_DEV) + complex = TRUE; } /* bottom */ @@ -1445,6 +1491,149 @@ FindStartTile(goodies, SourcePoint) MAX(LEFT(tile), LEFT(tp))) >> 1; return(tp); } + else if (tp->ti_client != CLIENTDEFAULT) + if (((tileJunk *)tp->ti_client)->tj_status & RES_TILE_DEV) + complex = TRUE; + } + + if (complex == TRUE) + { + /* Didn't find a terminal but device has multiple */ + /* tiles, so make a secondary search looking at all */ + /* tiles of the device. */ + + if (devStack == NULL) devStack = StackNew(8); + + ((tileJunk *)tile->ti_client)->tj_status |= RES_TILE_PUSHED; + STACKPUSH((ClientData)tile, devStack); + while (!StackEmpty(devStack)) + { + tile = (Tile *)STACKPOP(devStack); + + /* left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + { + t2 = TiGetRightType(tp); + if ((t2 != TT_SPACE) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t2)) + { + SourcePoint->p_x = LEFT(tile); + SourcePoint->p_y = (MIN(TOP(tile),TOP(tp)) + + MAX(BOTTOM(tile), BOTTOM(tp))) >> 1; + while (!StackEmpty(devStack)) + { + STACKPOP(devStack); + } + return(tp); + } + else if (tp->ti_client != CLIENTDEFAULT) + { + if (((tileJunk *)tp->ti_client)->tj_status & RES_TILE_DEV) + { + if (!(((tileJunk *)tp->ti_client)->tj_status + & RES_TILE_PUSHED)) + { + ((tileJunk *)tp->ti_client)->tj_status + |= RES_TILE_PUSHED; + STACKPUSH((ClientData)tp, devStack); + } + } + } + } + + /* right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + { + t2 = TiGetLeftType(tp); + if ((t2 != TT_SPACE) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t2)) + { + SourcePoint->p_x = RIGHT(tile); + SourcePoint->p_y = (MIN(TOP(tile), TOP(tp))+ + MAX(BOTTOM(tile), BOTTOM(tp))) >> 1; + while (!StackEmpty(devStack)) + { + STACKPOP(devStack); + } + return(tp); + } + else if (tp->ti_client != CLIENTDEFAULT) + { + if (((tileJunk *)tp->ti_client)->tj_status & RES_TILE_DEV) + { + if (!(((tileJunk *)tp->ti_client)->tj_status + & RES_TILE_PUSHED)) + { + ((tileJunk *)tp->ti_client)->tj_status + |= RES_TILE_PUSHED; + STACKPUSH((ClientData)tp, devStack); + } + } + } + } + + /* top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + { + t2 = TiGetBottomType(tp); + if ((t2 != TT_SPACE) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t2)) + { + SourcePoint->p_y = TOP(tile); + SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp)) + + MAX(LEFT(tile), LEFT(tp))) >> 1; + while (!StackEmpty(devStack)) + { + STACKPOP(devStack); + } + return(tp); + } + else if (tp->ti_client != CLIENTDEFAULT) + { + if (((tileJunk *)tp->ti_client)->tj_status & RES_TILE_DEV) + { + if (!(((tileJunk *)tp->ti_client)->tj_status + & RES_TILE_PUSHED)) + { + ((tileJunk *)tp->ti_client)->tj_status + |= RES_TILE_PUSHED; + STACKPUSH((ClientData)tp, devStack); + } + } + } + } + + /* bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + { + t2 = TiGetTopType(tp); + if ((t2 != TT_SPACE) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t2)) + { + SourcePoint->p_y = BOTTOM(tile); + SourcePoint->p_x = (MIN(RIGHT(tile), RIGHT(tp)) + + MAX(LEFT(tile), LEFT(tp))) >> 1; + while (!StackEmpty(devStack)) + { + STACKPOP(devStack); + } + return(tp); + } + else if (tp->ti_client != CLIENTDEFAULT) + { + if (((tileJunk *)tp->ti_client)->tj_status & RES_TILE_DEV) + { + if (!(((tileJunk *)tp->ti_client)->tj_status + & RES_TILE_PUSHED)) + { + ((tileJunk *)tp->ti_client)->tj_status + |= RES_TILE_PUSHED; + STACKPUSH((ClientData)tp, devStack); + } + } + } + } + } } } diff --git a/resis/ResUtils.c b/resis/ResUtils.c index 375981c9..05d5844e 100644 --- a/resis/ResUtils.c +++ b/resis/ResUtils.c @@ -445,6 +445,16 @@ ResAddPlumbing(tile, arg) Junk->deviceList = resDev; Junk->tj_status |= RES_TILE_DEV; + /* Update device position to point to the lower-leftmost tile */ + if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) || + ((tp2->ti_ll.p_x == resDev->rd_inside.r_ll.p_x) && + (tp2->ti_ll.p_y < resDev->rd_inside.r_ll.p_y))) + { + resDev->rd_inside.r_ll.p_x = LEFT(tp2); + resDev->rd_inside.r_ll.p_y = BOTTOM(tp2); + resDev->rd_inside.r_ur.p_x = RIGHT(tp2); + resDev->rd_inside.r_ur.p_y = TOP(tp2); + } } else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetBottomType(tp2)) @@ -464,6 +474,17 @@ ResAddPlumbing(tile, arg) STACKPUSH((ClientData)tp2, resDevStack); Junk->deviceList = resDev; Junk->tj_status |= RES_TILE_DEV; + + /* Update device position to point to the lower-leftmost tile */ + if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) || + ((tp2->ti_ll.p_x == resDev->rd_inside.r_ll.p_x) && + (tp2->ti_ll.p_y < resDev->rd_inside.r_ll.p_y))) + { + resDev->rd_inside.r_ll.p_x = LEFT(tp2); + resDev->rd_inside.r_ll.p_y = BOTTOM(tp2); + resDev->rd_inside.r_ur.p_x = RIGHT(tp2); + resDev->rd_inside.r_ur.p_y = TOP(tp2); + } } else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetTopType(tp2)) @@ -483,6 +504,17 @@ ResAddPlumbing(tile, arg) STACKPUSH((ClientData)tp2, resDevStack); Junk->deviceList = resDev; Junk->tj_status |= RES_TILE_DEV; + + /* Update device position to point to the lower-leftmost tile */ + if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) || + ((tp2->ti_ll.p_x == resDev->rd_inside.r_ll.p_x) && + (tp2->ti_ll.p_y < resDev->rd_inside.r_ll.p_y))) + { + resDev->rd_inside.r_ll.p_x = LEFT(tp2); + resDev->rd_inside.r_ll.p_y = BOTTOM(tp2); + resDev->rd_inside.r_ur.p_x = RIGHT(tp2); + resDev->rd_inside.r_ur.p_y = TOP(tp2); + } } else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetLeftType(tp2)) @@ -502,6 +534,17 @@ ResAddPlumbing(tile, arg) STACKPUSH((ClientData)tp2, resDevStack); Junk->deviceList = resDev; Junk->tj_status |= RES_TILE_DEV; + + /* Update device position to point to the lower-leftmost tile */ + if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) || + ((tp2->ti_ll.p_x == resDev->rd_inside.r_ll.p_x) && + (tp2->ti_ll.p_y < resDev->rd_inside.r_ll.p_y))) + { + resDev->rd_inside.r_ll.p_x = LEFT(tp2); + resDev->rd_inside.r_ll.p_y = BOTTOM(tp2); + resDev->rd_inside.r_ur.p_x = RIGHT(tp2); + resDev->rd_inside.r_ur.p_y = TOP(tp2); + } } else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetRightType(tp2)) diff --git a/resis/resis.h b/resis/resis.h index aabee014..1d614977 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -471,10 +471,12 @@ typedef struct capval #define RES_TILE_DONE 0x08 /*a temporary marking flag */ #define RES_TILE_MARK 0x10 +/*another temporary marking flag */ +#define RES_TILE_PUSHED 0x20 /* indicates that tile has unidirectional current flow */ #ifdef LAPLACE -#define RES_TILE_1D 0x20 -#define RES_TILE_GDONE 0x40 +#define RES_TILE_1D 0x40 +#define RES_TILE_GDONE 0x80 #endif /* tree walking flags */ #define RES_LOOP_OK 1