Compare commits

...
89 Commits
Author SHA1 Message Date
Tim Edwards a888502038 Merge branch 'master' into netgen-1.5 2021-03-02 03:00:35 -05:00
Tim Edwards ea07642172 Removed the symmetry breaking option from the scripted "lvs"
command.
2021-03-01 16:57:49 -05:00
Tim Edwards e9da037001 Removed the code for fast symmetry breaking, as it has been found
to generate incorrect results on occasion.  The method to parallelize
cells with the same no-connect pins should avoid the worst-case
symmetry breaking that was previously plaguing the LVS of large
standard-cell layouts.
2021-03-01 16:55:07 -05:00
Tim Edwards 7ee50a3f8f Modified the parallel combination code to treat cells as equivalently
parallel if the same pins are no-connects.  These were previously not
treated as parallel because each no-connect has a unique node number,
and cells were only considered as parallel if all pins connected to
the same node numbers.  This avoids issues with long-running symmetry
breaking on standard cell designs due to cells like antenna taps or
any cell that is placed without connecting it up.  To do:  This
makes indistinguishable certain cases, e.g., N cells in circuit 1
with pin X open vs. N cells in circuit 2 with pin X all tied together.
This could be caught during property matching.
2021-03-01 16:33:55 -05:00
Tim Edwards c16258d4d1 Merge branch 'master' into netgen-1.5 2021-02-25 03:00:36 -05:00
Tim Edwards c7848c9c02 Corrected an error that (in a rare circumstance) can cause netgen
to go into an infinite loop and fill memory until it crashes, due
to a complete pin mismatch between devices causing one device to
have its pins removed and replaced with proxy pins.
2021-02-24 16:12:19 -05:00
Tim Edwards 5341d7a5fd Merge branch 'master' into netgen-1.5 2021-02-17 03:00:31 -05:00
Tim Edwards 402e1f0f25 Found a chokepoint in FlattenInstancesOf that was unnecessary as it
was running through the entire object linked list to find the
predecessor of a record that it had already found.  Solved by simply
keeping track of the predecessor record.
2021-02-16 17:12:00 -05:00
Tim Edwards 8395df633c Merge branch 'master' into netgen-1.5 2021-02-10 03:00:16 -05:00
Tim Edwards 19471275df Added handling of control blocks (.CONTROL ... .ENDC) in ngspice-
format files to the SPICE parser, so that netgen can be run
directly on a testbench file and not generate errors due to
statements in the control block.
2021-02-09 09:30:27 -05:00
Tim Edwards e75f5661e2 Added a zero-value current source to the zero-valued devices handled
by the pre-matching method.  The current source is treated like the
others except that it forms an open circuit rather than a short.
2021-02-09 09:12:22 -05:00
Tim Edwards 6554063df3 Merge branch 'master' into netgen-1.5 2021-01-22 03:00:40 -05:00
Tim Edwards a034fc16d6 Updated VERSION. 2021-01-21 13:41:20 -05:00
Tim Edwards 62fbd422e2 Modified netcmp.c "addproxies" routine to not get confused by cells
with no pins marked with a "(no pins)" placeholder.  Otherwise it
goes into an infinite loop and eats up memory until it crashes.
2021-01-21 13:38:44 -05:00
Tim Edwards 4416a380b3 Merge branch 'master' into netgen-1.5 2021-01-18 03:00:51 -05:00
Tim Edwards d0bae6aff4 Updated VERSION with the merge of pull request #15 from Alessandro de
Laurenzis.
2021-01-17 11:38:11 -05:00
Alessandro De Laurenzis 8a7bb7f2ca Fix missing prototype for ReadVerilogFile function
Unbreak OpenBSD port for mips64 arch
2021-01-17 10:21:52 +01:00
Tim Edwards 46394b2000 Merge branch 'master' into netgen-1.5 2021-01-17 03:00:15 -05:00
Tim Edwards 0df6c83df5 Updated VERSION to go along with the merge of pull request #14
from Anton Blanchard.
2021-01-16 12:05:52 -05:00
Anton Blanchard 8996fe03dc Increase OBJHASHSIZE
I have a design that is taking quite a long time for netgen to complete LVS
checking. Profiles show a large chunk of runtime is in the hash functions.

Some of the hashtables are very sparsely populated, but others are
heavily used. One hashtable has chains of over 250. Longer term it would
be worth investigating resizing the hashtables (or perhaps using other
data strutures), but for now I looked at what changing the number of
hash buckets (OBJHASHSIZE) does for performance:

OBJHASHSIZE	time (mm:ss)
997		24:18
10093		 4:42
42073		 3:12
104729		 2:51

