Made a change to CDL format output to place the substrate parameter

in front of the device name, which is a very inconsistent way to
make the syntax, but whatever.
This commit is contained in:
R. Timothy Edwards 2025-10-06 16:40:19 -04:00
parent 5e74ecf9fa
commit acdfb256a1
2 changed files with 167 additions and 33 deletions

View File

@ -126,6 +126,49 @@ GetHierNode(
return(nn->efnn_node); return(nn->efnn_node);
} }
/*
* ----------------------------------------------------------------------------
*
* spcHierWriteSubParam ---
*
* Special case of spcHierWriteParams() below. Only check for the substrate
* parameter, which in the case of CDL format is written out before the
* device model, for whatever reason. Return TRUE if the substrate parameter
* was output; otherwise return FALSE.
*
* ----------------------------------------------------------------------------
*/
bool
spcHierWriteSubParam(
HierContext *hc,
Dev *dev) /* Dev being output */
{
DevParam *plist;
bool retvalue = FALSE;
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
while (plist != NULL)
{
switch (plist->parm_type[0])
{
case 's':
if (dev->dev_subsnode == NULL)
TxError("Error: Device %s missing substrate node!\n",
EFDevTypes[dev->dev_type]);
else
{
fprintf(esSpiceF, " %s=", plist->parm_name);
spcdevSubstrate(hc->hc_hierName,
dev->dev_subsnode->efnode_name->efnn_hier,
dev->dev_type, esSpiceF);
retvalue = TRUE;
}
}
plist = plist->parm_next;
}
return retvalue;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -145,7 +188,8 @@ spcHierWriteParams(
float scale, /* Scale transform for output */ float scale, /* Scale transform for output */
int l, /* Device length, in internal units */ int l, /* Device length, in internal units */
int w, /* Device width, in internal units */ int w, /* Device width, in internal units */
float sdM) /* Device multiplier */ float sdM, /* Device multiplier */
bool subdone) /* If TRUE, then substrate parameter was already output */
{ {
DevParam *plist, *dparam; DevParam *plist, *dparam;
int parmval; int parmval;
@ -342,14 +386,19 @@ spcHierWriteParams(
} }
break; break;
case 's': case 's':
fprintf(esSpiceF, " %s=", plist->parm_name); if (!subdone)
{
if (dev->dev_subsnode == NULL) if (dev->dev_subsnode == NULL)
TxError("Error: Device %s missing substrate node!\n", TxError("Error: Device %s missing substrate node!\n",
EFDevTypes[dev->dev_type]); EFDevTypes[dev->dev_type]);
else else
{
fprintf(esSpiceF, " %s=", plist->parm_name);
spcdevSubstrate(hc->hc_hierName, spcdevSubstrate(hc->hc_hierName,
dev->dev_subsnode->efnode_name->efnn_hier, dev->dev_subsnode->efnode_name->efnn_hier,
dev->dev_type, esSpiceF); dev->dev_type, esSpiceF);
}
}
break; break;
case 'x': case 'x':
fprintf(esSpiceF, " %s=", plist->parm_name); fprintf(esSpiceF, " %s=", plist->parm_name);
@ -453,10 +502,15 @@ esOutputHierResistor(
{ {
fprintf(esSpiceF, " %f", ((double)(dev->dev_res) fprintf(esSpiceF, " %f", ((double)(dev->dev_res)
/ (double)(dscale)) / (double)sdM); / (double)(dscale)) / (double)sdM);
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
} }
else else
{ {
bool subdone = FALSE;
if (esFormat == CDL)
subdone = spcHierWriteSubParam(hc, dev);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
if (esScale < 0) if (esScale < 0)
@ -471,7 +525,7 @@ esOutputHierResistor(
fprintf(esSpiceF, " l="); fprintf(esSpiceF, " l=");
esSIvalue(esSpiceF, 1.0E-6 * (float)((l * scale * esScale) / dscale)); esSIvalue(esSpiceF, 1.0E-6 * (float)((l * scale * esScale) / dscale));
} }
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
if (sdM != 1.0) if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);
} }
@ -588,6 +642,7 @@ spcdevHierVisit(
float sdM; float sdM;
char devchar; char devchar;
bool has_model = TRUE; bool has_model = TRUE;
bool subdone = FALSE;
/* If no terminals, or only a gate, can't do much of anything */ /* If no terminals, or only a gate, can't do much of anything */
if (dev->dev_nterm <= 1 ) if (dev->dev_nterm <= 1 )
@ -769,9 +824,11 @@ spcdevHierVisit(
source->dterm_node->efnode_name->efnn_hier, source->dterm_node->efnode_name->efnn_hier,
"base", esSpiceF); "base", esSpiceF);
if (esFormat == CDL)
subdone = spcHierWriteSubParam(hc, dev);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
sdM = getCurDevMult(); sdM = getCurDevMult();
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
break; break;
case DEV_MSUBCKT: case DEV_MSUBCKT:
@ -850,7 +907,7 @@ spcdevHierVisit(
/* Write all requested parameters to the subcircuit call. */ /* Write all requested parameters to the subcircuit call. */
sdM = getCurDevMult(); sdM = getCurDevMult();
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
if (sdM != 1.0) if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);
break; break;
@ -921,9 +978,11 @@ spcdevHierVisit(
spcdevOutNode(hc->hc_hierName, spcdevOutNode(hc->hc_hierName,
subnode->efnode_name->efnn_hier, subnode->efnode_name->efnn_hier,
"diode_bot", esSpiceF); "diode_bot", esSpiceF);
if (esFormat == CDL)
subdone = spcHierWriteSubParam(hc, dev);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
sdM = getCurDevMult(); sdM = getCurDevMult();
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
break; break;
case DEV_NDIODE: case DEV_NDIODE:
@ -942,9 +1001,11 @@ spcdevHierVisit(
spcdevOutNode(hc->hc_hierName, spcdevOutNode(hc->hc_hierName,
gate->dterm_node->efnode_name->efnn_hier, gate->dterm_node->efnode_name->efnn_hier,
"diode_top", esSpiceF); "diode_top", esSpiceF);
if (esFormat == CDL)
subdone = spcHierWriteSubParam(hc, dev);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
sdM = getCurDevMult(); sdM = getCurDevMult();
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
break; break;
case DEV_CAP: case DEV_CAP:
@ -971,10 +1032,12 @@ spcdevHierVisit(
if (!has_model) if (!has_model)
{ {
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap); esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
} }
else else
{ {
if (esFormat == CDL)
subdone = spcHierWriteSubParam(hc, dev);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
if (esScale < 0) if (esScale < 0)
@ -988,7 +1051,7 @@ spcdevHierVisit(
fprintf(esSpiceF, " l="); fprintf(esSpiceF, " l=");
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale); esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
} }
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
if (sdM != 1.0) if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);
} }
@ -1018,10 +1081,12 @@ spcdevHierVisit(
if (!has_model) if (!has_model)
{ {
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap); esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
} }
else else
{ {
if (esFormat == CDL)
subdone = spcHierWriteSubParam(hc, dev);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
if (esScale < 0) if (esScale < 0)
@ -1035,7 +1100,7 @@ spcdevHierVisit(
fprintf(esSpiceF, " l="); fprintf(esSpiceF, " l=");
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale); esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
} }
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
if (sdM != 1.0) if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);
} }
@ -1079,7 +1144,7 @@ spcdevHierVisit(
fprintf(esSpiceF, " l="); fprintf(esSpiceF, " l=");
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale); esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
} }
spcHierWriteParams(hc, dev, scale, l, w, sdM); spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
if (sdM != 1.0) if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);

