Changed the behavior of capacitance value output in ext2spice

and ext2sim to make use of the new esSIvalue() routine, so that
it no longer depends on a preformatted string.  Corrected an
issue where the esSIvalue() routine would output "a" for "atto"
which is not supported by ngspice.
This commit is contained in:
Tim Edwards 2023-03-13 13:21:34 -04:00
parent c077e1acef
commit a3f5f4db80
4 changed files with 86 additions and 90 deletions

View File

@ -62,7 +62,6 @@ bool esNoAttrs = FALSE;
bool esHierAP = FALSE;
bool esMergeDevsA = FALSE; /* merge devices of equal length */
bool esMergeDevsC = FALSE; /* merge devices of equal length & width */
int esCapAccuracy = 1;
#else
extern bool esDevNodesOnly;
@ -70,7 +69,8 @@ extern bool esNoAttrs;
extern bool esHierAP;
extern bool esMergeDevsA;
extern bool esMergeDevsC;
extern int esCapAccuracy;
extern char esSpiceDefaultGnd[];
extern char *esSpiceCapNode;
#endif
bool esDoSimExtResis = FALSE;
@ -690,11 +690,10 @@ runexttosim:
EFVisitDevs(simdevVisit, (ClientData)NULL);
if (flatFlags & EF_FLATCAPS) {
(void) sprintf( esCapFormat, " %%.%dlf\n", esCapAccuracy);
EFVisitCaps(simcapVisit, (ClientData) NULL);
}
EFVisitResists(simresistVisit, (ClientData) NULL);
(void) sprintf( esCapFormat, " GND %%.%dlf\n", esCapAccuracy);
esSpiceCapNode = esSpiceDefaultGnd;
EFVisitNodes(simnodeVisit, (ClientData) NULL);
EFFlatDone(NULL);
@ -817,12 +816,10 @@ main(argc, argv)
}
EFVisitDevs(simdevVisit, (ClientData) NULL);
if (flatFlags & EF_FLATCAPS) {
(void) sprintf( esCapFormat, " %%.%dlf\n", esCapAccuracy);
if (flatFlags & EF_FLATCAPS)
EFVisitCaps(simcapVisit, (ClientData) NULL);
}
EFVisitResists(simresistVisit, (ClientData) NULL);
(void) sprintf( esCapFormat, " GND %%.%dlf\n", esCapAccuracy);
esSpiceCapNode = esSpiceDefaultGnd;
EFVisitNodes(simnodeVisit, (ClientData) NULL);
EFFlatDone(NULL);
@ -922,7 +919,7 @@ simParseArgs(pargc, pargv)
if (( t = ArgStr(&argc, &argv, "cap-accuracy") ) == NULL)
goto usage;
esCapAccuracy = atoi(t);
TxPrintf("Cap accuracy option -y is deprecated.\n");
break;
}
case 'J':
@ -1535,7 +1532,7 @@ int simcapVisit(hierName1, hierName2, cap)
EFHNOut(hierName1, esSimF);
fprintf(esSimF, " ");
EFHNOut(hierName2, esSimF);
fprintf(esSimF, esCapFormat, cap);
fprintf(esSimF, " %.1lf\n", cap);
return 0;
}
@ -1618,7 +1615,8 @@ int simnodeVisit(node, res, cap)
{
fprintf(esSimF, "C ");
EFHNOut(hierName, esSimF);
fprintf(esSimF, esCapFormat, cap);
fprintf(esSimF, "%s ", esSpiceCapNode);
fprintf(esSimF, "%.1f\n", cap);
}
if (res > EFResistThreshold)
{

View File

@ -902,7 +902,7 @@ spcdevHierVisit(hc, dev, scale)
/* Capacitor is "Cnnn top bottom value" */
/* extraction sets top=gate bottom=source */
/* extracted units are fF; output is in fF */
/* extracted units are fF. */
spcdevOutNode(hc->hc_hierName,
gate->dterm_node->efnode_name->efnn_hier,
@ -920,8 +920,7 @@ spcdevHierVisit(hc, dev, scale)
if (!has_model)
{
fprintf(esSpiceF, " %ffF", (double)sdM *
(double)(dev->dev_cap));
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcHierWriteParams(hc, dev, scale, l, w, sdM);
}
else
@ -950,7 +949,7 @@ spcdevHierVisit(hc, dev, scale)
/* Capacitor is "Cnnn bottom top value" */
/* extraction sets top=source bottom=gate */
/* extracted units are fF; output is in fF */
/* extracted units are fF. */
spcdevOutNode(hc->hc_hierName,
gate->dterm_node->efnode_name->efnn_hier,
@ -968,8 +967,7 @@ spcdevHierVisit(hc, dev, scale)
if (!has_model)
{
fprintf(esSpiceF, " %ffF", (double)sdM *
(double)(dev->dev_cap));
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcHierWriteParams(hc, dev, scale, l, w, sdM);
}
else
@ -1226,9 +1224,11 @@ spccapHierVisit(hc, hierName1, hierName2, cap)
if (fabs(cap) <= EFCapThreshold)
return 0;
fprintf(esSpiceF, esSpiceCapFormat, esCapNum++,
fprintf(esSpiceF, "C%d %s %s ", esCapNum++,
nodeSpiceHierName(hc, hierName1),
nodeSpiceHierName(hc, hierName2), cap);
nodeSpiceHierName(hc, hierName2));
esSIvalue(esSpiceF, 1.0E-15 *cap);
fprintf(esSpiceF, "\n");
return 0;
}
@ -1397,10 +1397,14 @@ spcnodeHierVisit(hc, node, res, cap)
cap = cap / 1000;
if (fabs(cap) > EFCapThreshold)
{
fprintf(esSpiceF, esSpiceCapFormat, esCapNum++, nsn, cap,
(isConnected) ? "" :
(esFormat == NGSPICE) ? " $ **FLOATING" :
" **FLOATING");
fprintf(esSpiceF, "C%d %s %s ", esCapNum++, nsn, esSpiceCapNode);
esSIvalue(esSpiceF, 1.0E-15 * cap);
if (!isConnected)
{
if (esFormat == NGSPICE) fprintf(esSpiceF, " $");
fprintf(esSpiceF, " **FLOATING");
}
fprintf(esSpiceF, "\n");
}
if (node->efnode_attrs && !esNoAttrs)
{
@ -2121,18 +2125,17 @@ esHierVisit(hc, cdata)
EFHierVisitResists(hcf, spcresistHierVisit, (ClientData)NULL);
/* Output coupling capacitances */
sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n", esCapAccuracy);
EFHierVisitCaps(hcf, spccapHierVisit, (ClientData)NULL);
if (EFCompat == FALSE)
{
/* Find the substrate node */
EFHierVisitNodes(hcf, spcsubHierVisit, (ClientData)&resstr);
if (resstr == NULL) resstr = StrDup((char **)NULL, "0");
if (resstr == NULL)
resstr = esSpiceDefaultGnd;
/* Output lumped capacitance and resistance to substrate */
sprintf( esSpiceCapFormat, "C%%d %%s %s %%.%dlffF%%s\n",
resstr, esCapAccuracy);
esSpiceCapNode = resstr;
EFHierVisitNodes(hcf, spcnodeHierVisit, (ClientData) NULL);
freeMagic(resstr);
}

View File

@ -56,8 +56,8 @@ bool esMergeNames = TRUE;
bool esNoAttrs = FALSE;
bool esHierAP = FALSE;
char spcesDefaultOut[FNSIZE];
int esCapAccuracy = 2;
char esSpiceCapFormat[FNSIZE];
char *esSpiceCapNode;
char esSpiceDefaultGnd[] = "0";
char *spcesOutName = spcesDefaultOut;
FILE *esSpiceF = NULL;
float esScale = -1.0 ; /* negative if hspice the EFScale/100 otherwise */
@ -1116,21 +1116,17 @@ runexttospice:
EFVisitDevs(spcdevVisit, (ClientData) NULL);
TTMaskZero(&initMask);
if (flatFlags & EF_FLATCAPS)
{
(void) sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n",
esCapAccuracy);
EFVisitCaps(spccapVisit, (ClientData) NULL);
}
EFVisitResists(spcresistVisit, (ClientData) NULL);
EFVisitSubcircuits(subcktVisit, (ClientData) NULL);
/* Visit nodes to find the substrate node */
EFVisitNodes(spcsubVisit, (ClientData)&substr);
if (substr == NULL)
substr = StrDup((char **)NULL, "0");
substr = esSpiceDefaultGnd;
(void) sprintf( esSpiceCapFormat, "C%%d %%s %s %%.%dlffF%%s",
substr, esCapAccuracy);
esSpiceCapNode = substr;
EFVisitNodes(spcnodeVisit, (ClientData) NULL);
if (EFCompat == FALSE) freeMagic(substr);
@ -1295,13 +1291,12 @@ main(argc, argv)
EFVisitDevs(devDistJunctVisit, (ClientData) NULL);
EFVisitDevs(spcdevVisit, (ClientData) NULL);
TTMaskZero(&initMask);
if (flatFlags & EF_FLATCAPS) {
(void) sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n",esCapAccuracy);
if (flatFlags & EF_FLATCAPS)
EFVisitCaps(spccapVisit, (ClientData) NULL);
}
EFVisitResists(spcresistVisit, (ClientData) NULL);
EFVisitSubcircuits(subcktVisit, (ClientData) NULL);
(void) sprintf( esSpiceCapFormat, "C%%d %%s GND %%.%dlffF%%s", esCapAccuracy);
esSpiceCapNode = esSpiceDefaultGnd;
EFVisitNodes(spcnodeVisit, (ClientData) NULL);
if ((esDoSubckt == TRUE) || (locDoSubckt == TRUE))
@ -1359,10 +1354,10 @@ spcParseArgs(pargc, pargv)
{
char **argv = *pargv, *cp;
int argc = *pargc;
char *ftmp, *t;
char usage_text[] = "Usage: ext2spice "
"[-B] [-o spicefile] [-M|-m] [-y cap_digits] "
"[-J flat|hier]\n"
"[-B] [-o spicefile] [-M|-m] [-J flat|hier]\n"
"[-f spice2|spice3|hspice|ngspice] [-M] [-m] "
"[file]\n";
@ -1371,66 +1366,66 @@ spcParseArgs(pargc, pargv)
case 'd':
esDistrJunct = TRUE;
break;
case 'M':
esMergeDevsA = TRUE;
break;
case 'm':
esMergeDevsC = TRUE;
break;
case 'B':
esNoAttrs = TRUE;
break;
case 'F':
esDevNodesOnly = TRUE;
break;
case 'o':
if ((spcesOutName = ArgStr(&argc, &argv, "filename")) == NULL)
goto usage;
break;
case 'f': {
char *ftmp ;
if ((ftmp = ArgStr(&argc, &argv, "format")) == NULL)
case 'f':
if ((ftmp = ArgStr(&argc, &argv, "format")) == NULL)
goto usage;
if (strcasecmp(ftmp, "SPICE2") == 0)
if (strcasecmp(ftmp, "SPICE2") == 0)
esFormat = SPICE2;
else if (strcasecmp(ftmp, "SPICE3") == 0)
else if (strcasecmp(ftmp, "SPICE3") == 0)
esFormat = SPICE3;
else if (strcasecmp(ftmp, "HSPICE") == 0)
{
else if (strcasecmp(ftmp, "HSPICE") == 0)
{
esFormat = HSPICE;
esScale = -1.0;
}
else if (strcasecmp(ftmp, "NGSPICE") == 0)
}
else if (strcasecmp(ftmp, "NGSPICE") == 0)
esFormat = NGSPICE;
else goto usage;
break;
}
else goto usage;
break;
case 'J':
{
char *ftmp ;
if ((ftmp = ArgStr(&argc, &argv, "hierAP_SD")) == NULL)
if ((ftmp = ArgStr(&argc, &argv, "hierAP_SD")) == NULL)
goto usage;
if ( strcasecmp(ftmp, "HIER") == 0 )
if ( strcasecmp(ftmp, "HIER") == 0 )
esHierAP = TRUE ;
else if ( strcasecmp(ftmp, "FLAT") == 0 )
else if (strcasecmp(ftmp, "FLAT") == 0 )
esHierAP = FALSE ;
else goto usage;
else goto usage;
break;
}
case 'y': {
char *t;
break;
if (( t = ArgStr(&argc, &argv, "cap-accuracy") ) == NULL)
case 'y':
if ((t = ArgStr(&argc, &argv, "cap-accuracy")) == NULL)
goto usage;
esCapAccuracy = atoi(t);
break;
}
TxPrintf("The cap accuracy flag 'y' is deprecated.\n");
break;
case 'h': /* -h or -help, as suggested by "ext2spice help" */
TxPrintf(usage_text);
break;
default:
TxError("Unrecognized flag: %s\n", argv[0]);
goto usage;
@ -2822,7 +2817,7 @@ spcdevVisit(dev, hc, scale, trans)
/* Capacitor is "Cnnn top bottom value" */
/* extraction sets top=gate bottom=source */
/* extracted units are fF; output is in fF */
/* extracted units are fF. */
spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier,
name, esSpiceF);
@ -2838,8 +2833,7 @@ spcdevVisit(dev, hc, scale, trans)
if (!has_model)
{
fprintf(esSpiceF, " %ffF", (double)sdM *
(double)(dev->dev_cap));
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcWriteParams(dev, hierName, scale, l, w, sdM);
}
else
@ -2866,7 +2860,7 @@ spcdevVisit(dev, hc, scale, trans)
/* Capacitor is "Cnnn bottom top value" */
/* extraction sets top=source bottom=gate */
/* extracted units are fF; output is in fF */
/* extracted units are fF. */
spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier,
name, esSpiceF);
@ -2882,8 +2876,7 @@ spcdevVisit(dev, hc, scale, trans)
if (!has_model)
{
fprintf(esSpiceF, " %ffF", (double)sdM *
(double)(dev->dev_cap));
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcWriteParams(dev, hierName, scale, l, w, sdM);
}
else
@ -3113,13 +3106,9 @@ esSIvalue(file, value)
{
/* Do nothing---value is probably zero */
}
else if (avalue < 1.0E-15)
{
suffix = 'a';
value *= 1.0E18;
}
else if (avalue < 1.0E-12)
{
/* NOTE: ngspice does not support "a" for "atto" */
suffix = 'f';
value *= 1.0E15;
}
@ -3155,9 +3144,9 @@ esSIvalue(file, value)
}
if (suffix == '\0')
fprintf(file, "%g", value);
fprintf(file, "%.3g", value);
else
fprintf(file, "%g%c", value, suffix);
fprintf(file, "%.3g%c", value, suffix);
}
/*
@ -3470,8 +3459,10 @@ spccapVisit(hierName1, hierName2, cap)
if (cap <= EFCapThreshold)
return 0;
fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1, NULL),
nodeSpiceName(hierName2, NULL), cap);
fprintf(esSpiceF, "C%d %s %s ", esCapNum++, nodeSpiceName(hierName1, NULL),
nodeSpiceName(hierName2, NULL));
esSIvalue(esSpiceF, 1.0E-15 * cap);
fprintf(esSpiceF, "\n");
return 0;
}
@ -3638,10 +3629,14 @@ spcnodeVisit(node, res, cap)
cap = cap / 1000;
if (cap > EFCapThreshold)
{
fprintf(esSpiceF, esSpiceCapFormat, esCapNum++, nsn, cap,
(isConnected) ? "\n" :
(esFormat == NGSPICE) ? " $ **FLOATING\n" :
" **FLOATING\n");
fprintf(esSpiceF, "C%d %s %s ", esCapNum++, nsn, esSpiceCapNode);
esSIvalue(esSpiceF, 1.0E-15 * cap);
if (!isConnected)
{
if (esFormat == NGSPICE) fprintf(esSpiceF, " $");
fprintf(esSpiceF, " **FLOATING");
}
fprintf(esSpiceF, "\n");
}
if (node->efnode_attrs && !esNoAttrs)
{

View File

@ -65,8 +65,8 @@ extern bool esDevNodesOnly;
extern bool esNoAttrs;
extern bool esHierAP;
extern char spcesDefaultOut[FNSIZE];
extern int esCapAccuracy;
extern char esSpiceCapFormat[FNSIZE];
extern char *esSpiceCapNode;
extern char esSpiceDefaultGnd[];
extern char *spcesOutName;
extern FILE *esSpiceF;
extern float esScale; /* negative if hspice the EFScale/100 otherwise */