mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-24 23:17:28 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b826870be9 | ||
|
|
50b0e9cb65 | ||
|
|
ed5276d67b | ||
|
|
82be18ec4b | ||
|
|
4ee3a1464b | ||
|
|
69c9d85be7 | ||
|
|
8e215d3b66 | ||
|
|
c45d51e950 | ||
|
|
ad05d059c7 | ||
|
|
85eb34c01e | ||
|
|
8a24c6c3ca | ||
|
|
46cdf48bc4 | ||
|
|
9d542b92b0 | ||
|
|
1b2cd1497c | ||
|
|
71ad228d8d | ||
|
|
339a0d5d4e | ||
|
|
9cebb76787 | ||
|
|
d9d5a46c6e | ||
|
|
251622c8bc | ||
|
|
d73b711e3a | ||
|
|
18739235a9 | ||
|
|
07c493c796 | ||
|
|
cca0e4b3f3 | ||
|
|
1428580109 | ||
|
|
fb0e1d10b0 | ||
|
|
6f81e1d294 | ||
|
|
cec6d89474 |
+184
-47
@@ -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);
|
||||
}
|
||||
@@ -5243,6 +5246,12 @@ void DumpNetworkAll(char *model, int file)
|
||||
/* NOTE: ob1 must belong to Circuit1, and ob2 must belong to */
|
||||
/* Circuit2. The calling procedure is responsble for ensuring */
|
||||
/* that this is true. */
|
||||
/* */
|
||||
/* NOTE: This routine assumes that if file1 == file2 or if */
|
||||
/* file2 != Circuit1->graph, then "do_print" is FALSE. It */
|
||||
/* hard-codes "Circuit 1" and "Circuit 2" in most print */
|
||||
/* statements. file1 == file2 only when checking properties */
|
||||
/* for symmetry breaking, where nothing is printed. */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
@@ -5250,8 +5259,9 @@ Tcl_Obj *
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
|
||||
int do_list, int *retval)
|
||||
PropertyMatch(struct objlist *ob1, int file1,
|
||||
struct objlist *ob2, int file2,
|
||||
int do_print, int do_list, int *retval)
|
||||
{
|
||||
struct nlist *tc1, *tc2;
|
||||
struct objlist *tp1, *tp2, *obn1, *obn2;
|
||||
@@ -5265,8 +5275,22 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
|
||||
Tcl_Obj *proplist = NULL, *mpair, *mlist;
|
||||
#endif
|
||||
|
||||
tc1 = LookupCellFile(ob1->model.class, Circuit1->file);
|
||||
tc2 = LookupCellFile(ob2->model.class, Circuit2->file);
|
||||
tc1 = LookupCellFile(ob1->model.class, file1);
|
||||
tc2 = LookupCellFile(ob2->model.class, file2);
|
||||
|
||||
if (tc1 == NULL || tc2 == NULL) {
|
||||
if (tc1 == NULL)
|
||||
Fprintf(stdout, "Error: Circuit %d device \"%s\" not found!\n",
|
||||
file1, ob1->model.class);
|
||||
else
|
||||
Fprintf(stdout, "Error: Circuit %d device \"%s\" not found!\n",
|
||||
file2, ob2->model.class);
|
||||
#ifdef TCL_NETGEN
|
||||
return NULL;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (tc1->classhash != tc2->classhash) {
|
||||
*retval = -1;
|
||||
@@ -5283,8 +5307,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 */
|
||||
|
||||
@@ -5545,9 +5571,11 @@ PropertyCheck(struct ElementClass *EC, int do_print, int do_list, int *rval)
|
||||
E2 = Etmp;
|
||||
}
|
||||
#ifdef TCL_NETGEN
|
||||
return PropertyMatch(E1->object, E2->object, do_print, do_list, rval);
|
||||
return PropertyMatch(E1->object, E1->graph, E2->object, E2->graph,
|
||||
do_print, do_list, rval);
|
||||
#else
|
||||
PropertyMatch(E1->object, E2->object, do_print, do_list, rval);
|
||||
PropertyMatch(E1->object, E1->graph, E2->object, E2->graph,
|
||||
do_print, do_list, rval);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5685,21 +5713,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) {
|
||||
|
||||
@@ -5711,7 +5738,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)) {
|
||||
@@ -5749,6 +5775,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;
|
||||
@@ -5785,11 +5814,8 @@ 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
|
||||
PropertyMatch(E2->object, E1->object, FALSE, FALSE, &result);
|
||||
PropertyMatch(E1->object, E1->graph, E2->object, E2->graph,
|
||||
FALSE, FALSE, &result);
|
||||
if (result == 0) {
|
||||
E2->hashval = newhash;
|
||||
if (E2->graph == E1->graph)
|
||||
@@ -5836,21 +5862,20 @@ int ResolveAutomorphsByProperty()
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResolveAutormorphisms --
|
||||
* ResolveElementAutomorphisms --
|
||||
*
|
||||
* Arbitrarily equivalence one pair of elements within an automorphic class
|
||||
* Apply arbitrary symmetry breaking to symmetric element lists, then
|
||||
* iterate exhaustively to resolve all automorphisms.
|
||||
*
|
||||
* Return value is the same as VerifyMatching()
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int ResolveAutomorphisms()
|
||||
int ResolveElementAutomorphisms()
|
||||
{
|
||||
struct ElementClass *EC;
|
||||
struct NodeClass *NC;
|
||||
struct Element *E;
|
||||
struct Node *N;
|
||||
int C1, C2;
|
||||
|
||||
for (EC = ElementClasses; EC != NULL; EC = EC->next) {
|
||||
@@ -5869,13 +5894,55 @@ int ResolveAutomorphisms()
|
||||
}
|
||||
if (C1 == C2 && C1 != 1) {
|
||||
unsigned long newhash;
|
||||
Magic(newhash);
|
||||
E1->hashval = newhash;
|
||||
E2->hashval = newhash;
|
||||
goto converge;
|
||||
|
||||
/* 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 && E2 != 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FractureElementClass(&ElementClasses);
|
||||
FractureNodeClass(&NodeClasses);
|
||||
ExhaustiveSubdivision = 1;
|
||||
while (!Iterate() && VerifyMatching() != -1);
|
||||
return(VerifyMatching());
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResolveNodeAutomorphisms --
|
||||
*
|
||||
* Apply arbitrary symmetry breaking to symmetric node lists, then iterate
|
||||
* exhaustively to resolve all automorphisms. Normally, all automorphisms
|
||||
* should be resolved by ResolveElementAutomorphisms(). It is likely true
|
||||
* that this routine will never run, by definition.
|
||||
*
|
||||
* Return value is the same as VerifyMatching()
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
|
||||
int ResolveNodeAutomorphisms()
|
||||
{
|
||||
struct Node *N;
|
||||
struct NodeClass *NC;
|
||||
int C1, C2;
|
||||
|
||||
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
||||
struct Node *N1, *N2;
|
||||
C1 = C2 = 0;
|
||||
@@ -5892,14 +5959,26 @@ int ResolveAutomorphisms()
|
||||
}
|
||||
if (C1 == C2 && C1 != 1) {
|
||||
unsigned long newhash;
|
||||
Magic(newhash);
|
||||
N1->hashval = newhash;
|
||||
N2->hashval = newhash;
|
||||
goto converge;
|
||||
|
||||
/* 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 && N2 != 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
converge:
|
||||
FractureElementClass(&ElementClasses);
|
||||
FractureNodeClass(&NodeClasses);
|
||||
ExhaustiveSubdivision = 1;
|
||||
@@ -5907,6 +5986,29 @@ int ResolveAutomorphisms()
|
||||
return(VerifyMatching());
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResolveAutormorphisms --
|
||||
*
|
||||
* Arbitrarily equivalence one pair of elements within an automorphic class
|
||||
*
|
||||
* Return value is the same as VerifyMatching()
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int ResolveAutomorphisms()
|
||||
{
|
||||
int result;
|
||||
|
||||
result = ResolveElementAutomorphisms();
|
||||
if (result != 0)
|
||||
result = ResolveNodeAutomorphisms();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* PermuteSetup -- */
|
||||
/* Add an entry to a cell's "permutes" linked list. */
|
||||
@@ -6611,7 +6713,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
struct NodeClass *NC;
|
||||
struct Node *N1, *N2;
|
||||
int i, j, k, m, a, b, swapped, numnodes, numorig;
|
||||
int result = 1, haspins = 0;
|
||||
int result = 1, haspins = 0, notempty = 0;
|
||||
int hasproxy1 = 0, hasproxy2 = 0;
|
||||
int needclean1 = 0, needclean2 = 0;
|
||||
char *ostr;
|
||||
@@ -6776,12 +6878,15 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
/* has been left orphaned after flattening. If */
|
||||
/* disconnected, set its node number to -2. */
|
||||
|
||||
notempty = 0;
|
||||
for (obt = ob1->next; obt; obt = obt->next) {
|
||||
if (obt->type >= FIRSTPIN)
|
||||
if (obt->type >= FIRSTPIN) {
|
||||
notempty = 1;
|
||||
if (obt->node == ob1->node)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (obt == NULL) {
|
||||
if ((obt == NULL) && (notempty == 1)) {
|
||||
ob1->node = -2; // Will run this through cleanuppins
|
||||
needclean1 = 1;
|
||||
}
|
||||
@@ -6834,6 +6939,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (*(cover + i) == (char)0) {
|
||||
j = 0;
|
||||
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
|
||||
char *name1, *name2;
|
||||
|
||||
if (!IsPort(ob2)) break;
|
||||
|
||||
bangptr2 = strrchr(ob2->name, '!');
|
||||
@@ -6841,7 +6948,14 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
*bangptr2 = '\0';
|
||||
else bangptr2 = NULL;
|
||||
|
||||
if ((*matchfunc)(ob1->name, ob2->name)) {
|
||||
name1 = ob1->name;
|
||||
name2 = ob2->name;
|
||||
|
||||
/* Recognize proxy pins as matching */
|
||||
if (!strncmp(name1, "proxy", 5)) name1 +=5;
|
||||
if (!strncmp(name2, "proxy", 5)) name2 +=5;
|
||||
|
||||
if ((*matchfunc)(name1, name2)) {
|
||||
ob2->model.port = i; /* save order */
|
||||
*(cover + i) = (char)1;
|
||||
|
||||
@@ -6880,7 +6994,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
/* Find the end of the pin list in tc1, for adding proxy pins */
|
||||
|
||||
for (ob1 = tc1->cell; ob1 != NULL; ob1 = ob1->next) {
|
||||
if (ob1 && ob1->next && ob1->next->type != PORT)
|
||||
if (ob1 && ((ob1->next && ob1->next->type != PORT) || ob1->next == NULL))
|
||||
break;
|
||||
}
|
||||
if (ob1 == NULL) ob1 = tc1->cell; /* No ports */
|
||||
@@ -6923,12 +7037,15 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
/* flattening instances has left a port with a */
|
||||
/* net number that doesn't connect to anything */
|
||||
|
||||
notempty = 0;
|
||||
for (obt = ob2->next; obt; obt = obt->next) {
|
||||
if (obt->type >= FIRSTPIN)
|
||||
if (obt->type >= FIRSTPIN) {
|
||||
notempty = 1;
|
||||
if (obt->node == ob2->node)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (obt == NULL) {
|
||||
if ((obt == NULL) && (notempty == 1)) {
|
||||
ob2->node = -2; // Will run this through cleanuppins
|
||||
needclean2 = 1;
|
||||
continue;
|
||||
@@ -6945,7 +7062,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
obn->name = (char *)MALLOC(6 + strlen(ob2->name));
|
||||
sprintf(obn->name, "proxy%s", ob2->name);
|
||||
obn->type = UNKNOWN;
|
||||
obn->model.port = -1;
|
||||
// obn->model.port = -1;
|
||||
obn->instance.name = NULL;
|
||||
obn->node = -1;
|
||||
if (ob1 == tc1->cell) {
|
||||
@@ -6966,7 +7083,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
/* Find the end of the pin list in tc2, for adding proxy pins */
|
||||
|
||||
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
|
||||
if (ob2 && ob2->next && ob2->next->type != PORT)
|
||||
if (ob2 && ((ob2->next && ob2->next->type != PORT) || ob2->next == NULL))
|
||||
break;
|
||||
}
|
||||
if (ob2 == NULL) ob2 = tc2->cell; /* No ports */
|
||||
@@ -6997,7 +7114,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (obn == NULL) ob1->node = -1; /* Make disconnected */
|
||||
}
|
||||
|
||||
if (ob1 == NULL || ob1->type != PORT || ob1->node >= 0) {
|
||||
if (ob1 == NULL || ob1->type != PORT || ob1->node >= 0
|
||||
|| (ob1->node < 0 && tc1->class == CLASS_MODULE)) {
|
||||
|
||||
/* Add a proxy pin to tc2 */
|
||||
obn = (struct objlist *)CALLOC(1, sizeof(struct objlist));
|
||||
@@ -7014,6 +7132,25 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
obn->instance.name = NULL;
|
||||
obn->node = -1;
|
||||
|
||||
#if 0
|
||||
/* Note: This pin has already been accounted for */
|
||||
if (Debug == 0) {
|
||||
if (strcmp(ob1->name, "(no pins)")) {
|
||||
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
||||
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
||||
snprintf(ostr, left_col_end, "%s", ob1->name);
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)");
|
||||
for (m = 0; m < right_col_end + 1; m++)
|
||||
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Fprintf(stderr, "No netlist match for cell %s pin %s\n",
|
||||
tc1->name, ob1->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ob2 == tc2->cell) {
|
||||
obn->next = ob2;
|
||||
tc2->cell = obn;
|
||||
@@ -7353,7 +7490,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);
|
||||
|
||||
+41
-4
@@ -289,6 +289,7 @@ int GetNextLineNoNewline(char *delimiter)
|
||||
char *newbuf;
|
||||
int testc;
|
||||
int nested = 0;
|
||||
int llen;
|
||||
|
||||
if (feof(infile)) return -1;
|
||||
|
||||
@@ -306,12 +307,25 @@ int GetNextLineNoNewline(char *delimiter)
|
||||
linetok = (char *)MALLOC(linesize + 1);
|
||||
}
|
||||
fgets(line, linesize, infile);
|
||||
while (strlen(line) == linesize - 1) {
|
||||
/* 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 + 1);
|
||||
@@ -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
@@ -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
@@ -289,7 +289,7 @@ static struct hashdict cell_dict;
|
||||
void InitCellHashTable(void)
|
||||
{
|
||||
hashfunc = hash;
|
||||
matchfunc = match;
|
||||
matchfunc = NULL;
|
||||
matchintfunc = matchfile;
|
||||
InitializeHashTable(&cell_dict, CELLHASHSIZE);
|
||||
}
|
||||
|
||||
+6
-2
@@ -801,7 +801,11 @@ void DescribeInstance(char *name, int file)
|
||||
{
|
||||
if (ob->node > nodemax) nodemax = ob->node;
|
||||
else if ((ob->node == -1) && (ob->model.port != PROXY)) {
|
||||
if (!(tp->flags & CELL_PLACEHOLDER))
|
||||
|
||||
/* All black-box modules and placeholders by definition have all */
|
||||
/* disconnected pins, so don't report those. */
|
||||
|
||||
if (!(tp->flags & CELL_PLACEHOLDER) && (tp->class != CLASS_MODULE))
|
||||
{
|
||||
if (disconnectednodes == 0) Fprintf(stderr, "\n");
|
||||
disconnectednodes++;
|
||||
@@ -1066,7 +1070,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':
|
||||
|
||||
+26
-10
@@ -1883,20 +1883,36 @@ 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 */
|
||||
matchfunc = matchnocase;
|
||||
matchintfunc = matchfilenocase;
|
||||
hashfunc = hashnocase;
|
||||
/* Make sure all SPICE file reading is case insensitive */
|
||||
/* BUT if a verilog file was read before it, then it will */
|
||||
/* be forced to be case sensitive, caveat end-user. */
|
||||
|
||||
if (matchfunc == match) {
|
||||
Printf("Warning: A case-sensitive file has been read and so the "
|
||||
"SPICE netlist must be treated case-sensitive to match.\n");
|
||||
}
|
||||
else {
|
||||
matchfunc = matchnocase;
|
||||
matchintfunc = matchfilenocase;
|
||||
hashfunc = hashnocase;
|
||||
}
|
||||
|
||||
InitializeHashTable(&spiceparams, OBJHASHSIZE);
|
||||
|
||||
@@ -1980,7 +1996,7 @@ 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) {
|
||||
|
||||
+54
-16
@@ -1115,10 +1115,17 @@ 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);
|
||||
}
|
||||
if (kl) HashPtrInstall(kl->key, kl, &verilogdefs);
|
||||
}
|
||||
@@ -1218,9 +1225,16 @@ skip_endmodule:
|
||||
lhs = LookupObject(nodename, CurrentCell);
|
||||
*aptr = '[';
|
||||
}
|
||||
else {
|
||||
strcpy(noderoot, nexttok);
|
||||
/* Set LHS to the start of the vector */
|
||||
sprintf(nodename, "%s[%d]", nexttok, wb.start);
|
||||
lhs = LookupObject(nodename, CurrentCell);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lhs = LookupObject(nexttok, CurrentCell);
|
||||
strcpy(noderoot, nexttok);
|
||||
}
|
||||
SkipTokComments(VLOG_DELIMITERS);
|
||||
if (lhs && ((!nexttok) || (!match(nexttok, "=")))) {
|
||||
@@ -1281,13 +1295,21 @@ skip_endmodule:
|
||||
if (rhs != NULL) {
|
||||
Printf("Improper assignment; left-hand side cannot "
|
||||
"be parsed.\n");
|
||||
Printf("Right-hand side is \"%s\".\n", rhs->name);
|
||||
if (j != -1)
|
||||
Printf("Right-hand side is \"%s\".\n", assignroot);
|
||||
else
|
||||
Printf("Right-hand side is \"%s\".\n", rhs->name);
|
||||
Printf("Improper expression is \"%s\".\n", nexttok);
|
||||
break;
|
||||
}
|
||||
if (lhs != NULL) {
|
||||
Printf("Improper assignment; right-hand side cannot "
|
||||
"be parsed.\n");
|
||||
Printf("Left-hand side is \"%s\".\n", lhs->name);
|
||||
if (i != -1)
|
||||
Printf("Left-hand side is \"%s\".\n", noderoot);
|
||||
else
|
||||
Printf("Left-hand side is \"%s\".\n", lhs->name);
|
||||
Printf("Improper expression is \"%s\".\n", nexttok);
|
||||
/* Not parsable, probably behavioral verilog? */
|
||||
Printf("Module '%s' is not structural verilog, "
|
||||
"making black-box.\n", model);
|
||||
@@ -1786,7 +1808,7 @@ nextinst:
|
||||
// Net is bit-sliced across array of instances.
|
||||
|
||||
if (wb.start > wb.end) {
|
||||
char *bptr, *cptr = NULL, cchar, *netname;
|
||||
char *bptr = NULL, *cptr = NULL, cchar, *netname;
|
||||
unsigned char is_bundle = 0;
|
||||
struct bus wbb;
|
||||
|
||||
@@ -1845,7 +1867,7 @@ nextinst:
|
||||
if (is_bundle &&
|
||||
((i == -1) ||
|
||||
((wbb.start > wbb.end) && (i < wbb.end)) ||
|
||||
((wbb.start < wbb.end) && (i > wbb.end)))) {
|
||||
((wbb.start <= wbb.end) && (i > wbb.end)))) {
|
||||
if (bptr) *bptr = '[';
|
||||
|
||||
netname = cptr + 1;
|
||||
@@ -1918,11 +1940,15 @@ 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);
|
||||
@@ -2056,14 +2082,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 */
|
||||
@@ -2074,6 +2107,11 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
|
||||
Printf("Warning: A case-insensitive file has been read and so the "
|
||||
"verilog file must be treated case-insensitive to match.\n");
|
||||
}
|
||||
else {
|
||||
matchfunc = match;
|
||||
matchintfunc = matchfile;
|
||||
hashfunc = hash;
|
||||
}
|
||||
|
||||
InitializeHashTable(&verilogparams, OBJHASHSIZE);
|
||||
InitializeHashTable(&verilogdefs, OBJHASHSIZE);
|
||||
|
||||
+7
-1
@@ -501,6 +501,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
return
|
||||
}
|
||||
set properr {}
|
||||
set pinsgood 0
|
||||
while {$endval != {}} {
|
||||
if {$dolist == 1} {
|
||||
netgen::run -list converge
|
||||
@@ -546,6 +547,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
equate classes "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"
|
||||
}
|
||||
set pinsgood $result
|
||||
netgen::log echo on
|
||||
}
|
||||
if {$uresult == 2} {lappend properr [lindex $endval 0]}
|
||||
@@ -569,7 +571,11 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
netgen::log echo off
|
||||
puts stdout "Result: " nonewline
|
||||
netgen::log echo on
|
||||
verify only
|
||||
if {$pinsgood == 0} {
|
||||
netgen::log put "The top level cell failed pin matching.\n"
|
||||
} else {
|
||||
verify only
|
||||
}
|
||||
if {$properr != {}} {
|
||||
netgen::log put "The following cells had property errors: $properr\n"
|
||||
}
|
||||
|
||||
+1
-2
@@ -2982,8 +2982,7 @@ _netcmp_equate(ClientData clientData,
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user