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.
This commit is contained in:
Tim Edwards 2024-02-18 14:04:21 -05:00
parent 038f02d2b2
commit 814fb6f18d
4 changed files with 246 additions and 12 deletions

View File

@ -1 +1 @@
8.3.460
8.3.461

View File

@ -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);
}
}
}
}
}
}
}

View File

@ -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))

View File

@ -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