Corrected an error in the code that handles no-connects as valid
pins for enabling parallel combinations, which could cause a crash. Added a "-force" option to "equate pins" to allow pins to be matched even on subcircuits that did not correctly match; this was done in conjuction with an extra option to the "lvs" command "-noflatten=" to pass a list of cellname to not be flattened even if they do not match. This is generally discouraged, as it prevents netgen from resolving differences between layout and schematic hierarchy, but it can be useful for checking that the hierarchy above a certain cell is correct, given that if a subcell is really unmatched, then its errors will keep propagating up the top level, making additional errors hard to diagnose.
This commit is contained in:
parent
20077d3d56
commit
fd72e24a86
|
|
@ -5363,13 +5363,21 @@ PropertyMatch(struct objlist *ob1, int file1,
|
||||||
/* WIP---Check for no-connect pins in merged devices on both sides. */
|
/* WIP---Check for no-connect pins in merged devices on both sides. */
|
||||||
/* Both sides should either have no-connects marked, or neither. */
|
/* Both sides should either have no-connects marked, or neither. */
|
||||||
/* (Permutable pins may need to be handled correctly. . . */
|
/* (Permutable pins may need to be handled correctly. . . */
|
||||||
|
|
||||||
for (tp1 = ob1, tp2 = ob2; (tp1 != NULL) && tp1->type >= FIRSTPIN &&
|
for (tp1 = ob1, tp2 = ob2; (tp1 != NULL) && tp1->type >= FIRSTPIN &&
|
||||||
(tp2 != NULL) && tp2->type >= FIRSTPIN; tp1 = tp1->next, tp2 = tp2->next)
|
(tp2 != NULL) && tp2->type >= FIRSTPIN; tp1 = tp1->next, tp2 = tp2->next)
|
||||||
{
|
{
|
||||||
struct objlist *node1, *node2;
|
struct objlist *node1, *node2;
|
||||||
|
|
||||||
node1 = Circuit1->nodename_cache[tp1->node];
|
if (file1 == Circuit1->file)
|
||||||
node2 = Circuit2->nodename_cache[tp2->node];
|
node1 = Circuit1->nodename_cache[tp1->node];
|
||||||
|
else
|
||||||
|
node1 = Circuit2->nodename_cache[tp1->node];
|
||||||
|
|
||||||
|
if (file2 == Circuit1->file)
|
||||||
|
node2 = Circuit1->nodename_cache[tp2->node];
|
||||||
|
else
|
||||||
|
node2 = Circuit2->nodename_cache[tp2->node];
|
||||||
|
|
||||||
if (node1->instance.flags != node2->instance.flags)
|
if (node1->instance.flags != node2->instance.flags)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,7 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||||
close $fjson
|
close $fjson
|
||||||
}
|
}
|
||||||
|
|
||||||
#----------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Define the "lvs" command as a way of calling the netgen options
|
# Define the "lvs" command as a way of calling the netgen options
|
||||||
# for standard compare, essentially the same as the old "netcomp"
|
# for standard compare, essentially the same as the old "netcomp"
|
||||||
# standalone program.
|
# standalone program.
|
||||||
|
|
@ -361,14 +361,20 @@ proc netgen::convert_to_json {filename lvs_final} {
|
||||||
# although if the cells have not been read in yet, then the
|
# although if the cells have not been read in yet, then the
|
||||||
# original syntax of filename or {filename cellname} is required.
|
# original syntax of filename or {filename cellname} is required.
|
||||||
#
|
#
|
||||||
# "args" is passed to verify and may therefore contain only the
|
# "args" may be "-list", "-json", or "-blackbox".
|
||||||
# value "-list" or nothing. If "-list", then output is returned
|
# "-list" returns output as a nested list.
|
||||||
# as a nested list.
|
# "-json" creates a .json-format output file in addition to stdout.
|
||||||
#----------------------------------------------------------------
|
# "-blackbox" treats empty cells as black-box entries.
|
||||||
|
# "-noflatten={list}" is a list of cells not to flatten if mismatched.
|
||||||
|
# i.e., the cells are expected to match and any mismatch cannot be
|
||||||
|
# expected to be resolved by flattening the contents of the mismatched
|
||||||
|
# cells.
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
set dolist 0
|
set dolist 0
|
||||||
set dojson 0
|
set dojson 0
|
||||||
|
set noflat {}
|
||||||
foreach arg $args {
|
foreach arg $args {
|
||||||
if {$arg == "-list"} {
|
if {$arg == "-list"} {
|
||||||
puts stdout "Generating list result"
|
puts stdout "Generating list result"
|
||||||
|
|
@ -382,6 +388,9 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
} elseif {$arg == "-blackbox"} {
|
} elseif {$arg == "-blackbox"} {
|
||||||
puts stdout "Treating empty subcircuits as black-box cells"
|
puts stdout "Treating empty subcircuits as black-box cells"
|
||||||
netgen::model blackbox on
|
netgen::model blackbox on
|
||||||
|
} elseif {[string first "-noflatten=" $arg] == 0} {
|
||||||
|
set noflat [string trim [string range $arg 11 end] \"\{\}]
|
||||||
|
puts stdout "Will not flatten these subcells: $noflat"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -501,6 +510,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
set properr {}
|
set properr {}
|
||||||
|
set matcherr {}
|
||||||
set pinsgood 0
|
set pinsgood 0
|
||||||
while {$endval != {}} {
|
while {$endval != {}} {
|
||||||
if {$dolist == 1} {
|
if {$dolist == 1} {
|
||||||
|
|
@ -529,9 +539,30 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
|
|
||||||
# Flatten the non-matching subcircuit (but not the top-level cells)
|
# Flatten the non-matching subcircuit (but not the top-level cells)
|
||||||
if {[netgen::print queue] != {}} {
|
if {[netgen::print queue] != {}} {
|
||||||
netgen::log put " Flattening non-matched subcircuits $endval"
|
if {([lsearch $noflat [lindex $endval 0]] == -1) &&
|
||||||
netgen::flatten class "[lindex $endval 0] $fnum1"
|
([lsearch $noflat [lindex $endval 1]] == -1)} {
|
||||||
netgen::flatten class "[lindex $endval 1] $fnum2"
|
netgen::log put " Flattening non-matched subcircuits $endval"
|
||||||
|
netgen::flatten class "[lindex $endval 0] $fnum1"
|
||||||
|
netgen::flatten class "[lindex $endval 1] $fnum2"
|
||||||
|
} else {
|
||||||
|
netgen::log put " Continuing with black-boxed subcircuits $endval"
|
||||||
|
lappend matcherr [lindex $endval 0]
|
||||||
|
# Match pins
|
||||||
|
netgen::log echo off
|
||||||
|
if {$dolist == 1} {
|
||||||
|
set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \
|
||||||
|
"$fnum2 [lindex $endval 1]"]
|
||||||
|
} else {
|
||||||
|
set result [equate -force pins "$fnum1 [lindex $endval 0]" \
|
||||||
|
"$fnum2 [lindex $endval 1]"]
|
||||||
|
}
|
||||||
|
if {$result != 0} {
|
||||||
|
equate classes "$fnum1 [lindex $endval 0]" \
|
||||||
|
"$fnum2 [lindex $endval 1]"
|
||||||
|
}
|
||||||
|
set pinsgood $result
|
||||||
|
netgen::log echo on
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
# Match pins
|
# Match pins
|
||||||
|
|
@ -554,9 +585,32 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
} else {
|
} else {
|
||||||
# Flatten the non-matching subcircuit (but not the top-level cells)
|
# Flatten the non-matching subcircuit (but not the top-level cells)
|
||||||
if {[netgen::print queue] != {}} {
|
if {[netgen::print queue] != {}} {
|
||||||
netgen::log put " Flattening non-matched subcircuits $endval"
|
if {([lsearch $noflat [lindex $endval 1]] == -1) &&
|
||||||
netgen::flatten class "[lindex $endval 0] $fnum1"
|
([lsearch $noflat [lindex $endval 1]] == -1)} {
|
||||||
netgen::flatten class "[lindex $endval 1] $fnum2"
|
netgen::log put " Flattening non-matched subcircuits $endval"
|
||||||
|
netgen::flatten class "[lindex $endval 0] $fnum1"
|
||||||
|
netgen::flatten class "[lindex $endval 1] $fnum2"
|
||||||
|
} else {
|
||||||
|
netgen::log put " Continuing with black-boxed subcircuits $endval"
|
||||||
|
lappend matcherr [lindex $endval 0]
|
||||||
|
netgen::log put " Continuing with black-boxed subcircuits $endval"
|
||||||
|
lappend matcherr [lindex $endval 0]
|
||||||
|
# Match pins
|
||||||
|
netgen::log echo off
|
||||||
|
if {$dolist == 1} {
|
||||||
|
set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \
|
||||||
|
"$fnum2 [lindex $endval 1]"]
|
||||||
|
} else {
|
||||||
|
set result [equate -force pins "$fnum1 [lindex $endval 0]" \
|
||||||
|
"$fnum2 [lindex $endval 1]"]
|
||||||
|
}
|
||||||
|
if {$result != 0} {
|
||||||
|
equate classes "$fnum1 [lindex $endval 0]" \
|
||||||
|
"$fnum2 [lindex $endval 1]"
|
||||||
|
}
|
||||||
|
set pinsgood $result
|
||||||
|
netgen::log echo on
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
netgen::log echo off
|
netgen::log echo off
|
||||||
|
|
@ -579,6 +633,9 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
if {$properr != {}} {
|
if {$properr != {}} {
|
||||||
netgen::log put "The following cells had property errors: $properr\n"
|
netgen::log put "The following cells had property errors: $properr\n"
|
||||||
}
|
}
|
||||||
|
if {$matcherr != {}} {
|
||||||
|
netgen::log put "The following subcells failed to match: $matcherr\n"
|
||||||
|
}
|
||||||
if {$dolog} {
|
if {$dolog} {
|
||||||
netgen::log end
|
netgen::log end
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2827,11 +2827,13 @@ _netcmp_equate(ClientData clientData,
|
||||||
char *name1 = NULL, *name2 = NULL, *optstart;
|
char *name1 = NULL, *name2 = NULL, *optstart;
|
||||||
struct nlist *tp1, *tp2, *SaveC1, *SaveC2;
|
struct nlist *tp1, *tp2, *SaveC1, *SaveC2;
|
||||||
struct objlist *ob1, *ob2;
|
struct objlist *ob1, *ob2;
|
||||||
|
struct ElementClass *saveEclass = NULL;
|
||||||
|
struct NodeClass *saveNclass = NULL;
|
||||||
int file1, file2;
|
int file1, file2;
|
||||||
int i, l1, l2, ltest, lent, dolist = 0;
|
int i, l1, l2, ltest, lent, dolist = 0, doforce = 0;
|
||||||
Tcl_Obj *tobj1, *tobj2, *tobj3;
|
Tcl_Obj *tobj1, *tobj2, *tobj3;
|
||||||
|
|
||||||
if (objc > 1) {
|
while (objc > 1) {
|
||||||
optstart = Tcl_GetString(objv[1]);
|
optstart = Tcl_GetString(objv[1]);
|
||||||
if (*optstart == '-') optstart++;
|
if (*optstart == '-') optstart++;
|
||||||
if (!strcmp(optstart, "list")) {
|
if (!strcmp(optstart, "list")) {
|
||||||
|
|
@ -2839,6 +2841,13 @@ _netcmp_equate(ClientData clientData,
|
||||||
objv++;
|
objv++;
|
||||||
objc--;
|
objc--;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(optstart, "force")) {
|
||||||
|
doforce = 1;
|
||||||
|
objv++;
|
||||||
|
objc--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((objc != 2) && (objc != 4) && (objc != 6)) {
|
if ((objc != 2) && (objc != 4) && (objc != 6)) {
|
||||||
|
|
@ -2996,6 +3005,12 @@ _netcmp_equate(ClientData clientData,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PINS_IDX:
|
case PINS_IDX:
|
||||||
|
if ((ElementClasses != NULL) && (doforce == TRUE)) {
|
||||||
|
saveEclass = ElementClasses;
|
||||||
|
saveNclass = NodeClasses;
|
||||||
|
ElementClasses = NULL;
|
||||||
|
NodeClasses = NULL;
|
||||||
|
}
|
||||||
if ((ElementClasses == NULL) && (auto_blackbox == FALSE)) {
|
if ((ElementClasses == NULL) && (auto_blackbox == FALSE)) {
|
||||||
if (CurrentCell == NULL) {
|
if (CurrentCell == NULL) {
|
||||||
Fprintf(stderr, "Equate elements: no current cell.\n");
|
Fprintf(stderr, "Equate elements: no current cell.\n");
|
||||||
|
|
@ -3058,6 +3073,12 @@ _netcmp_equate(ClientData clientData,
|
||||||
/* Recover temporarily set global variables (see above) */
|
/* Recover temporarily set global variables (see above) */
|
||||||
Circuit1 = SaveC1;
|
Circuit1 = SaveC1;
|
||||||
Circuit2 = SaveC2;
|
Circuit2 = SaveC2;
|
||||||
|
|
||||||
|
/* Recover ElementClasses if forcing pins on mismatched circuits */
|
||||||
|
if (doforce == TRUE) {
|
||||||
|
ElementClasses = saveEclass;
|
||||||
|
NodeClasses = saveNclass;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue