Put more amphasis on net names to resolve ambiguities

The problem was that with the floating test case, the
ambiguity resolution sometimes assigned the wrong pins
and floating pins/connected pins were swapped.

One option is to make the ambiguity resolver consider
the pin connection state when tenatively evaluating
nodes.

Another option is to put more emphasis on net names
and use them for ambiguity resolution. This has helped
here.
This commit is contained in:
Matthias Koefferlein 2019-08-30 10:24:55 +02:00
parent 60ed0cdc89
commit 550e2622bf
10 changed files with 785 additions and 14 deletions

View File

@ -523,12 +523,13 @@ class NetGraph;
struct CompareData
{
CompareData ()
: other (0), max_depth (0), max_n_branch (0), logger (0), circuit_pin_mapper (0)
: other (0), max_depth (0), max_n_branch (0), dont_consider_net_names (false), logger (0), circuit_pin_mapper (0)
{ }
NetGraph *other;
size_t max_depth;
size_t max_n_branch;
bool dont_consider_net_names;
NetlistCompareLogger *logger;
CircuitPinMapper *circuit_pin_mapper;
};
@ -1009,7 +1010,7 @@ public:
* with a proposed identity. With "with_ambiguous", amiguities are resolved by trying
* different combinations in tentative mode and deciding for one combination if possible.
*/
size_t derive_node_identities_from_node_set (const std::vector<const NetGraphNode *> &nodes, const std::vector<const NetGraphNode *> &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data);
size_t derive_node_identities_from_node_set (std::vector<const NetGraphNode *> &nodes, std::vector<const NetGraphNode *> &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data);
private:
std::vector<NetGraphNode> m_nodes;
@ -1382,7 +1383,7 @@ NetGraphNode::edge_equal (const db::Net *a, const db::Net *b)
*/
struct NodeRange
{
NodeRange (size_t _num, std::vector<const NetGraphNode *>::const_iterator _n1, std::vector<const NetGraphNode *>::const_iterator _nn1, std::vector<const NetGraphNode *>::const_iterator _n2, std::vector<const NetGraphNode *>::const_iterator _nn2)
NodeRange (size_t _num, std::vector<const NetGraphNode *>::iterator _n1, std::vector<const NetGraphNode *>::iterator _nn1, std::vector<const NetGraphNode *>::iterator _n2, std::vector<const NetGraphNode *>::iterator _nn2)
: num (_num), n1 (_n1), nn1 (_nn1), n2 (_n2), nn2 (_nn2)
{
// .. nothing yet ..
@ -1394,7 +1395,7 @@ struct NodeRange
}
size_t num;
std::vector<const NetGraphNode *>::const_iterator n1, nn1, n2, nn2;
std::vector<const NetGraphNode *>::iterator n1, nn1, n2, nn2;
};
// --------------------------------------------------------------------------------------------------------------------
@ -1680,8 +1681,81 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
return new_nodes;
}
namespace {
struct SortNodeByNet
{
public:
bool operator() (const NetGraphNode *a, const NetGraphNode *b) const
{
tl_assert (a->net () && b->net ());
return a->net ()->name () < b->net ()->name ();
}
};
}
static void sort_node_range_by_best_match (NodeRange &nr)
{
std::stable_sort (nr.n1, nr.nn1, SortNodeByNet ());
std::stable_sort (nr.n2, nr.nn2, SortNodeByNet ());
std::vector<const NetGraphNode *> nomatch1, nomatch2;
nomatch1.reserve (nr.nn1 - nr.n1);
nomatch2.reserve (nr.nn2 - nr.n2);
std::vector<const NetGraphNode *>::const_iterator i = nr.n1, j = nr.n2;
std::vector<const NetGraphNode *>::iterator iw = nr.n1, jw = nr.n2;
SortNodeByNet compare;
while (i != nr.nn1 || j != nr.nn2) {
if (j == nr.nn2) {
nomatch1.push_back (*i);
++i;
} else if (i == nr.nn1) {
nomatch2.push_back (*j);
++j;
} else if (compare (*i, *j)) {
nomatch1.push_back (*i);
++i;
} else if (compare (*j, *i)) {
nomatch2.push_back (*j);
++j;
} else {
if (iw != i) {
*iw = *i;
}
++iw, ++i;
if (jw != j) {
*jw = *j;
}
++jw, ++j;
}
}
tl_assert (iw + nomatch1.size () == nr.nn1);
tl_assert (jw + nomatch2.size () == nr.nn2);
for (i = nomatch1.begin (); i != nomatch1.end (); ++i) {
*iw++ = *i;
}
for (j = nomatch2.begin (); j != nomatch2.end (); ++j) {
*jw++ = *j;
}
}
static bool net_names_are_different (const db::Net *a, const db::Net *b)
{
if (! a || ! b || a->name ().empty () || b->name ().empty ()) {
return false;
} else {
return (a->name () != b->name ());
}
}
size_t
NetGraph::derive_node_identities_from_node_set (const std::vector<const NetGraphNode *> &nodes, const std::vector<const NetGraphNode *> &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data)
NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *> &nodes, std::vector<const NetGraphNode *> &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data)
{
#if defined(PRINT_DEBUG_NETCOMPARE)
std::string indent;
@ -1757,8 +1831,8 @@ NetGraph::derive_node_identities_from_node_set (const std::vector<const NetGraph
std::vector<NodeRange> node_ranges;
std::vector<const NetGraphNode *>::const_iterator n1 = nodes.begin ();
std::vector<const NetGraphNode *>::const_iterator n2 = other_nodes.begin ();
std::vector<const NetGraphNode *>::iterator n1 = nodes.begin ();
std::vector<const NetGraphNode *>::iterator n2 = other_nodes.begin ();
while (n1 != nodes.end () && n2 != other_nodes.end ()) {
@ -1778,7 +1852,7 @@ NetGraph::derive_node_identities_from_node_set (const std::vector<const NetGraph
continue;
}
std::vector<const NetGraphNode *>::const_iterator nn1 = n1, nn2 = n2;
std::vector<const NetGraphNode *>::iterator nn1 = n1, nn2 = n2;
size_t num = 1;
++nn1;
@ -1853,6 +1927,16 @@ NetGraph::derive_node_identities_from_node_set (const std::vector<const NetGraph
if (! (*nr->n1)->has_other () && ! (*nr->n2)->has_other ()) {
// in tentative mode, reject this choice if both nets are named and
// their names differ -> this favors net matching by name
if (tentative && ! data->dont_consider_net_names && net_names_are_different ((*nr->n1)->net (), (*nr->n2)->net ())) {
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::info << indent << "rejecting pair as names are not identical: " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
#endif
return std::numeric_limits<size_t>::max ();
}
// A single candiate: just take this one -> this may render
// inexact matches, but further propagates net pairing
@ -1909,10 +1993,17 @@ NetGraph::derive_node_identities_from_node_set (const std::vector<const NetGraph
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::info << indent << "analyzing ambiguity group with " << nr->num << " members";
#endif
// sort the ambiguity group such that net names
std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> > pairs;
tl::equivalence_clusters<const NetGraphNode *> equivalent_other_nodes;
std::set<const NetGraphNode *> seen;
if (! data->dont_consider_net_names) {
sort_node_range_by_best_match (*nr);
}
for (std::vector<const NetGraphNode *>::const_iterator i1 = nr->n1; i1 != nr->nn1; ++i1) {
if ((*i1)->has_other ()) {
@ -2061,6 +2152,8 @@ NetlistComparer::NetlistComparer (NetlistCompareLogger *logger)
m_max_depth = 8;
m_max_n_branch = 100;
m_dont_consider_net_names = false;
}
NetlistComparer::~NetlistComparer ()
@ -2617,6 +2710,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
data.other = &g2;
data.max_depth = m_max_depth;
data.max_n_branch = m_max_n_branch;
data.dont_consider_net_names = m_dont_consider_net_names;
data.circuit_pin_mapper = &circuit_pin_mapper;
data.logger = mp_logger;
@ -2669,6 +2763,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
data.other = &g2;
data.max_depth = m_max_depth;
data.max_n_branch = m_max_n_branch;
data.dont_consider_net_names = m_dont_consider_net_names;
data.circuit_pin_mapper = &circuit_pin_mapper;
data.logger = mp_logger;

View File

@ -245,6 +245,23 @@ public:
return m_max_depth;
}
/**
* @brief Sets a value indicating whether not to consider net names
* This feature is mainly intended for testing.
*/
void set_dont_consider_net_names (bool f)
{
m_dont_consider_net_names = f;
}
/**
* @brief Gets a value indicating whether not to consider net names
*/
bool dont_consider_net_names () const
{
return m_dont_consider_net_names;
}
/**
* @brief Sets the maximum branch complexity
*
@ -308,6 +325,7 @@ protected:
double m_res_threshold;
size_t m_max_n_branch;
size_t m_max_depth;
bool m_dont_consider_net_names;
};
}

View File

@ -1661,6 +1661,7 @@ TEST(11_MismatchingSubcircuits)
NetlistCompareTestLogger logger;
db::NetlistComparer comp (&logger);
comp.set_dont_consider_net_names (true);
bool good = comp.compare (&nl1, &nl2);
@ -1696,6 +1697,7 @@ TEST(11_MismatchingSubcircuits)
db::NetlistCrossReference xref;
db::NetlistComparer comp_xref (&xref);
comp_xref.set_dont_consider_net_names (true);
good = comp_xref.compare (&nl1, &nl2);
@ -2521,6 +2523,7 @@ TEST(17_InherentlyAmbiguousDecoder)
NetlistCompareTestLogger logger;
db::NetlistComparer comp (&logger);
comp.equivalent_pins (nl2.circuit_by_name ("NAND"), 0, 1);
comp.set_dont_consider_net_names (true);
bool good = comp.compare (&nl1, &nl2);
@ -2572,7 +2575,61 @@ TEST(17_InherentlyAmbiguousDecoder)
EXPECT_EQ (good, true);
comp.set_dont_consider_net_names (false);
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (logger.text (),
"begin_circuit NAND NAND\n"
"match_nets VSS VSS\n"
"match_nets INT INT\n"
"match_nets OUT OUT\n"
"match_nets VDD VDD\n"
"match_nets B B\n"
"match_nets A A\n"
"match_pins $0 $0\n"
"match_pins $1 $1\n"
"match_pins $2 $2\n"
"match_pins $3 $3\n"
"match_pins $4 $4\n"
"match_devices $1 $1\n"
"match_devices $2 $2\n"
"match_devices $3 $3\n"
"match_devices $4 $4\n"
"end_circuit NAND NAND MATCH\n"
"begin_circuit DECODER DECODER\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets NQ0 NQ0\n"
"match_nets NQ1 NQ1\n"
"match_nets NQ2 NQ2\n"
"match_nets NQ3 NQ3\n"
"match_ambiguous_nets NA NA\n"
"match_ambiguous_nets NB NB\n"
"match_nets B B\n"
"match_nets A A\n"
"match_pins $0 $1\n"
"match_pins $1 $0\n"
"match_pins $2 $2\n"
"match_pins $3 $3\n"
"match_pins $4 $4\n"
"match_pins $5 $5\n"
"match_pins $6 $6\n"
"match_pins $7 $7\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $2 $2\n"
"match_subcircuits $4 $3\n"
"match_subcircuits $6 $4\n"
"match_subcircuits $3 $5\n"
"match_subcircuits $5 $6\n"
"end_circuit DECODER DECODER MATCH"
);
EXPECT_EQ (good, true);
logger.clear ();
comp.set_dont_consider_net_names (true);
comp.same_nets (nl1.circuit_by_name ("DECODER")->net_by_name ("A"), nl2.circuit_by_name ("DECODER")->net_by_name ("A"));
good = comp.compare (&nl1, &nl2);

View File

@ -28,7 +28,7 @@
#include "lymMacro.h"
#include "tlFileUtils.h"
void run_test (tl::TestBase *_this, const std::string &suffix, const std::string &layout, bool with_l2n = false)
void run_test (tl::TestBase *_this, const std::string &suffix, const std::string &layout, bool with_l2n = false, const std::string &top = std::string ())
{
std::string rs = tl::testsrc ();
rs += "/testdata/lvs/" + suffix + ".lvs";
@ -57,7 +57,8 @@ void run_test (tl::TestBase *_this, const std::string &suffix, const std::string
"$lvs_test_target_lvsdb = '%s'\n"
"$lvs_test_target_cir = '%s'\n"
"$lvs_test_target_l2n = '%s'\n"
, src, output_lvsdb, output_cir, output_l2n)
"$lvs_test_top = '%s'\n"
, src, output_lvsdb, output_cir, output_l2n, top)
);
config.set_interpreter (lym::Macro::Ruby);
EXPECT_EQ (config.run (), 0);
@ -148,3 +149,8 @@ TEST(15_simple_dummy_device)
{
run_test (_this, "ringo_simple_dummy_device", "ringo_dummy_device.gds");
}
TEST(16_floating)
{
run_test (_this, "floating", "floating.gds", false, "TOP");
}

50
testdata/lvs/floating.cir vendored Normal file
View File

@ -0,0 +1,50 @@
* Extracted by KLayout
* cell TOP
* pin A
* pin C
* pin SUBSTRATE
.SUBCKT TOP 2 3 4
* net 2 A
* net 3 C
* net 4 SUBSTRATE
* cell instance $1 r0 *1 0,0
X$1 2 3 1 6 4 DINV
* cell instance $2 r0 *1 3.6,0
X$2 5 6 1 4 INVX1
.ENDS TOP
* cell DINV
* pin A<1>
* pin A<2>
* pin B<2>
* pin VDD
* pin VSS
.SUBCKT DINV 1 2 3 5 6
* net 1 A<1>
* net 2 A<2>
* net 3 B<2>
* net 4 B<1>
* net 5 VDD
* net 6 VSS
* cell instance $1 r0 *1 0,0
X$1 4 5 1 6 INVX1
* cell instance $2 r0 *1 1.8,0
X$2 3 5 2 6 INVX1
.ENDS DINV
* cell INVX1
* pin OUT
* pin VDD
* pin IN
* pin VSS
.SUBCKT INVX1 1 2 3 4
* net 1 OUT
* net 2 VDD
* net 3 IN
* net 4 VSS
* device instance $1 r0 *1 0.85,2.135 NMOS
M$1 4 3 1 4 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
* device instance $2 r0 *1 0.85,5.8 PMOS
M$2 2 3 1 2 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
.ENDS INVX1

BIN
testdata/lvs/floating.gds vendored Normal file

Binary file not shown.

75
testdata/lvs/floating.lvs vendored Normal file
View File

@ -0,0 +1,75 @@
source($lvs_test_source, $lvs_test_top)
report_lvs($lvs_test_target_lvsdb, true)
target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
schematic("floating_ref.cir")
deep
# Drawing layers
nwell = input(1, 0)
active = input(2, 0)
pplus = input(3, 0)
nplus = input(4, 0)
poly = input(5, 0)
contact = input(8, 0)
metal1 = input(9, 0)
via1 = input(10, 0)
metal2 = input(11, 0)
# Bulk layer for terminal provisioning
bulk = polygon_layer
# Computed layers
active_in_nwell = active & nwell
pactive = active_in_nwell & pplus
pgate = pactive & poly
psd = pactive - pgate
ntie = active_in_nwell & nplus
active_outside_nwell = active - nwell
nactive = active_outside_nwell & nplus
ngate = nactive & poly
nsd = nactive - ngate
ptie = active_outside_nwell & pplus
# Device extraction
# PMOS transistor device extraction
extract_devices(mos4("PMOS"), { "SD" => psd, "G" => pgate, "W" => nwell,
"tS" => psd, "tD" => psd, "tG" => poly, "tW" => nwell })
# NMOS transistor device extraction
extract_devices(mos4("NMOS"), { "SD" => nsd, "G" => ngate, "W" => bulk,
"tS" => nsd, "tD" => nsd, "tG" => poly, "tW" => bulk })
# Define connectivity for netlist extraction
# Inter-layer
connect(psd, contact)
connect(nsd, contact)
connect(poly, contact)
connect(ntie, contact)
connect(nwell, ntie)
connect(ptie, contact)
connect(contact, metal1)
connect(metal1, via1)
connect(via1, metal2)
# Global
connect_global(bulk, "SUBSTRATE")
connect_global(ptie, "SUBSTRATE")
# Compare section
netlist.simplify
align
compare

454
testdata/lvs/floating.lvsdb vendored Normal file
View File

@ -0,0 +1,454 @@
#%lvsdb-klayout
# Layout
layout(
top(TOP)
unit(0.001)
# Layer section
# This section lists the mask layers (drawing or derived) and their connections.
# Mask layers
layer(l3 '1/0')
layer(l4 '5/0')
layer(l8 '8/0')
layer(l11 '9/0')
layer(l12 '5/0')
layer(l13 '5/0')
layer(l7)
layer(l2)
layer(l9)
layer(l6)
layer(l10)
# Mask layer connectivity
connect(l3 l3 l9)
connect(l4 l4 l8)
connect(l8 l4 l8 l11 l2 l9 l6 l10)
connect(l11 l8 l11 l12)
connect(l12 l11 l12 l13)
connect(l13 l12 l13)
connect(l7 l7)
connect(l2 l8 l2)
connect(l9 l3 l8 l9)
connect(l6 l8 l6)
connect(l10 l8 l10)
# Global nets and connectivity
global(l7 SUBSTRATE)
global(l10 SUBSTRATE)
# Device class section
class(PMOS MOS4)
class(NMOS MOS4)
# Device abstracts section
# Device abstracts list the pin shapes of the devices.
device(D$PMOS PMOS
terminal(S
rect(l2 (-550 -750) (425 1500))
)
terminal(G
rect(l4 (-125 -750) (250 1500))
)
terminal(D
rect(l2 (125 -750) (425 1500))
)
terminal(B
rect(l3 (-125 -750) (250 1500))
)
)
device(D$NMOS NMOS
terminal(S
rect(l6 (-550 -475) (425 950))
)
terminal(G
rect(l4 (-125 -475) (250 950))
)
terminal(D
rect(l6 (125 -475) (425 950))
)
terminal(B
rect(l7 (-125 -475) (250 950))
)
)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(INVX1
# Circuit boundary
rect((-100 400) (2000 7600))
# Nets with their geometries
net(1 name(OUT)
rect(l8 (1110 5160) (180 180))
rect(l8 (-180 920) (180 180))
rect(l8 (-180 -730) (180 180))
rect(l8 (-180 -4120) (180 180))
rect(l8 (-180 370) (180 180))
rect(l11 (-240 -790) (300 4790))
rect(l11 (-151 -2501) (2 2))
rect(l2 (-226 1049) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(2 name(VDD)
rect(l3 (-100 4500) (2000 3500))
rect(l8 (-1090 -890) (180 180))
rect(l8 (-580 -1030) (180 180))
rect(l8 (-180 -730) (180 180))
rect(l8 (-180 -730) (180 180))
rect(l11 (-590 1460) (1800 800))
rect(l11 (-1050 -550) (300 300))
rect(l11 (-700 -850) (300 300))
rect(l11 (299 499) (2 2))
rect(l11 (-601 -2201) (300 1400))
rect(l2 (-350 -1450) (425 1500))
rect(l9 (-75 450) (500 500))
)
net(3 name(IN)
rect(l4 (725 2860) (250 1940))
rect(l4 (-525 -1850) (300 300))
rect(l4 (-25 -1840) (250 1450))
rect(l4 (-250 1940) (250 2000))
rect(l4 (-250 -2000) (250 2000))
rect(l8 (-465 -3790) (180 180))
rect(l11 (-91 -91) (2 2))
rect(l11 (-151 -151) (300 300))
)
net(4 name(VSS)
rect(l8 (810 710) (180 180))
rect(l8 (-580 880) (180 180))
rect(l8 (-180 370) (180 180))
rect(l11 (-590 -2100) (1800 800))
rect(l11 (-1050 -550) (300 300))
rect(l11 (-101 -151) (2 2))
rect(l11 (-601 399) (300 1360))
rect(l6 (-350 -900) (425 950))
rect(l10 (-75 -2010) (500 400))
)
# Outgoing pins and their connections to nets
pin(1 name(OUT))
pin(2 name(VDD))
pin(3 name(IN))
pin(4 name(VSS))
# Devices and their connections
device(1 D$NMOS
location(850 2135)
param(L 0.25)
param(W 0.95)
param(AS 0.40375)
param(AD 0.40375)
param(PS 2.75)
param(PD 2.75)
terminal(S 4)
terminal(G 3)
terminal(D 1)
terminal(B 4)
)
device(2 D$PMOS
location(850 5800)
param(L 0.25)
param(W 1.5)
param(AS 0.6375)
param(AD 0.6375)
param(PS 3.85)
param(PD 3.85)
terminal(S 2)
terminal(G 3)
terminal(D 1)
terminal(B 2)
)
)
circuit(DINV
# Circuit boundary
rect((-100 400) (3800 7600))
# Nets with their geometries
net(1 name('A<1>')
rect(l8 (510 3010) (180 180))
rect(l11 (-91 -91) (2 2))
)
net(2 name('A<2>')
rect(l8 (2310 3010) (180 180))
rect(l11 (-91 -91) (2 2))
)
net(3 name('B<2>')
rect(l11 (2999 3999) (2 2))
rect(l2 (-226 1049) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(4 name('B<1>')
rect(l11 (1199 3999) (2 2))
rect(l2 (-226 1049) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(5 name(VDD)
rect(l11 (1799 7199) (2 2))
rect(l2 (299 -2151) (425 1500))
rect(l2 (-2225 -1500) (425 1500))
)
net(6 name(VSS)
rect(l11 (1799 799) (2 2))
rect(l6 (299 859) (425 950))
rect(l6 (-2225 -950) (425 950))
)
# Outgoing pins and their connections to nets
pin(1 name('A<1>'))
pin(2 name('A<2>'))
pin(3 name('B<2>'))
pin(5 name(VDD))
pin(6 name(VSS))
# Subcircuits and their connections
circuit(1 INVX1 location(0 0)
pin(0 4)
pin(1 5)
pin(2 1)
pin(3 6)
)
circuit(2 INVX1 location(1800 0)
pin(0 3)
pin(1 5)
pin(2 2)
pin(3 6)
)
)
circuit(TOP
# Circuit boundary
rect((-100 400) (5600 7600))
# Nets with their geometries
net(1
rect(l8 (4110 3010) (180 180))
rect(l11 (-1190 -240) (950 300))
rect(l2 (-1275 1800) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(2 name(A)
rect(l8 (510 3010) (180 180))
rect(l11 (-91 -91) (2 2))
)
net(3 name(C)
rect(l8 (2310 3010) (180 180))
rect(l11 (-91 -91) (2 2))
)
net(4 name(SUBSTRATE)
rect(l6 (3900 1660) (425 950))
rect(l6 (-2225 -950) (425 950))
rect(l6 (-2225 -950) (425 950))
)
net(5
rect(l2 (4575 5050) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(6
rect(l2 (3900 5050) (425 1500))
rect(l2 (-2225 -1500) (425 1500))
rect(l2 (-2225 -1500) (425 1500))
)
# Outgoing pins and their connections to nets
pin(2 name(A))
pin(3 name(C))
pin(4 name(SUBSTRATE))
# Subcircuits and their connections
circuit(1 DINV location(0 0)
pin(0 2)
pin(1 3)
pin(2 1)
pin(3 6)
pin(4 4)
)
circuit(2 INVX1 location(3600 0)
pin(0 5)
pin(1 6)
pin(2 1)
pin(3 4)
)
)
)
# Reference netlist
reference(
# Device class section
class(NMOS MOS4)
class(PMOS MOS4)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(INVX1
# Nets
net(1 name(A))
net(2 name(Z))
net(3 name(VDD))
net(4 name(VSS))
# Outgoing pins and their connections to nets
pin(1 name(A))
pin(2 name(Z))
pin(3 name(VDD))
pin(4 name(VSS))
# Devices and their connections
device(1 NMOS
name('0')
param(L 0.25)
param(W 0.95)
param(AS 0)
param(AD 0)
param(PS 0)
param(PD 0)
terminal(S 2)
terminal(G 1)
terminal(D 4)
terminal(B 4)
)
device(2 PMOS
name('1')
param(L 0.25)
param(W 1.5)
param(AS 0)
param(AD 0)
param(PS 0)
param(PD 0)
terminal(S 2)
terminal(G 1)
terminal(D 3)
terminal(B 3)
)
)
circuit(DINV
# Nets
net(1 name('A<1>'))
net(2 name('A<2>'))
net(3 name('B<1>'))
net(4 name('B<2>'))
net(5 name(VDD))
net(6 name(VSS))
# Outgoing pins and their connections to nets
pin(1 name('A<1>'))
pin(2 name('A<2>'))
pin(3 name('B<1>'))
pin(4 name('B<2>'))
pin(5 name(VDD))
pin(6 name(VSS))
# Subcircuits and their connections
circuit(1 INVX1 name(A)
pin(0 1)
pin(1 3)
pin(2 5)
pin(3 6)
)
circuit(2 INVX1 name(B)
pin(0 2)
pin(1 4)
pin(2 5)
pin(3 6)
)
)
circuit(TOP
# Nets
net(1 name(A))
net(2 name(C))
net(3 name(D))
net(4 name(VDD))
net(5 name(VSS))
net(6 name(B))
net(7 name(E))
# Outgoing pins and their connections to nets
pin(1 name(A))
pin(2 name(C))
pin(3 name(D))
pin(4 name(VDD))
pin(5 name(VSS))
# Subcircuits and their connections
circuit(1 DINV name('0')
pin(0 1)
pin(1 2)
pin(2 6)
pin(3 7)
pin(4 4)
pin(5 5)
)
circuit(2 INVX1 name('1')
pin(0 7)
pin(1 3)
pin(2 4)
pin(3 5)
)
)
)
# Cross reference
xref(
circuit(DINV DINV match
xref(
net(1 1 match)
net(2 2 match)
net(4 3 warning)
net(3 4 warning)
net(5 5 match)
net(6 6 match)
pin(() 2 match)
pin(0 0 match)
pin(1 1 match)
pin(2 3 match)
pin(3 4 match)
pin(4 5 match)
circuit(1 1 match)
circuit(2 2 match)
)
)
circuit(INVX1 INVX1 match
xref(
net(3 1 match)
net(1 2 match)
net(2 3 match)
net(4 4 match)
pin(2 0 match)
pin(0 1 match)
pin(1 2 match)
pin(3 3 match)
device(1 1 match)
device(2 2 match)
)
)
circuit(TOP TOP match
xref(
net(5 3 match)
net(1 7 match)
net(6 4 match)
net(2 1 match)
net(3 2 match)
net(4 5 match)
pin(() 2 match)
pin(() 3 match)
pin(0 0 match)
pin(1 1 match)
pin(2 4 match)
circuit(1 1 match)
circuit(2 2 match)
)
)
)

16
testdata/lvs/floating_ref.cir vendored Normal file
View File

@ -0,0 +1,16 @@
.global VDD VSS
.subckt TOP A C D
X0 A C B E DINV
X1 E D INVX1
.ends
.subckt DINV A<1> A<2> B<1> B<2>
XA A<1> B<1> INVX1
XB A<2> B<2> INVX1
.ends
.subckt INVX1 A Z
M0 Z A VSS VSS NMOS W=0.95U L=0.25U
M1 Z A VDD VDD PMOS W=1.5U L=0.25U
.ends

View File

@ -530,13 +530,13 @@ xref(
net(8 4 match)
net(5 3 match)
net(7 5 match)
net(6 1 warning)
net(9 2 warning)
net(6 2 warning)
net(9 1 warning)
pin(3 3 match)
pin(0 2 match)
pin(2 4 match)
pin(1 0 match)
pin(4 1 match)
pin(1 1 match)
pin(4 0 match)
circuit(2 2 match)
circuit(3 3 match)
circuit(17 4 match)