From 63829cbbaa6857133b5ad61a80537ae60e40ef91 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sat, 24 Aug 2019 14:18:03 -0400 Subject: [PATCH] Hopefully final correction to new extraction method. Now correctly handles diodes or other devices with source/drain on planes other than the plane of the device type. This no longer requires that the non-connecting type be in any given terminal position. The device type boundary is surveyed for all types, connecting or overlapping, and at least one of each required type must be present. --- extract/ExtBasic.c | 192 ++++++++++++++++++++++++++------------------- 1 file changed, 113 insertions(+), 79 deletions(-) diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 7787a09c..bfd25db0 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -142,6 +142,8 @@ void extOutputParameters(); void extTransOutTerminal(); void extTransBad(); +ExtDevice *extDevFindMatch(); + bool extLabType(); /* Function returns 1 if a tile is found by DBTreeSrTiles() */ @@ -1600,12 +1602,12 @@ extOutputDevices(def, transList, outFile) { NodeRegion *node, *subsNode; TransRegion *reg; - ExtDevice *devptr; + ExtDevice *devptr, *deventry; char *subsName; FindRegion arg; LabelList *ll; TileType t; - int nsd, length, width, n, i, ntiles, corners, tn, rc; + int nsd, length, width, n, i, ntiles, corners, tn, rc, termcount; double dres, dcap; char mesg[256]; bool isAnnular, hasModel; @@ -1675,28 +1677,61 @@ extOutputDevices(def, transList, outFile) devptr = extTransRec.tr_devrec; if (devptr == NULL) continue; /* Bad device; do not output */ + deventry = devptr; - nsd = devptr->exts_deviceSDCount; - while (extTransRec.tr_nterm < nsd) + /* Use devmatch flags to determine if the specific S/D */ + /* terminal was handled by extTransPerimFunc already. */ + /* Only look at required S/D terminals that have not */ + /* yet been found. */ + + while (TRUE) { - TileTypeBitMask *tmask; - - tmask = &devptr->exts_deviceSDTypes[extTransRec.tr_nterm]; - if (TTMaskIsZero(tmask)) break; - if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum])) + nsd = devptr->exts_deviceSDCount; + for (termcount = 0; termcount < nsd; termcount++) { - node = NULL; - extTransFindSubs(reg->treg_tile, t, tmask, def, &node, NULL); - if (node == NULL) break; - extTransRec.tr_termnode[extTransRec.tr_nterm++] = node; + TileTypeBitMask *tmask; + + if ((extTransRec.tr_devmatch & (MATCH_TERM << termcount)) != 0) + continue; /* This terminal already found by perimeter search */ + + tmask = &devptr->exts_deviceSDTypes[termcount]; + if (TTMaskIsZero(tmask)) break; /* End of SD terminals */ + else if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum])) + { + node = NULL; + extTransFindSubs(reg->treg_tile, t, tmask, def, &node, NULL); + if (node == NULL) { + /* See if there is another matching device record */ + /* with a different terminal type, and try again. */ + devptr = extDevFindMatch(devptr, t); + break; + } + extTransRec.tr_devmatch |= (MATCH_TERM << termcount); + extTransRec.tr_termnode[termcount++] = node; + } + else if (TTMaskHasType(tmask, TT_SPACE)) { + /* Device node is specified as being the substrate */ + if (glob_subsnode == NULL) { + /* See if there is another matching device record */ + /* with a different terminal type, and try again. */ + devptr = extDevFindMatch(devptr, t); + break; + } + extTransRec.tr_devmatch |= (MATCH_TERM << termcount); + extTransRec.tr_termnode[termcount] = glob_subsnode; + } + else { + /* Determine if there is another matching device record */ + /* that has fewer required terminals. */ + devptr = extDevFindMatch(devptr, t); + break; + } } - else if (TTMaskHasType(tmask, TT_SPACE)) { - /* Device node is specified as being the substrate */ - if (glob_subsnode == NULL) break; - extTransRec.tr_termnode[extTransRec.tr_nterm++] = glob_subsnode; - } - else break; + if (termcount == nsd) break; /* All terminals accounted for */ + if (devptr == deventry) break; /* No other device records available */ + /* Try again with a different device record */ } + extTransRec.tr_nterm = termcount; /* * For types that require a minimum number of terminals, @@ -1849,8 +1884,8 @@ extOutputDevices(def, transList, outFile) { /* Don't issue a warning on devices such as a */ /* vertical diode that may declare zero terminals */ - /* because the substrate node (i.e., well) is the */ - /* other terminal. */ + /* because the default substrate node is the other */ + /* terminal. */ if (ExtDoWarn && (devptr->exts_deviceSDCount > 0)) extTransBad(def, reg->treg_tile, @@ -2435,63 +2470,66 @@ extTransTileFunc(tile, pNum, arg) devtest = devtest->exts_next) TTMaskSetMask(&cmask, &devtest->exts_deviceSubstrateTypes); - if (TTMaskHasType(&cmask, TT_SPACE)) + if (!TTMaskIsZero(&cmask)) { - allow_globsubsnode = TRUE; - TTMaskClearType(&cmask, TT_SPACE); - } - - if (extTransRec.tr_subsnode == (NodeRegion *)NULL) - { - sublayer = TT_SPACE; - region = NULL; - extTransFindSubs(tile, loctype, &cmask, arg->fra_def, ®ion, &sublayer); - - /* If the device does not connect to a defined node, and - * the substrate types include "space", then it is assumed to - * connect to the global substrate. - */ - - if (region == (NodeRegion *)NULL) - if (allow_globsubsnode) - region = glob_subsnode; - - extTransRec.tr_subsnode = region; - - if ((region != (NodeRegion *)NULL) && - !(TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer))) + if (TTMaskHasType(&cmask, TT_SPACE)) { - /* A substrate layer was found but is not compatible with the */ - /* current device. Find a device record with the substrate */ - /* layer that was found, and set the substrate match flag. */ + allow_globsubsnode = TRUE; + TTMaskClearType(&cmask, TT_SPACE); + } - deventry = devptr; - while (devptr != NULL) + if (extTransRec.tr_subsnode == (NodeRegion *)NULL) + { + sublayer = TT_SPACE; + region = NULL; + extTransFindSubs(tile, loctype, &cmask, arg->fra_def, ®ion, &sublayer); + + /* If the device does not connect to a defined node, and + * the substrate types include "space", then it is assumed to + * connect to the global substrate. + */ + + if (region == (NodeRegion *)NULL) + if (allow_globsubsnode) + region = glob_subsnode; + + extTransRec.tr_subsnode = region; + + if ((region != (NodeRegion *)NULL) && + !(TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer))) { - devptr = extDevFindMatch(devptr, loctype); - if ((devptr == NULL) || (devptr == deventry)) + /* A substrate layer was found but is not compatible with the */ + /* current device. Find a device record with the substrate */ + /* layer that was found, and set the substrate match flag. */ + + deventry = devptr; + while (devptr != NULL) { - TxError("No matching device for %s with substrate layer %s\n", + devptr = extDevFindMatch(devptr, loctype); + if ((devptr == NULL) || (devptr == deventry)) + { + TxError("No matching device for %s with substrate layer %s\n", DBTypeLongNameTbl[loctype], DBTypeLongNameTbl[sublayer]); - devptr = NULL; - break; - } - if (TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer)) - { - extTransRec.tr_devmatch |= MATCH_SUB; - break; + devptr = NULL; + break; + } + if (TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer)) + { + extTransRec.tr_devmatch |= MATCH_SUB; + break; + } } } + else if (region == (NodeRegion *)NULL) + { + TxError("Device %s does not have a compatible substrate node!\n", + DBTypeLongNameTbl[loctype]); + devptr = NULL; + } } - else if (region == (NodeRegion *)NULL) - { - TxError("Device %s does not have a compatible substrate node!\n", - DBTypeLongNameTbl[loctype]); - devptr = NULL; - } + extTransRec.tr_devrec = devptr; + if (devptr == NULL) return 0; /* No matching devices, so forget it. */ } - extTransRec.tr_devrec = devptr; - if (devptr == NULL) return 0; /* No matching devices, so forget it. */ /* If at least one device type declares an ID layer, then make a */ /* mask of all device ID types, and search on the area of the */ @@ -2889,27 +2927,23 @@ extSpecialPerimFunc(bp, sense) break; } - devptr = extTransRec.tr_devrec; - if (devptr == NULL) devptr = ExtCurStyle->exts_device[tinside]; + /* Required to use the same device record that was used to find */ + /* the terminals. */ + if ((devptr = extTransRec.tr_devrec) == NULL) return 0; /* Check all terminal classes for a matching type */ needSurvey = FALSE; - for (; devptr; devptr = devptr->exts_next) + for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++) { - for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++) + if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], toutside)) { - if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], toutside)) - { - needSurvey = TRUE; - break; - } + needSurvey = TRUE; + break; } } if (!sense || needSurvey) { - extTransRec.tr_devrec = devptr; - if (toutside == TT_SPACE) if (glob_subsnode != NULL) diffNode = glob_subsnode;