diff options
author | Ruben Undheim <ruben.undheim@gmail.com> | 2019-01-29 15:59:54 +0000 |
---|---|---|
committer | Ruben Undheim <ruben.undheim@gmail.com> | 2019-01-29 15:59:54 +0000 |
commit | 4bbc29ed94c310d0d18d50e31ccaca19d4182485 (patch) | |
tree | d8b0fdc135ca53f8962989661f569396e07ee588 | |
parent | ca2dc774a4ffd969122e2d75cd8b5488fcfbe235 (diff) |
New upstream version 1.5.118
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | base/flatten.c | 12 | ||||
-rw-r--r-- | base/netcmp.c | 25 | ||||
-rw-r--r-- | base/netfile.c | 11 | ||||
-rw-r--r-- | base/netgen.h | 6 | ||||
-rw-r--r-- | base/objlist.h | 12 | ||||
-rw-r--r-- | base/spice.c | 35 | ||||
-rw-r--r-- | base/verilog.c | 50 | ||||
-rw-r--r-- | tcltk/tclnetgen.c | 49 |
9 files changed, 128 insertions, 74 deletions
@@ -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: |