Compare commits

...
43 Commits
Author SHA1 Message Date
Tim Edwards abaf896f7f Merge branch 'master' into netgen-1.5 2024-10-15 02:00:02 -04:00
Tim Edwards df8fa29b2f Fixed an issue with property matching that was preventing the last-
ditch effort of matching based on combining devices with the same
critical property (e.g., adding gate widths together for transistors
of the same gate length, if the property records remain stubbornly
mismatched to the end).  Thanks to Bondar Andrey Renatovich for
surfacing this issue and providing a reproducible example.
2024-10-14 13:24:35 -04:00
Tim Edwards e94d25b3f1 Merge branch 'master' into netgen-1.5 2024-10-08 02:00:03 -04:00
Tim Edwards d14bf70f1c Working to get some MatchPins improvements from Mitch Bailey from
a long time ago into the code.  The improvements collided with
intervening changes to the same routines and would not merge
cleanly, which is why they were never merged.  Step 1:  Show the
net name of a matching net that is missing a pin.  Remove output
of missing pins that is redundant (pin names being output twice).
2024-10-07 11:10:33 -04:00
Tim Edwards e659495ef5 Merge branch 'master' into netgen-1.5 2024-10-04 02:00:03 -04:00
Tim Edwards 5c21000a8b Made a modification to accommodate the situation where a SPICE
instance is matched to a verilog module definition, and the SPICE
instance is read before the verilog definition, forcing a
placeholder cell to be created.  Netgen will now make the
assumption that the verilog ports are in the same order as the
SPICE instance port order.  At the same time, it will output a
warning message that it is making this not-necessarily-warranted
assumption.  If the number of ports don't match or the placeholder
did not come from a SPICE instance, then the placeholder pins are
left alone.
2024-10-03 14:52:42 -04:00
Tim Edwards 2ce3cf8dd9 Merge branch 'master' into netgen-1.5 2024-10-03 02:00:02 -04:00
Tim Edwards 05872ca918 Corrected an apparently long-standing error that is responsible for
some errors failing to list in the output while also being responsible
for a number of non-errors showing up in the output.  This fix may
substantially clean up netgen output.  Also:  Added text to the
output noting that pin matching may be incorrect with respect to
symmetries if the nets have failed to match.
2024-10-02 21:20:27 -04:00
Tim Edwards 05f433f334 Merge branch 'master' into netgen-1.5 2024-10-01 02:00:02 -04:00
Tim Edwards e821381900 Corrected a rather obscure error in which an otherwise unconnected
port-to-port short (formed by "assign" in verilog or zero-valued
resistors in SPICE) does not get checked when counting nodes
before adding a proxy pin to a subcircuit in that cell, causing
the proxy pin to be assigned the same node number and forming an
unintended connection to the port-to-port connecting net.
2024-09-30 22:11:53 -04:00
Tim Edwards 2129073a38 Merge branch 'master' into netgen-1.5 2024-09-28 02:00:02 -04:00
Tim Edwards 8022e1370f Added a few lines to rebuild the node cache after removing devices
such a zero-ohm resistors or zero-volt sources during the pre-match
phase, since the list of nodes gets changed by merging nets across
the removed devices.  Otherwise, the node-name cache gets
corrupted and random LVS errors occur.
2024-09-27 10:08:37 -04:00
Tim Edwards b0d980bb7d Merge branch 'master' into netgen-1.5 2024-08-17 02:00:03 -04:00
Tim Edwards 2b88d79adc Corrected a rare case where a NULL value propagates in the flattening
routine and is not caught until it causes a segfault.
2024-08-16 19:48:36 -04:00
Tim Edwards ab0165b16c Merge branch 'master' into netgen-1.5 2024-05-17 02:00:02 -04:00
Tim Edwards bf4112db07 Corrected two statements that can cause a segfault because a
structure variable is not checked for the condition of being NULL
before attempting to read a component of the structure.  These
conditions imply that something is badly wrong in the netlist but
should not be causing a segfault.
2024-05-16 11:49:56 -04:00
Tim Edwards 5197eb6186 Merge branch 'master' into netgen-1.5 2024-05-15 02:00:01 -04:00
Tim Edwards fcee934580 Corrected the parsing of the "model" command, which was failing to
pass the right cell name to the routine which counts the number of
pins.  Using this in a setup file will prevent netgen from spending
time matching low-level devices.
2024-05-14 15:12:41 -04:00
Tim Edwards 48ed1f7583 Merge branch 'master' into netgen-1.5 2024-05-10 02:00:02 -04:00
Tim Edwards 2d427aef3c Corrected the bad placement of #ifdef TCL_NETGEN . . . #endif around
critical parts of the netcmp.c code, causing issues with the non-Tcl
build (not that anyone should be doing a non-Tcl build).
2024-05-09 14:11:26 -04:00
Tim Edwards e63593c7e2 Merge branch 'master' into netgen-1.5 2024-04-04 02:00:01 -04:00
Tim Edwards fd0c8c87ea Corrected another error in which, for device sorting, "M" was set
to 1 before the loop over devices in "run", resulting in "M"
taking the value of the previous property record if the following
record did not have an "M" value, instead of setting it to 1.
2024-04-03 21:05:08 -04:00
Tim Edwards 3d180f778d Corrected an error that had previously been corrected in
PropertyMatch() but not corrected symmetrically between circuit1
and circuit2;  this left the possibility that "M=1" in one
circuit vs. no "M" entry in the other would still pop up as a
property error, depending on which circuit (layout or schematic)
was listed first.
2024-04-03 11:01:58 -04:00
Tim Edwards 178af5f493 Merge branch 'master' into netgen-1.5 2024-03-05 02:00:02 -05:00
Tim Edwards 035fef5c72 Corrected an issue that prevents "cells list <file>" from reporting
empty cells (this does not solve the problem at hand, but is a part
of it).
2024-03-04 21:26:09 -05:00
Tim Edwards ac8956c32e Merge branch 'master' into netgen-1.5 2024-02-20 02:00:03 -05:00
Tim Edwards 202ea0431f Also updated configure (in addition to configure.in) with the
change to remove the "m4" dependency.
2024-02-19 12:46:20 -05:00
Tim Edwards 94754dbc4e Removed the requirement for package "m4" that is in the configuration
script.  It is not needed and doesn't exist in many OS distributions.
2024-02-19 12:41:08 -05:00
Tim Edwards b87f0fd5db Merge branch 'master' into netgen-1.5 2024-02-19 02:00:03 -05:00
Tim Edwards bf67d3c275 Having been given an example by Kareem Farid where the order of
verilog netlists makes a difference to the matching (or failure
thereof), I applied the same in-circuit pin matching as previously
applied to mixtures of SPICE and verilog netlists.  This is clearly
a more robust way to handle pin order differences between parent
and child than was implemented previously.
2024-02-18 15:22:40 -05:00
Tim Edwards 21e9207924 Merge branch 'master' into netgen-1.5 2024-02-10 02:00:02 -05:00
Tim Edwards 62feed812e Corrected an issue that arose due to a change made earlier: A
while back, shorted pins were moved into contiguous positions.
When that method was discovered to cause matching issues, it was
abandoned with a note that doing so might have unintended
consequences because other code might depend on the shorted pins
being contiguous.  Such a case was just found, and corrected.
However, it was also found that shorted pins were still not
completely handled correctly in MatchPins();  a solution was
found that adds such pins to the "permutes" list (which needs to
be done if the shorted pins are to be correctly handled in any
higher level of the hierarchy, if there is one), and the
"permutes" list is then checked by MatchPins() to determine if
pins match because they belong to the same group of shorted
pins.
2024-02-09 21:23:28 -05:00
Tim Edwards 8392721885 Merge branch 'master' into netgen-1.5 2024-02-07 02:00:02 -05:00
Tim Edwards d1c2848e4b Corrected another error in which some simple expressions are
incorrectly evaluated;  "(w+l)" for example treats "w+l" as
a single string instead of three tokens.  Corrected the code
to watch for a failure of strtod() when parsing the expression
at the "+" sign (also for "-").
2024-02-06 16:27:32 -05:00
Tim Edwards 6b0bd4d97b Found an error with the property sorting in which float values
were not compared for sorting in the same way they are compared
for property matching.  The "slop" value was treated as absolute,
not a percentage, so for example a slop of 0.01 on a dimension
of microns would cause all dimensions to be treated as round-off
error, and no sorting would occur.
2024-02-06 15:02:50 -05:00
Tim Edwards 79bab50a79 Merge branch 'master' into netgen-1.5 2024-02-04 02:00:02 -05:00
Tim Edwards d69fbc23bb Added code to handle the problem in which a verilog netlist is read
before its component cells, and the component cells are read in as
SPICE netlists.  Then the original verilog cell and its instances
need to have pins reordered to match the subcircuit definition in
the SPICE netlist.  Otherwise, when verilog and SPICE netlists are
mixed, the order in which the files are read is critical, and
failures due to reading out-of-order are very obscure and nearly
impossible to debug.
2024-02-03 21:21:09 -05:00
Tim Edwards b83800d69b Merge branch 'master' into netgen-1.5 2024-02-03 02:00:02 -05:00
Tim Edwards c7fa0324d9 Added a piece of code that handles implicit pins in verilog by doing
the following:  (1) Checking that the parent cell is verilog,
(2) only running after the two cells themselves have been compared
and matched, then (3) added the missing pin or pins while reordering
pins on instances (note: this may not work if the verilog netlist is
the first passed to netgen;  that case needs to be checked).
2024-02-02 14:51:10 -05:00
Tim Edwards 93b9cf6577 Merge branch 'master' into netgen-1.5 2024-01-04 02:00:02 -05:00
Tim Edwards eb27a18ae3 Corrected two different errors:
(1) When a comment line follows a ".subckt" line, and the comment
    line is empty or all whitespace, then the following line would
    be ignored.  This condition appears to be very specific and
    was solved simply by detecting it and handling it.
(2) Occasionally the "M" parameter of a subcircuit will be recorded
    as type double, and this was not being anticipated by the code
    that checks if "M=1" matches a corresponding entry with no "M"
    parameter.  Simple fix to check the condition where the "M"
    parameter is type double.
2024-01-03 21:21:03 -05:00
Tim Edwards bf53d52970 Merge branch 'master' into netgen-1.5 2023-12-04 02:00:02 -05:00
Tim Edwards 1817f4dd6a Corrected the LDDL_FLAGS setting for Mac OS, which is to replace
"-flat_namespace -undefined suppress -noprebind" to "-undefined
dynamic_lookup" which is what was done in magic, which has a
similar structure to netgen.
2023-12-03 20:32:05 -05:00
11 changed files with 482 additions and 247 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.263
1.5.283
+32 -14
View File
@@ -600,8 +600,10 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
else break;
/* Put the child cell at the start of ChildObjList */
ChildEnd->next = ChildObjList;
ChildObjList = ChildStart;
if (ChildEnd) {
ChildEnd->next = ChildObjList;
ChildObjList = ChildStart;
}
}
/* Put the child cell at the start of ChildObjList */
@@ -1230,6 +1232,10 @@ int UniquePins(char *name, int filenum)
* Removed the code 9/1/2023. But---Not sure if any code depends
* on shorted pins being adjacent.
*/
/* When two pins are shorted, they are by definition permutable */
PermuteSetup(ThisCell->name, ThisCell->file, ob->name,
firstport[ob->node]->name);
continue;
}
else {
@@ -1630,7 +1636,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
ECompare *ecomp, *ncomp;
ECompList *list0X, *listX0;
int hascontents1, hascontents2;
int match, modified = 0;
int match, modified1 = 0, modified2 = 0;
int not_top;
if (file1 == -1)
@@ -1708,7 +1714,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
" makes a better match\n", ecomp->cell1->name,
name1, file1);
flattenInstancesOf(name1, file1, ecomp->cell1->name);
modified++;
modified1++;
}
if (ecomp->cell2 && (ecomp->num2 > 0) &&
(!(ecomp->cell2->flags & CELL_PLACEHOLDER))) {
@@ -1716,7 +1722,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
" makes a better match\n", ecomp->cell2->name,
name2, file2);
flattenInstancesOf(name2, file2, ecomp->cell2->name);
modified++;
modified2++;
}
}
@@ -1806,7 +1812,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
" makes a better match\n", ecomp->cell2->name,
name2, file2);
flattenInstancesOf(name2, file2, ecomp->cell2->name);
modified++;
modified2++;
}
}
}
@@ -1872,7 +1878,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
" makes a better match\n", ecomp->cell1->name,
name1, file1);
flattenInstancesOf(name1, file1, ecomp->cell1->name);
modified++;
modified1++;
}
}
}
@@ -2026,7 +2032,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
/* Remove from list */
ecomp->num1--;
modified++;
modified1++;
ob1 = lob;
}
@@ -2164,8 +2170,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
/* Remove from list */
ecomp->num1--;
modified++;
ecomp->num2--;
modified2++;
ob2 = lob;
}
@@ -2199,7 +2205,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
// are no other modifications, as this rule is relaxed compared to other
// rules, and the other rules should be exhaustively applied first.
if ((listX0 != NULL) && (list0X != NULL) && (modified == 0)) {
if ((listX0 != NULL) && (list0X != NULL) && ((modified1 + modified2) == 0)) {
ECompare *ecomp0X, *ecompX0;
ECompList *elist0X, *elistX0;
for (elistX0 = listX0; elistX0; elistX0 = elistX0->next) {
@@ -2231,7 +2237,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
flattenInstancesOf(name1, file1, ecompX0->cell1->name);
ecompX0->num1 = 0;
ecomp0X->num1 += ecompX0->num1;
modified++;
modified1++;
break;
}
}
@@ -2257,7 +2263,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
flattenInstancesOf(name2, file2, ecomp0X->cell2->name);
ecomp0X->num2 = 0;
ecompX0->num2 += ecomp0X->num2;
modified++;
modified2++;
break;
}
}
@@ -2288,5 +2294,17 @@ done:
FREE(list0X);
list0X = nextptr;
}
return modified;
// If either netlist was modified, rebuild its node cache
if (modified1 > 0) {
FreeNodeNames(tc1);
CacheNodeNames(tc1);
}
if (modified2 > 0) {
FreeNodeNames(tc2);
CacheNodeNames(tc2);
}
return modified1 + modified2;
}
+178 -60
View File
@@ -2706,7 +2706,9 @@ CheckLegalElementPartition(struct ElementClass *head)
found = 0;
for (scan = head; scan != NULL; scan = scan->next) {
if (scan->count == 2) continue;
/* Quick check for matching 1:1 case */
if ((scan->count == 2) && (scan->elements->graph != scan->elements->next->graph))
continue;
C1 = C2 = 0;
for (E = scan->elements; E != NULL; E = E->next) {
if (E->graph == Circuit1->file) C1++;
@@ -2828,7 +2830,9 @@ CheckLegalNodePartition(struct NodeClass *head)
found = 0;
for (scan = head; scan != NULL; scan = scan->next) {
if (scan->count == 2) continue;
/* Quick check for matching 1:1 case */
if ((scan->count == 2) && (scan->nodes->graph != scan->nodes->next->graph))
continue;
C1 = C2 = 0;
for (N = scan->nodes; N != NULL; N = N->next) {
if (N->graph == Circuit1->file) C1++;
@@ -4204,6 +4208,28 @@ static int compsort(const void *p1, const void *p2)
return (s1->value > s2->value) ? 1 : 0;
}
/*--------------------------------------------------------------*/
/* compdsort() is like compsort() but uses the definition for */
/* "slop" used for type double instead of type integer. */
/*--------------------------------------------------------------*/
static int compdsort(const void *p1, const void *p2)
{
propsort *s1, *s2;
double smax, ddiff;
s1 = (propsort *)p1;
s2 = (propsort *)p2;
smax = fmax(s1->slop, s2->slop);
ddiff = fabs(s1->value - s2->value) /
fabs(s1->value + s2->value);
if (ddiff <= smax)
return (s1->avalue > s2->avalue) ? 1 : 0;
else
return (s1->value > s2->value) ? 1 : 0;
}
/*--------------------------------------------------------------*/
/* Sort properties of ob1 starting at property idx1 up to */
/* property (idx1 + run). Use series critical property for */
@@ -4221,7 +4247,8 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
struct valuelist *vl, *sl;
int i, p, sval, merge_type;
// double cval, slop;
int has_crit;
int (*sortfunc)() = compsort;
int has_crit, is_float;
char ca, co;
double tval, tslop;
double aval, pval, oval, aslop, pslop;
@@ -4241,6 +4268,7 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
for (i = 0; i < run; i++) {
has_crit = FALSE;
merge_type = MERGE_NONE;
is_float = FALSE;
ca = co = (char)0;
for (p = 0;; p++) {
@@ -4273,6 +4301,8 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
else {
tval = vl->value.dval;
tslop = kl->slop.dval;
sortfunc = compdsort;
is_float = TRUE;
}
if (kl->merge & MERGE_S_CRIT) {
@@ -4327,7 +4357,7 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
obn = obp; /* Link from last property */
qsort(&proplist[0], run, sizeof(propsort), compsort);
qsort(&proplist[0], run, sizeof(propsort), sortfunc);
// Re-sort list
obp = ob1;
@@ -4417,6 +4447,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
propsort *proplist;
struct property *kl;
struct valuelist *vl;
int (*sortfunc)() = compsort;
int i, p, mval, merge_type;
int has_crit;
char ca, co;
@@ -4440,9 +4471,9 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
proplist = (propsort *)MALLOC(run * sizeof(propsort));
obp = obn;
mval = 1;
pval = aval = oval = 0.0;
for (i = 0; i < run; i++) {
mval = 1;
has_crit = FALSE;
merge_type = MERGE_NONE;
ca = co = (char)0;
@@ -4477,6 +4508,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
else {
tval = vl->value.dval;
tslop = kl->slop.dval;
sortfunc = compdsort;
}
if (kl->merge & MERGE_P_CRIT) {
@@ -4531,7 +4563,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
obn = obp; /* Link from last property */
qsort(&proplist[0], run, sizeof(propsort), compsort);
qsort(&proplist[0], run, sizeof(propsort), sortfunc);
// Re-sort list
obp = ob1;
@@ -5143,8 +5175,12 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
critval.value.dval = 0.0;
for (i = 0; i < run; i++) {
avl = NULL;
if (vlist[0][i] == NULL) continue;
mult = vlist[0][i]->value.ival;
// if (vlist[0][i] == NULL) continue;
// mult = vlist[0][i]->value.ival;
if (vlist[0][i] == NULL)
mult = 1;
else
mult = vlist[0][i]->value.ival;
changed = 0;
/* For all properties that are not M, S, or crit, */
@@ -5211,6 +5247,11 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
ctype = clist[p][i];
if (ctype & (MERGE_S_ADD | MERGE_P_ADD)) {
if (!vlist[0][i]) {
/* Create an entry with M = 0 to force removal */
vlist[0][i] = (struct valuelist *)CALLOC(1,
sizeof(struct valuelist));
}
vlist[0][i]->value.ival = 0; /* set M to 0 */
if (cvl && (cvl->type == PROP_INTEGER))
{
@@ -5230,6 +5271,11 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
}
}
else if (ctype & (MERGE_S_PAR | MERGE_P_PAR)) {
if (!vlist[0][i]) {
/* Create an entry with M = 0 to force removal */
vlist[0][i] = (struct valuelist *)CALLOC(1,
sizeof(struct valuelist));
}
vlist[0][i]->value.ival = 0; /* set M to 0 */
/* To do parallel combination, both types need to
* be double, so recast them if they are integer.
@@ -6124,7 +6170,9 @@ PropertyMatch(struct Element *E1, struct Element *E2,
if (kl2 != NULL)
break; // Property is required
}
else if (vl2->value.ival != 1)
else if ((vl2->type == PROP_INTEGER) && (vl2->value.ival != 1))
break; // Property M != 1 or S != 1 is a mismatch.
else if ((vl2->type == PROP_DOUBLE) && (vl2->value.dval != 1))
break; // Property M != 1 or S != 1 is a mismatch.
}
if (vl2->type != PROP_ENDLIST) {
@@ -6181,7 +6229,9 @@ PropertyMatch(struct Element *E1, struct Element *E2,
if (kl1 != NULL)
break; // Property is required
}
else if (vl1->value.ival != 1)
else if ((vl1->type == PROP_INTEGER) && (vl1->value.ival != 1))
break; // Property M != 1 or S != 1 is a mismatch.
else if ((vl1->type == PROP_DOUBLE) && (vl1->value.dval != 1))
break; // Property M != 1 or S != 1 is a mismatch.
}
if (vl1->type != PROP_ENDLIST) {
@@ -6214,22 +6264,20 @@ PropertyMatch(struct Element *E1, struct Element *E2,
int multmatch, count;
PropertyCheckMismatch(tp1, tc1, inst1, tp2, tc2,
inst2, E1, E2, FALSE, FALSE, &multmatch, NULL);
if (multmatch == 1) {
/* Final attempt: Reduce M to 1 on both devices */
run1 = run2 = 0;
for (tpc = tp1; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run1++;
for (tpc = tp2; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run2++;
PropertyOptimize(tp1, tc1, run1, FALSE, TRUE);
PropertyOptimize(tp2, tc2, run2, FALSE, TRUE);
}
else if (multmatch == 2) {
run1 = run2 = 0;
for (tpc = tp1; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run1++;
for (tpc = tp2; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run2++;
if (multmatch == 2) {
/* Final attempt: Reduce S to 1 on both devices */
run1 = run2 = 0;
for (tpc = tp1; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run1++;
for (tpc = tp2; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run2++;
PropertyOptimize(tp1, tc1, run1, TRUE, TRUE);
PropertyOptimize(tp2, tc2, run2, TRUE, TRUE);
}
else if ((multmatch == 1) || (run1 != run2)) {
/* Final attempt: Reduce M to 1 on both devices */
PropertyOptimize(tp1, tc1, run1, FALSE, TRUE);
PropertyOptimize(tp2, tc2, run2, FALSE, TRUE);
}
#ifdef TCL_NETGEN
mlist =
#endif
@@ -7172,8 +7220,6 @@ int EquivalenceClasses(char *name1, int file1, char *name2, int file2, int douni
return 1;
}
#ifdef TCL_NETGEN
/*----------------------------------------------------------------------*/
/* Callback function used by MatchPins */
/*----------------------------------------------------------------------*/
@@ -7182,7 +7228,7 @@ int reorderpins(struct hashlist *p, int file)
{
struct nlist *ptr;
struct nlist *tc2 = Circuit2;
struct objlist *ob, *ob2, *firstpin;
struct objlist *ob, *ob2, *firstpin, *oblast, *newob;
int i, numports, *nodes, unordered;
char **names;
@@ -7234,6 +7280,7 @@ int reorderpins(struct hashlist *p, int file)
names[ob2->model.port] = ob->name;
}
oblast = ob;
ob = ob->next;
ob2 = ob2->next;
if (i < numports - 1) {
@@ -7241,7 +7288,34 @@ int reorderpins(struct hashlist *p, int file)
Fprintf(stderr, "Instance of %s has only "
"%d of %d ports\n",
tc2->name, i + 1, numports);
break;
if (ptr->flags & CELL_VERILOG) {
/* If parent cell is verilog, and the cells
* have been matched, then the instance can
* be assumed to be using an implicit pin.
*/
Fprintf(stderr, "Assuming implicit verilog pin \"%s\".\n",
ob2->name);
newob = (struct objlist *)CALLOC(1,
sizeof(struct objlist));
newob->name = (char *)MALLOC(strlen(oblast->instance.name)
+ strlen(ob2->name) + 2);
sprintf(newob->name, "%s/%s",
oblast->instance.name, ob2->name);
newob->type = oblast->type + 1;
newob->model.class = strsave(oblast->model.class);
newob->instance.name = strsave(oblast->instance.name);
newob->flags = 0;
ptr->nodename_cache_maxnodenum++;
newob->node = ptr->nodename_cache_maxnodenum;
newob->next = ob;
oblast->next = newob; /* Splice into object list */
/* Fill in the missing entries */
nodes[ob2->model.port] = newob->node;
names[ob2->model.port] = newob->name;
ob = newob;
}
else
break;
}
else if (ob2 == NULL || ob2->type != PORT) {
Fprintf(stderr, "Instance of %s has "
@@ -7302,7 +7376,7 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
// Count the largest node number used in the cell
maxnode = -1;
for (ob = ptr->cell; ob; ob = ob->next)
if (ob->type >= FIRSTPIN || ob->type == NODE)
if (ob->type >= FIRSTPIN || ob->type == NODE || ob->type == PORT)
if (ob->node >= maxnode)
maxnode = ob->node + 1;
numnodes = maxnode;
@@ -7443,6 +7517,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
int hasproxy1 = 0, hasproxy2 = 0;
int needclean1 = 0, needclean2 = 0;
int nomatch = 0;
int filenum = -1;
int *correspond;
char *ostr;
#ifdef TCL_NETGEN
@@ -7560,17 +7635,13 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
break;
}
}
else {
ob3 = NULL;
break; /* All pins w/the same node should be together */
}
}
if (ob3 == NULL) {
if (Debug == 0) {
if (ob2->model.port == -1)
snprintf(ostr + left_col_end + 1, left_col_end, "%s **Mismatch**", ob2->name);
else
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)");
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)", ob2->name);
}
nomatch = TRUE;
/* Pins with different names are on different nets,
@@ -7611,15 +7682,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
ob2->model.port = i; /* save order */
*(cover + i) = (char)1;
/* If there are multiple pins on the same net, cycle through them; */
/* otherwise, move to the next entry in the partition. */
if (ob1->next && (ob1->next->type == PORT) && (ob1->next->node == ob1->node)) {
ob1 = ob1->next;
ob2 = tc2->cell; /* Restart search for matching pin */
i++;
}
else
break;
break;
}
}
if (ob2 == NULL) {
@@ -7633,7 +7696,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
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, 32, "%s", obn->name);
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)");
snprintf(ostr + left_col_end + 1, left_col_end, "(no pin, node is %s)", obp->name);
for (m = 0; m < right_col_end + 1; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
@@ -7845,6 +7908,72 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
if (bangptr2) *bangptr2 = '!';
break;
}
else {
struct Permutation *permute1, *permute2;
struct objlist *ob1a = NULL, *ob2a = NULL;
/* Check the permutation list. If any permutable pin
* matches, and both nodes equal the nodes of their
* pin permutations, then the pins also match.
*/
for (permute1 = tc1->permutes; permute1; permute1 = permute1->next) {
if ((*matchfunc)(ob1->name, permute1->pin1)) {
ob1a = LookupObject(permute1->pin1, tc1);
break;
}
else if ((*matchfunc)(ob1->name, permute1->pin2)) {
ob1a = LookupObject(permute1->pin2, tc1);
break;
}
}
for (permute2 = tc2->permutes; permute2; permute2 = permute2->next) {
if ((*matchfunc)(ob2->name, permute2->pin1)) {
ob2a = LookupObject(permute2->pin1, tc2);
break;
}
else if ((*matchfunc)(ob2->name, permute2->pin2)) {
ob2a = LookupObject(permute2->pin2, tc2);
break;
}
}
if (ob1a && ob2a) {
if ((ob1->node == ob1a->node) && (ob2->node == ob2a->node)) {
/* This should be enough to prove equivalency */
if ((correspond[ob1->node] == 0) || (correspond[ob1->node] == ob2->node)) {
correspond[ob1->node] = ob2->node; /* remember corresponding node */
ob2->model.port = i; /* save order */
*(cover + i) = (char)1;
if (Debug == 0) {
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, "%s", ob2->name);
for (m = 0; m < right_col_end + 1; m++)
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
Fprintf(stdout, ostr);
}
else {
Fprintf(stdout, "Circuit %s port %d \"%s\""
" = cell %s port %d \"%s\"\n",
tc1->name, i, ob1->name,
tc2->name, j, ob2->name);
}
#ifdef TCL_NETGEN
if (dolist) {
Tcl_ListObjAppendElement(netgeninterp, plist1,
Tcl_NewStringObj(ob1->name, -1));
Tcl_ListObjAppendElement(netgeninterp, plist2,
Tcl_NewStringObj(ob2->name, -1));
}
#endif
}
if (bangptr2) *bangptr2 = '!';
break;
}
}
}
}
}
if (bangptr2) *bangptr2 = '!';
@@ -8015,23 +8144,6 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
obn->instance.name = NULL;
obn->node = -1;
/* Note: Has this pin 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);
}
if (ob2 == tc2->cell) {
obn->next = ob2;
tc2->cell = obn;
@@ -8120,7 +8232,11 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
/* Reorder pins in Circuit2 instances to match Circuit1 */
RecurseCellFileHashTable(reorderpins, Circuit2->file);
if (Circuit2 != NULL)
filenum = Circuit2->file;
else
filenum = tc2->file;
RecurseCellFileHashTable(reorderpins, filenum);
/* Reorder pins in Circuit2 cell to match Circuit1 */
/* Unlike the instance records, the structures are swapped, */
@@ -8293,6 +8409,8 @@ void FlattenCurrent()
}
}
#ifdef TCL_NETGEN
/*------------------------------------------------------*/
/* Handler is only used when netgen is run from a */
/* terminal, not the Tk console. */
+14 -2
View File
@@ -587,6 +587,12 @@ void SkipTokNoNewline(char *delimiter)
/* */
/* Modified 3/30/2015 to include the condition where a comment line is */
/* in the middle of a series of continuation lines. */
/* */
/* Modified 1/3/2024 to avoid skipping two lines if a line has only the */
/* comment character '*' followed by a newline. It seems that '\n' is */
/* being ignored in WHITESPACE_DELIMITER, but it's easier to write the */
/* code to find the exception rather than track down the problem in */
/* GetNextLine(). */
/*----------------------------------------------------------------------*/
void SpiceTokNoNewline(void)
@@ -598,8 +604,14 @@ void SpiceTokNoNewline(void)
while (nexttok == NULL) {
contline = getc(infile);
if (contline == '*') {
GetNextLine(WHITESPACE_DELIMITER);
SkipNewLine(NULL);
char testline = ' ';
while ((testline == ' ') || (testline == '\t'))
testline = getc(infile);
if (testline != '\n') {
ungetc(testline, infile);
GetNextLine(WHITESPACE_DELIMITER);
SkipNewLine(NULL);
}
continue;
}
else if (contline != '+') {
+8 -4
View File
@@ -300,7 +300,9 @@ int ReduceOneExpression(struct valuelist *kv, struct objlist *parprops,
tstr = sstr - 1;
numlast = 1;
}
break;
/* But might not be. . . */
if ((dval != 0) || (sstr > estr))
break;
}
/* Not a number, so must be arithmetic */
*tstr = '\0';
@@ -320,7 +322,9 @@ int ReduceOneExpression(struct valuelist *kv, struct objlist *parprops,
tstr = sstr - 1;
numlast = 1;
}
break;
/* But might not be. . . */
if ((dval != 0) || (sstr > estr))
break;
}
/* Not a number, so must be arithmetic */
*tstr = '\0';
@@ -3090,7 +3094,7 @@ void add_balancing_close(struct objlist *ob1, struct objlist *ob2)
for (nob = ob1->next; nob && nob->type != FIRSTPIN; nob = nob->next)
if (nob->type == PROPERTY)
break;
if (nob->type != PROPERTY) return; // shouldn't happen
if (nob == NULL || nob->type != PROPERTY) return; // shouldn't happen
opentags = 0;
for (; nob->next && nob->next->type == PROPERTY; nob = nob->next) {
@@ -3640,7 +3644,7 @@ int CombineSeries(char *model, int file)
nob->type = PROPERTY;
nob->name = strsave("properties");
nob->node = -2; /* Don't report as disconnected node */
nob->model.class = (obp->model.class == NULL) ? NULL :
nob->model.class = (obp == NULL || obp->model.class == NULL) ? NULL :
strsave(obp->model.class);
nob->instance.props = NewPropValue(2);
+75 -68
View File
@@ -224,6 +224,13 @@ int matchnocase(char *st1, char *st2)
char *sp1 = st1;
char *sp2 = st2;
/* In case of a property that does not exist in one netlist, matchnocase()
* may be passed a null value, so return 0 to indicate a non-match.
* *Both* values null will also be treated as a mismatch (debatable
* behavior).
*/
if (!sp1 || !sp2) return 0;
while (*sp1 != '\0' && *sp2 != '\0') {
if (to_lower[*sp1] != to_lower[*sp2]) break;
sp1++;
@@ -596,65 +603,65 @@ int freeprop(struct hashlist *p)
void CellDelete(char *name, int fnum)
{
/* delete all the contents of cell 'name', and remove 'name' from
the cell hash table. NOTE: this procedure does not care or check
if 'name' has been instanced anywhere. It is assumed that if this
is the case, the user will (quickly) define a new cell of that name.
*/
struct objlist *ob, *obnext;
struct nlist *tp;
/* delete all the contents of cell 'name', and remove 'name' from
the cell hash table. NOTE: this procedure does not care or check
if 'name' has been instanced anywhere. It is assumed that if this
is the case, the user will (quickly) define a new cell of that name.
*/
struct objlist *ob, *obnext;
struct nlist *tp;
tp = LookupCellFile(name, fnum);
if (tp == NULL) {
Printf ("No cell '%s' found.\n", name);
return;
}
tp = LookupCellFile(name, fnum);
if (tp == NULL) {
Printf ("No cell '%s' found.\n", name);
return;
}
HashIntDelete(name, fnum, &cell_dict);
/* now make sure that we free all the fields of the nlist struct */
if (tp->name != NULL) FREE(tp->name);
HashKill(&(tp->objdict));
HashKill(&(tp->instdict));
RecurseHashTable(&(tp->propdict), freeprop);
HashKill(&(tp->propdict));
FreeNodeNames(tp);
ob = tp->cell;
while (ob != NULL) {
obnext = ob->next;
FreeObject (ob);
ob = obnext;
}
HashIntDelete(name, fnum, &cell_dict);
/* now make sure that we free all the fields of the nlist struct */
if (tp->name != NULL) FREE(tp->name);
HashKill(&(tp->objdict));
HashKill(&(tp->instdict));
RecurseHashTable(&(tp->propdict), freeprop);
HashKill(&(tp->propdict));
FreeNodeNames(tp);
ob = tp->cell;
while (ob != NULL) {
obnext = ob->next;
FreeObject (ob);
ob = obnext;
}
}
static int PrintCellHashTableElement(struct hashlist *p)
{
struct nlist *ptr;
struct nlist *ptr;
ptr = (struct nlist *)(p->ptr);
if ((TopFile >= 0) && (ptr->file != TopFile)) return 1;
ptr = (struct nlist *)(p->ptr);
if ((TopFile >= 0) && (ptr->file != TopFile)) return 1;
if (ptr->class != CLASS_SUBCKT) {
/* only print primitive cells if Debug is enabled */
if (Debug == 1) Printf("Cell: %s (instanced %d times); Primitive\n",
if ((ptr->class != CLASS_SUBCKT) && (ptr->class != CLASS_MODULE)) {
/* only print primitive cells if Debug is enabled */
if (Debug == 1) Printf("Cell: %s (instanced %d times); Primitive\n",
ptr->name, ptr->number);
else if (Debug == 3) { /* list */
else if (Debug == 3) { /* list */
#ifdef TCL_NETGEN
Tcl_AppendElement(netgeninterp, ptr->name);
Tcl_AppendElement(netgeninterp, ptr->name);
#else
Printf("%s ", ptr->name);
Printf("%s ", ptr->name);
#endif
}
}
else if ((Debug == 2) || (Debug == 3)) { /* list only */
}
}
else if ((Debug == 2) || (Debug == 3)) { /* list only */
#ifdef TCL_NETGEN
Tcl_AppendElement(netgeninterp, ptr->name);
Tcl_AppendElement(netgeninterp, ptr->name);
#else
Printf("%s ", ptr->name);
Printf("%s ", ptr->name);
#endif
}
else
Printf("Cell: %s (instanced %d times)\n",ptr->name,ptr->number);
return(1);
}
else
Printf("Cell: %s (instanced %d times)\n", ptr->name, ptr->number);
return(1);
}
/* Print the contents of the cell hash table. */
@@ -663,65 +670,65 @@ static int PrintCellHashTableElement(struct hashlist *p)
void PrintCellHashTable(int full, int filenum)
{
int total, bins;
int OldDebug;
int total, bins;
int OldDebug;
if ((filenum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
if ((filenum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
PrintCellHashTable(full, Circuit1->file);
PrintCellHashTable(full, Circuit2->file);
return;
}
}
TopFile = filenum;
TopFile = filenum;
bins = RecurseHashTable(&cell_dict, CountHashTableBinsUsed);
total = RecurseHashTable(&cell_dict, CountHashTableEntries);
if (full < 2)
Printf("Hash table: %d of %d bins used; %d cells total (%.2f per bin)\n",
bins = RecurseHashTable(&cell_dict, CountHashTableBinsUsed);
total = RecurseHashTable(&cell_dict, CountHashTableEntries);
if (full < 2)
Printf("Hash table: %d of %d bins used; %d cells total (%.2f per bin)\n",
bins, CELLHASHSIZE, total, (bins == 0) ? 0 :
(float)((float)total / (float)bins));
OldDebug = Debug;
Debug = full;
RecurseHashTable(&cell_dict, PrintCellHashTableElement);
Debug = OldDebug;
OldDebug = Debug;
Debug = full;
RecurseHashTable(&cell_dict, PrintCellHashTableElement);
Debug = OldDebug;
#ifndef TCL_NETGEN
if (full >= 2) Printf("\n");
if (full >= 2) Printf("\n");
#endif
}
struct nlist *FirstCell(void)
{
return((struct nlist *)HashFirst(&cell_dict));
return((struct nlist *)HashFirst(&cell_dict));
}
struct nlist *NextCell(void)
{
return((struct nlist *)HashNext(&cell_dict));
return((struct nlist *)HashNext(&cell_dict));
}
static int ClearDumpedElement(struct hashlist *np)
{
struct nlist *p;
struct nlist *p;
p = (struct nlist *)(np->ptr);
p->dumped = 0;
return(1);
p = (struct nlist *)(np->ptr);
p->dumped = 0;
return(1);
}
void ClearDumpedList(void)
{
RecurseHashTable(&cell_dict, ClearDumpedElement);
RecurseHashTable(&cell_dict, ClearDumpedElement);
}
int RecurseCellHashTable(int (*foo)(struct hashlist *np))
{
return RecurseHashTable(&cell_dict, foo);
return RecurseHashTable(&cell_dict, foo);
}
int RecurseCellFileHashTable(int (*foo)(struct hashlist *, int), int value)
{
return RecurseHashTableValue(&cell_dict, foo, value);
return RecurseHashTableValue(&cell_dict, foo, value);
}
/* Yet another version, passing one parameter that is a pointer */
@@ -729,7 +736,7 @@ int RecurseCellFileHashTable(int (*foo)(struct hashlist *, int), int value)
struct nlist *RecurseCellHashTable2(struct nlist *(*foo)(struct hashlist *,
void *), void *pointer)
{
return RecurseHashTablePointer(&cell_dict, foo, pointer);
return RecurseHashTablePointer(&cell_dict, foo, pointer);
}
/************************** WILD-CARD STUFF *******************************/
+75 -6
View File
@@ -43,6 +43,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "print.h"
#include "query.h"
#include "objlist.h"
#include "netcmp.h"
// Global storage for parameters from .PARAM
struct hashdict spiceparams;
@@ -519,7 +520,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
char *eqptr, devtype, in_subckt;
struct keyvalue *kvlist = NULL;
char inst[MAX_STR_LEN], model[MAX_STR_LEN], instname[MAX_STR_LEN];
struct nlist *tp;
struct nlist *tp, *tpsave;
struct objlist *parent, *sobj, *nobj, *lobj, *pobj;
inst[MAX_STR_LEN-1] = '\0';
@@ -557,6 +558,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
tp = LookupCellFile(nexttok, filenum);
tpsave = NULL;
/* Check for name conflict with duplicate cell names */
/* This may mean that the cell was used before it was */
@@ -595,11 +597,46 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
tp = LookupCellFile(nexttok, filenum);
}
else if (tp != NULL) { /* Make a new definition for an empty cell */
FreePorts(nexttok);
CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
CellDef(model, filenum);
tp = LookupCellFile(model, filenum);
update = 1; /* Will need to update existing instances */
/* Handle issue with SPICE read after verilog, where a placeholder
* was created from the verilog. (1) If the pin names are "1", "2",
* "3", then this is a SPICE placeholder, and just remove the CellDef
* and re-create it. Otherwise, create new cell "_PLACEHOLDER_".
* (2) After encountering .ends, run MatchPins between the two cells.
* (3) delete the original cell and rename the new cell.
*/
int i = 1;
char pname[10];
for (pobj = tp->cell; pobj && pobj->type == PORT; pobj = pobj->next) {
sprintf(pname, "%d", i);
if (!matchnocase(pobj->name, pname)) break;
i++;
}
if ((pobj == NULL) || (pobj->type != PORT)) {
/* This is a SPICE placeholder created because the cell was instanced
* before it was defined. However, the pins can be assumed to be in
* the correct order, and pin reordering does not need to be done.
*/
FreePorts(nexttok);
CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
CellDef(model, filenum);
tp = LookupCellFile(model, filenum);
update = 1; /* Will need to update existing instances */
}
else {
/* This is (probably) a verilog placeholder created because the
* verilog was read before the (SPICE) definitions. The verilog
* netlist should have named the pins of the parent cell. However,
* there is no guarantee the order of pins is correct. The MatchPins()
* routine from netcmp.c can be used here to match the cell against
* the placeholder, and reorder the pins in all instances to match.
* Note that we cannot just reorder the SPICE pins to match the
* verilog order, because there may be other SPICE netlists which
* instance the cell with the correct SPICE port order.
*/
tpsave = tp;
CellDef("_PLACEHOLDER_", filenum);
tp = LookupCellFile("_PLACEHOLDER_", filenum);
}
}
else if (tp == NULL) { /* Completely new cell, no name conflict */
CellDef(model, filenum);
@@ -691,6 +728,38 @@ skip_ends:
if (*CellStackPtr) PopStack(CellStackPtr);
if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
SkipNewLine(NULL);
if (tpsave != NULL) {
struct nlist *tpplace;
char *savename;
/* Handle a placeholder from a verilog file that has been replaced
* by a netlist with pins in a different order. The pins need to
* be matched, corrected in the original cell and all instances,
* and the new cell deleted.
*/
Printf("Verilog placeholder %s replaced by SPICE definition\n",
tpsave->name);
tpplace = LookupCellFile("_PLACEHOLDER_", filenum);
/* MatchPins is part of netcmp and normally Circuit2 is the
* circuit being matched, so set Circuit2 to the original
* verilog black-box cell, and MatchPins() will force its
* pins to be rearranged to match the SPICE definition just
* read.
*/
Circuit2 = tpsave;
MatchPins(tpplace, tpsave, 0);
savename = strsave(tpsave->name);
/* Now the original verilog black-box cell can be removed */
FreePorts(savename);
CellDelete(savename, filenum);
/* And _PLACEHOLDER_ is renamed to the original name of the cell. */
CellRehash("_PLACEHOLDER_", savename, filenum);
tpsave = NULL;
Circuit2 = NULL;
FREE(savename);
}
}
else if (matchnocase(nexttok, ".MODEL")) {
unsigned char class = CLASS_SUBCKT;
+93 -30
View File
@@ -57,6 +57,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "netfile.h"
#include "print.h"
#include "hash.h"
#include "netcmp.h"
// See netfile.c for explanation of delimiters. 'X'
// separates single-character delimiters from two-character delimiters.
@@ -1018,7 +1019,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
char *eqptr, *matchptr;
struct keyvalue *kvlist = NULL;
char inst[MAX_STR_LEN], model[MAX_STR_LEN], portname[MAX_STR_LEN], pkey[MAX_STR_LEN];
struct nlist *tp;
struct nlist *tp, *tpsave;
struct objlist *parent, *sobj, *nobj, *lobj, *pobj, *cref;
inst[MAX_STR_LEN-1] = '\0';
@@ -1152,6 +1153,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
tp = LookupCellFile(nexttok, filenum);
tpsave = NULL;
hasports = (char)0;
/* Check for name conflict with duplicate cell names */
@@ -1191,35 +1193,9 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
tp = LookupCellFile(nexttok, filenum);
}
else if (tp != NULL) { /* Cell exists, but as a placeholder */
struct nlist *tptmp = NULL;
char ctemp[8];
int n = 0;
/* This redefines a placeholder module to an unused temporary cell name */
while (1) {
sprintf(ctemp, "%d", n);
tptmp = LookupCellFile(ctemp, filenum);
if (tptmp == NULL) break;
n++;
}
CellRehash(nexttok, ctemp, filenum);
tptmp = LookupCellFile(ctemp, filenum);
/* Create a new module definition */
CellDef(model, filenum);
tp = LookupCellFile(model, filenum);
/* Find an instance of this module in the netlist */
cref = FindInstanceOf(tp);
if ((cref != NULL) && (cref->name != NULL)) {
hasports = (char)1;
/* Copy ports from the original parent cell to the new parent cell */
for (pobj = tptmp->cell; pobj && (pobj->type == PORT); pobj = pobj->next)
Port(pobj->name);
}
/* Remove the original cell definition */
FreePorts(ctemp);
CellDelete(ctemp, filenum); /* This removes any PLACEHOLDER flag */
tpsave = tp;
CellDef("_PLACEHOLDER_", filenum);
tp = LookupCellFile("_PLACEHOLDER_", filenum);
}
else if (tp == NULL) { /* Completely new cell, no name conflict */
CellDef(model, filenum);
@@ -1428,6 +1404,93 @@ skip_endmodule:
if (*CellStackPtr) PopStack(CellStackPtr);
if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
SkipNewLine(VLOG_DELIMITERS);
if (tpsave != NULL) {
struct nlist *tpplace;
char *savename;
int lnum, pnum, ltest;
unsigned char valid;
struct objlist *lobj, *pobj;
/* Handle a placeholder from a verilog file that has been replaced
* by a netlist with pins in a different order. The pins need to
* be matched, corrected in the original cell and all instances,
* and the new cell deleted.
*/
Printf("Verilog placeholder module %s replaced by module definition\n",
tpsave->name);
tpplace = LookupCellFile("_PLACEHOLDER_", filenum);
/* If tpsave was generated from an instance in a SPICE netlist that
* did not have a black-box subcircuit definition, then the pins
* will all be labeled 1, 2, 3, etc. If so, then assume that the
* verilog pins are in order, and rename the placeholder pins.
* If the number of pins does not match, or if the pins are not
* labeled as ascending integers, then leave the cell alone.
* In either case, output a warning message.
*/
/* Get the number of ports in the placeholder */
pnum = 0;
for (pobj = tpplace->cell; pobj; pobj = pobj->next) {
if (pobj->type != PORT) break;
pnum++;
}
/* Get the number of ports in the saved cell and make */
/* sure that it equals the number of ports in the */
/* placeholder, and that all of the ports in the saved */
/* cell are integers in ascending order. */
valid = TRUE;
lnum = 0;
for (lobj = tpsave->cell; lobj; lobj = lobj->next) {
if (lobj->type != PORT) break;
lnum++;
if (sscanf(lobj->name, "%d", &ltest) != 1) break;
if (ltest != lnum) break;
}
if ((lobj != NULL) && (lobj->type == PORT))
valid = FALSE; /* Pins are not integers in ascending order */
if (pnum != lnum) valid = FALSE; /* Different number of pins */
if (valid == TRUE) {
Printf("Replacing pins of placeholder cell %s from cell definition.\n",
tpsave->name);
pobj = tpplace->cell;
for (lobj = tpsave->cell; lobj; lobj = lobj->next) {
if (lobj->type != PORT) break;
if (pobj == NULL) break; /* should not happen */
FREE(lobj->name);
lobj->name = (char *)MALLOC(strlen(pobj->name) + 1);
strcpy(lobj->name, pobj->name);
pobj = pobj->next;
}
}
else {
Printf("Placeholder pins of cell %s are not compatible and"
" will be left unchanged\n", tpsave->name);
}
/* MatchPins is part of netcmp and normally Circuit2 is the
* circuit being matched, so set Circuit2 to the original
* verilog black-box cell, and MatchPins() will force its
* pins to be rearranged to match the module definition just
* read.
*/
Circuit2 = tpsave;
MatchPins(tpplace, tpsave, 0);
savename = strsave(tpsave->name);
/* Now the original verilog black-box cell can be removed */
FreePorts(savename);
CellDelete(savename, filenum);
/* And _PLACEHOLDER_ is renamed to the original name of the cell. */
CellRehash("_PLACEHOLDER_", savename, filenum);
tpsave = NULL;
Circuit2 = NULL;
FREE(savename);
}
}
else if (match(nexttok, "`include")) {
+1 -52
View File
@@ -668,7 +668,6 @@ XMKMF
HAVE_PYTHON3
EGREP
GREP
M4
RANLIB
INSTALL_DATA
INSTALL_SCRIPT
@@ -3702,56 +3701,6 @@ else
fi
for ac_prog in gm4 gnum4 m4
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_M4+:} false; then :
$as_echo_n "(cached) " >&6
else
case $M4 in
[\\/]* | ?:[\\/]*)
ac_cv_path_M4="$M4" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_M4="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
M4=$ac_cv_path_M4
if test -n "$M4"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4" >&5
$as_echo "$M4" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$M4" && break
done
test -n "$M4" || M4="no"
if test x$M4 = xno; then
as_fn_error $? "M4 is required" "$LINENO" 5
fi
if test "$CPP" = "$CC -E" ; then
CPP="$CPP -x c"
@@ -6302,7 +6251,7 @@ fi
*darwin*)
SHDLIB_EXT=".dylib"
LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind"
LDDL_FLAGS="-dynamiclib -undefined dynamic_lookup"
LDFLAGS="${LDFLAGS} ${LIB_SPECS}"
CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common"
;;
+1 -7
View File
@@ -26,12 +26,6 @@ AC_ISC_POSIX
AC_PROG_INSTALL
AC_PROG_RANLIB
dnl GNU M4 is preferred due to some of the option switches.
AC_PATH_PROGS([M4], [gm4 gnum4 m4], [no])
if test x$M4 = xno; then
AC_MSG_ERROR([M4 is required])
fi
dnl check size of pointer for correct behavior on 64-bit systems
dnl If the C preprocessor is GCC, we need to force the flag to
dnl assert that input files are of type C, or else the preprocessing
@@ -1033,7 +1027,7 @@ fi
*darwin*)
SHDLIB_EXT=".dylib"
LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind"
LDDL_FLAGS="-dynamiclib -undefined dynamic_lookup"
LDFLAGS="${LDFLAGS} ${LIB_SPECS}"
CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common"
;;
+4 -3
View File
@@ -1595,8 +1595,7 @@ _netgen_model(ClientData clientData,
return result;
if (objc == 3) {
model = Tcl_GetString(objv[2]);
nports = NumberOfPorts(model, fnum);
nports = NumberOfPorts(tp->name, fnum);
if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)modelclasses,
"class", 0, &index) != TCL_OK) {
@@ -2652,8 +2651,10 @@ _netcmp_verify(ClientData clientData,
disable_interrupt();
if (index == EQUIV_IDX || index == UNIQUE_IDX)
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
else
else {
Fprintf(stdout, "Netlists do not match.\n");
Fprintf(stdout, "Port matching may fail to disambiguate symmetries.\n");
}
}
else if (automorphisms == -2) {
if (index == EQUIV_IDX)