summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2019-01-29 15:59:54 +0000
committerRuben Undheim <ruben.undheim@gmail.com>2019-01-29 15:59:54 +0000
commit4bbc29ed94c310d0d18d50e31ccaca19d4182485 (patch)
treed8b0fdc135ca53f8962989661f569396e07ee588
parentca2dc774a4ffd969122e2d75cd8b5488fcfbe235 (diff)
New upstream version 1.5.118
-rw-r--r--VERSION2
-rw-r--r--base/flatten.c12
-rw-r--r--base/netcmp.c25
-rw-r--r--base/netfile.c11
-rw-r--r--base/netgen.h6
-rw-r--r--base/objlist.h12
-rw-r--r--base/spice.c35
-rw-r--r--base/verilog.c50
-rw-r--r--tcltk/tclnetgen.c49
9 files changed, 128 insertions, 74 deletions
diff --git a/VERSION b/VERSION
index d2fdc33..3c2b324 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.5.116
+1.5.118
diff --git a/base/flatten.c b/base/flatten.c
index 2aedcf2..96bfdce 100644
--- a/base/flatten.c
+++ b/base/flatten.c
@@ -1659,7 +1659,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) {
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
- (ecomp->cell1->class == CLASS_RES)) {
+ ((ecomp->cell1->class == CLASS_RES) ||
+ (ecomp->cell1->class == CLASS_VSOURCE))) {
int node1 = -1, node2 = -1;
lob = NULL;
for (ob1 = tc1->cell; ob1; ) {
@@ -1703,7 +1704,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (found) break;
}
if (found) {
- Fprintf(stdout, "Removing zero-valued device"
+ Fprintf(stdout, "Removing zero-valued device "
"%s from cell %s makes a better match\n",
tsub1->name,
tc1->name);
@@ -1763,7 +1764,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
// Repeat the last section for the other circuit
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell2 != NULL) &&
- (ecomp->cell2->class == CLASS_RES)) {
+ ((ecomp->cell2->class == CLASS_RES) ||
+ (ecomp->cell2->class == CLASS_VSOURCE))) {
int node1 = -1, node2 = -1;
lob = NULL;
for (ob2 = tc2->cell; ob2; ) {
@@ -1807,7 +1809,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (found) break;
}
if (found) {
- Fprintf(stdout, "Removing zero-valued device"
+ Fprintf(stdout, "Removing zero-valued device "
"%s from cell %s makes a better match\n",
tsub2->name,
tc2->name);
@@ -1917,7 +1919,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
char *dstr = NULL;
tc2 = LookupCellFile(ob2->model.class, ecomp0X->cell2->file);
if (tc2->flags & CELL_DUPLICATE) {
- dstr = strstr(ob1->model.class, "[[");
+ dstr = strstr(ob2->model.class, "[[");
if (dstr) *dstr = '\0';
}
ncomp = (ECompare *)HashInt2Lookup(ob2->model.class,
diff --git a/base/netcmp.c b/base/netcmp.c
index 69dc11b..38272fb 100644
--- a/base/netcmp.c
+++ b/base/netcmp.c
@@ -3728,6 +3728,7 @@ int series_combine(struct objlist *ob1, struct nlist *tp1, int idx1, int run1,
typedef struct _propsort {
double value;
int idx;
+ unsigned char flags;
struct objlist *ob;
} propsort;
@@ -3748,7 +3749,9 @@ static int compsort(const void *p1, const void *p2)
/*--------------------------------------------------------------*/
/* Sort properties of ob1 starting at property idx1 up to */
/* property (idx1 + run). Use series critical property for */
-/* sorting. Multiply critical property by S before sort. */
+/* sorting. Combine properties by S before sort. Note that */
+/* use of "S" implies that the devices are the same in all */
+/* properties. */
/* ob1 is the record before the first property. */
/*--------------------------------------------------------------*/
@@ -3764,8 +3767,8 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
obn = ob1->next;
for (i = 0; i < idx1; i++) obn = obn->next;
- // Create a structure of length (run) to hold critical property
- // value and index. Then sort that list, then use the sorted
+ // Create a structure of length (run) to hold property value
+ // and index. Then sort that list, then use the sorted
// indexes to sort the actual property linked list.
proplist = (propsort *)MALLOC(run * sizeof(propsort));
@@ -4376,16 +4379,16 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
kl->idx = pcount++;
// Set critical property index, if there is one.
- // To do: deal with possibility of multiple critical properties
- // per instance?
- if ((series == FALSE) && (kl->merge & MERGE_P_CRIT)) {
- crit = kl->idx;
- ctype = kl->merge & (MERGE_P_ADD | MERGE_P_PAR);
+ if (series == FALSE) {
+ if (kl->merge & MERGE_P_CRIT) crit = kl->idx;
+ if (kl->merge & (MERGE_P_ADD | MERGE_P_PAR))
+ ctype = kl->merge & (MERGE_P_ADD | MERGE_P_PAR);
}
- else if ((series == TRUE) && (kl->merge & MERGE_S_CRIT)) {
- crit = kl->idx;
- ctype = kl->merge & (MERGE_S_ADD | MERGE_S_PAR);
+ else if (series == TRUE) {
+ if (kl->merge & MERGE_S_CRIT) crit = kl->idx;
+ if (kl->merge & (MERGE_S_ADD | MERGE_S_PAR))
+ ctype = kl->merge & (MERGE_S_ADD | MERGE_S_PAR);
}
kl = (struct property *)HashNext(&(tp->propdict));
diff --git a/base/netfile.c b/base/netfile.c
index 36020ec..dd29d3c 100644
--- a/base/netfile.c
+++ b/base/netfile.c
@@ -437,7 +437,10 @@ void SpiceSkipNewLine(void)
/* delimiters (this presumably could be further extended as needed). */
/* so ",;()" would be a valid delimiter set, but to include C-style */
/* comments and verilog-style parameter lists, one would need */
-/* ",;()X/**///#(". */
+/* "X/**///#(X,;()". Two-character delimiters should go first so that */
+/* they have precedence over one-character delimiters. 'X' should be */
+/* the first character of the delimiter string in addition to marking */
+/* the boundary between two-character and one-character delimiters. */
/*----------------------------------------------------------------------*/
char *strdtok(char *pstring, char *delim1, char *delim2)
@@ -477,10 +480,10 @@ char *strdtok(char *pstring, char *delim1, char *delim2)
/* return the token. */
for (s = stoken; *s; s++) {
- twofer = FALSE;
- for (s2 = delim2; s2 && *s2; s2++) {
+ twofer = (delim2 && (*delim2 == 'X')) ? TRUE : FALSE;
+ for (s2 = ((twofer == TRUE) ? delim2 + 1 : delim2); s2 && *s2; s2++) {
if (*s2 == 'X') {
- twofer = TRUE;
+ twofer = FALSE;
continue;
}
if (twofer) {
diff --git a/base/netgen.h b/base/netgen.h
index a3a18e7..90d28c1 100644
--- a/base/netgen.h
+++ b/base/netgen.h
@@ -87,8 +87,10 @@ extern int PrematchLists(char *, int, char *, int);
#define CLASS_DIODE 16 /* standard SPICE diode */
#define CLASS_INDUCTOR 17 /* standard SPICE inductor */
#define CLASS_XLINE 18 /* transmission line model */
-#define CLASS_MODULE 19 /* sim "x"; black-box subcircuit */
-#define CLASS_UNDEF 20 /* not defined; error */
+#define CLASS_VSOURCE 19 /* independent voltage source */
+#define CLASS_ISOURCE 20 /* independent current source */
+#define CLASS_MODULE 21 /* sim "x"; black-box subcircuit */
+#define CLASS_UNDEF 22 /* not defined; error */
extern char *P(char *fname, char *inststr, char *drain, char *gate, char *source);
extern char *P4(char *fname, char *inststr, char *drain, char *gate, char *source,
diff --git a/base/objlist.h b/base/objlist.h
index 6e8be6c..5ed4b41 100644
--- a/base/objlist.h
+++ b/base/objlist.h
@@ -108,13 +108,15 @@ struct valuelist {
#define MERGE_P_ADD 0x01 /* Properties sum with device parallel merge */
#define MERGE_P_PAR 0x02 /* Properties add in parallel with parallel merge */
#define MERGE_P_CRIT 0x04 /* This property enables parallel merging */
+#define MERGE_P_XCRIT 0x08 /* Old "critical" behavior (deprecated) */
-#define MERGE_S_ADD 0x08 /* Properties sum with device series merge */
-#define MERGE_S_PAR 0x10 /* Properties add in parallel with series merge */
-#define MERGE_S_CRIT 0x20 /* This property enables series merging */
+#define MERGE_S_ADD 0x10 /* Properties sum with device series merge */
+#define MERGE_S_PAR 0x20 /* Properties add in parallel with series merge */
+#define MERGE_S_CRIT 0x40 /* This property enables series merging */
+#define MERGE_S_XCRIT 0x80 /* Old "critical" behavior (deprecated) */
-#define MERGE_P_MASK (MERGE_P_ADD | MERGE_P_PAR | MERGE_P_CRIT)
-#define MERGE_S_MASK (MERGE_S_ADD | MERGE_S_PAR | MERGE_S_CRIT)
+#define MERGE_P_MASK (MERGE_P_ADD | MERGE_P_PAR | MERGE_P_CRIT | MERGE_P_XCRIT)
+#define MERGE_S_MASK (MERGE_S_ADD | MERGE_S_PAR | MERGE_S_CRIT | MERGE_S_XCRIT)
#define MERGE_ALL_MASK (MERGE_P_MASK | MERGE_S_MASK)
/* Although the above are flags, "ADD" and "PAR" are mutually exclusive. */
diff --git a/base/spice.c b/base/spice.c
index 9736c66..060c2f9 100644
--- a/base/spice.c
+++ b/base/spice.c
@@ -117,6 +117,12 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
case CLASS_NPN: case CLASS_PNP: case CLASS_BJT:
spice_class = 'Q';
break;
+ case CLASS_VSOURCE:
+ spice_class = 'V';
+ break;
+ case CLASS_ISOURCE:
+ spice_class = 'I';
+ break;
case CLASS_RES: case CLASS_RES3:
spice_class = 'R';
break;
@@ -172,7 +178,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
break;
}
- /* caps and resistors, print out device value */
+ /* caps, resistors, voltage and current sources, print out device value */
/* print out device type (model/subcircuit name) */
@@ -217,6 +223,23 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
FlushString(" %s", model); /* semiconductor resistor */
break;
+ case CLASS_VSOURCE:
+ case CLASS_ISOURCE:
+ ob = ob->next;
+ if (ob->type == PROPERTY) {
+ struct valuelist *vl;
+ int i;
+ for (i == 0;; i++) {
+ vl = &(ob->instance.props[i]);
+ if (vl->type == PROP_ENDLIST) break;
+ else if (vl->type == PROP_VALUE) {
+ FlushString(" %g", vl->value.dval);
+ break;
+ }
+ }
+ }
+ break;
+
default:
FlushString(" %s", model); /* everything else */
}
@@ -711,6 +734,12 @@ skip_ends:
else if (!strcasecmp(nexttok, "R")) {
class = CLASS_RES;
}
+ else if (!strcasecmp(nexttok, "V")) {
+ class = CLASS_VSOURCE;
+ }
+ else if (!strcasecmp(nexttok, "I")) {
+ class = CLASS_ISOURCE;
+ }
else if (!strcasecmp(nexttok, "C")) {
class = CLASS_CAP;
}
@@ -1436,7 +1465,7 @@ skip_ends:
Port("pos");
Port("neg");
PropertyInteger(model, filenum, "M", 0, 1);
- SetClass(CLASS_MODULE);
+ SetClass(CLASS_VSOURCE);
EndCell();
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
}
@@ -1490,7 +1519,7 @@ skip_ends:
Port("pos");
Port("neg");
PropertyInteger(model, filenum, "M", 0, 1);
- SetClass(CLASS_MODULE);
+ SetClass(CLASS_ISOURCE);
EndCell();
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
}
diff --git a/base/verilog.c b/base/verilog.c
index 0eaa59e..78d70b1 100644
--- a/base/verilog.c
+++ b/base/verilog.c
@@ -59,8 +59,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
// See netfile.c for explanation of delimiters. 'X'
// separates single-character delimiters from two-character delimiters.
-#define VLOG_DELIMITERS ",;:(){}[]=X///**/#("
-#define VLOG_PIN_NAME_DELIMITERS "()X///**/"
+#define VLOG_DELIMITERS "X///**/#((**)X,::(){}[]="
+#define VLOG_PIN_NAME_DELIMITERS "X///**/(**)X()"
// Global storage for verilog parameters
struct hashdict verilogparams;
@@ -1062,14 +1062,25 @@ skip_endmodule:
}
}
- else if (match(nexttok, "wire")) { /* wire = node */
+ else if (match(nexttok, "wire") || match(nexttok, "assign")) { /* wire = node */
struct bus wb, *nb;
char nodename[128];
+ int is_assignment = FALSE;
+ struct objlist *lhs, *rhs;
+
+ // Several allowed uses of "assign":
+ // "assign a = b" joins two nets.
+ // "assign a = {b, c, ...}" creates a bus from components.
+ // "assign" using any boolean arithmetic is not structural verilog.
+
SkipTokNoNewline(VLOG_DELIMITERS);
if (match(nexttok, "real")) SkipTokNoNewline(VLOG_DELIMITERS);
while (nexttok != NULL) {
- /* Handle bus notation */
- if (GetBusTok(&wb) == 0) {
+ if (match(nexttok, "=")) {
+ is_assignment = TRUE;
+ }
+ else if (GetBusTok(&wb) == 0) {
+ /* Handle bus notation */
SkipTokNoNewline(VLOG_DELIMITERS);
if (wb.start > wb.end) {
for (i = wb.end; i <= wb.start; i++) {
@@ -1091,10 +1102,28 @@ skip_endmodule:
HashPtrInstall(nexttok, nb, &buses);
}
else {
- if (LookupObject(nexttok, CurrentCell) == NULL)
+ if (is_assignment) {
+ /* Handle assignment statements */
+ /* To be done: Handle where both are bus names, and */
+ /* where lhs is a bus name and rhs is a list of nets */
+ if ((rhs = LookupObject(nexttok, CurrentCell)) != NULL) {
+ join(lhs->name, rhs->name);
+ }
+ else {
+ Printf("Module '%s' is not structural verilog, "
+ "making black-box.\n", model);
+ SetClass(CLASS_MODULE);
+ goto skip_endmodule;
+ }
+ is_assignment = FALSE;
+ }
+ else if (LookupObject(nexttok, CurrentCell) == NULL)
Node(nexttok);
+ lhs = LookupObject(nexttok, CurrentCell);
}
- SkipTokNoNewline(VLOG_DELIMITERS);
+ do {
+ SkipTokNoNewline(VLOG_DELIMITERS);
+ } while (nexttok && match(nexttok, ";"));
}
}
else if (match(nexttok, "endmodule")) {
@@ -1106,8 +1135,7 @@ skip_endmodule:
// Ignore any other directive starting with a backtick
SkipNewLine(VLOG_DELIMITERS);
}
- else if (match(nexttok, "reg") || match(nexttok, "assign")
- || match(nexttok, "always")) {
+ else if (match(nexttok, "reg") || match(nexttok, "always")) {
Printf("Module '%s' is not structural verilog, making black-box.\n", model);
// To be done: Remove any contents (but may not be necessary)
// Recast as module
@@ -1680,10 +1708,6 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
kl->pdefault.ival = 1;
HashPtrInstall(kl->key, kl, &verilogdefs);
- /* All verilog files should start with a comment line, */
- /* but we won't depend upon it. Any comment line */
- /* will be handled by the main Verilog file processing. */
-
ReadVerilogFile(fname, filenum, &CellStack, blackbox);
CloseParseFile();
diff --git a/tcltk/tclnetgen.c b/tcltk/tclnetgen.c
index 8b21a19..14cdd2c 100644
--- a/tcltk/tclnetgen.c
+++ b/tcltk/tclnetgen.c
@@ -3227,12 +3227,11 @@ _netcmp_property(ClientData clientData,
};
char *combineoptions[] = {
- "none", "par", "add", "par_critical", "add_critical", NULL
+ "none", "par", "add", "critical", NULL
};
enum CombineOptionIdx {
- COMB_NONE_IDX, COMB_PAR_IDX, COMB_ADD_IDX, COMB_PAR_CRITICAL_IDX,
- COMB_ADD_CRITICAL_IDX
+ COMB_NONE_IDX, COMB_PAR_IDX, COMB_ADD_IDX, COMB_CRITICAL_IDX
};
char *yesno[] = {
@@ -3268,24 +3267,24 @@ _netcmp_property(ClientData clientData,
break;
case CLASS_RES: case CLASS_RES3:
PropertyMerge(tp->name, tp->file, "w",
- MERGE_P_PAR | MERGE_P_CRIT, MERGE_ALL_MASK);
+ MERGE_P_PAR | MERGE_S_CRIT, MERGE_ALL_MASK);
PropertyMerge(tp->name, tp->file, "l",
- MERGE_S_ADD | MERGE_S_CRIT, MERGE_ALL_MASK);
+ MERGE_S_ADD | MERGE_P_CRIT, MERGE_ALL_MASK);
PropertyMerge(tp->name, tp->file, "value",
MERGE_S_ADD | MERGE_P_PAR, MERGE_ALL_MASK);
tp->flags |= COMB_SERIES;
break;
case CLASS_CAP: case CLASS_ECAP: case CLASS_CAP3:
- // NOTE: No attempt to combine area, width, or length;
- // only value.
+ /* NOTE: No attempt to modify perimeter, length, or width */
+ PropertyMerge(tp->name, tp->file, "area",
+ MERGE_P_ADD | MERGE_S_PAR, MERGE_ALL_MASK);
PropertyMerge(tp->name, tp->file, "value",
- MERGE_P_ADD | MERGE_P_CRIT |
- MERGE_S_PAR | MERGE_S_CRIT, MERGE_ALL_MASK);
+ MERGE_P_ADD | MERGE_S_PAR, MERGE_ALL_MASK);
+ tp->flags |= COMB_SERIES;
break;
case CLASS_INDUCTOR:
PropertyMerge(tp->name, tp->file, "value",
- MERGE_P_PAR | MERGE_P_CRIT |
- MERGE_S_PAR | MERGE_S_CRIT, MERGE_ALL_MASK);
+ MERGE_S_ADD | MERGE_P_PAR, MERGE_ALL_MASK);
tp->flags |= COMB_SERIES;
break;
}
@@ -3437,8 +3436,7 @@ _netcmp_property(ClientData clientData,
mergemask = MERGE_S_MASK;
switch (idx2) {
case COMB_NONE_IDX:
- mergeval &= ~(MERGE_S_ADD | MERGE_S_PAR
- | MERGE_S_CRIT);
+ mergeval &= ~(MERGE_S_MASK);
tp->flags &= ~COMB_SERIES;
break;
case COMB_PAR_IDX:
@@ -3449,12 +3447,8 @@ _netcmp_property(ClientData clientData,
mergeval |= MERGE_S_ADD;
tp->flags |= COMB_SERIES;
break;
- case COMB_PAR_CRITICAL_IDX:
- mergeval |= (MERGE_S_PAR | MERGE_S_CRIT);
- tp->flags |= COMB_SERIES;
- break;
- case COMB_ADD_CRITICAL_IDX:
- mergeval |= (MERGE_S_ADD | MERGE_S_CRIT);
+ case COMB_CRITICAL_IDX:
+ mergeval |= MERGE_S_CRIT;
tp->flags |= COMB_SERIES;
break;
}
@@ -3463,8 +3457,7 @@ _netcmp_property(ClientData clientData,
mergemask = MERGE_P_MASK;
switch (idx2) {
case COMB_NONE_IDX:
- mergeval &= ~(MERGE_P_ADD | MERGE_P_PAR
- | MERGE_P_CRIT);
+ mergeval &= ~(MERGE_P_MASK);
tp->flags |= COMB_NO_PARALLEL;
break;
case COMB_PAR_IDX:
@@ -3475,12 +3468,8 @@ _netcmp_property(ClientData clientData,
mergeval |= MERGE_P_ADD;
tp->flags &= ~COMB_NO_PARALLEL;
break;
- case COMB_PAR_CRITICAL_IDX:
- mergeval |= (MERGE_P_PAR | MERGE_P_CRIT);
- tp->flags &= ~COMB_NO_PARALLEL;
- break;
- case COMB_ADD_CRITICAL_IDX:
- mergeval |= (MERGE_P_ADD | MERGE_P_CRIT);
+ case COMB_CRITICAL_IDX:
+ mergeval |= MERGE_P_CRIT;
tp->flags &= ~COMB_NO_PARALLEL;
break;
}
@@ -3695,7 +3684,7 @@ _netcmp_property(ClientData clientData,
mergeval = MERGE_P_ADD;
break;
case ADD_CRIT_IDX:
- mergeval = MERGE_P_ADD | MERGE_P_CRIT;
+ mergeval = MERGE_P_ADD | MERGE_P_XCRIT;
break;
case PAR_ONLY_IDX:
case PAR2_ONLY_IDX:
@@ -3703,12 +3692,12 @@ _netcmp_property(ClientData clientData,
break;
case PAR_CRIT_IDX:
case PAR2_CRIT_IDX:
- mergeval = MERGE_P_PAR | MERGE_P_CRIT;
+ mergeval = MERGE_P_PAR | MERGE_P_XCRIT;
break;
case SER_CRIT_IDX:
case SER2_CRIT_IDX:
case SER3_CRIT_IDX:
- mergeval = MERGE_S_ADD | MERGE_S_CRIT;
+ mergeval = MERGE_S_ADD | MERGE_S_XCRIT;
break;
case SER_IDX:
case SER2_IDX: