Compare commits

...
8 Commits
Author SHA1 Message Date
Tim Edwards 69c9d85be7 Merge branch 'master' into netgen-1.5 2020-08-01 03:00:23 -04:00
Tim Edwards 8e215d3b66 Corrected the PropertyMatch() routine; previously the symmetry
breaking by property was only matching properties between circuits but
not within the same circuit, which is needed for correct symmetry
breaking.  But the PropertyMatch() routine assumed that it is passed
one item from each circuit, leading to a segfault when running the
symmetry breaking within a single circuit.  This has been fixed.
2020-07-31 12:56:20 -04:00
Tim Edwards c45d51e950 Tracked down and fixed problems with implicit pins in verilog (pins
that are not declared in the verilog netlist because they don't
connect to anything, and their presence is not required by verilog
syntax) and the printing of proxy pins created to act as placeholders
for those implicit pins.  Also removed the pinting of the "disconnected
pin" messages for black-box modules (since by definition they have
disconnected pins, because black-box modules have no contents).
2020-07-31 12:22:50 -04:00
Tim Edwards ad05d059c7 Merge branch 'master' into netgen-1.5 2020-07-31 03:00:27 -04:00
Tim Edwards 85eb34c01e 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.
2020-07-30 22:51:34 -04:00
Tim Edwards 8a24c6c3ca 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.
2020-07-30 14:48:08 -04:00
Tim Edwards 46cdf48bc4 Updated the version to force the tarball and github mirror. 2020-07-30 08:10:09 -04:00
Tim Edwards 9d542b92b0 Corrected one logical error in netcmp.c from the last commit,
discovered and fixed by Ahmed Ghazy.
2020-07-30 08:06:44 -04:00
6 changed files with 156 additions and 37 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.151
1.5.153
+131 -30
View File
@@ -5246,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
@@ -5253,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;
@@ -5268,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;
@@ -5550,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
}
@@ -5791,10 +5814,8 @@ int ResolveAutomorphsByProperty()
badmatch = FALSE;
for (E2 = E1->next; E2 != NULL; E2 = E2->next) {
if (E2->hashval != orighash) 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)
@@ -5841,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) {
@@ -5882,7 +5902,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);
@@ -5891,10 +5911,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;
@@ -5919,7 +5967,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);
@@ -5928,11 +5976,9 @@ int ResolveAutomorphisms()
N1 = N1->next;
N2 = N2->next;
}
goto converge;
}
}
converge:
FractureElementClass(&ElementClasses);
FractureNodeClass(&NodeClasses);
ExhaustiveSubdivision = 1;
@@ -5940,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. */
@@ -6644,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;
@@ -6809,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;
}
@@ -6867,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, '!');
@@ -6874,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;
@@ -6913,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 */
@@ -6956,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;
@@ -6978,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) {
@@ -6999,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 */
@@ -7030,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));
@@ -7047,6 +7132,22 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
obn->instance.name = NULL;
obn->node = -1;
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);
}
if (ob2 == tc2->cell) {
obn->next = ob2;
tc2->cell = obn;
+1 -1
View File
@@ -289,7 +289,7 @@ static struct hashdict cell_dict;
void InitCellHashTable(void)
{
hashfunc = hash;
matchfunc = match;
matchfunc = NULL;
matchintfunc = matchfile;
InitializeHashTable(&cell_dict, CELLHASHSIZE);
}
+5 -1
View File
@@ -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++;
+13 -4
View File
@@ -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);
+5
View File
@@ -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);