Compare commits

..
8 Commits
Author SHA1 Message Date
Tim Edwards aaf8fefc1a Merge branch 'master' into netgen-1.5 2024-10-16 02:00:02 -04:00
Tim Edwards e1aa231db1 Corrected another error discovered by Andrei Bondar in which
the critical property (e.g., L for transistors) is required to
match exactly between devices in order to allow the additive
property (e.g., W for transistors) to be summed.  The critical
property should match if all values are within the slop value,
for floating-point values.  Note:  The implementation is still
not rigorous, as the saved critical value may shift from
device to device;  so comparing, e.g., 1.00 to 1.01 to 1.02 to
1.03, etc., can find that all individual comparisons are within
the slop value even though the slop is exceeded across all values.
2024-10-15 20:52:23 -04:00
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
3 changed files with 92 additions and 36 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.280
1.5.284
+36 -35
View File
@@ -5169,26 +5169,34 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
// (if any)
if (comb == TRUE) {
double pd;
int mult, cidx = -1;
struct valuelist *avl, *cvl = NULL;
critval.type = PROP_ENDLIST;
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, */
/* combine as specified by the merge type of the property. */
for (p = 1; p < pcount; p++) {
kl = plist[p];
vl = vlist[p][i];
ctype = clist[p][i];
/* critical properties never combine, but track them */
if ((series == TRUE) && (ctype & MERGE_S_CRIT)) {
if ((vl->type != critval.type) || (vl->value.dval != critval.value.dval))
pd = 2 * fabs(vl->value.dval - critval.value.dval) /
(vl->value.dval + critval.value.dval);
if ((vl->type != critval.type) || (pd > kl->slop.dval))
{
critval.type = vl->type;
critval.value = vl->value;
@@ -5197,7 +5205,9 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
continue;
}
if ((series == FALSE) && (ctype & MERGE_P_CRIT)) {
if ((vl->type != critval.type) || (vl->value.dval != critval.value.dval))
pd = 2 * fabs(vl->value.dval - critval.value.dval) /
(vl->value.dval + critval.value.dval);
if ((vl->type != critval.type) || (pd > kl->slop.dval))
{
critval.type = vl->type;
critval.value = vl->value;
@@ -5243,6 +5253,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))
{
@@ -5262,6 +5277,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.
@@ -6250,22 +6270,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
@@ -7629,7 +7647,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
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,
@@ -7684,7 +7702,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);
@@ -8132,23 +8150,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;
+55
View File
@@ -1408,6 +1408,9 @@ skip_endmodule:
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
@@ -1418,6 +1421,58 @@ skip_endmodule:
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