From b0719384e48cd76a240c90808d08b4eb753ba9aa Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 14 Oct 2019 11:09:58 -0400 Subject: [PATCH 1/5] Modified the new extraction method with multiple records for each device type so that it is now properly backwards compatible with the old-style "fet" records. Also corrected the record matching such that it properly matches according to the number of terminals while allowing the traditional interpretation that there may be fewer S/D type records than terminals if the S/D types are the same for all terminals. --- ext2spice/ext2spice.c | 2 +- extract/ExtBasic.c | 52 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 6947027a..46853437 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1248,7 +1248,7 @@ spcmainArgs(pargc, pargv) usage: TxError("Usage: ext2spice [-B] [-o spicefile] [-M|-m] [-y cap_digits] " "[-J flat|hier]\n" - "[-f spice2|spice3|hspice] [-M] [-m] " + "[-f spice2|spice3|hspice|ngspice] [-M] [-m] " #ifdef MAGIC_WRAPPER "[file]\n" #else diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 38d76441..e0503d20 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -2337,7 +2337,7 @@ extDevFindMatch(deventry, t) TileType t; { ExtDevice *devptr; - int i, j, matchflags; + int i, j, k, matchflags; bool match; matchflags = extTransRec.tr_devmatch; @@ -2362,10 +2362,11 @@ extDevFindMatch(deventry, t) &deventry->exts_deviceSubstrateTypes)) continue; j = MATCH_TERM; + i = 0; match = True; - for (i = 0; i < MAXSD; i++) + for (k = 0; k < devptr->exts_deviceSDCount; k++) { - if (extTransRec.tr_termnode[i] == NULL) break; + if (extTransRec.tr_termnode[k] == NULL) break; if (matchflags & j) /* Must have the same terminal type */ { if (TTMaskIsZero(&devptr->exts_deviceSDTypes[i])) @@ -2380,7 +2381,13 @@ extDevFindMatch(deventry, t) break; } } - j >>= 1; + j <<= 1; + + /* NOTE: There are fewer exts_deviceSDTypes records than */ + /* terminals if all S/D terminals are the same type. In */ + /* that case k increments and j bit shifts but i remains */ + /* the same. */ + if (!TTMaskIsZero(&devptr->exts_deviceSDTypes[i + 1])) i++; } if (match) break; } @@ -2522,9 +2529,19 @@ extTransTileFunc(tile, pNum, arg) } else if (region == (NodeRegion *)NULL) { - TxError("Device %s does not have a compatible substrate node!\n", - DBTypeLongNameTbl[loctype]); - devptr = NULL; + /* If ExtCurStyle->exts_globSubstrateTypes contains no types */ + /* then this is an older style techfile without a "substrate" */ + /* definition in the extract section. In that case, it is */ + /* expected that the substrate name in the device line will be */ + /* used. */ + + if (!TTMaskIsZero(&ExtCurStyle->exts_globSubstrateTypes) || + (devptr->exts_deviceSubstrateName == NULL)) + { + TxError("Device %s does not have a compatible substrate node!\n", + DBTypeLongNameTbl[loctype]); + devptr = NULL; + } } } extTransRec.tr_devrec = devptr; @@ -2737,8 +2754,27 @@ extTransPerimFunc(bp) ll->ll_attr = thisterm; } } - SDterm = TRUE; + + /* Check if number of terminals exceeds the number allowed in */ + /* this device record. If so, check if there is another device */ + /* record with a different number of terminals. */ + extTransRec.tr_devmatch |= (MATCH_TERM << thisterm); + if (thisterm >= devptr->exts_deviceSDCount) + { + devptr = extDevFindMatch(devptr, tinside); + + /* Should this be an error instead of a warning? */ + /* Traditionally more terminals than defined was allowed */ + /* but not necessarily handled correctly by ext2spice. */ + + if (devptr == deventry) + TxError("Warning: Device has more terminals than defined " + "for type!\n"); + else + extTransRec.tr_devrec = devptr; + } + SDterm = TRUE; break; } } From 1933c5d4a5a747b79eb20e10982dd03b4e7d2edc Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 14 Oct 2019 11:56:39 -0400 Subject: [PATCH 2/5] Corrected another problem where the device source/drain area and perimeter were not output because of recent code that broke the routine that assigns the resistance classes to devices. This is now fixed. Thanks to Dan Moore for bringing this to my attention, and debugging investigations. --- extract/ExtTech.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 314bed99..d2b3ebbf 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -298,12 +298,12 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) TileType t; TileTypeBitMask *rmask, *tmask; int n, i = 0, j; - bool repeat; + bool repeat, found; ExtDevice *devptr; char *locdname; char **uniquenamelist = (char **)mallocMagic(DBNumTypes * sizeof(char *)); - + found = FALSE; for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) { for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) @@ -320,12 +320,17 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) } if (repeat == FALSE) { - if (i == idx) break; + if (i == idx) + { + found = TRUE; + break; + } uniquenamelist[i] = locdname; i++; } } } + if (found == TRUE) break; } if (t == DBNumTypes) return FALSE; if (devptr == NULL) return FALSE; From 58c4c8a32e8685262617ceb010bb5b184b3b6b6e Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 14 Oct 2019 13:49:41 -0400 Subject: [PATCH 3/5] Corrected problem in which using "ext2spice -d" (distributed junctions) causes magic to crash. --- ext2spice/ext2spice.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 46853437..a5bc4817 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -2714,7 +2714,9 @@ FILE *outf; if ((nodeClient *)nn->efnn_node->efnode_client == (ClientData)NULL) initNodeClientHier(nn->efnn_node); - ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + if (!esDistrJunct) + ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= + DEV_CONNECT_MASK; return nn->efnn_node; } } @@ -2919,8 +2921,11 @@ spcdevOutNode(prefix, suffix, name, outf) nn = (EFNodeName *) HashGetValue(he); nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier); fprintf(outf, " %s", nname); + /* Mark node as visited */ - ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + if (!esDistrJunct) + ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + return (1 + strlen(nname)); } From 57a5ff60944704aa70dca67c0b69d23f662ad61a Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 14 Oct 2019 17:17:08 -0400 Subject: [PATCH 4/5] Corrected errors preventing extresist from working properly with hierarchical cells (namely a scaling issue with .sim file units). More can be done to make the extresist command more user friendly, but at least port connections as drivers appears to work. --- resis/Depend | 2 +- resis/ResConDCS.c | 4 ++-- resis/ResMain.c | 4 ++-- resis/ResMakeRes.c | 11 +++++++---- resis/ResReadSim.c | 8 ++++++-- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/resis/Depend b/resis/Depend index b73eacf7..f22d303f 100644 --- a/resis/Depend +++ b/resis/Depend @@ -15,7 +15,7 @@ ResMakeRes.o: ResMakeRes.c ../utils/magic.h ../utils/geometry.h \ ../database/database.h ../utils/malloc.h ../textio/textio.h \ ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ ../windows/windows.h ../dbwind/dbwind.h ../utils/tech.h \ - ../textio/txcommands.h ../resis/resis.h + ../textio/txcommands.h ../resis/resis.h ../cif/CIFint.h ResSimple.o: ResSimple.c ../utils/magic.h ../utils/geometry.h \ ../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \ ../database/database.h ../utils/malloc.h ../textio/textio.h \ diff --git a/resis/ResConDCS.c b/resis/ResConDCS.c index 69adc06a..da5cb7fe 100644 --- a/resis/ResConDCS.c +++ b/resis/ResConDCS.c @@ -450,8 +450,8 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) { devptr = ExtCurStyle->exts_device[tran]; - tran_name = devptr->exts_deviceName; - if ((tran_name != NULL) && (strcmp(tran_name, "None"))) + if ((devptr != NULL) && ((tran_name = devptr->exts_deviceName) != NULL) + && (strcmp(tran_name, "None"))) { TTMaskSetMask(&DiffTypeBitMask, &(devptr->exts_deviceSDTypes[0])); diff --git a/resis/ResMain.c b/resis/ResMain.c index 33657767..767c599e 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -72,8 +72,8 @@ ResInitializeConn() for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) { devptr = ExtCurStyle->exts_device[tran]; - tran_name = devptr->exts_deviceName; - if ((tran_name != NULL) && (strcmp(tran_name, "None"))) + if ((devptr != NULL) && ((tran_name = devptr->exts_deviceName) != NULL) + && (strcmp(tran_name, "None"))) { for (diff = TT_TECHDEPBASE; diff < TT_MAXTYPES; diff++) { diff --git a/resis/ResMakeRes.c b/resis/ResMakeRes.c index 1ff30a22..5d874d1d 100644 --- a/resis/ResMakeRes.c +++ b/resis/ResMakeRes.c @@ -24,6 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "utils/tech.h" #include "textio/txcommands.h" #include "resis/resis.h" +#include "cif/CIFint.h" /* Forward declarations */ bool ResCalcNearTransistor(); @@ -783,13 +784,14 @@ ResDoContacts(contact, nodes, resList) resNode *resptr; cElement *ccell; int tilenum, squaresx, squaresy, viawidth; - int minside, spacing, border; + int minside, spacing, border, cscale; float squaresf; resResistor *resistor; resElement *element; static int too_small = 1; minside = CIFGetContactSize(contact->cp_type, &viawidth, &spacing, &border); + cscale = CIFCurStyle->cs_scaleFactor; if ((ExtCurStyle->exts_viaResist[contact->cp_type] == 0) || (viawidth == 0)) { @@ -818,7 +820,8 @@ ResDoContacts(contact, nodes, resList) } else { - if ((contact->cp_width < minside) || (contact->cp_height < minside)) + if (((contact->cp_width * cscale) < minside) || + ((contact->cp_height * cscale) < minside)) { if (too_small) { @@ -832,13 +835,13 @@ ResDoContacts(contact, nodes, resList) else { viawidth += spacing; - squaresf = (float)(contact->cp_width - minside) / (float)viawidth; + squaresf = (float)((contact->cp_width * cscale) - minside) / (float)viawidth; squaresf *= ExtCurStyle->exts_unitsPerLambda; squaresf /= (float)viawidth; squaresx = (int)squaresf; squaresx++; - squaresf = (float)(contact->cp_height - minside) / (float)viawidth; + squaresf = (float)((contact->cp_height * cscale) - minside) / (float)viawidth; squaresf *= ExtCurStyle->exts_unitsPerLambda; squaresf /= (float)viawidth; squaresy = (int)squaresf; diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index 6cb38633..cc47fb4b 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -146,8 +146,12 @@ ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc) case '|': if (strcmp(line[NODEUNITS],"units:") == 0) { - lambda = (float)atof(line[NODELAMBDA]); - if (lambda == 0.0) lambda = 1.0; + lambda = (float)atof(line[NODELAMBDA]); + if (lambda == 0.0) lambda = 1.0; + /* NOTE: units is derived from EFScale */ + /* which needs a factor of 100 conversion */ + /* to database units. */ + lambda *= 100.0; } result=0; break; From e9f3dcadefb2f938b8f45ccd3ef362fb2546afb1 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 14 Oct 2019 21:46:07 -0400 Subject: [PATCH 5/5] Added substitution for commas in SPICE output, because commas in instance names and node names are basically fatal to running ngspice. --- ext2spice/ext2spice.c | 35 +++++++++++++++++++++++++++-------- extflat/EFargs.c | 4 +++- extflat/EFvisit.c | 14 ++++++++++---- extflat/extflat.h | 5 +++-- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index a5bc4817..43ebabbe 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -140,9 +140,16 @@ esFormatSubs(outf, suf) if ((EFTrimFlags & EF_TRIMGLOB ) && suf[l] == '!' || (EFTrimFlags & EF_TRIMLOCAL) && suf[l] == '#') suf[l] = '\0' ; - if (EFTrimFlags & EF_CONVERTCOMMAS) + if (EFTrimFlags & EF_CONVERTCOMMA) while ((specchar = strchr(suf, ',')) != NULL) - *specchar = ';'; + *specchar = '|'; + if (EFTrimFlags & EF_CONVERTBRACKETS) + { + while ((specchar = strchr(suf, '[')) != NULL) + *specchar = '_'; + while ((specchar = strchr(suf, ']')) != NULL) + *specchar = '_'; + } if (EFTrimFlags & EF_CONVERTEQUAL) while ((specchar = strchr(suf, '=')) != NULL) *specchar = ':'; @@ -607,7 +614,7 @@ CmdExtToSpice(w, cmd) case EXTTOSPC_DEFAULT: LocCapThreshold = 2; LocResistThreshold = INFINITE_THRESHOLD; - EFTrimFlags = EF_CONVERTCOMMAS | EF_CONVERTEQUAL; + EFTrimFlags = EF_CONVERTCOMMA | EF_CONVERTEQUAL; EFScale = 0.0; if (EFArgTech) { @@ -821,7 +828,7 @@ runexttospice: // This forces options TRIMGLOB and CONVERTEQUAL, not sure that's such a // good idea. . . - EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL; + EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL | EF_CONVERTCOMMA; if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS; if (esFormat == HSPICE) EFTrimFlags |= EF_TRIMLOCAL; @@ -1379,7 +1386,7 @@ subcktVisit(use, hierName, is_top) else { int savflags = EFTrimFlags; - EFTrimFlags = 0; // Do no substitutions on subcircuit names + EFTrimFlags = EF_CONVERTCOMMA; // Only substitute commas on subcircuit names /* Use full hierarchical decomposition for name */ /* (not just use->use_id. hierName already has use->use_id at end) */ @@ -3220,7 +3227,7 @@ EFHNSprintf(str, hierName) char *str; HierName *hierName; { - bool trimGlob, trimLocal, convertComma, convertEqual; + bool trimGlob, trimLocal, convertComma, convertEqual, convertBrackets; char *s, *cp, c; char *efHNSprintfPrefix(HierName *, char *); @@ -3231,8 +3238,9 @@ EFHNSprintf(str, hierName) cp = hierName->hn_name; trimGlob = (EFTrimFlags & EF_TRIMGLOB); trimLocal = (EFTrimFlags & EF_TRIMLOCAL); - convertComma = (EFTrimFlags & EF_CONVERTCOMMAS); + convertComma = (EFTrimFlags & EF_CONVERTCOMMA); convertEqual = (EFTrimFlags & EF_CONVERTEQUAL); + convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS); while (c = *cp++) { switch (c) @@ -3240,7 +3248,9 @@ EFHNSprintf(str, hierName) case '!': if (!trimGlob) *str++ = c; break; case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break; case '=': if (convertEqual) *str++ = ':'; break; - case ',': if (convertComma) *str++ = ';'; break; + case ',': if (convertComma) *str++ = '|'; break; + case '[': *str++ = (convertBrackets) ? '_' : '['; break; + case ']': *str++ = (convertBrackets) ? '_' : ']'; break; case '#': if (trimLocal) break; // else fall through default: *str++ = c; break; } @@ -3257,6 +3267,8 @@ char *efHNSprintfPrefix(hierName, str) { char *cp, c; bool convertEqual = (EFTrimFlags & EF_CONVERTEQUAL) ? TRUE : FALSE; + bool convertComma = (EFTrimFlags & EF_CONVERTCOMMA) ? TRUE : FALSE; + bool convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS) ? TRUE : FALSE; if (hierName->hn_parent) str = efHNSprintfPrefix(hierName->hn_parent, str); @@ -3265,6 +3277,13 @@ char *efHNSprintfPrefix(hierName, str) while (1) { if (convertEqual && (*cp == '=')) *str = ':'; + else if (convertBrackets && ((*cp == '[') || (*cp == ']'))) + *str = '_'; + else if (*cp == ',') + { + if (convertComma) *str = '|'; + else str--; + } else *str = *cp; if (!(*str)) break; diff --git a/extflat/EFargs.c b/extflat/EFargs.c index 40b57278..dd812dac 100644 --- a/extflat/EFargs.c +++ b/extflat/EFargs.c @@ -209,8 +209,10 @@ EFArgs(argc, argv, err_result, argsProc, cdata) goto usage; if (strchr(cp, '!')) EFTrimFlags |= EF_TRIMGLOB; if (strchr(cp, '#')) EFTrimFlags |= EF_TRIMLOCAL; - if (strchr(cp, ',')) EFTrimFlags |= EF_CONVERTCOMMAS; + if (strchr(cp, ',')) EFTrimFlags |= EF_CONVERTCOMMA; if (strchr(cp, '=')) EFTrimFlags |= EF_CONVERTEQUAL; + if (strchr(cp, '[')) EFTrimFlags |= EF_CONVERTBRACKETS; + if (strchr(cp, ']')) EFTrimFlags |= EF_CONVERTBRACKETS; break; case 'C': EFCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F; diff --git a/extflat/EFvisit.c b/extflat/EFvisit.c index aadb98ff..8d802edd 100644 --- a/extflat/EFvisit.c +++ b/extflat/EFvisit.c @@ -859,7 +859,7 @@ EFHNOut(hierName, outf) HierName *hierName; FILE *outf; { - bool trimGlob, trimLocal, trimComma; + bool trimGlob, trimLocal, convComma, convBrackets; char *cp, c; if (hierName->hn_parent) efHNOutPrefix(hierName->hn_parent, outf); @@ -868,13 +868,19 @@ EFHNOut(hierName, outf) cp = hierName->hn_name; trimGlob = (EFTrimFlags & EF_TRIMGLOB); trimLocal = (EFTrimFlags & EF_TRIMLOCAL); - trimComma = (EFTrimFlags & EF_CONVERTCOMMAS); + convComma = (EFTrimFlags & EF_CONVERTCOMMA); + convBrackets = (EFTrimFlags & EF_CONVERTBRACKETS); while (c = *cp++) { if (*cp) { - if (trimComma && (c == ',')) - putc(';', outf); + if (c == ',') + { + if (convComma) + putc('|', outf); + } + else if (convBrackets && ((c == '[') || (c == ']'))) + putc('_', outf); else putc(c, outf); } diff --git a/extflat/extflat.h b/extflat/extflat.h index 8d8f1dba..f249e37c 100644 --- a/extflat/extflat.h +++ b/extflat/extflat.h @@ -40,8 +40,9 @@ typedef unsigned char U_char; /* Flags to control output of node names. Stored in EFTrimFlags */ #define EF_TRIMGLOB 0x01 /* Delete trailing '!' from names */ #define EF_TRIMLOCAL 0x02 /* Delete trailing '#' from names */ -#define EF_CONVERTCOMMAS 0x04 /* Change ',' to ';' in names */ -#define EF_CONVERTEQUAL 0x08 /* Change '=' to ':' in names */ +#define EF_CONVERTCOMMA 0x04 /* Change ',' to '|' in names, else remove */ +#define EF_CONVERTEQUAL 0x08 /* Change '=' to ':' in names, else remove */ +#define EF_CONVERTBRACKETS 0x10 /* Change '[' and ']' to '_' in names */ /* * capacitance type now set to float