Compare commits

..
30 Commits
Author SHA1 Message Date
Tim Edwards 1b2cd1497c Merge branch 'master' into netgen-1.5 2020-07-30 03:00:28 -04:00
Tim Edwards 71ad228d8d Modified the symmetry breaking routine that arbitrarily resolves
automorphisms so that it arbitrarily assigns all pairs from
circuit1 and circuit2 at once rather than assigning one pair at
a time and rerunning to convergence.  I'm not sure of the validity
of this, other than that I have never seen a circuit fail to match
after resolving automorphisms, leading me to believe that the way
the symmetry breaking is done is irrelevant.
2020-07-29 21:13:45 -04:00
Tim Edwards 339a0d5d4e Updated version to force the new tarball and github mirror. 2020-07-29 13:59:24 -04:00
Tim Edwards 9cebb76787 Corrected a problem in ResolveAutomorphsByProperty() that causes
long run-times even when there are no properties to check.  Corrected
a problem with SPICE and verilog netlist reading which arbitrarily
replaces file extensions even when a file extension is given,
resulting in reading the wrong file.
2020-07-29 13:57:08 -04:00
Tim Edwards d9d5a46c6e Merge branch 'master' into netgen-1.5 2020-07-25 03:00:09 -04:00
Tim Edwards 251622c8bc Corrected the routines DescendCountQueue and DescendCompareQueue
to include type CLASS_MODULE in the list of types to descend into,
since "module" (black-box) types need to be checked for pin
matching even if they have no contents.  This allows two verilog
netlists to be compared against each other.
2020-07-24 20:50:07 -04:00
Tim Edwards d73b711e3a Merge branch 'master' into netgen-1.5 2020-07-02 03:00:09 -04:00
Tim Edwards 18739235a9 Extended the code from the last commit to cover cases in which the
definition covers multiple lines;  this also is a general handler
of the backslash-newline continuation line.
2020-07-01 16:00:54 -04:00
Tim Edwards 07c493c796 Corrected the verilog parser's behavior with respect to string
definitions:  Now correctly parses everything from the definition
name to the end of line as the definition value.  Also:  The
search for definitions in the body of the text does not reject
non-alphanumerics "_" and "$" in the definition name, without
which definition names containing those characters will go
unrecongized.  Have not yet extended this to multi-line definition
values.
2020-07-01 14:28:00 -04:00
Tim Edwards cca0e4b3f3 Corrected an error in bundle assignment that failed to make a copy
of the root name of the LHS net, and so would use the last root
name copied, which might have belonged to something entirely
different, or nothing at all.
2020-07-01 13:11:37 -04:00
Tim Edwards 1428580109 Merge branch 'master' into netgen-1.5 2020-06-17 03:00:38 -04:00
Tim Edwards fb0e1d10b0 Added back a correction that did not get made in this code base
and so didn't make it into the commit.  Handles implicit pins in
verilog.
2020-06-16 17:16:30 -04:00
Tim Edwards 6f81e1d294 Removed a restriction on the "equate pins" command such that pins
are matched on circuits that have no elements.  This condition
does not necessarily indicate an error, and matching pins has no
adverse affect (while refusing to match them certainly can).
2020-06-16 15:56:59 -04:00
Tim Edwards cec6d89474 Corrected an uninitialized variable error in the verilog reading code
that produces a segfault condition.
2020-06-16 12:52:29 -04:00
Tim Edwards 210dfb25c3 Merge branch 'master' into netgen-1.5 2020-06-04 03:00:24 -04:00
Tim Edwards 9bcca3ac21 Corrected the verilog parsing (yet again!) so that it does not
mistakenly flag bus delimiter characters inside backslash-escaped
names when looking for bus delimiters.
2020-06-03 17:00:42 -04:00
Tim Edwards 27f2ab8b3f Merge branch 'master' into netgen-1.5 2020-03-28 03:00:24 -04:00
Tim Edwards 6ae6a246e9 Some additional changes to better identify behavioral verilog
blocks.
2020-03-27 15:09:56 -04:00
Tim Edwards d985ea340e One more bug fix. . . unitialized variable error. 2020-03-27 12:47:24 -04:00
Tim Edwards 5ea7916ff1 Final (I hope) correction to netgen for handling signal wraparound
for buses applied to instance arrayes.
2020-03-27 12:15:57 -04:00
Tim Edwards cf9dedb2f7 Additional corrections; needed to maintain port width in the
scan structure because it is used in two different places and
would have to run a cost-prohibitive search of the cell's
object list.  Also, was missing recording a bus input/output
signal from an "input" or "output" statement (as opposed to
in-line signals in the I/O list).
2020-03-27 11:31:21 -04:00
Tim Edwards da667c3b17 Corrected handling of wire bundles in the verilog parser. 2020-03-27 08:48:48 -04:00
Tim Edwards 1be00bbd99 Merge branch 'master' into netgen-1.5 2020-03-27 03:00:21 -04:00
Tim Edwards 36aa373fb2 Corrected an error in the verilog read to correctly assign signals
to bus pins over an array of instances.  Takes care of the three
situations where the length of the signal bus equals the number of
instances;  where the length of the signal bus is a multiple of
the number of instances;  and where the number of instances is a
multiple of the length of the signal bus.
2020-03-26 11:53:52 -04:00
Tim Edwards 18f230fc46 Changed the default string size for tmpstr in flattenInstancesOf
from 200 to 1024.  Probably this should be dynamically allocated
and expanded as needed, as it is holding names that are of
increasing length as a hierarchy is descended and the instance
prefixes appended to the name.
2020-03-26 09:04:52 -04:00
Tim Edwards 03b241a5d4 Merge branch 'master' into netgen-1.5 2020-03-11 03:00:17 -04:00
Tim Edwards 0f5a618353 Corrected some problems with property matching in netcmp.c.
However, I have identified an issue that has not yet been resolved,
which is that there can be automorphisms that are potentially
broken by property matching.  Currently, the automorphisms are
arbitrarily resolved, then properties are matched---and may fail
accordingly.
2020-03-10 21:39:41 -04:00
Tim Edwards 43cebd1ef9 Merge branch 'master' into netgen-1.5 2020-03-06 03:00:39 -05:00
Tim Edwards 983c654086 Corrected error in property matching that can cause a segfault. 2020-03-05 15:20:46 -05:00
Tim Edwards 515fccc633 Corrected error in printing the name of a file when it is not found
in an "include" statement in either SPICE or verilog.  Modified pin
matching behavior to force cells in both netlists to be marked as
black-box entries if either one is marked as a black-box entry (this
may not be needed, but shouldn't do any harm, either).
2020-03-05 09:41:22 -05:00
9 changed files with 398 additions and 121 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.142
1.5.151
+1 -1
View File
@@ -259,7 +259,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
struct nlist *ChildCell;
struct objlist *tmp, *ob2, *ob3;
int notdone, rnodenum;
char tmpstr[200];
char tmpstr[1024];
int nextnode, oldmax, numflat = 0;
#if !OLDPREFIX
int prefixlength;
+101 -23
View File
@@ -3145,7 +3145,9 @@ void DescendCountQueue(struct nlist *tc, int *level, int loclevel)
if (ob->type == FIRSTPIN) {
/* First check if there is a class equivalent */
tcsub = LookupCellFile(ob->model.class, tc->file);
if (!tcsub || (tcsub->class != CLASS_SUBCKT)) continue;
/* Module (black-box) class needs pin checking */
if (!tcsub || ((tcsub->class != CLASS_SUBCKT) &&
(tcsub->class != CLASS_MODULE))) continue;
else if (tcsub == tc) continue;
DescendCountQueue(tcsub, level, loclevel + 1);
}
@@ -3238,7 +3240,8 @@ void DescendCompareQueue(struct nlist *tc, struct nlist *tctop, int stoplevel,
tcsub = NULL;
if (ob->type == FIRSTPIN) {
tcsub = LookupCellFile(ob->model.class, tc->file);
if (!tcsub || (tcsub->class != CLASS_SUBCKT)) continue;
if (!tcsub || ((tcsub->class != CLASS_SUBCKT) &&
(tcsub->class != CLASS_MODULE))) continue;
else if (tcsub == tc) continue;
DescendCompareQueue(tcsub, tctop, stoplevel, loclevel + 1, flip);
}
@@ -3825,6 +3828,51 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
}
obp->next = obn; /* Restore last link */
// In series runs, all records after the first start with tag "+".
// If the tag got moved to the first record, then move it down to
// the record that is missing the tag.
obn = ob1->next;
if (!strcmp(obn->instance.props[0].key, "_tag")) {
char *tmpkey;
struct valuelist *kv2;
int l;
if (!strcmp(obn->instance.props[0].value.string, "+")) {
/* Remove this property tag "+" */
FREE(obn->instance.props[0].key);
FREE(obn->instance.props[0].value.string);
for (p = 0;; p++) {
obn->instance.props[p].key = obn->instance.props[p + 1].key;
obn->instance.props[p].type = obn->instance.props[p + 1].type;
obn->instance.props[p].value = obn->instance.props[p + 1].value;
if (obn->instance.props[p].type == PROP_ENDLIST) break;
}
for (i = 1; i < run; i++) {
obn = obn->next;
if (strcmp(obn->instance.props[0].key, "_tag")) {
for (p = 1;; p++)
if (obn->instance.props[p].type == PROP_ENDLIST) break;
/* Create a new property record to hold all the existing */
/* properties plus the tag at the beginning. */
kv2 = (struct valuelist *)MALLOC((p + 2) * sizeof(struct valuelist));
kv2->key = strsave("_tag");
kv2->type = PROP_STRING;
kv2->value.string = (char *)MALLOC(2);
kv2->value.string[0] = '+';
kv2->value.string[1] = '\0';
for (l = 0; l <= p; l++)
kv2[l + 1] = obn->instance.props[l];
FREE(obn->instance.props);
obn->instance.props = kv2;
break;
}
}
}
}
FREE(proplist);
}
@@ -4135,8 +4183,8 @@ void PropertySortAndCombine(struct objlist *pre1, struct nlist *tp1,
max2 = 0;
for (c2 = netwk2; ; c2++) {
if (*c2 == 'D') {
cnt++;
run++;
cnt++;
}
else {
if (run > max2) {
@@ -4418,7 +4466,7 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
// Now combine records with same properties by summing M (S).
if (comb == FALSE) {
for (i = 0; i < run - 1; i++) {
for (j = 1; j < run; j++) {
for (j = i + 1; j < run; j++) {
pmatch = 0;
for (p = 1; p < pcount; p++) {
kl = plist[p];
@@ -4436,12 +4484,13 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
if (vl == NULL) {
if (kl->type != vlist[p][j]->type)
PromoteProperty(kl, vl2);
vl = &dfltvl;
}
else {
if (kl->type != vlist[p][i]->type)
PromoteProperty(kl, vl);
vl2 = &dfltvl;
}
vl = &dfltvl;
dfltvl.type = kl->type;
switch (kl->type) {
case PROP_STRING:
@@ -4557,7 +4606,6 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
vlist[0][j]->value.ival = 0;
}
}
else j++;
}
}
}
@@ -5238,8 +5286,10 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
obn1 = tp1;
for (tp2 = ob2->next; (tp2 != NULL) && tp2->type > FIRSTPIN; tp2 = tp2->next)
obn2 = tp2;
if (tp1 && (tp1->type == FIRSTPIN)) tp1 = NULL; /* tp1 had no properties */
if (tp2 && (tp2->type == FIRSTPIN)) tp2 = NULL; /* tp2 had no properties */
if (tp1 && ((tp1->type == FIRSTPIN) || (tp1->type == NODE)))
tp1 = NULL; /* tp1 had no properties */
if (tp2 && ((tp2->type == FIRSTPIN) || (tp2->type == NODE)))
tp2 = NULL; /* tp2 had no properties */
/* Check if there are any properties to match */
@@ -5640,21 +5690,20 @@ int ResolveAutomorphsByPin()
struct Node *N;
int C1, C2;
unsigned long newhash, orighash;
struct nlist *tc1, *tc2;
struct objlist *tob, *ob1, *ob2;
int portnum;
/* Diagnostic */
Fprintf(stdout, "Resolving automorphisms by pin name.\n");
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
struct Node *N1, *N2;
C1 = C2 = 0;
N1 = N2 = NULL;
for (N = NC->nodes; N != NULL; N = N->next) {
if (N->graph == Circuit1->file) {
if (N->graph == Circuit1->file)
C1++;
}
else {
else
C2++;
}
}
if (C1 == C2 && C1 != 1) {
@@ -5666,7 +5715,6 @@ int ResolveAutomorphsByPin()
orighash = NC->nodes->hashval;
for (N1 = NC->nodes; N1 != NULL; N1 = N1->next) {
if (N1->hashval != orighash) continue;
ob1 = N1->object;
for (N2 = N1->next; N2 != NULL; N2 = N2->next) {
if ((N2->graph != N1->graph) &&
(*matchfunc)(N2->object->name, N1->object->name)) {
@@ -5704,6 +5752,9 @@ int ResolveAutomorphsByProperty()
int C1, C2, result, badmatch;
unsigned long orighash, newhash;
/* Diagnostic */
Fprintf(stdout, "Resolving automorphisms by property value.\n");
for (EC = ElementClasses; EC != NULL; EC = EC->next) {
struct Element *E1, *E2;
C1 = C2 = 0;
@@ -5740,7 +5791,6 @@ int ResolveAutomorphsByProperty()
badmatch = FALSE;
for (E2 = E1->next; E2 != NULL; E2 = E2->next) {
if (E2->hashval != orighash) continue;
if (E2->graph == E1->graph) continue;
if (E1->graph == Circuit1->file)
PropertyMatch(E1->object, E2->object, FALSE, FALSE, &result);
else
@@ -5824,9 +5874,23 @@ int ResolveAutomorphisms()
}
if (C1 == C2 && C1 != 1) {
unsigned long newhash;
Magic(newhash);
E1->hashval = newhash;
E2->hashval = newhash;
/* Do all of them at once. */
/* NOTE: If this were to fail for some reason, it would */
/* probably be necessary to do this the original slow way */
/* which is to rehash one pair at a time and iterate to */
/* convergence, and repeat. */
E1 = E2 = EC->elements;
while (E1 != NULL) {
while (E1->graph != Circuit1->file) E1 = E1->next;
while (E2->graph != Circuit2->file) E2 = E2->next;
Magic(newhash);
E1->hashval = newhash;
E2->hashval = newhash;
E1 = E1->next;
E2 = E2->next;
}
goto converge;
}
}
@@ -5847,9 +5911,23 @@ int ResolveAutomorphisms()
}
if (C1 == C2 && C1 != 1) {
unsigned long newhash;
Magic(newhash);
N1->hashval = newhash;
N2->hashval = newhash;
/* Do all of them at once */
/* NOTE: If this were to fail for some reason, it would */
/* probably be necessary to do this the original slow way */
/* which is to rehash one pair at a time and iterate to */
/* convergence, and repeat. */
N1 = N2 = NC->nodes;
while (N1 != NULL) {
while (N1->graph != Circuit1->file) N1 = N1->next;
while (N2->graph != Circuit2->file) N2 = N2->next;
Magic(newhash);
N1->hashval = newhash;
N2->hashval = newhash;
N1 = N1->next;
N2 = N2->next;
}
goto converge;
}
}
@@ -7308,7 +7386,7 @@ int Compare(char *cell1, char *cell2)
/* arbitrarily resolve automorphisms */
Fprintf(stdout, "\n");
Fprintf(stdout, "Arbitrarily resolving automorphisms:\n");
Fprintf(stdout, "Resolving automorphisms by arbitrary symmetry breaking:\n");
while ((automorphisms = ResolveAutomorphisms()) > 0) ;
if (automorphisms == -1) {
MatchFail(cell1, cell2);
+46 -9
View File
@@ -289,6 +289,7 @@ int GetNextLineNoNewline(char *delimiter)
char *newbuf;
int testc;
int nested = 0;
int llen;
if (feof(infile)) return -1;
@@ -301,20 +302,33 @@ int GetNextLineNoNewline(char *delimiter)
if (linesize == 0) {
/* Allocate memory for line */
linesize = 500;
line = (char *)MALLOC(linesize);
linetok = (char *)MALLOC(linesize);
linesize = 2000;
line = (char *)MALLOC(linesize + 1);
linetok = (char *)MALLOC(linesize + 1);
}
fgets(line, linesize, infile);
while (strlen(line) == linesize - 1) {
newbuf = (char *)MALLOC(linesize + 500);
/* Immediately resolve backslash-EOL */
llen = strlen(line);
while ((llen > 1) && (llen < linesize - 1) && *(line + llen - 2) == '\\') {
*(line + llen - 2) = '\n';
fgets(line + llen - 1, linesize - llen + 1, infile);
llen = strlen(line);
}
while (llen == linesize - 1) {
newbuf = (char *)MALLOC(linesize + 501);
strcpy(newbuf, line);
FREE(line);
line = newbuf;
fgets(line + linesize - 1, 501, infile);
llen = strlen(line);
while ((llen > 1) && (llen < linesize - 1) && *(line + llen - 2) == '\\') {
*(line + llen - 2) = '\n';
fgets(line + llen - 1, linesize - llen + 1, infile);
llen = strlen(line);
}
linesize += 500;
FREE(linetok);
linetok = (char *)MALLOC(linesize);
linetok = (char *)MALLOC(linesize + 1);
}
/* Check for substitutions (verilog only). Make sure linetok is */
@@ -329,7 +343,7 @@ int GetNextLineNoNewline(char *delimiter)
for (s = line; *s != '\0'; s++) {
if (*s == '`') {
w = s + 1;
while (isalnum(*w)) w++;
while (isalnum(*w) || (*w == '_') || (*w == '$')) w++;
e = *w;
*w = '\0';
kl = (struct property *)HashLookup(s + 1, definitions);
@@ -365,7 +379,7 @@ int GetNextLineNoNewline(char *delimiter)
for (s = line; *s != '\0'; s++) {
if (*s == '`') {
w = s + 1;
while (isalnum(*w)) w++;
while (isalnum(*w) || (*w == '_') || (*w == '$')) w++;
e = *w;
*w = '\0';
kl = (struct property *)HashLookup(s + 1, definitions);
@@ -496,6 +510,24 @@ void GetNextLine(char *delimiter)
} while (nexttok == NULL);
}
/*----------------------------------------------------------------------*/
/* Return a pointer to the line at the position of nexttok */
/* This is used only when returning the entire line, untokenized, and */
/* is only called by the verilog read routine when reading the value of */
/* a `define statement. */
/*----------------------------------------------------------------------*/
char *GetLineAtTok()
{
char *lpos;
if (nexttok == NULL) return NULL;
if (line == NULL) return NULL;
lpos = strstr(line, nexttok);
return lpos;
}
/*----------------------------------------------------------------------*/
/* if nexttok is already NULL, force scanner to read new line */
/*----------------------------------------------------------------------*/
@@ -766,7 +798,7 @@ int OpenParseFile(char *name, int fnum)
FILE *locfile;
struct filestack *newfile;
locfile = fopen(name,"r");
locfile = fopen(name, "r");
linenum = 0;
/* reset the token scanner */
nexttok = NULL;
@@ -851,7 +883,12 @@ char *ReadNetlist(char *fname, int *fnum)
{SPICE_EXTENSION, ReadSpice},
{SPICE_EXT2, ReadSpice},
{SPICE_EXT3, ReadSpice},
{SPICE_EXT4, ReadSpice},
{SPICE_EXT5, ReadSpice},
{SPICE_EXT6, ReadSpice},
{SPICE_EXT7, ReadSpice},
{VERILOG_EXTENSION, ReadVerilog},
{SYS_VERILOG_EXTENSION, ReadVerilog},
{NETGEN_EXTENSION, ReadNetgenFile},
{NULL, NULL}
};
+7 -1
View File
@@ -9,11 +9,16 @@
#define SIM_EXTENSION ".sim"
#define SPICE_EXTENSION ".spice"
#define SPICE_EXT2 ".spc"
#define SPICE_EXT3 ".fspc"
#define SPICE_EXT3 ".sp"
#define SPICE_EXT4 ".spi"
#define SPICE_EXT5 ".fspc"
#define SPICE_EXT6 ".cir"
#define SPICE_EXT7 ".ckt"
#define NETGEN_EXTENSION ".ntg"
#define CCODE_EXTENSION ".c.code"
#define ESACAP_EXTENSION ".esa"
#define VERILOG_EXTENSION ".v"
#define SYS_VERILOG_EXTENSION ".sv"
#define LINELENGTH 80
@@ -31,6 +36,7 @@ extern struct hashdict *definitions;
extern char *nexttok;
#define SKIPTO(a) do {SkipTok(NULL);} while (!match(nexttok,a))
extern char *strdtok(char *pstring, char *delim1, char *delim2);
extern char *GetLineAtTok();
extern void SkipTok(char *delimiter);
extern void SkipTokNoNewline(char *delimiter);
extern void SkipTokComments(char *delimiter);
+1 -1
View File
@@ -1066,7 +1066,7 @@ void Query(void)
ActelLib();
break;
case 'S':
promptstring("Read SPICE (.ckt) file? ", repstr);
promptstring("Read SPICE (.spice) file? ", repstr);
ReadSpice(repstr, &filenum);
break;
case 'V':
+21 -10
View File
@@ -1883,14 +1883,21 @@ char *ReadSpiceTop(char *fname, int *fnum, int blackbox)
CurrentCell = NULL;
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
char name[100];
SetExtension(name, fname, SPICE_EXTENSION);
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
Fprintf(stderr,"Error in SPICE file read: No file %s\n",name);
if (strrchr(fname, '.') == NULL) {
char name[1024];
SetExtension(name, fname, SPICE_EXTENSION);
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
Fprintf(stderr, "Error in SPICE file read: No file %s\n", name);
*fnum = filenum;
return NULL;
}
}
else {
Fprintf(stderr, "Error in SPICE file read: No file %s\n", fname);
*fnum = filenum;
return NULL;
}
}
}
/* Make sure all SPICE file reading is case insensitive */
@@ -1980,14 +1987,18 @@ void IncludeSpice(char *fname, int parent, struct cellstack **CellStackPtr,
/* helps, if the file didn't have an extension. But */
/* really, we're getting desperate at this point. */
if (strchr(fname, '.') == NULL) {
if (strrchr(fname, '.') == NULL) {
SetExtension(name, fname, SPICE_EXTENSION);
filenum = OpenParseFile(name, parent);
}
if (filenum < 0) {
Fprintf(stderr,"Error in SPICE file include: No file %s\n",name);
return;
if (filenum < 0) {
Fprintf(stderr, "Error in SPICE file include: No file %s\n", name);
return;
}
}
else {
Fprintf(stderr, "Error in SPICE file include: No file %s\n", fname);
return;
}
}
}
ReadSpiceFile(fname, parent, CellStackPtr, blackbox);
+215 -73
View File
@@ -98,6 +98,31 @@ struct bus *NewBus()
return (wb);
}
//-------------------------------------------------------------------------
// Find a character c in a string, assuming that string may contain
// verilog names, where anything, including char c, may appear in the
// string if it is a backslash-escaped name. Only the position of
// character c outside of a verilog name is reported.
//-------------------------------------------------------------------------
char *strvchr(char *string, char c)
{
char *s;
for (s = string; *s != '\0'; s++) {
if (*s == '\\') {
while (*s != '\0' && *s != ' ') s++;
if (*s == '\0') {
Fprintf(stderr, "Error: Verilog backslash-escaped name"
" does not end with a space.\n");
break;
}
}
if (*s == c) return s;
}
return NULL;
}
//-------------------------------------------------------------------------
// Get bus indexes from the notation name[a:b]. If there is only "name"
// then look up the name in the bus hash list and return the index bounds.
@@ -302,8 +327,8 @@ int GetBus(char *astr, struct bus *wb)
astr++;
wb->end = 0;
while((*astr != '\0') && (*astr != '}')) {
sigend = strchr(astr, ',');
if (sigend == NULL) sigend = strchr(astr, '}');
sigend = strvchr(astr, ',');
if (sigend == NULL) sigend = strvchr(astr, '}');
if (sigend == NULL) {
Printf("Badly formed wire bundle \"%s\"\n", astr - 1);
return 1;
@@ -332,15 +357,15 @@ int GetBus(char *astr, struct bus *wb)
while (*aastr != ' ' && *aastr != '\\' && *aastr != '\0') aastr++;
}
brackstart = strchr(aastr, '[');
brackstart = strvchr(aastr, '[');
if (brackstart != NULL) {
brackend = strchr(aastr, ']');
brackend = strvchr(aastr, ']');
if (brackend == NULL) {
Printf("Badly formed array notation \"%s\"\n", astr);
return 1;
}
*brackend = '\0';
colonptr = strchr(aastr, ':');
colonptr = strvchr(aastr, ':');
if (colonptr) *colonptr = '\0';
result = sscanf(brackstart + 1, "%d", &start);
if (colonptr) *colonptr = ':';
@@ -919,7 +944,7 @@ skip_endmodule:
}
else if (match(nexttok, "input") || match(nexttok, "output")
|| match(nexttok, "inout")) {
struct bus wb;
struct bus wb, *nb;
// Parsing of ports as statements not in the module pin list.
wb.start = wb.end = -1;
@@ -952,6 +977,11 @@ skip_endmodule:
Port(portname);
}
}
/* Also register this port as a bus */
nb = NewBus();
nb->start = wb.start;
nb->end = wb.end;
HashPtrInstall(nexttok, nb, &buses);
wb.start = wb.end = -1;
}
else {
@@ -1065,6 +1095,13 @@ skip_endmodule:
kl->pdefault.ival = 1;
kl->slop.ival = 0;
}
else if (nexttok[0] == '(') {
/* For now, the netgen verilog parser doesn't handle `define f(X) ... */
SkipNewLine(VLOG_DELIMITERS);
FREE(kl->key);
FREE(kl);
kl = NULL;
}
else if (ConvertStringToInteger(nexttok, &ival) == 1) {
/* Parameter parses as an integer */
kl->type = PROP_INTEGER;
@@ -1078,12 +1115,19 @@ skip_endmodule:
kl->slop.dval = 0.01; // One percent default
}
else {
/* Treat the parameter as a string */
char *toks;
/* Treat the parameter as a string; BUT pull everything to */
/* EOL, not just the current token. */
toks = GetLineAtTok();
kl->type = PROP_STRING;
kl->pdefault.string = strsave(nexttok);
kl->pdefault.string = strsave(toks);
kl->slop.dval = 0.0;
SkipNewLine(VLOG_DELIMITERS);
}
HashPtrInstall(kl->key, kl, &verilogdefs);
if (kl) HashPtrInstall(kl->key, kl, &verilogdefs);
}
else if (match(nexttok, "`undef")) {
struct property *kl = NULL;
@@ -1172,7 +1216,7 @@ skip_endmodule:
else { /* "assign" */
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
if (GetBus(nexttok, &wb) == 0) {
char *aptr = strchr(nexttok, '[');
char *aptr = strvchr(nexttok, '[');
if (aptr != NULL) {
*aptr = '\0';
/* Find object of first net in bus */
@@ -1181,9 +1225,11 @@ skip_endmodule:
lhs = LookupObject(nodename, CurrentCell);
*aptr = '[';
}
else strcpy(noderoot, nexttok);
}
else {
lhs = LookupObject(nexttok, CurrentCell);
strcpy(noderoot, nexttok);
}
SkipTokComments(VLOG_DELIMITERS);
if (lhs && ((!nexttok) || (!match(nexttok, "=")))) {
@@ -1226,7 +1272,7 @@ skip_endmodule:
}
else {
if (GetBus(nexttok, &wb2) == 0) {
char *aptr = strchr(nexttok, '[');
char *aptr = strvchr(nexttok, '[');
j = wb2.start;
if (aptr != NULL) {
*aptr = '\0';
@@ -1315,6 +1361,7 @@ skip_endmodule:
struct portelement {
char *name; // Name of port in subcell
char *net; // Name of net connecting to port in the parent
int width; // Width of port, if port is a bus
struct portelement *next;
};
@@ -1322,6 +1369,22 @@ skip_endmodule:
struct objlist *obptr;
strncpy(modulename, nexttok, 99);
/* If module name is a verilog primitive, then treat the module as a */
/* black box (this is not a complete list. Preferable to use hash */
/* function instead of lots of strcmp() calls). */
if (!strcmp(modulename, "buf") || !strcmp(modulename, "notif1") ||
!strcmp(modulename, "not") || !strcmp(modulename, "and") ||
!strcmp(modulename, "or") || !strcmp(modulename, "bufif0") ||
!strcmp(modulename, "bufif1") || !strcmp(modulename, "notif0")) {
Printf("Module contains verilog primitive '%s'.\n", nexttok);
Printf("Module '%s' is not structural verilog, making black-box.\n", model);
SetClass(CLASS_MODULE);
goto skip_endmodule;
}
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
@@ -1424,6 +1487,7 @@ nextinst:
else {
new_port = (struct portelement *)CALLOC(1, sizeof(struct portelement));
new_port->name = strsave(nexttok + 1);
new_port->width = -1;
SkipTokComments(VLOG_DELIMITERS);
if (!match(nexttok, "(")) {
Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok);
@@ -1445,25 +1509,25 @@ nextinst:
}
else {
if (!strcmp(nexttok, "{")) {
char *in_line_net = (char *)MALLOC(1);
char *new_in_line_net = NULL;
*in_line_net = '\0';
/* In-line array---read to "}" */
char *wire_bundle = (char *)MALLOC(1);
char *new_wire_bundle = NULL;
*wire_bundle = '\0';
/* Wire bundle---read to "}" */
while (nexttok) {
new_in_line_net = (char *)MALLOC(strlen(in_line_net) +
new_wire_bundle = (char *)MALLOC(strlen(wire_bundle) +
strlen(nexttok) + 1);
/* Roundabout way to do realloc() becase there is no REALLOC() */
strcpy(new_in_line_net, in_line_net);
strcat(new_in_line_net, nexttok);
FREE(in_line_net);
in_line_net = new_in_line_net;
strcpy(new_wire_bundle, wire_bundle);
strcat(new_wire_bundle, nexttok);
FREE(wire_bundle);
wire_bundle = new_wire_bundle;
if (!strcmp(nexttok, "}")) break;
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
}
if (!nexttok) {
Printf("Unterminated net in pin %s\n", in_line_net);
Printf("Unterminated net in pin %s\n", wire_bundle);
}
new_port->net = in_line_net;
new_port->net = wire_bundle;
}
else
new_port->net = strsave(nexttok);
@@ -1565,19 +1629,40 @@ nextinst:
// Check if net name is a wire bus or portion of a bus
if (GetBus(scan->net, &wb) == 0) {
int range;
// This takes care of three situations:
// (1) The signal bus length matches the number of instances:
// apply one signal per instance.
// (2) The signal bus length is a multiple of the number of instances:
// apply a signal sub-bus to each instance.
// (3) The number of instances is a multiple of the signal bus length:
// apply the same signal to each instance.
if ((arrayend - arraystart) == (wb.end - wb.start)) {
// Net is a bus, but net is split over arrayed instances
Port(scan->name);
}
else if (wb.start > wb.end) {
range = wb.start - wb.end;
if ((arraystart - arrayend) > (wb.start - wb.end))
range = (((arraystart - arrayend) + 1) /
((wb.start - wb.end) + 1)) - 1;
else
range = (((wb.start - wb.end) + 1) /
((arraystart - arrayend) + 1)) - 1;
for (i = range; i >= 0; i--) {
sprintf(defport, "%s[%d]", scan->name, i);
Port(defport);
}
}
else {
range = wb.end - wb.start;
if ((arrayend - arraystart) > (wb.end - wb.start))
range = (((arrayend - arraystart) + 1) /
((wb.end - wb.start) + 1)) - 1;
else
range = (((wb.end - wb.start) + 1) /
((arrayend - arraystart) + 1)) - 1;
for (i = 0; i <= range; i++) {
sprintf(defport, "%s[%d]", scan->name, i);
Port(defport);
@@ -1629,7 +1714,12 @@ nextinst:
int j, result;
struct objlist *bobj;
char *bptr;
int minnet, maxnet, testidx;
int minnet, maxnet, testidx, width;
width = portstart - portend;
if (width < 0) width = -width;
width++;
scan->width = width;
result = GetBus(scan->net, &wb);
if (result == -1) {
@@ -1643,7 +1733,7 @@ nextinst:
for (bobj = CurrentCell->cell; bobj; bobj = bobj->next) {
if (bobj->type == PORT) {
if ((bptr = strchr(bobj->name, '[')) != NULL) {
if ((bptr = strvchr(bobj->name, '[')) != NULL) {
*bptr = '\0';
if (!strcmp(bobj->name, scan->net)) {
*bptr = '[';
@@ -1655,7 +1745,7 @@ nextinst:
}
}
else if (bobj->type == NODE) {
if ((bptr = strchr(bobj->name, '[')) != NULL) {
if ((bptr = strvchr(bobj->name, '[')) != NULL) {
*bptr = '\0';
if (!strcmp(bobj->name, scan->net)) {
if (sscanf(bptr + 1, "%d", &testidx) == 1) {
@@ -1681,17 +1771,31 @@ nextinst:
}
if (result == 0) {
if (((wb.start - wb.end) != (portstart - portend)) &&
((wb.start - wb.end) != (portend - portstart))) {
if (((wb.start - wb.end) != (arraystart - arrayend)) &&
((wb.start - wb.end) != (arrayend - arraystart))) {
Fprintf(stderr, "Error: Net %s bus width does not match "
"port %s bus width.\n", scan->net, scan->name);
}
// Otherwise, net is bit-sliced across array of instances.
int match = 0;
int wblen, arraylen;
arraylen = arraystart - arrayend;
wblen = wb.start - wb.end;
if (arraylen < 0) arraylen = -arraylen;
if (wblen < 0) wblen = -wblen;
arraylen++;
wblen++;
if ((scan->width * arraylen) == wblen) match = 1;
else if (wblen == scan->width) match = 1;
else if (wblen == arraylen) match = 1;
else {
Fprintf(stderr, "Warning: Net %s bus width (%d) does not match "
"port %s bus width (%d) or array width (%d).\n",
scan->net, wblen, scan->name, scan->width, arraylen);
}
else if (wb.start > wb.end) {
char *bptr, *cptr, cchar, *netname;
// Net is bit-sliced across array of instances.
if (wb.start > wb.end) {
char *bptr = NULL, *cptr = NULL, cchar, *netname;
unsigned char is_bundle = 0;
struct bus wbb;
@@ -1702,8 +1806,8 @@ nextinst:
if (*netname == '{') {
is_bundle = 1;
netname++;
cptr = strchr(netname, ',');
if (cptr == NULL) cptr = strchr(netname, '}');
cptr = strvchr(netname, ',');
if (cptr == NULL) cptr = strvchr(netname, '}');
if (cptr == NULL) cptr = netname + strlen(netname) - 1;
cchar = *cptr;
*cptr = '\0';
@@ -1712,14 +1816,12 @@ nextinst:
// Remove indexed part of scan->net
if (GetBus(netname, &wbb) == 0) {
i = wbb.start;
if ((bptr = strchr(netname, '[')) != NULL)
if ((bptr = strvchr(netname, '[')) != NULL)
*bptr = '\0';
}
else
i = -1;
if (is_bundle) *cptr = cchar; /* Restore bundle delimiter */
while (1) {
new_port = (struct portelement *)CALLOC(1,
sizeof(struct portelement));
@@ -1730,6 +1832,7 @@ nextinst:
else
sprintf(vname, "%s[%d]", netname, i);
new_port->net = strsave(vname);
new_port->width = scan->width;
if (last == NULL)
head = new_port;
@@ -1743,8 +1846,10 @@ nextinst:
if (portstart > portend) j--;
else j++;
if (wbb.start > wbb.end) i--;
else i++;
if (i != -1) {
if (wbb.start > wbb.end) i--;
else i++;
}
if (is_bundle &&
((i == -1) ||
@@ -1753,24 +1858,24 @@ nextinst:
if (bptr) *bptr = '[';
netname = cptr + 1;
cptr = strchr(netname, ',');
if (cptr == NULL) cptr = strchr(netname, '}');
if (cptr) *cptr = cchar; /* Restore previous bundle delimiter */
cptr = strvchr(netname, ',');
if (cptr == NULL) cptr = strvchr(netname, '}');
if (cptr == NULL) cptr = netname + strlen(netname) - 1;
cchar = *cptr;
*cptr = '\0';
if (GetBus(netname, &wbb) == 0) {
i = wbb.start;
if ((bptr = strchr(netname, '[')) != NULL)
if ((bptr = strvchr(netname, '[')) != NULL)
*bptr = '\0';
}
else i = -1;
*cptr = cchar; /* Restore delimiter */
}
}
FREE(scan);
scan = last;
if (cptr) *cptr = cchar; /* Restore bundle delimiter */
}
}
else if (portstart != portend) {
@@ -1800,7 +1905,7 @@ nextinst:
obptr = LookupInstance(locinst, CurrentCell);
if (obptr != NULL) {
do {
struct bus wb;
struct bus wb, wb2;
char *obpinname;
int obpinidx;
@@ -1822,14 +1927,19 @@ nextinst:
scan = scan->next;
}
if (scan == NULL) {
Fprintf(stderr, "Error: No match in call for pin %s\n", obpinname);
break;
}
char localnet[100];
if (GetBus(scan->net, &wb) == 0) {
/* Assume an implicit unconnected pin */
sprintf(localnet, "_noconnect_%d_", localcount++);
Node(localnet);
join(localnet, obptr->name);
Fprintf(stderr, "Note: Implicit pin %s\n", obpinname);
}
else if (GetBus(scan->net, &wb) == 0) {
char *bptr2;
char *scanroot;
scanroot = strsave(scan->net);
brackptr = strchr(scanroot, '[');
brackptr = strvchr(scanroot, '[');
if (brackptr) *brackptr = '\0';
if (arraystart == -1) {
@@ -1861,16 +1971,37 @@ nextinst:
else {
// Instance must be an array
char netname[128];
int slice;
if (wb.start >= wb.end && arraystart >= arrayend)
slice = wb.start - (arraystart - i);
else if (wb.start < wb.end && arraystart > arrayend)
slice = wb.start + (arraystart - i);
else if (wb.start > wb.end && arraystart < arrayend)
slice = wb.start - (arraystart + i);
else // (wb.start < wb.end && arraystart < arrayend)
slice = wb.start + (arraystart + i);
int slice, portlen, siglen;
/* Get the array size of the port for bit slicing */
portlen = (scan->width < 0) ? 1 : scan->width;
/* Get the full array size of the connecting bus */
GetBus(scanroot, &wb2);
siglen = wb2.start - wb2.end;
if (siglen < 0) siglen = -siglen;
siglen++;
// If signal array is smaller than the portlength *
// length of instance array, then the signal wraps.
if (wb2.start >= wb2.end && arraystart >= arrayend) {
slice = wb.start - (arraystart - i) * portlen;
while (slice < wb2.end) slice += siglen;
}
else if (wb2.start < wb2.end && arraystart > arrayend) {
slice = wb.start + (arraystart - i) * portlen;
while (slice > wb2.end) slice -= siglen;
}
else if (wb2.start > wb2.end && arraystart < arrayend) {
slice = wb.start - (arraystart + i) * portlen;
while (slice < wb2.end) slice += siglen;
}
else { // (wb2.start < wb2.end && arraystart < arrayend)
slice = wb.start + (arraystart + i) * portlen;
while (slice > wb2.end) slice -= siglen;
}
sprintf(netname, "%s[%d]", scanroot, slice);
if (LookupObject(netname, CurrentCell) == NULL) Node(netname);
join(netname, obptr->name);
@@ -1938,14 +2069,21 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
CurrentCell = NULL;
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
char name[100];
SetExtension(name, fname, VERILOG_EXTENSION);
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
Fprintf(stderr,"Error in Verilog file read: No file %s\n",name);
*fnum = filenum;
return NULL;
if (strchr(fname, '.') == NULL) {
char name[1024];
SetExtension(name, fname, VERILOG_EXTENSION);
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
Fprintf(stderr, "Error in Verilog file read: No file %s\n", name);
*fnum = filenum;
return NULL;
}
}
else {
Fprintf(stderr, "Error in Verilog file read: No file %s\n", fname);
*fnum = filenum;
return NULL;
}
}
/* All Verilog file reading is case sensitive. However: if */
@@ -2043,11 +2181,15 @@ void IncludeVerilog(char *fname, int parent, struct cellstack **CellStackPtr,
if (strchr(fname, '.') == NULL) {
SetExtension(name, fname, VERILOG_EXTENSION);
filenum = OpenParseFile(name, parent);
if (filenum < 0) {
fprintf(stderr,"Error in Verilog file include: No file %s\n", name);
return;
}
}
if (filenum < 0) {
else {
fprintf(stderr,"Error in Verilog file include: No file %s\n", fname);
return;
}
}
}
}
ReadVerilogFile(fname, parent, CellStackPtr, blackbox);
+5 -2
View File
@@ -2974,12 +2974,15 @@ _netcmp_equate(ClientData clientData,
Fprintf(stdout, "Warning: Equate pins: cell %s "
"has no definition, treated as a black box.\n", name2);
}
// If a cell in either circuit is marked as a black box, then
// the cells in both circuits should be marked as a black box.
tp1->flags |= CELL_PLACEHOLDER;
tp2->flags |= CELL_PLACEHOLDER;
}
else {
Fprintf(stdout, "Equate pins: cell %s and/or %s "
"has no elements.\n", name1, name2);
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
return TCL_OK;
/* This is not necessarily an error, so go ahead and match pins. */
}
}
if (ElementClasses == NULL) {