From 0a671512923a9caf6802e813ac2b4308930331a0 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 6 Dec 2024 16:42:43 -0500 Subject: [PATCH] Extended the device parameters to allow a terminal width that is different from the device (i.e., gate) width, for devices that do not define a MOS-like gate spanning the width of the device. This is restricted to the assumption that the terminal is rectangular and therefore a simple width and length can be derived from the area and perimeter. Also, length is defined as the smaller dimension and width as the larger dimension. For additional restrictions, see the updated documentation. This was added to allow correct width and length extraction of a bipolar emitter window, but may be more generally useful. --- VERSION | 2 +- ext2spice/ext2hier.c | 47 ++++++++++++++++++++++++++++++++++++------- ext2spice/ext2spice.c | 47 ++++++++++++++++++++++++++++++++++++------- extract/ExtBasic.c | 39 +++++++++++++++++++++++++++++------ 4 files changed, 114 insertions(+), 21 deletions(-) diff --git a/VERSION b/VERSION index 5d8128a3..b30ad93f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.503 +8.3.504 diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 42d6786d..1bf292f0 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -300,15 +300,48 @@ spcHierWriteParams(hc, dev, scale, l, w, sdM) break; case 'w': - fprintf(esSpiceF, " %s=", plist->parm_name); - if (esScale < 0) - fprintf(esSpiceF, "%g", w * scale); - else if (plist->parm_scale != 1.0) - fprintf(esSpiceF, "%g", (double)w * scale * esScale + // Check for device width vs. terminal width + if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0') + { + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", w * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", (double)w * scale * esScale * plist->parm_scale * 1E-6); - else - esSIvalue(esSpiceF, 1.0E-6 * (w + plist->parm_offset) + else + esSIvalue(esSpiceF, 1.0E-6 * (w + plist->parm_offset) * scale * esScale); + } + else + { + /* w1, w2, etc. used to indicate the width of the terminal */ + /* Find value in dev_params */ + for (dparam = dev->dev_params; dparam; dparam = dparam->parm_next) + { + if ((strlen(dparam->parm_name) > 2) && + (dparam->parm_name[0] == 'w') && + (dparam->parm_name[1] == plist->parm_type[1]) && + (dparam->parm_name[2] == '=')) + { + int dval; + if (sscanf(&dparam->parm_name[3], "%d", &dval) == 1) + { + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", dval * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", (double)dval * scale * esScale + * plist->parm_scale * 1E-6); + else + esSIvalue(esSpiceF, (dval + plist->parm_offset) + * scale * esScale * 1.0E-6); + dparam->parm_name[0] = '\0'; + break; + } + } + } + } break; case 's': fprintf(esSpiceF, " %s=", plist->parm_name); diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 06d06900..5a53690e 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -2181,15 +2181,48 @@ spcWriteParams(dev, hierName, scale, l, w, sdM) break; case 'w': - fprintf(esSpiceF, " %s=", plist->parm_name); - if (esScale < 0) - fprintf(esSpiceF, "%g", w * scale); - else if (plist->parm_scale != 1.0) - fprintf(esSpiceF, "%g", (double)w * scale * esScale + // Check for width of device vs. width of terminal + if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0') + { + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", w * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", (double)w * scale * esScale * plist->parm_scale * 1E-6); - else - esSIvalue(esSpiceF, 1.0E-6 * (w + plist->parm_offset) + else + esSIvalue(esSpiceF, 1.0E-6 * (w + plist->parm_offset) * scale * esScale); + } + else + { + /* w1, w2, etc. used to indicate the width of the terminal */ + /* Find the value in dev_params */ + for (dparam = dev->dev_params; dparam; dparam = dparam->parm_next) + { + if ((strlen(dparam->parm_name) > 2) && + (dparam->parm_name[0] == 'w') && + (dparam->parm_name[1] == plist->parm_type[1]) && + (dparam->parm_name[2] == '=')) + { + int dval; + if (sscanf(&dparam->parm_name[3], "%d", &dval) == 1) + { + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", dval * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", (double)dval * scale * esScale + * plist->parm_scale * 1E-6); + else + esSIvalue(esSpiceF, (dval + plist->parm_offset) + * scale * esScale * 1.0E-6); + dparam->parm_name[0] = '\0'; + break; + } + } + } + } break; case 's': fprintf(esSpiceF, " %s=", plist->parm_name); diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 76777e80..150563cb 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -1768,13 +1768,14 @@ extOutputParameters(def, transList, outFile) */ void -extOutputDevParams(reg, devptr, outFile, length, width, areavec) +extOutputDevParams(reg, devptr, outFile, length, width, areavec, perimvec) TransRegion *reg; ExtDevice *devptr; FILE *outFile; int length; int width; int *areavec; + int *perimvec; { ParamList *chkParam; @@ -1815,8 +1816,34 @@ extOutputDevParams(reg, devptr, outFile, length, width, areavec) } break; case 'w': - fprintf(outFile, " %c=%d", chkParam->pl_param[0], + if (chkParam->pl_param[1] == '\0' || + chkParam->pl_param[1] == '0') + fprintf(outFile, " %c=%d", chkParam->pl_param[0], width); + else if (chkParam->pl_param[1] > '0' && chkParam->pl_param[1] <= '9') + { + int tidx = chkParam->pl_param[1] - '1'; + /* NOTE: For a MOSFET, the gate width is the terminal + * width, and only "w" should be used as a parameter. + * For other devices, "w" with an index indicates that + * the device width is *not* the gate width. Since only + * the device area is maintained, then in this case the + * terminal must be a single rectangle, from which the + * length and width are extracted as the length of the + * short and long sides, respectively. This changes the + * value "width"; therefore, "w" with a suffix should + * come before "l" with a suffix in the device line in + * the tech file, since the "l" value will be derived + * from the area and width. + */ + double newwidth = (double)(perimvec[tidx] * perimvec[tidx]); + newwidth -= (double)(16 * areavec[tidx]); + newwidth = sqrt(newwidth); + newwidth += perimvec[tidx]; + width = (int)(0.25 * newwidth); + fprintf(outFile, " %c%c=%d", chkParam->pl_param[0], + chkParam->pl_param[1], width); + } break; case 'c': fprintf(outFile, " %c=%g", chkParam->pl_param[0], @@ -2546,7 +2573,7 @@ extOutputDevices(def, transList, outFile) } extOutputDevParams(reg, devptr, outFile, length, width, - extTransRec.tr_termarea); + extTransRec.tr_termarea, extTransRec.tr_termperim); fprintf(outFile, " \"%s\"", (subsName == NULL) ? "None" : subsName); @@ -2565,7 +2592,7 @@ extOutputDevices(def, transList, outFile) reg->treg_ll.p_x + 1, reg->treg_ll.p_y + 1); extOutputDevParams(reg, devptr, outFile, length, width, - extTransRec.tr_termarea); + extTransRec.tr_termarea, extTransRec.tr_termperim); if (subsName != NULL) fprintf(outFile, " \"%s\"", subsName); break; @@ -2712,7 +2739,7 @@ extOutputDevices(def, transList, outFile) fprintf(outFile, " %g", dres / 1000.0); /* mOhms -> Ohms */ extOutputDevParams(reg, devptr, outFile, length, width, - extTransRec.tr_termarea); + extTransRec.tr_termarea, extTransRec.tr_termperim); if (devptr->exts_deviceClass == DEV_RSUBCKT) { @@ -2811,7 +2838,7 @@ extOutputDevices(def, transList, outFile) } extOutputDevParams(reg, devptr, outFile, length, width, - extTransRec.tr_termarea); + extTransRec.tr_termarea, extTransRec.tr_termperim); if (devptr->exts_deviceClass == DEV_CSUBCKT) {