View File

@ -2030,6 +2030,50 @@ topVisit(
fprintf(esSpiceF, "\n"); fprintf(esSpiceF, "\n");
} }
/*
* ----------------------------------------------------------------------------
*
* spcWriteSubParam ---
*
* Special handling for CDL format: Output any substrate parameter before
* the device model. Why this makes sense, I have no idea.
*
* ----------------------------------------------------------------------------
*/
bool
spcWriteSubParam(
Dev *dev, /* Dev being output */
HierName *hierName) /* Hierarchical path down to this dev */
{
bool retval; /* True if substrate parameter was output */
DevParam *plist;
retval = FALSE;
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
while (plist != NULL)
{
switch (plist->parm_type[0])
{
case 's':
if (dev->dev_subsnode == NULL)
TxError("Error: No substrate definition for device %s\n",
EFDevTypes[dev->dev_type]);
else
{
fprintf(esSpiceF, " %s=", plist->parm_name);
spcdevSubstrate(hierName,
dev->dev_subsnode->efnode_name->efnn_hier,
dev->dev_type, esSpiceF);
retval = TRUE;
}
break;
}
plist = plist->parm_next;
}
return retval;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -2049,7 +2093,8 @@ spcWriteParams(
float scale, /* Scale transform for output */ float scale, /* Scale transform for output */
int l, /* Device length, in internal units */ int l, /* Device length, in internal units */
int w, /* Device width, in internal units */ int w, /* Device width, in internal units */
float sdM) /* Device multiplier */ float sdM, /* Device multiplier */
bool subdone) /* If TRUE, substrate parameter was already output */
{ {
bool hierD; bool hierD;
DevParam *plist, *dparam; DevParam *plist, *dparam;
@ -2283,10 +2328,19 @@ spcWriteParams(
} }
break; break;
case 's': case 's':
if (!subdone)
{
if (dev->dev_subsnode == NULL)
TxError("Error: No substrate definition for device %s\n",
EFDevTypes[dev->dev_type]);
else
{
fprintf(esSpiceF, " %s=", plist->parm_name); fprintf(esSpiceF, " %s=", plist->parm_name);
/*EFNode *subnodeFlat =*/ spcdevSubstrate(hierName, spcdevSubstrate(hierName,
dev->dev_subsnode->efnode_name->efnn_hier, dev->dev_subsnode->efnode_name->efnn_hier,
dev->dev_type, esSpiceF); dev->dev_type, esSpiceF);
}
}
break; break;
case 'x': case 'x':
fprintf(esSpiceF, " %s=", plist->parm_name); fprintf(esSpiceF, " %s=", plist->parm_name);
@ -2382,10 +2436,13 @@ esOutputResistor(
{ {
fprintf(esSpiceF, " %f", ((double)(dev->dev_res) fprintf(esSpiceF, " %f", ((double)(dev->dev_res)
/ (double)(dscale)) / (double)sdM); / (double)(dscale)) / (double)sdM);
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
} }
else else
{ {
bool subdone = FALSE;
if (esFormat == CDL)
subdone = spcWriteSubParam(dev, hierName);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
if (esScale < 0) if (esScale < 0)
@ -2398,7 +2455,7 @@ esOutputResistor(
esSIvalue(esSpiceF, 1.0E-6 * (l * scale * esScale) / dscale); esSIvalue(esSpiceF, 1.0E-6 * (l * scale * esScale) / dscale);
} }
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
if (sdM != 1.0) if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);
} }
@ -2545,6 +2602,7 @@ spcdevVisit(
float sdM; float sdM;
char name[12], devchar; char name[12], devchar;
bool has_model = TRUE; bool has_model = TRUE;
bool subdone = FALSE;
HierName *hierName = hc->hc_hierName; HierName *hierName = hc->hc_hierName;
sprintf(name, "output"); sprintf(name, "output");
@ -2759,9 +2817,11 @@ spcdevVisit(
spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier,
name, esSpiceF); name, esSpiceF);
if (esFormat == CDL)
subdone = spcWriteSubParam(dev, hierName);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
sdM = getCurDevMult(); sdM = getCurDevMult();
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
break; break;
case DEV_MSUBCKT: case DEV_MSUBCKT:
@ -2841,7 +2901,7 @@ spcdevVisit(
/* Write all requested parameters to the subcircuit call. */ /* Write all requested parameters to the subcircuit call. */
sdM = getCurDevMult(); sdM = getCurDevMult();
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
if (sdM != 1.0) if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);
break; break;
@ -2907,9 +2967,12 @@ spcdevVisit(
spcdevOutNode(hierName, subnode->efnode_name->efnn_hier, spcdevOutNode(hierName, subnode->efnode_name->efnn_hier,
name, esSpiceF); name, esSpiceF);
if (esFormat == CDL)
subdone = spcWriteSubParam(dev, hierName);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
sdM = getCurDevMult(); sdM = getCurDevMult();
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
break; break;
case DEV_NDIODE: case DEV_NDIODE:
@ -2925,9 +2988,11 @@ spcdevVisit(
spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier,
name, esSpiceF); name, esSpiceF);
if (esFormat == CDL)
subdone = spcWriteSubParam(dev, hierName);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
sdM = getCurDevMult(); sdM = getCurDevMult();
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
break; break;
case DEV_CAP: case DEV_CAP:
@ -2951,10 +3016,12 @@ spcdevVisit(
if (!has_model) if (!has_model)
{ {
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap); esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
} }
else else
{ {
if (esFormat == CDL)
subdone = spcWriteSubParam(dev, hierName);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
if (esScale < 0) if (esScale < 0)
@ -2967,7 +3034,7 @@ spcdevVisit(
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale); esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
} }
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
if (sdM != 1.0) if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);
} }
@ -2994,10 +3061,12 @@ spcdevVisit(
if (!has_model) if (!has_model)
{ {
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap); esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
} }
else else
{ {
if (esFormat == CDL)
subdone = spcWriteSubParam(dev, hierName);
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
if (esScale < 0) if (esScale < 0)
@ -3010,7 +3079,7 @@ spcdevVisit(
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale); esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
} }
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
if (sdM != 1.0) if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);
} }
@ -3058,7 +3127,7 @@ spcdevVisit(
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale); esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
} }
spcWriteParams(dev, hierName, scale, l, w, sdM); spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
if (sdM != 1.0) if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);