diff --git a/VERSION b/VERSION
index 6f3ba7cc..14f434b8 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-8.3.589
+8.3.590
diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c
index dd21fd8d..45690838 100644
--- a/extflat/EFbuild.c
+++ b/extflat/EFbuild.c
@@ -860,13 +860,13 @@ efBuildDevice(
const Rect *r, /* Coordinates of 1x1 rectangle entirely inside device */
int argc, /* Size of argv */
char *argv[]) /* Tokens for the rest of the dev line.
- * Starts with the last two position values, used to
- * hash the device record. The next arguments depend
- * on the type of device. The rest are taken in groups
- * of 3, one for each terminal. Each group of 3 consists
- * of the node name to which the terminal connects, the
- * length of the terminal, and an attribute list (or the
- * token 0).
+ * Starts after the four device coordinate arguments.
+ * The next arguments (0, 1, or 2) depend on the type of
+ * device, followed by optional parameters. The rest are
+ * taken in groups of 3, one for each terminal. Each
+ * group of 3 consists of the node name to which the
+ * terminal connects, the length of the terminal, and
+ * an attribute list (or the token 0).
*/
{
int n, nterminals, pn;
@@ -878,7 +878,7 @@ efBuildDevice(
int dev_type;
char ptype, *pptr, **av;
char devhash[64];
- int argstart = 1; /* start of terminal list in argv[] */
+ int termstart;
bool hasModel = strcmp(type, "None") ? TRUE : FALSE;
int area, perim; /* Total area, perimeter of primary type (i.e., channel) */
@@ -893,24 +893,37 @@ efBuildDevice(
devtmp.dev_width = 0;
devtmp.dev_params = NULL;
+ termstart = 1; /* Start of terminal list in argv[]; this is a default
+ * value if none of the cases below applies. The value
+ * of termstart does not initially account for parameter
+ * entries (=) but is adjusted as the
+ * parameters are parsed. The first terminal may be an
+ * (optional) substrate which is determined by whether
+ * the number of remaining arguments is divisible by 3
+ * or not.
+ */
switch (class)
{
case DEV_FET:
case DEV_MOSFET:
case DEV_ASYMMETRIC:
case DEV_BJT:
- argstart = 3;
+ /* Terminals start after L and W values, plus parameters */
+ termstart = 2;
break;
case DEV_DIODE:
case DEV_NDIODE:
case DEV_PDIODE:
- argstart = 0;
+ /* Terminals start immediately after parameters */
+ termstart = 0;
break;
case DEV_RES:
case DEV_CAP:
case DEV_CAPREV:
if (hasModel)
- argstart = 2;
+ /* Terminals start after L and W values, plus parameters */
+ termstart = 2;
+ /* Otherwise, terminals start after device value, plus parameters */
break;
case DEV_SUBCKT:
case DEV_VERILOGA:
@@ -918,13 +931,14 @@ efBuildDevice(
case DEV_RSUBCKT:
case DEV_CSUBCKT:
case DEV_DSUBCKT:
- argstart = 0;
+ /* Terminals start immediately after parameters */
+ termstart = 0;
}
devp = efGetDeviceParams(type);
/* Parse initial arguments for parameters */
- while ((pptr = strchr(argv[argstart], '=')) != NULL)
+ while ((pptr = strchr(argv[termstart], '=')) != NULL)
{
/* If the parameter is in the parameter list "devp", then save
* the value as appropriate. If not, then the entire phrase
@@ -936,7 +950,7 @@ efBuildDevice(
*pptr = '\0';
for (sparm = devp; sparm; sparm = sparm->parm_next)
- if (!strncasecmp(sparm->parm_type, argv[argstart], 2))
+ if (!strncasecmp(sparm->parm_type, argv[termstart], 2))
break;
*pptr = '=';
if (sparm == NULL)
@@ -944,18 +958,18 @@ efBuildDevice(
/* 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]);
+ newparm->parm_name = StrDup((char **)NULL, argv[termstart]);
newparm->parm_next = devtmp.dev_params;
devtmp.dev_params = newparm;
- argstart++;
+ termstart++;
continue;
}
pptr++;
- switch(*argv[argstart])
+ switch(*argv[termstart])
{
case 'a':
- if ((pptr - argv[argstart]) == 2)
+ if ((pptr - argv[termstart]) == 2)
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
* locScale * locScale);
else
@@ -963,7 +977,7 @@ efBuildDevice(
/* Check for a0, a1, a2, ... If a0, handle like "a".
* Otherwise, don't handle it here.
*/
- pn = *(argv[argstart] + 1) - '0';
+ pn = *(argv[termstart] + 1) - '0';
if (pn == 0)
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
* locScale * locScale);
@@ -971,21 +985,21 @@ efBuildDevice(
break;
case 'p':
- if ((pptr - argv[argstart]) == 2)
+ if ((pptr - argv[termstart]) == 2)
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';
+ pn = *(argv[termstart] + 1) - '0';
if (pn == 0)
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
}
break;
case 'l':
- if ((pptr - argv[argstart]) == 2)
+ if ((pptr - argv[termstart]) == 2)
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
else
{
@@ -995,14 +1009,14 @@ efBuildDevice(
* values like "a1, a2, ..." or "p1, p2, ...".
*/
- pn = *(argv[argstart] + 1) - '0';
+ pn = *(argv[termstart] + 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_name = StrDup((char **)NULL, argv[termstart]);
newparm->parm_next = devtmp.dev_params;
devtmp.dev_params = newparm;
}
@@ -1010,7 +1024,28 @@ efBuildDevice(
break;
case 'w':
- devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
+ if ((pptr - argv[termstart]) == 2)
+ devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
+ else
+ {
+ /* Check for w0, w1, w2, ... If w0, handle like "w".
+ * 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[termstart] + 1) - '0';
+ if (pn == 0)
+ devtmp.dev_width = (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[termstart]);
+ newparm->parm_next = devtmp.dev_params;
+ devtmp.dev_params = newparm;
+ }
+ }
break;
case 'c':
devtmp.dev_cap = (float)atof(pptr);
@@ -1019,7 +1054,7 @@ efBuildDevice(
devtmp.dev_res = (float)atof(pptr);
break;
}
- argstart++;
+ termstart++;
}
/* Check for optional substrate node */
@@ -1027,6 +1062,7 @@ efBuildDevice(
{
case DEV_RES:
case DEV_CAP:
+ case DEV_BJT:
case DEV_CAPREV:
case DEV_RSUBCKT:
case DEV_CSUBCKT:
@@ -1037,22 +1073,22 @@ efBuildDevice(
case DEV_DIODE:
case DEV_NDIODE:
case DEV_PDIODE:
- n = argc - argstart;
+ n = argc - termstart;
if ((n % 3) == 1)
{
- if (strncmp(argv[argstart], "None", 4) != 0)
- devtmp.dev_subsnode = efBuildDevNode(def, argv[argstart], TRUE);
+ if (strncmp(argv[termstart], "None", 4) != 0)
+ devtmp.dev_subsnode = efBuildDevNode(def, argv[termstart], TRUE);
- argstart++;
+ termstart++;
}
break;
}
- /* Between argstart and argc, we should only have terminal triples */
- if (((argc - argstart) % 3) != 0)
+ /* Between termstart and argc, we should only have terminal triples */
+ if (((argc - termstart) % 3) != 0)
return 1;
- nterminals = (argc - argstart) / 3;
+ nterminals = (argc - termstart) / 3;
dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, type);
@@ -1215,17 +1251,17 @@ efBuildDevice(
case DEV_ASYMMETRIC:
case DEV_BJT:
/* "None" in the place of the substrate name means substrate is ignored */
- if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
+ if ((termstart == 3) && (strncmp(argv[2], "None", 4) != 0))
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
break;
case DEV_RES:
- if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
+ if ((termstart == 3) && (strncmp(argv[2], "None", 4) != 0))
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
break;
case DEV_CAP:
case DEV_CAPREV:
- if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
+ if ((termstart == 3) && (strncmp(argv[2], "None", 4) != 0))
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
break;
@@ -1235,7 +1271,7 @@ efBuildDevice(
#define TERM_PERIM 1
#define TERM_ATTRS 2
- for (av = &argv[argstart], n = 0; n < nterminals; n++, av += 3)
+ for (av = &argv[termstart], n = 0; n < nterminals; n++, av += 3)
{
term = &newdev->dev_terms[n];
term->dterm_node = efBuildDevNode(def, av[TERM_NAME], FALSE);