Corrected an error that had been introduced when creating the

parameter types "l1", "l2", etc., for terminal lengths.  There
was a string comparison against an unterminated character array
which was causing intermittant errors.  This problem was masking
the incorrect handling of "l1", "l2", etc., parameters.  The
parameter types had been introduced to cover a specific type of
drain-unsalicided FET in GF180MCU, which is used as an ESD
device in the foundry I/O cells, so the impact had been
relatively limited, although typically showed up as unexpected
property errors on the ESD devices when running LVS on a chip
top level.  Both discovered errors have been fixed.
This commit is contained in:
R. Timothy Edwards 2025-12-29 10:52:08 -05:00
parent 949ec7672c
commit 662e21a2d1
3 changed files with 61 additions and 13 deletions

View File

@ -1 +1 @@
8.3.585
8.3.586

View File

@ -242,9 +242,20 @@ spcHierWriteParams(
/* Write all requested parameters to the subcircuit call. */
bool checkme = FALSE;
if ((!strcmp(EFDevTypes[dev->dev_type], "pfet_06v0_dss")) ||
(!strcmp(EFDevTypes[dev->dev_type], "nfet_06v0_dss")))
{
checkme = TRUE;
TxPrintf("Diagnostic: Parameter list for %s\n", EFDevTypes[dev->dev_type]);
}
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
while (plist != NULL)
{
if (checkme) TxPrintf("Plist entry %s %s\n", plist->parm_name, plist->parm_type);
switch (plist->parm_type[0])
{
case 'a':
@ -345,6 +356,7 @@ spcHierWriteParams(
// Check for device length vs. terminal length
if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0')
{
if (checkme) TxPrintf("Handling entry l or l0\n");
fprintf(esSpiceF, " %s=", plist->parm_name);
if (esScale < 0)
fprintf(esSpiceF, "%g", l * scale);
@ -359,8 +371,10 @@ spcHierWriteParams(
{
/* l1, l2, etc. used to indicate the length of the terminal */
/* Find value in dev_params */
if (checkme) TxPrintf("Handling entry l1 or l2\n");
for (dparam = dev->dev_params; dparam; dparam = dparam->parm_next)
{
if (checkme) TxPrintf("Checking dev_params entry %s\n", dparam->parm_name);
if ((strlen(dparam->parm_name) > 2) &&
(dparam->parm_name[0] == 'l') &&
(dparam->parm_name[1] == plist->parm_type[1]) &&
@ -369,6 +383,8 @@ spcHierWriteParams(
int dval;
if (sscanf(&dparam->parm_name[3], "%d", &dval) == 1)
{
if (checkme) TxPrintf("Handling dev_params entry %s (to be "
"culled at end)\n", dparam->parm_name);
fprintf(esSpiceF, " %s=", plist->parm_name);
if (esScale < 0)
fprintf(esSpiceF, "%g", dval * scale);
@ -378,6 +394,7 @@ spcHierWriteParams(
else
esSIvalue(esSpiceF, (dval + plist->parm_offset)
* scale * esScale * 1.0E-6);
/* Why is this here? */
dparam->parm_name[0] = '\0';
break;
}

View File

@ -926,20 +926,22 @@ efBuildDevice(
/* Parse initial arguments for parameters */
while ((pptr = strchr(argv[argstart], '=')) != NULL)
{
// Check if this parameter is in the table.
// If so, handle appropriately. Otherwise, the
// parameter gets saved verbatim locally. The
// "parameters" line comes before any "device" line
// in the .ext file, so the table should be complete.
/* If the parameter is in the parameter list "devp", then save
* the value as appropriate. If not, then the entire phrase
* will be output verbatim, so just save the whole string.
*
* The "parameters" line comes before any "device" line in the
* .ext file, so the "devp" list should be complete.
*/
*pptr = '\0';
for (sparm = devp; sparm; sparm = sparm->parm_next)
if (!strcasecmp(sparm->parm_type, argv[argstart]))
if (!strncasecmp(sparm->parm_type, argv[argstart], 2))
break;
*pptr = '=';
if (sparm == NULL)
{
/* Copy the parameter into dev_params */
/* Copy the whole string into dev_params */
/* (parm_type and parm_scale records are not used) */
newparm = (DevParam *)mallocMagic(sizeof(DevParam));
newparm->parm_name = StrDup((char **)NULL, argv[argstart]);
@ -954,30 +956,59 @@ efBuildDevice(
{
case 'a':
if ((pptr - argv[argstart]) == 2)
devtmp.dev_area = atoi(pptr);
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
* locScale * locScale);
else
{
/* Check for a0, a1, a2, ... If a0, handle like "a".
* Otherwise, don't handle it here.
*/
pn = *(argv[argstart] + 1) - '0';
if (pn == 0)
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
* locScale * locScale);
/* Otherwise, punt */
}
break;
case 'p':
if ((pptr - argv[argstart]) == 2)
devtmp.dev_perim = atoi(pptr);
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
else
{
/* Check for p0, p1, p2, ... If p0, handle like "p".
* Otherwise, don't handle it here.
*/
pn = *(argv[argstart] + 1) - '0';
if (pn == 0)
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
/* Otherwise, use verbatim */
}
break;
case 'l':
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
if ((pptr - argv[argstart]) == 2)
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
else
{
/* Check for l0, l1, l2, ... If l0, handle like "l".
* Otherwise, save it verbatim like an unknown parameter,
* because its value will not be calculated from terminal
* values like "a1, a2, ..." or "p1, p2, ...".
*/
pn = *(argv[argstart] + 1) - '0';
if (pn == 0)
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
else
{
/* Copy the whole string into dev_params */
newparm = (DevParam *)mallocMagic(sizeof(DevParam));
newparm->parm_name = StrDup((char **)NULL, argv[argstart]);
newparm->parm_next = devtmp.dev_params;
devtmp.dev_params = newparm;
}
}
break;
case 'w':
devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
break;