Implemented a command option "ext2spice short voltage|resistor|none" that

implements a method for handling ports in a subcircuit that have different
port names and indexes but are shorted together.  "none" is the default
and backwards-compatible behavior that merges ports together, which will
often cause one of the ports to be optimized out of the netlist.  "resistor"
will separate the port names with a 0-ohm ideal resistor.  "voltage" will
separate the port names with a 0-volt voltage source.  This should work
well for simulation and potentially for LVS, although its impact on LVS
has not been fully investigated.
This commit is contained in:
Tim Edwards 2021-07-10 21:13:24 -04:00
parent 355399d3ef
commit 6136d3ff0f
11 changed files with 222 additions and 77 deletions

View File

@ -446,7 +446,7 @@ CmdExtToSim(w, cmd)
case EXTTOSIM_DEFAULT: case EXTTOSIM_DEFAULT:
LocCapThreshold = 2; LocCapThreshold = 2;
LocResistThreshold = 10; LocResistThreshold = 10;
EFTrimFlags = 0; EFOutputFlags = 0;
EFScale = 0.0; EFScale = 0.0;
if (EFArgTech) if (EFArgTech)
{ {
@ -1307,8 +1307,8 @@ FILE *outf;
suf = EFHNToStr(suffix); suf = EFHNToStr(suffix);
if (fetInfo[type].defSubs && strcasecmp(suf,fetInfo[type].defSubs) == 0) { if (fetInfo[type].defSubs && strcasecmp(suf,fetInfo[type].defSubs) == 0) {
l = strlen(suf) - 1; l = strlen(suf) - 1;
if ( ( EFTrimFlags & EF_TRIMGLOB ) && suf[l] =='!' || if ( ( EFOutputFlags & EF_TRIMGLOB ) && suf[l] =='!' ||
( EFTrimFlags & EF_TRIMLOCAL ) && suf[l] == '#' ) ( EFOutputFlags & EF_TRIMLOCAL ) && suf[l] == '#' )
suf[l] = '\0' ; suf[l] = '\0' ;
if ( esFormat == SU ) if ( esFormat == SU )
fprintf(outf, "S_"); fprintf(outf, "S_");

View File

@ -555,7 +555,8 @@ spcdevHierVisit(hc, dev, scale)
case DEV_RES: case DEV_RES:
case DEV_CAP: case DEV_CAP:
case DEV_CAPREV: case DEV_CAPREV:
if (dev->dev_type == esNoModelType) if ((dev->dev_type == esNoModelType) ||
!strcmp(EFDevTypes[dev->dev_type], "None"))
has_model = FALSE; has_model = FALSE;
break; break;
} }
@ -601,6 +602,9 @@ spcdevHierVisit(hc, dev, scale)
case DEV_RES: case DEV_RES:
devchar = 'R'; devchar = 'R';
break; break;
case DEV_VOLT:
devchar = 'V';
break;
case DEV_CAP: case DEV_CAP:
case DEV_CAPREV: case DEV_CAPREV:
devchar = 'C'; devchar = 'C';
@ -638,6 +642,9 @@ spcdevHierVisit(hc, dev, scale)
case DEV_CAPREV: case DEV_CAPREV:
fprintf(esSpiceF, "%d", esCapNum++); fprintf(esSpiceF, "%d", esCapNum++);
break; break;
case DEV_VOLT:
fprintf(esSpiceF, "%d", esVoltNum++);
break;
case DEV_SUBCKT: case DEV_SUBCKT:
case DEV_RSUBCKT: case DEV_RSUBCKT:
case DEV_CSUBCKT: case DEV_CSUBCKT:
@ -792,6 +799,21 @@ spcdevHierVisit(hc, dev, scale)
} }
break; break;
case DEV_VOLT:
/* Voltage source is "Vnnn term1 term2 0.0". It is used only to
* separate port names that have been shorted.
*/
if (dev->dev_nterm > 1)
spcdevOutNode(hc->hc_hierName,
source->dterm_node->efnode_name->efnn_hier,
"plus", esSpiceF);
if (dev->dev_nterm > 2)
spcdevOutNode(hc->hc_hierName,
drain->dterm_node->efnode_name->efnn_hier,
"minus", esSpiceF);
fprintf(esSpiceF, " 0.0");
break;
case DEV_DIODE: case DEV_DIODE:
case DEV_PDIODE: case DEV_PDIODE:
if (source == NULL) break; if (source == NULL) break;
@ -1083,7 +1105,8 @@ spcdevHierMergeVisit(hc, dev, scale)
break; break;
case DEV_RSUBCKT: case DEV_RSUBCKT:
case DEV_RES: case DEV_RES:
if (fp->dev->dev_type == esNoModelType) if ((fp->dev->dev_type == esNoModelType) ||
!strcmp(EFDevTypes[fp->dev->dev_type], "None"))
m = esFMult[cfp->esFMIndex] + (fp->dev->dev_res m = esFMult[cfp->esFMIndex] + (fp->dev->dev_res
/ cfp->dev->dev_res); / cfp->dev->dev_res);
else else
@ -1092,7 +1115,8 @@ spcdevHierMergeVisit(hc, dev, scale)
case DEV_CSUBCKT: case DEV_CSUBCKT:
case DEV_CAP: case DEV_CAP:
case DEV_CAPREV: case DEV_CAPREV:
if (fp->dev->dev_type == esNoModelType) if ((fp->dev->dev_type == esNoModelType) ||
!strcmp(EFDevTypes[fp->dev->dev_type], "None"))
m = esFMult[cfp->esFMIndex] + (fp->dev->dev_cap m = esFMult[cfp->esFMIndex] + (fp->dev->dev_cap
/ cfp->dev->dev_cap); / cfp->dev->dev_cap);
else else
@ -1481,7 +1505,8 @@ mergeThem:
break; break;
case DEV_RSUBCKT: case DEV_RSUBCKT:
case DEV_RES: case DEV_RES:
if (fp->dev->dev_type == esNoModelType) if ((fp->dev->dev_type == esNoModelType) ||
!strcmp(EFDevTypes[fp->dev->dev_type], "None"))
m = esFMult[cfp->esFMIndex] + (fp->dev->dev_res m = esFMult[cfp->esFMIndex] + (fp->dev->dev_res
/ cfp->dev->dev_res); / cfp->dev->dev_res);
else else
@ -1490,7 +1515,8 @@ mergeThem:
case DEV_CSUBCKT: case DEV_CSUBCKT:
case DEV_CAP: case DEV_CAP:
case DEV_CAPREV: case DEV_CAPREV:
if (fp->dev->dev_type == esNoModelType) if ((fp->dev->dev_type == esNoModelType) ||
!strcmp(EFDevTypes[fp->dev->dev_type], "None"))
m = esFMult[cfp->esFMIndex] + (fp->dev->dev_cap m = esFMult[cfp->esFMIndex] + (fp->dev->dev_cap
/ cfp->dev->dev_cap); / cfp->dev->dev_cap);
else else

View File

@ -65,7 +65,7 @@ float esScale = -1.0 ; /* negative if hspice the EFScale/100 otherwise */
unsigned short esFormat = SPICE3 ; unsigned short esFormat = SPICE3 ;
int esCapNum, esDevNum, esResNum, esDiodeNum; int esCapNum, esDevNum, esResNum, esDiodeNum, esVoltNum;
int esNodeNum; /* just in case we're extracting spice2 */ int esNodeNum; /* just in case we're extracting spice2 */
int esSbckNum; /* used in hspice node name shortening */ int esSbckNum; /* used in hspice node name shortening */
int esNoModelType; /* index for device type "None" (model-less device) */ int esNoModelType; /* index for device type "None" (model-less device) */
@ -137,20 +137,20 @@ esFormatSubs(outf, suf)
if (outf) if (outf)
{ {
l = strlen(suf) - 1; l = strlen(suf) - 1;
if ((EFTrimFlags & EF_TRIMGLOB ) && suf[l] == '!' || if ((EFOutputFlags & EF_TRIMGLOB ) && suf[l] == '!' ||
(EFTrimFlags & EF_TRIMLOCAL) && suf[l] == '#') (EFOutputFlags & EF_TRIMLOCAL) && suf[l] == '#')
suf[l] = '\0' ; suf[l] = '\0' ;
if (EFTrimFlags & EF_CONVERTCOMMA) if (EFOutputFlags & EF_CONVERTCOMMA)
while ((specchar = strchr(suf, ',')) != NULL) while ((specchar = strchr(suf, ',')) != NULL)
*specchar = '|'; *specchar = '|';
if (EFTrimFlags & EF_CONVERTBRACKETS) if (EFOutputFlags & EF_CONVERTBRACKETS)
{ {
while ((specchar = strchr(suf, '[')) != NULL) while ((specchar = strchr(suf, '[')) != NULL)
*specchar = '_'; *specchar = '_';
while ((specchar = strchr(suf, ']')) != NULL) while ((specchar = strchr(suf, ']')) != NULL)
*specchar = '_'; *specchar = '_';
} }
if (EFTrimFlags & EF_CONVERTEQUAL) if (EFOutputFlags & EF_CONVERTEQUAL)
while ((specchar = strchr(suf, '=')) != NULL) while ((specchar = strchr(suf, '=')) != NULL)
*specchar = ':'; *specchar = ':';
fprintf(outf, "%s", suf); fprintf(outf, "%s", suf);
@ -213,13 +213,14 @@ Exttospice_Init(interp)
#define EXTTOSPC_EXTRESIST 6 #define EXTTOSPC_EXTRESIST 6
#define EXTTOSPC_RESISTORTEE 7 #define EXTTOSPC_RESISTORTEE 7
#define EXTTOSPC_SCALE 8 #define EXTTOSPC_SCALE 8
#define EXTTOSPC_SUBCIRCUITS 9 #define EXTTOSPC_SHORT 9
#define EXTTOSPC_HIERARCHY 10 #define EXTTOSPC_SUBCIRCUITS 10
#define EXTTOSPC_BLACKBOX 11 #define EXTTOSPC_HIERARCHY 11
#define EXTTOSPC_RENUMBER 12 #define EXTTOSPC_BLACKBOX 12
#define EXTTOSPC_MERGENAMES 13 #define EXTTOSPC_RENUMBER 13
#define EXTTOSPC_LVS 14 #define EXTTOSPC_MERGENAMES 14
#define EXTTOSPC_HELP 15 #define EXTTOSPC_LVS 15
#define EXTTOSPC_HELP 16
void void
CmdExtToSpice(w, cmd) CmdExtToSpice(w, cmd)
@ -264,6 +265,8 @@ CmdExtToSpice(w, cmd)
"extresist [on|off] incorporate information from extresist", "extresist [on|off] incorporate information from extresist",
"resistor tee [on|off] model resistor capacitance as a T-network", "resistor tee [on|off] model resistor capacitance as a T-network",
"scale [on|off] use .option card for scaling", "scale [on|off] use .option card for scaling",
"short [voltage|resistor|none]\n"
" set method for handling shorted ports",
"subcircuits [top|descend] [on|off|auto]\n" "subcircuits [top|descend] [on|off|auto]\n"
" standard cells become subcircuit calls", " standard cells become subcircuit calls",
"hierarchy [on|off] output hierarchical spice for LVS", "hierarchy [on|off] output hierarchical spice for LVS",
@ -283,6 +286,12 @@ CmdExtToSpice(w, cmd)
NULL NULL
}; };
static char *cmdShortTypes[] = {
"none merge shorted ports",
"resistor separate shorted ports with 0 ohm resistor",
"voltage separate shorted ports with 0 volt source",
NULL
};
static char *cmdExtToSpcFormat[] = { static char *cmdExtToSpcFormat[] = {
"spice2", "spice2",
"spice3", "spice3",
@ -314,6 +323,13 @@ CmdExtToSpice(w, cmd)
NULL NULL
}; };
static char *shorttypes[] = {
"none",
"resistor",
"voltage",
NULL
};
typedef enum { typedef enum {
IDX_YES, IDX_TRUE, IDX_ON, IDX_NO, IDX_FALSE, IDX_OFF, IDX_YES, IDX_TRUE, IDX_ON, IDX_NO, IDX_FALSE, IDX_OFF,
IDX_AUTO, IDX_TOP, IDX_DESCEND IDX_AUTO, IDX_TOP, IDX_DESCEND
@ -428,6 +444,36 @@ CmdExtToSpice(w, cmd)
esMergeNames = FALSE; esMergeNames = FALSE;
break; break;
case EXTTOSPC_SHORT:
if (cmd->tx_argc == 2)
{
if ((EFOutputFlags & EF_SHORT_MASK) == EF_SHORT_NONE)
Tcl_SetResult(magicinterp, "none", NULL);
else if ((EFOutputFlags & EF_SHORT_MASK) == EF_SHORT_R)
Tcl_SetResult(magicinterp, "resistor", NULL);
else if ((EFOutputFlags & EF_SHORT_MASK) == EF_SHORT_V)
Tcl_SetResult(magicinterp, "voltage source", NULL);
return;
}
idx = Lookup(cmd->tx_argv[2], cmdShortTypes);
if (idx < 0) goto usage;
else switch (idx)
{
case 0:
EFOutputFlags &= ~EF_SHORT_MASK;
EFOutputFlags |= EF_SHORT_NONE;
break;
case 1:
EFOutputFlags &= ~EF_SHORT_MASK;
EFOutputFlags |= EF_SHORT_R;
break;
case 2:
EFOutputFlags &= ~EF_SHORT_MASK;
EFOutputFlags |= EF_SHORT_V;
break;
}
break;
case EXTTOSPC_LVS: case EXTTOSPC_LVS:
/* Apply default command settings for LVS */ /* Apply default command settings for LVS */
/* hierarchy = on */ /* hierarchy = on */
@ -615,7 +661,7 @@ CmdExtToSpice(w, cmd)
case EXTTOSPC_DEFAULT: case EXTTOSPC_DEFAULT:
LocCapThreshold = 2; LocCapThreshold = 2;
LocResistThreshold = INFINITE_THRESHOLD; LocResistThreshold = INFINITE_THRESHOLD;
EFTrimFlags = EF_CONVERTCOMMA | EF_CONVERTEQUAL; EFOutputFlags = EF_CONVERTCOMMA | EF_CONVERTEQUAL;
EFScale = 0.0; EFScale = 0.0;
if (EFArgTech) if (EFArgTech)
{ {
@ -647,6 +693,7 @@ runexttospice:
/* Reset the device indices */ /* Reset the device indices */
esCapNum = 0; esCapNum = 0;
esVoltNum = 0;
esDevNum = 1000; esDevNum = 1000;
esResNum = 0; esResNum = 0;
esDiodeNum = 0; esDiodeNum = 0;
@ -832,10 +879,10 @@ runexttospice:
// This forces options TRIMGLOB and CONVERTEQUAL, not sure that's such a // This forces options TRIMGLOB and CONVERTEQUAL, not sure that's such a
// good idea. . . // good idea. . .
EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL | EF_CONVERTCOMMA; EFOutputFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL | EF_CONVERTCOMMA;
if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS; if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS;
if (esFormat == HSPICE) if (esFormat == HSPICE)
EFTrimFlags |= EF_TRIMLOCAL; EFOutputFlags |= EF_TRIMLOCAL;
/* Write globals under a ".global" card */ /* Write globals under a ".global" card */
@ -1054,10 +1101,10 @@ main(argc, argv)
/* Convert the hierarchical description to a flat one */ /* Convert the hierarchical description to a flat one */
flatFlags = EF_FLATNODES; flatFlags = EF_FLATNODES;
EFTrimFlags |= EF_TRIMGLOB ; EFOutputFlags |= EF_TRIMGLOB ;
if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS; if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS;
if (esFormat == HSPICE) { if (esFormat == HSPICE) {
EFTrimFlags |= EF_TRIMLOCAL ; EFOutputFlags |= EF_TRIMLOCAL ;
HashInit(&subcktNameTable, 32, HT_STRINGKEYS); HashInit(&subcktNameTable, 32, HT_STRINGKEYS);
#ifndef UNSORTED_SUBCKT #ifndef UNSORTED_SUBCKT
DQInit(&subcktNameQueue, 64); DQInit(&subcktNameQueue, 64);
@ -1392,14 +1439,14 @@ subcktVisit(use, hierName, is_top)
} }
else else
{ {
int savflags = EFTrimFlags; int savflags = EFOutputFlags;
EFTrimFlags = EF_CONVERTCOMMA; // Only substitute commas on subcircuit names EFOutputFlags = EF_CONVERTCOMMA; // Only substitute commas on subcircuit names
/* Use full hierarchical decomposition for name */ /* Use full hierarchical decomposition for name */
/* (not just use->use_id. hierName already has use->use_id at end) */ /* (not just use->use_id. hierName already has use->use_id at end) */
EFHNSprintf(stmp, hierName); EFHNSprintf(stmp, hierName);
fprintf(esSpiceF, "X%s", stmp); fprintf(esSpiceF, "X%s", stmp);
EFTrimFlags = savflags; EFOutputFlags = savflags;
tchars = 1 + strlen(stmp); tchars = 1 + strlen(stmp);
} }
@ -2393,7 +2440,8 @@ spcdevVisit(dev, hc, scale, trans)
case DEV_CAPREV: case DEV_CAPREV:
if (dev->dev_nterm < 1) if (dev->dev_nterm < 1)
return 0; return 0;
if (dev->dev_type == esNoModelType) if ((dev->dev_type == esNoModelType) ||
!strcmp(EFDevTypes[dev->dev_type], "None"))
has_model = FALSE; has_model = FALSE;
break; break;
} }
@ -2439,6 +2487,9 @@ spcdevVisit(dev, hc, scale, trans)
case DEV_RES: case DEV_RES:
devchar = 'R'; devchar = 'R';
break; break;
case DEV_VOLT:
devchar = 'V';
break;
case DEV_CAP: case DEV_CAP:
case DEV_CAPREV: case DEV_CAPREV:
devchar = 'C'; devchar = 'C';
@ -2480,6 +2531,9 @@ spcdevVisit(dev, hc, scale, trans)
case DEV_CAPREV: case DEV_CAPREV:
fprintf(esSpiceF, "%d", esCapNum++); fprintf(esSpiceF, "%d", esCapNum++);
break; break;
case DEV_VOLT:
fprintf(esSpiceF, "%d", esVoltNum++);
break;
case DEV_SUBCKT: case DEV_SUBCKT:
case DEV_RSUBCKT: case DEV_RSUBCKT:
case DEV_CSUBCKT: case DEV_CSUBCKT:
@ -2631,6 +2685,19 @@ spcdevVisit(dev, hc, scale, trans)
} }
break; break;
case DEV_VOLT:
/* The voltage source is "Vnnn term1 term2 0.0" and is used
* only to separate shorted port names.
*/
if (dev->dev_nterm > 1)
spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier,
name, esSpiceF);
if (dev->dev_nterm > 1)
spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier,
name, esSpiceF);
fprintf(esSpiceF, " 0.0");
break;
case DEV_DIODE: case DEV_DIODE:
case DEV_PDIODE: case DEV_PDIODE:
@ -3408,7 +3475,7 @@ retName:
* EFHNSprintf -- * EFHNSprintf --
* *
* Create a hierarchical node name. * Create a hierarchical node name.
* The flags in EFTrimFlags control whether global (!) or local (#) * The flags in EFOutputFlags control whether global (!) or local (#)
* suffixes are to be trimmed. Also substitutes \. with \@ if the * suffixes are to be trimmed. Also substitutes \. with \@ if the
* format is hspice. * format is hspice.
* *
@ -3432,14 +3499,14 @@ EFHNSprintf(str, hierName)
s = str; s = str;
if (hierName->hn_parent) str = efHNSprintfPrefix(hierName->hn_parent, str); if (hierName->hn_parent) str = efHNSprintfPrefix(hierName->hn_parent, str);
if (EFTrimFlags) if (EFOutputFlags)
{ {
cp = hierName->hn_name; cp = hierName->hn_name;
trimGlob = (EFTrimFlags & EF_TRIMGLOB); trimGlob = (EFOutputFlags & EF_TRIMGLOB);
trimLocal = (EFTrimFlags & EF_TRIMLOCAL); trimLocal = (EFOutputFlags & EF_TRIMLOCAL);
convertComma = (EFTrimFlags & EF_CONVERTCOMMA); convertComma = (EFOutputFlags & EF_CONVERTCOMMA);
convertEqual = (EFTrimFlags & EF_CONVERTEQUAL); convertEqual = (EFOutputFlags & EF_CONVERTEQUAL);
convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS); convertBrackets = (EFOutputFlags & EF_CONVERTBRACKETS);
while (c = *cp++) while (c = *cp++)
{ {
switch (c) switch (c)
@ -3465,9 +3532,9 @@ char *efHNSprintfPrefix(hierName, str)
char *str; char *str;
{ {
char *cp, c; char *cp, c;
bool convertEqual = (EFTrimFlags & EF_CONVERTEQUAL) ? TRUE : FALSE; bool convertEqual = (EFOutputFlags & EF_CONVERTEQUAL) ? TRUE : FALSE;
bool convertComma = (EFTrimFlags & EF_CONVERTCOMMA) ? TRUE : FALSE; bool convertComma = (EFOutputFlags & EF_CONVERTCOMMA) ? TRUE : FALSE;
bool convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS) ? TRUE : FALSE; bool convertBrackets = (EFOutputFlags & EF_CONVERTBRACKETS) ? TRUE : FALSE;
if (hierName->hn_parent) if (hierName->hn_parent)
str = efHNSprintfPrefix(hierName->hn_parent, str); str = efHNSprintfPrefix(hierName->hn_parent, str);
@ -3750,6 +3817,9 @@ parallelDevs(f1, f2)
case DEV_RSUBCKT: case DEV_RSUBCKT:
case DEV_CSUBCKT: case DEV_CSUBCKT:
break; break;
case DEV_VOLT:
break;
} }
return NOT_PARALLEL; return NOT_PARALLEL;
} }

View File

@ -62,7 +62,7 @@ extern float esScale; /* negative if hspice the EFScale/100 otherwise */
extern unsigned short esFormat; extern unsigned short esFormat;
extern TileTypeBitMask initMask; extern TileTypeBitMask initMask;
extern int esCapNum, esDevNum, esResNum, esDiodeNum; extern int esCapNum, esDevNum, esResNum, esDiodeNum, esVoltNum;
extern int esNodeNum; /* just in case we're extracting spice2 */ extern int esNodeNum; /* just in case we're extracting spice2 */
extern int esSbckNum; /* used in hspice node name shortening */ extern int esSbckNum; /* used in hspice node name shortening */
extern int esNoModelType; /* index for device type "None" (model-less device) */ extern int esNoModelType; /* index for device type "None" (model-less device) */
@ -144,8 +144,6 @@ typedef struct {
TTMaskZero (&((nodeClientHier *) (node)->efnode_client)->m_w.visitMask); \ TTMaskZero (&((nodeClientHier *) (node)->efnode_client)->m_w.visitMask); \
} }
/* attributes controlling the Area/Perimeter extraction of dev terminals */ /* attributes controlling the Area/Perimeter extraction of dev terminals */
#define ATTR_FLATAP "*[Ee][Xx][Tt]:[Aa][Pp][Ff]*" #define ATTR_FLATAP "*[Ee][Xx][Tt]:[Aa][Pp][Ff]*"
#define ATTR_HIERAP "*[Ee][Xx][Tt]:[Aa][Pp][Hh]*" #define ATTR_HIERAP "*[Ee][Xx][Tt]:[Aa][Pp][Hh]*"

View File

@ -43,7 +43,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/* Command-line flags */ /* Command-line flags */
EFCapValue EFCapThreshold = 2; /* -c/-C: (fF) smallest interesting C */ EFCapValue EFCapThreshold = 2; /* -c/-C: (fF) smallest interesting C */
int EFResistThreshold = 10; /* -r/-R: (Ohms) smallest interesting R */ int EFResistThreshold = 10; /* -r/-R: (Ohms) smallest interesting R */
int EFTrimFlags = 0; /* -t: output of nodename trailing #!'s */ int EFOutputFlags = 0; /* -t: output of nodename trailing #!'s */
char *EFSearchPath = NULL; /* -p: Search path for .ext files */ char *EFSearchPath = NULL; /* -p: Search path for .ext files */
char *EFArgTech = NULL; /* -T: Tech specified on command line */ char *EFArgTech = NULL; /* -T: Tech specified on command line */
@ -216,12 +216,12 @@ EFArgs(argc, argv, err_result, argsProc, cdata)
case 't': case 't':
if ((cp = ArgStr(&argc, &argv, "trim characters")) == NULL) if ((cp = ArgStr(&argc, &argv, "trim characters")) == NULL)
goto usage; goto usage;
if (strchr(cp, '!')) EFTrimFlags |= EF_TRIMGLOB; if (strchr(cp, '!')) EFOutputFlags |= EF_TRIMGLOB;
if (strchr(cp, '#')) EFTrimFlags |= EF_TRIMLOCAL; if (strchr(cp, '#')) EFOutputFlags |= EF_TRIMLOCAL;
if (strchr(cp, ',')) EFTrimFlags |= EF_CONVERTCOMMA; if (strchr(cp, ',')) EFOutputFlags |= EF_CONVERTCOMMA;
if (strchr(cp, '=')) EFTrimFlags |= EF_CONVERTEQUAL; if (strchr(cp, '=')) EFOutputFlags |= EF_CONVERTEQUAL;
if (strchr(cp, '[')) EFTrimFlags |= EF_CONVERTBRACKETS; if (strchr(cp, '[')) EFOutputFlags |= EF_CONVERTBRACKETS;
if (strchr(cp, ']')) EFTrimFlags |= EF_CONVERTBRACKETS; if (strchr(cp, ']')) EFOutputFlags |= EF_CONVERTBRACKETS;
break; break;
case 'C': case 'C':
EFCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F; EFCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F;

View File

@ -479,6 +479,35 @@ efBuildEquiv(def, nodeName1, nodeName2)
else if (nn2->efnn_node == (EFNode *)NULL) else if (nn2->efnn_node == (EFNode *)NULL)
return; /* Repeated "equiv" statement */ return; /* Repeated "equiv" statement */
/* If both names exist and are for different ports, then keep */
/* them separate and add a zero ohm resistor or a zero volt */
/* source between them, based on the method set by "ext2spice */
/* shorts". */
if (nn1 && nn2 && (nn1->efnn_port >= 0) && (nn2->efnn_port >= 0) &&
(nn1->efnn_port != nn2->efnn_port))
{
if ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE)
{
int i;
int sdev;
char *argv[7], zeroarg[] = "0";
if ((EFOutputFlags & EF_SHORT_MASK) == EF_SHORT_R)
sdev = DEV_RES;
else
sdev = DEV_VOLT;
for (i = 0; i < 10; i++) argv[i] = zeroarg;
argv[4] = StrDup((char **)NULL, nodeName1);
argv[7] = StrDup((char **)NULL, nodeName2);
efBuildDevice(def, sdev, "None", &GeoNullRect, 10, argv);
freeMagic(argv[4]);
freeMagic(argv[7]);
return;
}
}
/* If both names exist and are for different nodes, merge them */ /* If both names exist and are for different nodes, merge them */
if (nn1) if (nn1)
{ {
@ -813,9 +842,24 @@ efBuildDevice(def, class, type, r, argc, argv)
*/ */
ttype = extGetDevType(type); ttype = extGetDevType(type);
if (ttype < 0)
{
/* For zero-ohm resistors used to separate ports on the same */
/* net, generate a unique devhash. */
ttype = DBNumTypes;
while (1)
{
sprintf(devhash, "%dx%d_%d", r->r_xbot, r->r_ybot, ttype);
he = HashLookOnly(&def->def_devs, devhash);
if (he == NULL) break;
ttype++;
}
}
sprintf(devhash, "%dx%d_%d", r->r_xbot, r->r_ybot, ttype); sprintf(devhash, "%dx%d_%d", r->r_xbot, r->r_ybot, ttype);
he = HashFind(&def->def_devs, devhash); he = HashFind(&def->def_devs, devhash);
newdev = (Dev *)HashGetValue(he); newdev = (Dev *)HashGetValue(he);
if (newdev) if (newdev)
{ {
/* Duplicate device. Duplicates will only appear in res.ext files /* Duplicate device. Duplicates will only appear in res.ext files

View File

@ -44,8 +44,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#ifndef MAGIC_WRAPPER #ifndef MAGIC_WRAPPER
/* This must match the definition for extDevTable in extract/ExtBasic.c */ /* This must match the definition for extDevTable in extract/ExtBasic.c */
char *extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres", char *extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres",
"devcap", "devcaprev", "diode", "pdiode", "ndiode", "devcap", "devcaprev", "vsource", "diode", "pdiode",
"subckt", "rsubckt", "msubckt", "csubckt", NULL}; "ndiode", "subckt", "rsubckt", "msubckt", "csubckt", NULL};
#endif #endif
/* /*

View File

@ -847,7 +847,7 @@ EFLookDist(hn1, hn2, pMinDist, pMaxDist)
* EFHNOut -- * EFHNOut --
* *
* Output a hierarchical node name. * Output a hierarchical node name.
* The flags in EFTrimFlags control whether global (!) or local (#) * The flags in EFOutputFlags control whether global (!) or local (#)
* suffixes are to be trimmed. * suffixes are to be trimmed.
* *
* Results: * Results:
@ -868,13 +868,13 @@ EFHNOut(hierName, outf)
char *cp, c; char *cp, c;
if (hierName->hn_parent) efHNOutPrefix(hierName->hn_parent, outf); if (hierName->hn_parent) efHNOutPrefix(hierName->hn_parent, outf);
if (EFTrimFlags) if (EFOutputFlags)
{ {
cp = hierName->hn_name; cp = hierName->hn_name;
trimGlob = (EFTrimFlags & EF_TRIMGLOB); trimGlob = (EFOutputFlags & EF_TRIMGLOB);
trimLocal = (EFTrimFlags & EF_TRIMLOCAL); trimLocal = (EFOutputFlags & EF_TRIMLOCAL);
convComma = (EFTrimFlags & EF_CONVERTCOMMA); convComma = (EFOutputFlags & EF_CONVERTCOMMA);
convBrackets = (EFTrimFlags & EF_CONVERTBRACKETS); convBrackets = (EFOutputFlags & EF_CONVERTBRACKETS);
while (c = *cp++) while (c = *cp++)
{ {
if (*cp) if (*cp)

View File

@ -37,13 +37,18 @@ typedef unsigned char U_char;
#define EF_NONAMEMERGE 0x20 /* Don't merge unconnected nets */ #define EF_NONAMEMERGE 0x20 /* Don't merge unconnected nets */
/* with the same name. */ /* with the same name. */
/* Flags to control output of node names. Stored in EFTrimFlags */ /* Flags to control output of node names. Stored in EFOutputFlags */
#define EF_TRIMGLOB 0x01 /* Delete trailing '!' from names */ #define EF_TRIMGLOB 0x01 /* Delete trailing '!' from names */
#define EF_TRIMLOCAL 0x02 /* Delete trailing '#' from names */ #define EF_TRIMLOCAL 0x02 /* Delete trailing '#' from names */
#define EF_CONVERTCOMMA 0x04 /* Change ',' to '|' in names, else remove */ #define EF_CONVERTCOMMA 0x04 /* Change ',' to '|' in names, else remove */
#define EF_CONVERTEQUAL 0x08 /* Change '=' to ':' in names, else remove */ #define EF_CONVERTEQUAL 0x08 /* Change '=' to ':' in names, else remove */
#define EF_CONVERTBRACKETS 0x10 /* Change '[' and ']' to '_' in names */ #define EF_CONVERTBRACKETS 0x10 /* Change '[' and ']' to '_' in names */
#define EF_SHORT_MASK 0x30 /* Mask for handling port shorts */
#define EF_SHORT_NONE 0x00 /* Shorted ports are merged */
#define EF_SHORT_R 0x10 /* Shorted ports separated with 0 ohm resistor */
#define EF_SHORT_V 0x20 /* Shorted ports separated with 0 volt source */
/* /*
* capacitance type now set to float * capacitance type now set to float
*/ */
@ -327,7 +332,7 @@ extern char *EFLayerNames[];
extern int EFLayerNumNames; extern int EFLayerNumNames;
/* Output control flags */ /* Output control flags */
extern int EFTrimFlags; extern int EFOutputFlags;
/* -------------------------- Exported procedures --------------------- */ /* -------------------------- Exported procedures --------------------- */

View File

@ -55,8 +55,8 @@ static char sccsid[] = "@(#)ExtBasic.c 4.13 MAGIC (Berkeley) 12/5/85";
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
char *extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres", char *extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres",
"devcap", "devcaprev", "diode", "pdiode", "ndiode", "subckt", "devcap", "devcaprev", "vsource", "diode", "pdiode", "ndiode",
"rsubckt", "msubckt", "csubckt", NULL}; "subckt", "rsubckt", "msubckt", "csubckt", NULL};
#endif #endif
/* --------------------- Data local to this file ---------------------- */ /* --------------------- Data local to this file ---------------------- */

