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.
This commit is contained in:
parent
9184ccd395
commit
0a67151292
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue