From 9d542b92b02b9cb79e74646badc9fc53c5f99492 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 30 Jul 2020 08:06:44 -0400 Subject: [PATCH 1/4] Corrected one logical error in netcmp.c from the last commit, discovered and fixed by Ahmed Ghazy. --- base/netcmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/netcmp.c b/base/netcmp.c index 977035d..9063451 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -5882,7 +5882,7 @@ int ResolveAutomorphisms() /* convergence, and repeat. */ E1 = E2 = EC->elements; - while (E1 != NULL) { + while (E1 != NULL && E2 != NULL) { while (E1->graph != Circuit1->file) E1 = E1->next; while (E2->graph != Circuit2->file) E2 = E2->next; Magic(newhash); @@ -5919,7 +5919,7 @@ int ResolveAutomorphisms() /* convergence, and repeat. */ N1 = N2 = NC->nodes; - while (N1 != NULL) { + while (N1 != NULL && N2 != NULL) { while (N1->graph != Circuit1->file) N1 = N1->next; while (N2->graph != Circuit2->file) N2 = N2->next; Magic(newhash); From 46cdf48bc4343056fdac9add400b1c9cede4b6af Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 30 Jul 2020 08:10:09 -0400 Subject: [PATCH 2/4] Updated the version to force the tarball and github mirror. --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 78e942c..589628c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.151 +1.5.152 From 8a24c6c3ca54d4c21d27f0b5910f3e5732c301b9 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 30 Jul 2020 14:48:08 -0400 Subject: [PATCH 3/4] Modified the ResolveAutomorphisms() routine once again, to break symmetry of all elements in all symmetric partitions, rather than (as previously done) all elements in each partition, before re- running iterations to convergence. This solves the problem of having a very large number of partitions with a few elements each taking a long time to run. --- base/netcmp.c | 64 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/base/netcmp.c b/base/netcmp.c index 9063451..1bc7fa2 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -5841,21 +5841,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) { @@ -5891,10 +5890,38 @@ int ResolveAutomorphisms() E1 = E1->next; E2 = E2->next; } - goto converge; } } + 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; @@ -5928,11 +5955,9 @@ int ResolveAutomorphisms() N1 = N1->next; N2 = N2->next; } - goto converge; } } - converge: FractureElementClass(&ElementClasses); FractureNodeClass(&NodeClasses); ExhaustiveSubdivision = 1; @@ -5940,6 +5965,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. */ From 85eb34c01e0156830ce1bb13a9e6313da2c96682 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 30 Jul 2020 22:51:34 -0400 Subject: [PATCH 4/4] Made several corrections to handling of proxy pins when matching black-box circuits, especially those coming from verilog netlists where a pin does not need to be declared and is implicitly floating. This prevents the need to have an explicit black-box entry for any verilog module that may have an instance that does not declare all the pin connections. Also corrected an error which causes mysterious failures if a verilog netlist is read before a SPICE netlist, because the former gets hashed case-sensitive and the latter changes the hashing to case-insensitive. Modified to force the SPICE netlist to be treated case-sensitive, which may cause errors, but is consistent with the reverse order handling, and doesn't cause unexplained errors. --- base/netcmp.c | 23 +++++++++++++++-------- base/objlist.c | 2 +- base/spice.c | 17 +++++++++++++---- base/verilog.c | 5 +++++ 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/base/netcmp.c b/base/netcmp.c index 1bc7fa2..fb49c30 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -6692,7 +6692,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; @@ -6857,12 +6857,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; } @@ -6961,7 +6964,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 */ @@ -7004,12 +7007,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; @@ -7047,7 +7053,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 */ @@ -7078,7 +7084,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)); diff --git a/base/objlist.c b/base/objlist.c index e864a17..aa189b1 100644 --- a/base/objlist.c +++ b/base/objlist.c @@ -289,7 +289,7 @@ static struct hashdict cell_dict; void InitCellHashTable(void) { hashfunc = hash; - matchfunc = match; + matchfunc = NULL; matchintfunc = matchfile; InitializeHashTable(&cell_dict, CELLHASHSIZE); } diff --git a/base/spice.c b/base/spice.c index af2ec6c..9f29b88 100644 --- a/base/spice.c +++ b/base/spice.c @@ -1900,10 +1900,19 @@ char *ReadSpiceTop(char *fname, int *fnum, int blackbox) } } - /* 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); diff --git a/base/verilog.c b/base/verilog.c index c4e500b..f6f04b0 100644 --- a/base/verilog.c +++ b/base/verilog.c @@ -2094,6 +2094,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);