View File

@ -46,13 +46,14 @@ extern int ExtDoWarn; /* Bitmask of above */
#define DEV_RES 4 /* Resistor */ #define DEV_RES 4 /* Resistor */
#define DEV_CAP 5 /* Capacitor */ #define DEV_CAP 5 /* Capacitor */
#define DEV_CAPREV 6 /* Capacitor, terminals reversed */ #define DEV_CAPREV 6 /* Capacitor, terminals reversed */
#define DEV_DIODE 7 /* Diode */ #define DEV_VOLT 7 /* Voltage source (used for shorts) */
#define DEV_PDIODE 8 /* pDiode, same as Diode */ #define DEV_DIODE 8 /* Diode */
#define DEV_NDIODE 9 /* nDiode, terminals reversed */ #define DEV_PDIODE 9 /* pDiode, same as Diode */
#define DEV_SUBCKT 10 /* general-purpose subcircuit */ #define DEV_NDIODE 10 /* nDiode, terminals reversed */
#define DEV_RSUBCKT 11 /* Resistor-like subcircuit. */ #define DEV_SUBCKT 11 /* general-purpose subcircuit */
#define DEV_MSUBCKT 12 /* MOSFET-like subcircuit. */ #define DEV_RSUBCKT 12 /* Resistor-like subcircuit. */
#define DEV_CSUBCKT 13 /* Capacitor-like subcircuit. */ #define DEV_MSUBCKT 13 /* MOSFET-like subcircuit. */
#define DEV_CSUBCKT 14 /* Capacitor-like subcircuit. */
/* Device names for .ext file output (new in version 7.2) */ /* Device names for .ext file output (new in version 7.2) */
/* (defined in extract/ExtBasic.c *and* extflat/EFread.c) */ /* (defined in extract/ExtBasic.c *and* extflat/EFread.c) */
@ -60,14 +61,15 @@ extern int ExtDoWarn; /* Bitmask of above */
extern char *extDevTable[]; extern char *extDevTable[];
/* Extractor options */ /* Extractor options */
#define EXT_DOADJUST 0x01 /* Extract hierarchical adjustments */
#define EXT_DOCAPACITANCE 0x02 /* Extract capacitance */ #define EXT_DOADJUST 0x001 /* Extract hierarchical adjustments */
#define EXT_DOCOUPLING 0x04 /* Extract coupling capacitance */ #define EXT_DOCAPACITANCE 0x002 /* Extract capacitance */
#define EXT_DORESISTANCE 0x08 /* Extract resistance */ #define EXT_DOCOUPLING 0x004 /* Extract coupling capacitance */
#define EXT_DOLENGTH 0x10 /* Extract pathlengths */ #define EXT_DORESISTANCE 0x008 /* Extract resistance */
#define EXT_DOALL 0x1f /* ALL OF THE ABOVE */ #define EXT_DOLENGTH 0x010 /* Extract pathlengths */
#define EXT_DOLOCAL 0x20 /* Write to local directory only */ #define EXT_DOALL 0x01f /* ALL OF THE ABOVE */
#define EXT_DOLABELCHECK 0x40 /* Check for connections by label */ #define EXT_DOLOCAL 0x020 /* Write to local directory only */
#define EXT_DOLABELCHECK 0x040 /* Check for connections by label */
extern int ExtOptions; /* Bitmask of above */ extern int ExtOptions; /* Bitmask of above */