Compare commits

..
49 Commits
Author SHA1 Message Date
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 b9769b9f55 Updated version to go along with pull request merge from github. 2020-12-03 20:17:59 -05:00
Tim 'mithro' Ansell 7e42483986 Fix configure script to not clobber CFLAGS.
Signed-off-by: Tim 'mithro' Ansell <[email protected]>
2020-11-29 16:39:28 -08:00
Tim 'mithro' Ansell 97b0d08e4f Rework configure script so exit code works.
The previous script would swallow the exit code of the `./configure`
script and thus it looked like doing a configure always succeeded.

Signed-off-by: Tim 'mithro' Ansell <[email protected]>
2020-11-29 16:35:47 -08:00
Tim Edwards 99e35d8b11 Merge branch 'master' into netgen-1.5 2020-10-09 03:00:25 -04:00
Tim Edwards d2c356f9e2 Added a "-full" switch to the scripted "lvs" command that switches
to the old symmetry breaking method (see previous commit message).
2020-10-08 09:57:01 -04:00
Tim Edwards 5e99fd5ef9 Found a counterexample which shows that the fast symmetry breaking
introduced in revision 150 can result in an incorrect result
reporting a bad match where the match is actually good (as proven
by running the full symmetry breaking on the same netlist).
Because the fast symmetry breaking is orders of magnitude faster
for large circuits, and because the false positive result appears
to be rare, I have introduced a command "symmetry" to switch
methods between fast and full.  So fast symmetry breaking can be
run unless the result fails on symmetry breaking, in which case
the method can be switched to full to see if the problem is a
false positive or not.  This is not an ideal solution, and some
investigation is needed to determine if there is a way to apply
fast symmetry breaking without encountering a false positive
error.
2020-10-08 09:43:25 -04:00
Tim Edwards 65b542f0ab Merge branch 'master' into netgen-1.5 2020-10-08 03:00:22 -04:00
Tim Edwards 04dd4a64d5 Corrected problems with the port count routine not being specified
with the file number, so that it can get confused between libraries.
Also made a fix to coerce one cell class to be forced to be the
same in both circuits under some circumstances.
2020-10-07 21:32:07 -04:00
Tim Edwards b826870be9 Merge branch 'master' into netgen-1.5 2020-08-09 03:01:40 -04:00
Tim Edwards 50b0e9cb65 Found examples where the automated "pin matching" algorithm causes
the top level circuits to be declared matching with no errors even
though the pins do not match.  "proxy pins" are fine for subcells
to detect cases where one subcell has an unused pin and the matching
subcell does not declare it, but that should not be allowed on the
top level, as it cannot be known whether the pin is unused or not.
2020-08-08 13:19:26 -04:00
Tim Edwards ed5276d67b Merge branch 'master' into netgen-1.5 2020-08-04 03:00:31 -04:00
Tim Edwards 82be18ec4b Corrected a bounds check on sub-arrays inside bundles, that prevents
the bundle from being parsed correctly when any sub-array is only one
bit wide.
2020-08-03 22:57:19 -04:00
Tim Edwards 4ee3a1464b Corrected the left-hand side assignment for "assign" statements and
corrected the error statement so that it refers both to the (corrected)
left-hand side and also the portion of the right-hand side that cannot
be parsed as structural verilog.
2020-08-03 11:49:09 -04:00
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
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
17 changed files with 564 additions and 122 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.149
1.5.166
+19 -10
View File
@@ -1660,7 +1660,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 +1710,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 +1771,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 +1822,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 */
+291 -52
View File
@@ -158,6 +158,9 @@ 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)
{
@@ -3145,7 +3148,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 +3243,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 +5249,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 +5262,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 +5278,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 +5310,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 +5574,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 +5716,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 +5741,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 +5778,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 +5817,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,7 +5865,7 @@ int ResolveAutomorphsByProperty()
/*
*-------------------------------------------------------------------------
*
* ResolveAutormorphisms --
* ResolveAutormorphismsFull --
*
* Arbitrarily equivalence one pair of elements within an automorphic class
*
@@ -5845,11 +5874,11 @@ int ResolveAutomorphsByProperty()
*-------------------------------------------------------------------------
*/
int ResolveAutomorphisms()
int ResolveAutomorphismsFull()
{
struct ElementClass *EC;
struct NodeClass *NC;
struct Element *E;
struct NodeClass *NC;
struct Node *N;
int C1, C2;
@@ -5900,6 +5929,68 @@ int ResolveAutomorphisms()
}
converge:
FractureElementClass(&ElementClasses);
FractureNodeClass(&NodeClasses);
ExhaustiveSubdivision = 1;
while (!Iterate() && VerifyMatching() != -1);
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;
@@ -5907,6 +5998,110 @@ int ResolveAutomorphisms()
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. */
@@ -6520,24 +6715,32 @@ 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)
/* ??? Do not do anything with (no pins) entries */
if (strcmp(tob->name, "proxy(no pins)")) {
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;
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;
// 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) {
@@ -6611,7 +6814,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 +6979,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 +7040,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 +7049,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 +7095,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 +7138,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 +7163,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 +7184,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 +7215,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 +7233,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;
@@ -7317,7 +7555,8 @@ static void handler(int sig)
/*----------------------------------------------------------------------*/
/* Note that this cover-all routine is not called from the Tcl/Tk */
/* version, which replaces it with the script "lvs". */
/* return 1 if the two are identical. Try to resolve automorphisms. */
/* return 1 if the two are identical. Try to resolve automorphisms */
/* using the original "full" symmetry breaking algorithm. */
/*----------------------------------------------------------------------*/
int Compare(char *cell1, char *cell2)
@@ -7353,7 +7592,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);
+1
View File
@@ -7,6 +7,7 @@ extern struct nlist *Circuit1;
extern struct nlist *Circuit2;
extern int ExhaustiveSubdivision;
extern int FastSymmetryBreaking;
extern int left_col_end;
extern int right_col_end;
+6 -1
View File
@@ -798,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;
@@ -883,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}
};
+6 -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
+4 -3
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);
}
}
@@ -3583,8 +3584,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. */
+7 -3
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);
}
@@ -1112,13 +1112,17 @@ void FreeObjectAndHash(struct objlist *ob, struct nlist *ptr)
/*************** GENERAL UTILITIES ****************************/
int NumberOfPorts(char *cellname)
int NumberOfPorts(char *cellname, int file)
{
struct nlist *tp;
struct objlist *ob;
int ports;
tp = LookupCell(cellname);
if (file == -1)
tp = LookupCell(cellname);
else
tp = LookupCellFile(cellname, file);
if (tp == NULL) return(0);
ports = 0;
for (ob = tp->cell; ob != NULL; ob = ob->next)
+2 -3
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 */
@@ -242,7 +241,7 @@ extern void FreeObjectAndHash(struct objlist *ob, struct nlist *ptr);
extern void FreePorts(char *cellname);
extern struct IgnoreList *ClassIgnore;
extern int NumberOfPorts(char *cellname);
extern int NumberOfPorts(char *cellname, int file);
extern struct objlist *InstanceNumber(struct nlist *tp, int inst);
extern struct objlist *List(char *list_template);
+1 -1
View File
@@ -929,7 +929,7 @@ void ToggleDebug(void)
void DescribeCell(char *name, int detail)
{
Printf("Cell: %s contains %d instances, %d nodes and %d ports\n", name,
NumberOfInstances(name), RenumberNodes(name), NumberOfPorts(name));
NumberOfInstances(name), RenumberNodes(name), NumberOfPorts(name, -1));
PrintEmbeddingTree(stdout,name,detail);
}
+8 -4
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++;
@@ -903,7 +907,7 @@ void PrintLeavesInCell(char *cellname, int filenum)
np->dumped = 1;
if (np->class != CLASS_SUBCKT) {
Printf("%s; %d ports; Primitive.\n", cellname, NumberOfPorts(cellname));
Printf("%s; %d ports; Primitive.\n", cellname, NumberOfPorts(cellname, filenum));
return;
}
@@ -916,7 +920,7 @@ void PrintLeavesInCell(char *cellname, int filenum)
am_a_leaf = 0;
}
if (am_a_leaf) Printf("%s; %d ports\n", cellname, NumberOfPorts(cellname));
if (am_a_leaf) Printf("%s; %d ports\n", cellname, NumberOfPorts(cellname, filenum));
return;
}
@@ -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':
+37 -19
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.
@@ -1883,20 +1885,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 +1998,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) {
+72 -16
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);
@@ -1225,7 +1254,12 @@ skip_endmodule:
lhs = LookupObject(nodename, CurrentCell);
*aptr = '[';
}
else strcpy(noderoot, nexttok);
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);
@@ -1290,13 +1324,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);
@@ -1854,7 +1896,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;
@@ -1933,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;
@@ -2069,14 +2113,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 */
@@ -2087,6 +2138,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);
Vendored
+3 -1
View File
@@ -4,4 +4,6 @@
# all of its config scripts in a different directory than the configure
# script itself.
( CFLAGS="-g" ; export CFLAGS ; cd scripts ; ./configure "$@" )
export CFLAGS="$CFLAGS -g"
cd scripts
exec ./configure "$@"
+10 -1
View File
@@ -382,6 +382,9 @@ 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
}
}
@@ -501,6 +504,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 +550,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 +574,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"
}
+87 -6
View File
@@ -94,6 +94,7 @@ int _netcmp_ignore(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_symmetry(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_global(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_convert(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
@@ -244,6 +245,9 @@ Command netcmp_cmds[] = {
{"exhaustive", _netcmp_exhaustive,
"\n "
"toggle exhaustive subdivision"},
{"symmetry", _netcmp_symmetry,
"[fast|full]\n "
"apply method for symmetry breaking"},
{"restart", _netcmp_restart,
"\n "
"start over (reset data structures)"},
@@ -1532,23 +1536,24 @@ int
_netgen_model(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
struct nlist *tp;
struct nlist *tp, *tp2;
char *model, *retclass;
unsigned char class;
int fnum = -1;
int result, index, nports;
int result, index, nports, nports2;
char *modelclasses[] = {
"undefined", "nmos", "pmos", "pnp", "npn",
"resistor", "capacitor", "diode",
"inductor", "module", "blackbox", "xline",
"moscap", "mosfet", "bjt", "subcircuit", NULL
"moscap", "mosfet", "bjt", "subcircuit", "copy",
NULL
};
enum OptionIdx {
UNDEF_IDX, NMOS_IDX, PMOS_IDX, PNP_IDX, NPN_IDX,
RES_IDX, CAP_IDX, DIODE_IDX, INDUCT_IDX,
MODULE_IDX, BLACKBOX_IDX, XLINE_IDX, MOSCAP_IDX,
MOSFET_IDX, BJT_IDX, SUBCKT_IDX
MOSFET_IDX, BJT_IDX, SUBCKT_IDX, COPY_IDX
};
if (objc != 3 && objc != 2) {
@@ -1580,7 +1585,7 @@ _netgen_model(ClientData clientData,
if (objc == 3) {
model = Tcl_GetString(objv[2]);
nports = NumberOfPorts(model);
nports = NumberOfPorts(model, fnum);
if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)modelclasses,
"class", 0, &index) != TCL_OK) {
@@ -1644,6 +1649,40 @@ _netgen_model(ClientData clientData,
break;
case SUBCKT_IDX:
class = CLASS_SUBCKT;
break;
case COPY_IDX:
/* "copy" is not a class, but indicates that the cell, */
/* if undefined or a module, should have its class */
/* taken from the other circuit, if that circuit has a */
/* cell of the same name. */
if (Circuit1 == NULL || Circuit2 == NULL) {
Tcl_SetResult(interp, "Circuits have not been queued for comparison.",
NULL);
return TCL_ERROR;
}
if (tp == Circuit1) {
tp2 = LookupCellFile(tp->name, Circuit2->file);
nports2 = NumberOfPorts(tp2->name, Circuit2->file);
}
else if (tp == Circuit2) {
tp2 = LookupCellFile(tp->name, Circuit1->file);
nports2 = NumberOfPorts(tp2->name, Circuit1->file);
}
else {
Tcl_SetResult(interp, "The referenced netlist is not being compared.",
NULL);
return TCL_ERROR;
}
/* Should a non-matching number of ports be considered a fatal error? */
// if (nports2 != nports) {
// Tcl_SetResult(interp, "The number of ports for this cell does not "
// "match between netlists.", NULL);
// return TCL_ERROR;
// }
class = tp2->class;
/* To do (maybe): Rename tp ports to match tp2? */
break;
}
tp->class = class;
@@ -3937,6 +3976,48 @@ _netcmp_permute(ClientData clientData,
return TCL_OK;
}
/*------------------------------------------------------*/
/* Function name: _netcmp_symmetry */
/* Syntax: netgen::symmetry [fast|full] */
/* Formerly: x */
/* Results: */
/* Side Effects: */
/*------------------------------------------------------*/
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");
return TCL_OK;
}
/*------------------------------------------------------*/
/* Function name: _netcmp_exhaustive */
/* Syntax: netgen::exhaustive [on|off] */
@@ -3958,7 +4039,7 @@ _netcmp_exhaustive(ClientData clientData,
int result, index;
if (objc == 1)
index = YES_IDX;
index = -1;
else {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
"option", 0, &index) != TCL_OK)