I somewhat arbitrarily chose 42073 which gives us a 7.6x improvement in
runtime.
2021-01-15 18:24:34 -07:00
Tim Edwards 3fe3bc4cfa Merge branch 'master' into netgen-1.5 2021-01-09 03:00:32 -05:00
Tim Edwards f3cebd9099 Corrected a potential crash condition while doing series combination. 2021-01-08 09:55:00 -05:00
Tim Edwards 6661910672 Merge branch 'master' into netgen-1.5 2020-12-21 03:00:30 -05:00
Tim Edwards 920c6e6928 Corrected a problem causing a segfault during a property record
copy if the property record does not have a model.class record
(should it always?).
2020-12-20 11:55:20 -05:00
Tim Edwards e7a36630f6 Merge branch 'master' into netgen-1.5 2020-12-16 03:00:54 -05:00
Tim Edwards 69780aa048 Added patch from Mitch Bailey which sorts the objects in a verilog
file input so that pins occur first before nodes, as they do in a
SPICE netlist.  Certain parts of the comparison code depend on pins
being first in the netlist, and reordering them when reading input
is easier than rewriting the rest of the code.
2020-12-15 09:57:49 -05:00
Tim Edwards f32b0b34a3 Merge branch 'master' into netgen-1.5 2020-12-06 03:00:10 -05:00
Tim Edwards 2a0ebfde93 Updated VERSION with the commit. 2020-12-05 15:46:45 -05:00
Tim Edwards 6e9e6abe98 Removed the netgen.sh and netgen.tcl scripts from the repository,
which are generated by ./configure and should not be in the repo.
2020-12-05 15:46:03 -05:00
Tim Edwards 6b731ddd7a Merge branch 'master' into netgen-1.5 2020-12-04 03:00:27 -05:00
Tim Edwards 99e35d8b11 Merge branch 'master' into netgen-1.5 2020-10-09 03:00:25 -04:00
Tim Edwards 65b542f0ab Merge branch 'master' into netgen-1.5 2020-10-08 03:00:22 -04:00
Tim Edwards b826870be9 Merge branch 'master' into netgen-1.5 2020-08-09 03:01:40 -04:00
Tim Edwards ed5276d67b Merge branch 'master' into netgen-1.5 2020-08-04 03:00:31 -04:00
Tim Edwards 69c9d85be7 Merge branch 'master' into netgen-1.5 2020-08-01 03:00:23 -04:00
Tim Edwards ad05d059c7 Merge branch 'master' into netgen-1.5 2020-07-31 03:00:27 -04:00
Tim Edwards 1b2cd1497c Merge branch 'master' into netgen-1.5 2020-07-30 03:00:28 -04:00
Tim Edwards d9d5a46c6e Merge branch 'master' into netgen-1.5 2020-07-25 03:00:09 -04:00
Tim Edwards d73b711e3a Merge branch 'master' into netgen-1.5 2020-07-02 03:00:09 -04:00
Tim Edwards 1428580109 Merge branch 'master' into netgen-1.5 2020-06-17 03:00:38 -04:00
Tim Edwards 210dfb25c3 Merge branch 'master' into netgen-1.5 2020-06-04 03:00:24 -04:00
Tim Edwards 27f2ab8b3f Merge branch 'master' into netgen-1.5 2020-03-28 03:00:24 -04:00
Tim Edwards 1be00bbd99 Merge branch 'master' into netgen-1.5 2020-03-27 03:00:21 -04:00
Tim Edwards 03b241a5d4 Merge branch 'master' into netgen-1.5 2020-03-11 03:00:17 -04:00
Tim Edwards 43cebd1ef9 Merge branch 'master' into netgen-1.5 2020-03-06 03:00:39 -05:00
Tim Edwards 0490959b07 Merge branch 'master' into netgen-1.5 2020-03-05 03:00:09 -05:00
Tim Edwards dc841f3293 Merge branch 'master' into netgen-1.5 2020-02-24 17:35:04 -05:00
Tim Edwards 05bcfede69 Merge branch 'master' into netgen-1.5 2020-02-24 16:39:19 -05:00
Tim Edwards 72ed78e55a Update for change in ocd git script 2020-02-24 15:04:59 -05:00
Tim Edwards 59bb8a89c0 "ocd_git_pure automatic update to repo" 2020-02-24 15:04:27 -05:00
Tim Edwards 9bdaee652e "ocd_git_pure automatic update to repo" 2020-02-18 03:00:14 -05:00
Tim Edwards 9879b58f83 Merge branch 'master' into netgen-1.5 2020-02-18 03:00:13 -05:00
Tim Edwards 9e3b705fcc "ocd_git_pure automatic update to repo" 2020-02-11 03:00:09 -05:00
Tim Edwards d2c9129242 Merge branch 'master' into netgen-1.5 2020-02-11 03:00:09 -05:00
Tim Edwards 942f421fa3 "ocd_git_pure automatic update to repo" 2020-01-30 03:01:39 -05:00
Tim Edwards 6bc948d8ba Merge branch 'master' into netgen-1.5 2020-01-30 03:01:38 -05:00
Tim Edwards c1ad37f05a "ocd_git_pure automatic update to repo" 2020-01-14 03:00:47 -05:00
Tim Edwards 9edefe7d59 Merge branch 'master' into netgen-1.5 2020-01-14 03:00:47 -05:00
Tim Edwards f6b9629521 "ocd_git_pure automatic update to repo" 2019-11-20 03:00:33 -05:00
Tim Edwards 7b2e01f2af Merge branch 'master' into netgen-1.5 2019-11-20 03:00:33 -05:00
Tim Edwards 224050f153 "ocd_git_pure automatic update to repo" 2019-10-09 03:00:08 -04:00
Tim Edwards 74e8c3e168 Merge branch 'master' into netgen-1.5 2019-10-09 03:00:08 -04:00
Tim Edwards 95a29fcd8c "ocd_git_pure automatic update to repo" 2019-09-11 03:00:07 -04:00
Tim Edwards 723a950fd3 Merge branch 'master' into netgen-1.5 2019-09-11 03:00:07 -04:00
Tim Edwards e3368cb22a "ocd_git_pure automatic update to repo" 2019-09-10 03:00:08 -04:00
Tim Edwards f06e6548bb Merge branch 'master' into netgen-1.5 2019-09-10 03:00:08 -04:00
Tim Edwards 72ed19ff36 "ocd_git_pure automatic update to repo" 2019-09-09 03:00:10 -04:00
Tim Edwards 39b8e3d14a Merge branch 'master' into netgen-1.5 2019-09-09 03:00:10 -04:00
Tim Edwards b63dfa8638 "ocd_git_pure automatic update to repo" 2019-08-20 03:00:20 -04:00
Tim Edwards f918f33c51 Merge branch 'master' into netgen-1.5 2019-08-20 03:00:20 -04:00
Tim Edwards 63b2e48ea1 "ocd_git_pure automatic update to repo" 2019-08-13 03:00:08 -04:00
Tim Edwards 6e63f49d53 Merge branch 'master' into netgen-1.5 2019-08-13 03:00:07 -04:00
Tim Edwards 419b6de29a "ocd_git_pure automatic update to repo" 2019-08-11 03:00:07 -04:00
Tim Edwards 205cf2aa58 Merge branch 'master' into netgen-1.5 2019-08-11 03:00:07 -04:00
Tim Edwards 52b6766fc8 "ocd_git_pure automatic update to repo" 2019-08-04 03:00:20 -04:00
Tim Edwards 7b0bdd29e8 Merge branch 'master' into netgen-1.5 2019-08-04 03:00:20 -04:00
Tim Edwards 433cbd090a "ocd_git_pure automatic update to repo" 2019-07-25 03:00:16 -04:00
Tim Edwards 3087bd3337 Merge branch 'master' into netgen-1.5 2019-07-25 03:00:16 -04:00
Tim Edwards b79a29d662 "ocd_git_pure automatic update to repo" 2019-07-15 03:00:27 -04:00
Tim Edwards bf9c61e412 Merge branch 'master' into netgen-1.5 2019-07-15 03:00:27 -04:00
Tim Edwards 8d34bd372d "ocd_git_pure automatic update to repo" 2019-07-03 03:00:22 -04:00
Tim Edwards 229c2931a8 Merge branch 'master' into netgen-1.5 2019-07-03 03:00:22 -04:00
Tim Edwards b8da97deb1 "ocd_git_pure automatic update to repo" 2019-06-16 03:00:15 -04:00
Tim Edwards b7187d5899 Merge branch 'master' into netgen-1.5 2019-06-16 03:00:15 -04:00
Tim Edwards d27d441c58 "ocd_git_pure automatic update to repo" 2019-06-13 03:00:05 -04:00
Tim Edwards 48c9e6b292 Merge branch 'master' into netgen-1.5 2019-06-13 03:00:05 -04:00
Tim Edwards ced5846da3 "ocd_git_pure automatic update to repo" 2019-05-18 03:00:05 -04:00
Tim Edwards b99d33064f Merge branch 'master' into netgen-1.5 2019-05-18 03:00:04 -04:00
Tim Edwards 399472e940 "ocd_git_pure automatic update to repo" 2019-05-07 09:13:00 -04:00
11 changed files with 242 additions and 273 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.158
1.5.169
+95 -27
View File
@@ -253,7 +253,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
{
struct objlist *ParentParams;
struct objlist *ParentProps;
struct objlist *NextObj;
struct objlist *NextObj, *LastObj, *prepp;
struct objlist *ChildObjList;
struct nlist *ThisCell;
struct nlist *ChildCell;
@@ -296,21 +296,35 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
while (notdone) {
notdone = 0;
ParentParams = ThisCell->cell;
LastObj = NULL;
for (ParentParams = ThisCell->cell; ParentParams != NULL;
ParentParams = NextObj) {
ParentParams = NextObj) {
if (Debug) Printf("Parent = %s, type = %d\n",
ParentParams->name, ParentParams->type);
NextObj = ParentParams->next;
if (ParentParams->type != FIRSTPIN) continue;
if (!(*matchfunc)(ParentParams->model.class, instance)) continue;
if (ParentParams->type != FIRSTPIN) {
LastObj = ParentParams;
continue;
}
if (!(*matchfunc)(ParentParams->model.class, instance)) {
LastObj = ParentParams;
continue;
}
ChildCell = LookupCellFile(ParentParams->model.class, ThisCell->file);
if (Debug)
Printf(" Flattening instance: %s, primitive = %s\n",
ParentParams->instance.name, (ChildCell->class ==
CLASS_SUBCKT) ? "no" : "yes");
if (ChildCell->class != CLASS_SUBCKT) continue;
if (ChildCell == ThisCell) continue; // Avoid infinite loop
if (ChildCell->class != CLASS_SUBCKT) {
LastObj = ParentParams;
continue;
}
if (ChildCell == ThisCell) {
LastObj = ParentParams;
continue; // Avoid infinite loop
}
/* Does the parent cell have properties? If so, save a pointer to them */
for (ParentProps = ParentParams->next; ParentProps &&
@@ -373,10 +387,10 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
}
/* in pathological cases, the lengths of the port lists may
change. This is an error, but that is no reason to allow
the code to core dump. We avoid this by placing a
superfluous check on ob2->type
*/
* change. This is an error, but that is no reason to allow
* the code to core dump. We avoid this by placing a
* superfluous check on ob2->type
*/
if (ob2 != NULL)
ob2 = ob2->next;
@@ -497,10 +511,21 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
for (ob2 = ChildObjList; ob2 && ob2->next != NULL; ob2 = ob2->next) ;
}
else {
/* find ParentParams in ThisCell list */
for (ob2 = ThisCell->cell; ob2 && ob2->next != ParentParams; ob2=ob2->next);
/* find ParentParams in ThisCell list. In most cases, LastObj */
/* should be pointing to it. */
if (LastObj && (LastObj->next == ParentParams)) {
ob2 = LastObj;
}
else {
for (ob2 = LastObj; ob2 && ob2->next != ParentParams; ob2=ob2->next);
if (ob2 == NULL) {
/* It should not happen that LastObj is ahead of ParentParams */
/* but just in case, this long loop will find it. */
for (ob2 = ThisCell->cell; ob2 && ob2->next != ParentParams; ob2=ob2->next);
}
}
if (ob2)
for (ob2->next = ChildObjList; ob2->next != NULL; ob2 = ob2->next) ;
for (ob2->next = ChildObjList; ob2->next != NULL; ob2 = ob2->next) ;
}
/* now, ob2 is last element in child list, so skip and reclaim parent */
@@ -1136,9 +1161,10 @@ int UniquePins(char *name, int filenum)
struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
{
struct nlist *ptr;
struct objlist *ob, *obt, *lob, *nob, *firstpin;
struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob;
struct nlist *tc = (struct nlist *)clientdata;
int pinnum;
char *saveinst = NULL;
ptr = (struct nlist *)(p->ptr);
if (tc->file != ptr->file) return NULL;
@@ -1186,13 +1212,44 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
}
FREE(ob->name);
if (ob->instance.name != NULL) FREE(ob->instance.name);
if (ob->instance.name != NULL) {
/* Keep a copy of the instance name (see below) */
if (saveinst != NULL) FREE(saveinst);
saveinst = ob->instance.name;
}
if (ob->model.class != NULL) FREE(ob->model.class);
FREE(ob);
}
else {
lob = ob;
ob->type = pinnum++; // Renumber pins in order
if ((ob->type == PROPERTY) && (pinnum == 1))
{
/* If this happens, then all the pins got removed,
* and there is probably something very much wrong
* with the setup. However, to keep netgen from
* blowing up, add back a "proxy(no pins)" record
* in front; otherwise we'd have an orphaned
* property record.
*/
pob = GetObject();
pob->name = (char *)MALLOC(15);
sprintf(pob->name, "proxy(no pins)");
pob->model.class = strsave(ob->model.class);
if (saveinst != NULL)
pob->instance.name = strsave(saveinst);
else
/* This should never happen */
pob->instance.name = strsave("error");
pob->type = pinnum++;
pob->node = -1;
pob->next = ob;
lob->next = pob;
lob = ob;
}
else
{
lob = ob;
ob->type = pinnum++; // Renumber pins in order
}
}
ob = nob;
obt = obt->next;
@@ -1203,6 +1260,8 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
}
}
if (saveinst != NULL) FREE(saveinst);
return NULL; /* Keep the search going */
}
@@ -1660,7 +1719,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
while (ecomp != NULL) {
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
((ecomp->cell1->class == CLASS_RES) ||
(ecomp->cell1->class == CLASS_VSOURCE))) {
(ecomp->cell1->class == CLASS_VSOURCE) ||
(ecomp->cell1->class == CLASS_ISOURCE))) {
int node1 = -1, node2 = -1;
lob = NULL;
for (ob1 = tc1->cell; ob1; ) {
@@ -1709,11 +1769,16 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
tsub1->name,
tc1->name);
/* merge node of endpoints */
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
if (ob2->node == node2)
ob2->node = node1;
}
/* A current source is an open, while a */
/* resistor or voltage source is a short. */
if (ecomp->cell1->class != CLASS_ISOURCE) {
/* merge node of endpoints */
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
if (ob2->node == node2)
ob2->node = node1;
}
}
/* snip, snip. Excise this device */
if (lob == NULL) {
@@ -1765,7 +1830,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell2 != NULL) &&
((ecomp->cell2->class == CLASS_RES) ||
(ecomp->cell2->class == CLASS_VSOURCE))) {
(ecomp->cell2->class == CLASS_VSOURCE) ||
(ecomp->cell2->class == CLASS_ISOURCE))) {
int node1 = -1, node2 = -1;
lob = NULL;
for (ob2 = tc2->cell; ob2; ) {
@@ -1815,9 +1881,11 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
tc2->name);
/* merge node of endpoints */
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
if (ob1->node == node2)
ob1->node = node1;
if (ecomp->cell2->class != CLASS_ISOURCE) {
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
if (ob1->node == node2)
ob1->node = node1;
}
}
/* snip, snip. Excise this device */
+43 -188
View File
@@ -158,9 +158,6 @@ int right_col_end = 87;
/* if TRUE, always partition ALL classes */
int ExhaustiveSubdivision = 0;
/* if TRUE, use fast symmetry breaking to resolve automorphisms */
int FastSymmetryBreaking = 1;
#ifdef TEST
static void PrintElement_List(struct Element *E)
{
@@ -5865,16 +5862,19 @@ int ResolveAutomorphsByProperty()
/*
*-------------------------------------------------------------------------
*
* ResolveAutormorphismsFull --
* ResolveAutormorphisms --
*
* Arbitrarily equivalence one pair of elements within an automorphic class
* Do symmetry breaking of automorphisms.
*
* Arbitrarily equivalence all pairs of elements and nodes within all
* automorphic classes, and run to completion.
*
* Return value is the same as VerifyMatching()
*
*-------------------------------------------------------------------------
*/
int ResolveAutomorphismsFull()
int ResolveAutomorphisms()
{
struct ElementClass *EC;
struct Element *E;
@@ -5936,172 +5936,6 @@ int ResolveAutomorphismsFull()
return(VerifyMatching());
}
/*
*-------------------------------------------------------------------------
*
* ResolveElementAutomorphismsFast --
*
* Apply arbitrary symmetry breaking to symmetric element lists, then
* iterate exhaustively to resolve all automorphisms.
*
* Return value is the same as VerifyMatching()
*
*-------------------------------------------------------------------------
*/
int ResolveElementAutomorphismsFast()
{
struct ElementClass *EC;
struct Element *E;
int C1, C2;
for (EC = ElementClasses; EC != NULL; EC = EC->next) {
struct Element *E1, *E2;
C1 = C2 = 0;
E1 = E2 = NULL;
for (E = EC->elements; E != NULL; E = E->next) {
if (E->graph == Circuit1->file) {
C1++;
E1 = E;
}
else {
C2++;
E2 = E;
}
}
if (C1 == C2 && C1 != 1) {
unsigned long 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 && 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());
}
/*
*-------------------------------------------------------------------------
*
* ResolveNodeAutomorphismsFast --
*
* 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 ResolveNodeAutomorphismsFast()
{
struct Node *N;
struct NodeClass *NC;
int C1, C2;
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) {
C1++;
N1 = N;
}
else {
C2++;
N2 = N;
}
}
if (C1 == C2 && C1 != 1) {
unsigned long 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 && 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;
}
}
}
FractureElementClass(&ElementClasses);
FractureNodeClass(&NodeClasses);
ExhaustiveSubdivision = 1;
while (!Iterate() && VerifyMatching() != -1);
return(VerifyMatching());
}
/*
*-------------------------------------------------------------------------
*
* ResolveAutormorphisms --
*
* Do symmetry breaking of automorphisms. If FastSymmetryBreaking is
* False (not the default), then run ResolveAutomorphismsFull() (q.v.).
* Otherwise, run the fast symmetry breaking method:
*
* Arbitrarily equivalence all pairs of elements and nodes within all
* automorphic classes, and run to completion. Note that this is a
* fast version of ResolveAutomorphismsFull(), and can run many orders
* of magnitude faster. However, it can also produce an incorrect
* result, declaring a global mismatch where none exists. In that
* case, the matching should be re-run with ResolveAutomorphismsFull().
*
* Some investigation needs to be done to determine if there is a way
* to execute faster symmetry breaking without the possibility of
* producing an incorrect result.
*
* Return value is the same as VerifyMatching()
*
*-------------------------------------------------------------------------
*/
int ResolveAutomorphisms()
{
int result;
if (FastSymmetryBreaking == 0)
return ResolveAutomorphismsFull();
result = ResolveElementAutomorphismsFast();
if (result != 0)
result = ResolveNodeAutomorphismsFast();
return result;
}
/*------------------------------------------------------*/
/* PermuteSetup -- */
/* Add an entry to a cell's "permutes" linked list. */
@@ -6715,24 +6549,45 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
firstpin = ob;
while (tob && (tob->type == PORT || tob->type == UNKNOWN)) {
if (tob->type == UNKNOWN) {
obn = (struct objlist *)CALLOC(1, sizeof(struct objlist));
obn->name = (char *)MALLOC(strlen(firstpin->instance.name)
+ strlen(tob->name) + 2);
sprintf(obn->name, "%s/%s", firstpin->instance.name, tob->name);
obn->instance.name = strsave(firstpin->instance.name);
obn->model.class = strsave(tc->name);
obn->type = i++;
obn->node = numnodes++;
obn->next = ob; // Splice into object list
lob->next = obn;
lob = obn;
/* Do not do anything with (no pins) entries (in the reference cell) */
if (strcmp(tob->name, "proxy(no pins)")) {
/* But if the target cell instance has proxy(no pins), then reuse
* the record and modify it.
*/
if (!strcmp(ob->name, "proxy(no pins)")) {
obn = ob;
FREE(ob->name);
obn->name = (char *)MALLOC(strlen(ob->instance.name)
+ strlen(tob->name) + 2);
sprintf(obn->name, "%s/%s", ob->instance.name, tob->name);
ob = obn->next;
}
else {
obn = (struct objlist *)CALLOC(1, sizeof(struct objlist));
obn->name = (char *)MALLOC(strlen(firstpin->instance.name)
+ strlen(tob->name) + 2);
sprintf(obn->name, "%s/%s", firstpin->instance.name, tob->name);
obn->instance.name = strsave(firstpin->instance.name);
obn->model.class = strsave(tc->name);
obn->next = ob; // Splice into object list
lob->next = obn;
}
obn->type = i++;
obn->node = numnodes++;
lob = obn;
// Hash the new pin record for "LookupObject()"
HashPtrInstall(obn->name, obn, &(ptr->objdict));
// Hash the new pin record for "LookupObject()"
HashPtrInstall(obn->name, obn, &(ptr->objdict));
if (tob == tc->cell) {
// Rehash the instance in instdict
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
if (tob == tc->cell) {
// Rehash the instance in instdict
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
}
}
else {
lob = ob;
ob->type = i++;
ob = ob->next;
}
}
else if (ob == NULL) {
-1
View File
@@ -7,7 +7,6 @@ extern struct nlist *Circuit1;
extern struct nlist *Circuit2;
extern int ExhaustiveSubdivision;
extern int FastSymmetryBreaking;
extern int left_col_end;
extern int right_col_end;
+42 -7
View File
@@ -2470,7 +2470,8 @@ void CopyProperties(struct objlist *obj_to, struct objlist *obj_from)
kvcur->value.ival = 0;
obj_to->instance.props = kvcopy;
obj_to->model.class = strsave(obj_from->model.class);
if (obj_from->model.class)
obj_to->model.class = strsave(obj_from->model.class);
}
}
@@ -3131,6 +3132,9 @@ int remove_group_tags(struct objlist *ob)
/* If the device has permutable pins, then duplicate hashes are made */
/* for each permutation. */
/* */
/* If the device has isolated (unconnected) pins, then treat them as */
/* all belonging to the same net for the purpose of parallel merging. */
/* */
/* Return the number of devices merged. */
/*----------------------------------------------------------------------*/
@@ -3145,6 +3149,7 @@ int CombineParallel(char *model, int file)
size_t pcnt;
int i, dcnt = 0, hastag;
char *pstr, *p2str, *pptr;
int *nodecount;
struct valuelist *kv;
if ((tp = LookupCellFile(model, file)) == NULL) {
@@ -3154,6 +3159,17 @@ int CombineParallel(char *model, int file)
InitializeHashTable(&devdict, OBJHASHSIZE);
/* Make one pass to count the number of times each node number is */
/* used. This list indicates which pins are no-connects, so they */
/* can be treated as equivalent for the purpose of parallelization. */
nodecount = (int *)CALLOC((tp->nodename_cache_maxnodenum + 1), sizeof(int));
for (ob = tp->cell; ob; ob = ob->next) {
if (ob->node >= 0)
if (ob->type != NODE)
nodecount[ob->node]++;
}
lob = NULL;
for (ob = tp->cell; ob; ) {
if (ob->type == FIRSTPIN) {
@@ -3200,7 +3216,10 @@ int CombineParallel(char *model, int file)
pptr += pstr - (char *)2;
for (ob2 = ob; ob2 && (ob2->type > FIRSTPIN || ob2 == ob); ob2 = ob2->next) {
sprintf(pptr, "_%d", ob2->node);
if ((ob->node >= 0) && (nodecount[ob->node] == 1))
strcat(pptr, "_nc");
else
sprintf(pptr, "_%d", ob2->node);
pptr += strlen(pptr);
}
@@ -3236,11 +3255,26 @@ int CombineParallel(char *model, int file)
for (ob2 = ob; ob2 && (ob2->type > FIRSTPIN || ob2 == ob);
ob2 = ob2->next) {
if (ob2 == pob1)
sprintf(pptr, "_%d", pob2->node);
{
if ((pob2->node >= 0) && (nodecount[pob2->node] == 1))
strcat(pptr, "_nc");
else
sprintf(pptr, "_%d", pob2->node);
}
else if (ob2 == pob2)
sprintf(pptr, "_%d", pob1->node);
{
if ((pob1->node >= 0) && (nodecount[pob1->node] == 1))
strcat(pptr, "_nc");
else
sprintf(pptr, "_%d", pob1->node);
}
else
sprintf(pptr, "_%d", ob2->node);
{
if ((ob2->node >= 0) && (nodecount[ob2->node] == 1))
strcat(pptr, "_nc");
else
sprintf(pptr, "_%d", ob2->node);
}
pptr += strlen(pptr);
}
HashPtrInstall(p2str, ob, &devdict);
@@ -3364,6 +3398,7 @@ int CombineParallel(char *model, int file)
if (dcnt > 0) {
Fprintf(stdout, "Class %s: Merged %d devices.\n", model, dcnt);
}
FREE(nodecount);
return dcnt;
}
@@ -3583,8 +3618,8 @@ int CombineSeries(char *model, int file)
/* Excise the 2nd instance. instlist[i][1] remains as the */
/* only pointer to it. */
for (obp = instlist[i][0]; obp->next->type > FIRSTPIN ||
obp->next->type == PROPERTY; obp = obp->next);
for (obp = instlist[i][0]; obp->next && (obp->next->type > FIRSTPIN ||
obp->next->type == PROPERTY); obp = obp->next);
for (ob2 = obp; ob2 && ob2->next != instlist[i][1]; ob2 = ob2->next);
/* Device may have been moved by the above code. If so, look for */
+9
View File
@@ -65,6 +65,15 @@ extern void AssignCircuits(char *name1, int file1, char *name2, int file2);
/* flatten.c */
extern int PrematchLists(char *, int, char *, int);
/* verilog.c */
struct cellstack {
char *cellname;
struct cellstack *next;
};
void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
int blackbox);
/* Define (enumerate) various device classes, largely based on SPICE */
/* model types, mixed with some ext/sim types. */
+1 -2
View File
@@ -192,9 +192,8 @@ struct Permutation {
struct Permutation *next;
};
#define OBJHASHSIZE 997 /* the size of the object and instance hash lists */
#define OBJHASHSIZE 42073 /* the size of the object and instance hash lists */
/* prime numbers are good choices as hash sizes */
/* 101 is a good number for IBMPC */
/* cell definition for hash table */
/* NOTE: "file" must come first for the hash matching by name and file */
+11 -9
View File
@@ -473,15 +473,6 @@ void CleanupSubcell() {
SetClass(CLASS_MODULE);
}
/*------------------------------------------------------*/
/* Structure for stacking nested subcircuit definitions */
/*------------------------------------------------------*/
struct cellstack {
char *cellname;
struct cellstack *next;
};
/*------------------------------------------------------*/
/* Push a subcircuit name onto the stack */
/*------------------------------------------------------*/
@@ -874,6 +865,17 @@ skip_ends:
}
}
/* Ignore anything in a .CONTROL ... .ENDC block */
else if (matchnocase(nexttok, ".CONTROL")) {
while (1) {
SpiceSkipNewLine();
SkipTok(NULL);
if (EndParseFile()) break;
if (matchnocase(nexttok, ".ENDC"))
break;
}
}
// Blackbox (library) mode---parse only subcircuits and models;
// ignore all components.
+37 -6
View File
@@ -553,9 +553,43 @@ void CleanupModule() {
int maxnode = 0;
int has_submodules = FALSE;
struct objlist *sobj, *nobj, *lobj, *pobj;
struct objlist *myLastPort, *object_it, *myNextObject;
if (CurrentCell == NULL) return;
myLastPort = NULL;
/* Reorder objects so that all ports come first, before nodes, because
* parts of the code depend on it.
*/
for (object_it = CurrentCell->cell; object_it && object_it->type <= 0;
object_it = myNextObject ) {
myNextObject = object_it->next;
if (!myNextObject) // end of list
continue;
if (myLastPort == NULL) {
if (object_it->type == PORT) {
myLastPort = object_it; // port at begining of list
myNextObject = object_it; // otherwise skips one
}
else if (myNextObject->type == PORT) {
object_it->next = myNextObject->next;
myNextObject->next = CurrentCell->cell;
CurrentCell->cell = myNextObject;
myLastPort = myNextObject;
}
}
else if (myNextObject->type == PORT) {
object_it->next = myNextObject->next;
myNextObject->next = myLastPort->next;
myLastPort->next = myNextObject;
myLastPort = myNextObject;
}
}
for (sobj = CurrentCell->cell; sobj; sobj = sobj->next)
if (sobj->node > maxnode)
maxnode = sobj->node + 1;
@@ -598,11 +632,6 @@ void CleanupModule() {
/* Structure for stacking nested module definitions */
/*------------------------------------------------------*/
struct cellstack {
char *cellname;
struct cellstack *next;
};
/* Forward declarations */
extern void IncludeVerilog(char *, int, struct cellstack **, int);
@@ -1946,7 +1975,9 @@ nextinst:
sprintf(localnet, "_noconnect_%d_", localcount++);
Node(localnet);
join(localnet, obptr->name);
Fprintf(stderr, "Note: Implicit pin %s\n", obpinname);
Fprintf(stderr,
"Note: Implicit pin %s in instance %s of %s in cell %s\n",
obpinname, locinst, modulename, CurrentCell->name);
}
else if (GetBus(scan->net, &wb) == 0) {
char *bptr2;
-3
View File
@@ -382,9 +382,6 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
} elseif {$arg == "-blackbox"} {
puts stdout "Treating empty subcircuits as black-box cells"
netgen::model blackbox on
} elseif {$arg == "-full"} {
puts stdout "Using full symmetry breaking method"
netgen::symmetry full
}
}
+3 -29
View File
@@ -246,8 +246,7 @@ Command netcmp_cmds[] = {
"\n "
"toggle exhaustive subdivision"},
{"symmetry", _netcmp_symmetry,
"[fast|full]\n "
"apply method for symmetry breaking"},
"(deprecated)"},
{"restart", _netcmp_restart,
"\n "
"start over (reset data structures)"},
@@ -3982,39 +3981,14 @@ _netcmp_permute(ClientData clientData,
/* Formerly: x */
/* Results: */
/* Side Effects: */
/* Notes: Deprecated, retained for compatibility. */
/*------------------------------------------------------*/
int
_netcmp_symmetry(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
char *fastfull[] = {
"fast", "full", NULL
};
enum OptionIdx {
FAST_IDX, FULL_IDX
};
int result, index;
if (objc == 1)
index = -1;
else {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)fastfull,
"option", 0, &index) != TCL_OK)
return TCL_ERROR;
}
switch(index) {
case FAST_IDX:
FastSymmetryBreaking = TRUE;
break;
case FULL_IDX:
FastSymmetryBreaking = FALSE;
break;
}
Printf("Symmetry breaking method: %s.\n",
FastSymmetryBreaking ? "FAST" : "FULL");
Printf("Symmetry breaking method has been deprecated.\n");
return TCL_OK;
}