diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc
index c3555691e..1d146713d 100644
--- a/src/db/db/dbNetlistCompare.cc
+++ b/src/db/db/dbNetlistCompare.cc
@@ -776,8 +776,9 @@ public:
{
if (is_for_subcircuit ()) {
const db::SubCircuit *sc = subcircuit_pair ().first;
+ size_t pin_id = std::numeric_limits::max () - m_id1;
const db::Circuit *c = sc->circuit_ref ();
- return std::string ("X") + sc->expanded_name () + " " + c->name ();
+ return std::string ("X") + sc->expanded_name () + " " + c->name () + " " + c->pin_by_id (pin_id)->expanded_name () + " (virtual)";
} else {
size_t term_id1 = m_id1;
size_t term_id2 = m_id2;
@@ -1012,6 +1013,14 @@ public:
return j->second;
}
+ /**
+ * @brief Gets a value indicating whether there is a node for the given net
+ */
+ bool has_node_index_for_net (const db::Net *net) const
+ {
+ return m_net_index.find (net) != m_net_index.end ();
+ }
+
/**
* @brief Gets the node for a given node index
*/
@@ -2879,9 +2888,16 @@ NetlistComparer::exclude_resistors (double threshold)
}
void
-NetlistComparer::same_nets (const db::Net *na, const db::Net *nb)
+NetlistComparer::same_nets (const db::Net *na, const db::Net *nb, bool must_match)
{
- m_same_nets [std::make_pair (na->circuit (), nb->circuit ())].push_back (std::make_pair (na, nb));
+ tl_assert (na && na);
+ m_same_nets [std::make_pair (na->circuit (), nb->circuit ())].push_back (std::make_pair (std::make_pair (na, nb), must_match));
+}
+
+void
+NetlistComparer::same_nets (const db::Circuit *ca, const db::Circuit *cb, const db::Net *na, const db::Net *nb, bool must_match)
+{
+ m_same_nets [std::make_pair (ca, cb)].push_back (std::make_pair (std::make_pair (na, nb), must_match));
}
void
@@ -3113,9 +3129,9 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
tl_assert (i->second.second.size () == size_t (1));
const db::Circuit *cb = i->second.second.front ();
- std::vector > empty;
- const std::vector > *net_identity = ∅
- std::map, std::vector > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb));
+ std::vector, bool> > empty;
+ const std::vector, bool> > *net_identity = ∅
+ std::map, std::vector, bool> > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb));
if (sn != m_same_nets.end ()) {
net_identity = &sn->second;
}
@@ -3168,14 +3184,16 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
}
static
-std::vector collect_pins_with_empty_nets (const db::Circuit *c, CircuitPinMapper *circuit_pin_mapper)
+std::vector collect_anonymous_empty_pins (const db::Circuit *c, CircuitPinMapper *circuit_pin_mapper)
{
std::vector pins;
for (db::Circuit::const_pin_iterator p = c->begin_pins (); p != c->end_pins (); ++p) {
- const db::Net *net = c->net_for_pin (p->id ());
- if ((! net || net->is_passive ()) && ! circuit_pin_mapper->is_mapped (c, p->id ())) {
- pins.push_back (p->id ());
+ if (p->name ().empty () && ! circuit_pin_mapper->is_mapped (c, p->id ())) {
+ const db::Net *net = c->net_for_pin (p->id ());
+ if (! net || net->is_passive ()) {
+ pins.push_back (p->id ());
+ }
}
}
@@ -3185,13 +3203,11 @@ std::vector collect_pins_with_empty_nets (const db::Circuit *c, CircuitP
void
NetlistComparer::derive_pin_equivalence (const db::Circuit *ca, const db::Circuit *cb, CircuitPinMapper *circuit_pin_mapper)
{
- // TODO: All pins with empty nets are treated as equivalent - this as a quick way to
- // treat circuits abstracts, although it's not really valid. By doing this, we
- // don't capture the case of multiple (abstract) subcircuits wired in different ways.
+ // NOTE: All unnamed pins with empty nets are treated as equivalent. There is no other criterion to match these pins.
std::vector pa, pb;
- pa = collect_pins_with_empty_nets (ca, circuit_pin_mapper);
- pb = collect_pins_with_empty_nets (cb, circuit_pin_mapper);
+ pa = collect_anonymous_empty_pins (ca, circuit_pin_mapper);
+ pb = collect_anonymous_empty_pins (cb, circuit_pin_mapper);
circuit_pin_mapper->map_pins (ca, pa);
circuit_pin_mapper->map_pins (cb, pb);
@@ -3524,7 +3540,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
db::DeviceCategorizer &device_categorizer,
db::CircuitCategorizer &circuit_categorizer,
db::CircuitPinMapper &circuit_pin_mapper,
- const std::vector > &net_identity,
+ const std::vector, bool> > &net_identity,
bool &pin_mismatch,
std::map &c12_circuit_and_pin_mapping,
std::map &c22_circuit_and_pin_mapping) const
@@ -3537,18 +3553,52 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
// NOTE: for normalization we map all subcircuits of c1 to c2.
// Also, pin swapping will only happen there.
+ if (options ()->debug_netgraph) {
+ tl::info << "Netlist graph:";
+ }
g1.build (c1, device_categorizer, circuit_categorizer, device_filter, &c12_circuit_and_pin_mapping, &circuit_pin_mapper);
+ if (options ()->debug_netgraph) {
+ tl::info << "Other netlist graph:";
+ }
g2.build (c2, device_categorizer, circuit_categorizer, device_filter, &c22_circuit_and_pin_mapping, &circuit_pin_mapper);
// Match dummy nodes for null nets
g1.identify (0, 0);
g2.identify (0, 0);
- for (std::vector >::const_iterator p = net_identity.begin (); p != net_identity.end (); ++p) {
- size_t ni1 = g1.node_index_for_net (p->first);
- size_t ni2 = g2.node_index_for_net (p->second);
- g1.identify (ni1, ni2);
- g2.identify (ni2, ni1);
+ for (std::vector, bool> >::const_iterator p = net_identity.begin (); p != net_identity.end (); ++p) {
+
+ // NOTE: nets may vanish, hence there
+ if (g1.has_node_index_for_net (p->first.first) && g2.has_node_index_for_net (p->first.second)) {
+
+ size_t ni1 = g1.node_index_for_net (p->first.first);
+ size_t ni2 = g2.node_index_for_net (p->first.second);
+ g1.identify (ni1, ni2);
+ g2.identify (ni2, ni1);
+
+ // in must_match mode, check if the nets are identical
+ if (p->second && ! (g1.node(ni1) == g2.node(ni2))) {
+ mp_logger->net_mismatch (p->first.first, p->first.second);
+ } else {
+ mp_logger->match_nets (p->first.first, p->first.second);
+ }
+
+ } else if (p->second && g1.has_node_index_for_net (p->first.first)) {
+
+ mp_logger->net_mismatch (p->first.first, 0);
+
+ size_t ni1 = g1.node_index_for_net (p->first.first);
+ g1.identify (ni1, 0);
+
+ } else if (p->second && g2.has_node_index_for_net (p->first.second)) {
+
+ mp_logger->net_mismatch (0, p->first.second);
+
+ size_t ni2 = g2.node_index_for_net (p->first.second);
+ g2.identify (ni2, 0);
+
+ }
+
}
int iter = 0;
@@ -3851,7 +3901,7 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
mp_logger->match_pins (p.operator-> (), fp->second);
}
c12_pin_mapping.map_pin (p->id (), fp->second->id ());
- c22_pin_mapping.map_pin (fp->second->id (), p->id ());
+ c22_pin_mapping.map_pin (fp->second->id (), fp->second->id ());
} else if (next_abstract != abstract_pins2.end ()) {
@@ -3861,7 +3911,7 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
mp_logger->match_pins (p.operator-> (), *next_abstract);
}
c12_pin_mapping.map_pin (p->id (), (*next_abstract)->id ());
- c22_pin_mapping.map_pin ((*next_abstract)->id (), p->id ());
+ c22_pin_mapping.map_pin ((*next_abstract)->id (), (*next_abstract)->id ());
++next_abstract;
@@ -4470,7 +4520,9 @@ NetlistComparer::join_symmetric_nets (db::Circuit *circuit)
std::map circuit_and_pin_mapping;
db::NetGraph graph;
- graph.build (circuit, *mp_device_categorizer, *mp_circuit_categorizer, device_filter, &circuit_and_pin_mapping, &circuit_pin_mapper);
+ db::CircuitCategorizer circuit_categorizer;
+ db::DeviceCategorizer device_categorizer;
+ graph.build (circuit, device_categorizer, circuit_categorizer, device_filter, &circuit_and_pin_mapping, &circuit_pin_mapper);
// sort the nodes so we can easily identify the identical ones (in terms of topology)
// nodes are identical if the attached devices and circuits are of the same kind and with the same parameters
diff --git a/src/db/db/dbNetlistCompare.h b/src/db/db/dbNetlistCompare.h
index 2d4e81506..197d5ef6c 100644
--- a/src/db/db/dbNetlistCompare.h
+++ b/src/db/db/dbNetlistCompare.h
@@ -181,7 +181,17 @@ public:
* net nb in netlist b.
* By default nets are not identical expect through their topology.
*/
- void same_nets (const db::Net *na, const db::Net *nb);
+ void same_nets (const db::Net *na, const db::Net *nb, bool must_match = false);
+
+ /**
+ * @brief Mark two nets as identical
+ *
+ * This makes a net na in netlist a identical to the corresponding
+ * net nb in netlist b.
+ * By default nets are not identical expect through their topology.
+ * This version allows mapping one net to a null net because the circuits are explicitly specified.
+ */
+ void same_nets (const db::Circuit *ca, const db::Circuit *cb, const db::Net *na, const db::Net *nb, bool must_match);
/**
* @brief Mark two pins as equivalent (i.e. can be swapped)
@@ -344,7 +354,7 @@ private:
NetlistComparer &operator= (const NetlistComparer &);
protected:
- bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinMapper &circuit_pin_mapper, const std::vector > &net_identity, bool &pin_mismatch, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping) const;
+ bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinMapper &circuit_pin_mapper, const std::vector, bool> > &net_identity, bool &pin_mismatch, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping) const;
bool all_subcircuits_verified (const db::Circuit *c, const std::set &verified_circuits) const;
std::string generate_subcircuits_not_verified_warning (const db::Circuit *ca, const std::set &verified_circuits_a, const db::Circuit *cb, const std::set &verified_circuits_b) const;
static void derive_pin_equivalence (const db::Circuit *ca, const db::Circuit *cb, CircuitPinMapper *circuit_pin_mapper);
@@ -354,7 +364,7 @@ protected:
bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const;
mutable NetlistCompareLogger *mp_logger;
- std::map, std::vector > > m_same_nets;
+ std::map, std::vector, bool> > > m_same_nets;
std::unique_ptr mp_circuit_pin_mapper;
std::unique_ptr mp_device_categorizer;
std::unique_ptr mp_circuit_categorizer;
diff --git a/src/db/db/dbNetlistCrossReference.cc b/src/db/db/dbNetlistCrossReference.cc
index 4ebae1072..99ab8c780 100644
--- a/src/db/db/dbNetlistCrossReference.cc
+++ b/src/db/db/dbNetlistCrossReference.cc
@@ -113,6 +113,10 @@ NetlistCrossReference::other_net_for (const db::Net *net) const
const NetlistCrossReference::PerNetData *
NetlistCrossReference::per_net_data_for (const std::pair &nets) const
{
+ if (! nets.first && ! nets.second) {
+ return 0;
+ }
+
std::map, PerNetData>::iterator i = m_per_net_data.find (nets);
if (i == m_per_net_data.end ()) {
i = m_per_net_data.insert (std::make_pair (nets, PerNetData ())).first;
@@ -628,11 +632,13 @@ NetlistCrossReference::build_subcircuit_pin_refs (const std::pair &nets, PerNetData &data) const
{
- if (! nets.second) {
+ if (! nets.first && ! nets.second) {
+ // .. nothing ..
+ } else if (! nets.second) {
init_data_from_single (nets.first, data, true);
} else if (! nets.first) {
init_data_from_single (nets.second, data, false);
- } else if (nets.first) {
+ } else {
build_terminal_refs (nets, data);
build_pin_refs (nets, data);
build_subcircuit_pin_refs (nets, data);
diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc
index be85f137f..19bfd3a5e 100644
--- a/src/db/db/gsiDeclDbNetlist.cc
+++ b/src/db/db/gsiDeclDbNetlist.cc
@@ -1234,6 +1234,50 @@ static db::Pin *create_pin (db::Circuit *circuit, const std::string &name)
return & circuit->add_pin (name);
}
+static std::vector
+nets_by_name (db::Circuit *circuit, const std::string &name_pattern)
+{
+ std::vector res;
+ if (! circuit) {
+ return res;
+ }
+
+ tl::GlobPattern glob (name_pattern);
+ if (circuit->netlist ()) {
+ glob.set_case_sensitive (circuit->netlist ()->is_case_sensitive ());
+ }
+ for (db::Circuit::net_iterator n = circuit->begin_nets (); n != circuit->end_nets (); ++n) {
+ db::Net *net = n.operator-> ();
+ if (glob.match (net->name ())) {
+ res.push_back (net);
+ }
+ }
+
+ return res;
+}
+
+static std::vector
+nets_by_name_const (const db::Circuit *circuit, const std::string &name_pattern)
+{
+ std::vector res;
+ if (! circuit) {
+ return res;
+ }
+
+ tl::GlobPattern glob (name_pattern);
+ if (circuit->netlist ()) {
+ glob.set_case_sensitive (circuit->netlist ()->is_case_sensitive ());
+ }
+ for (db::Circuit::const_net_iterator n = circuit->begin_nets (); n != circuit->end_nets (); ++n) {
+ const db::Net *net = n.operator-> ();
+ if (glob.match (net->name ())) {
+ res.push_back (net);
+ }
+ }
+
+ return res;
+}
+
Class decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit",
gsi::method_ext ("create_pin", &create_pin, gsi::arg ("name"),
"@brief Creates a new \\Pin object inside the circuit\n"
@@ -1347,6 +1391,18 @@ Class decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit",
"\n\n"
"This constness variant has been introduced in version 0.26.8"
) +
+ gsi::method_ext ("nets_by_name", &nets_by_name, gsi::arg ("name_pattern"),
+ "@brief Gets the net objects for a given name filter.\n"
+ "The name filter is a glob pattern. This method will return all \\Net objects matching the glob pattern.\n"
+ "\n"
+ "This method has been introduced in version 0.27.3.\n"
+ ) +
+ gsi::method_ext ("nets_by_name", &nets_by_name_const, gsi::arg ("name_pattern"),
+ "@brief Gets the net objects for a given name filter (const version).\n"
+ "The name filter is a glob pattern. This method will return all \\Net objects matching the glob pattern.\n"
+ "\n\n"
+ "This constness variant has been introduced in version 0.27.3"
+ ) +
gsi::method ("pin_by_id", (db::Pin *(db::Circuit::*) (size_t)) &db::Circuit::pin_by_id, gsi::arg ("id"),
"@brief Gets the \\Pin object corresponding to a specific ID\n"
"If the ID is not a valid pin ID, nil is returned."
@@ -1637,8 +1693,13 @@ static std::vector
circuits_by_name (db::Netlist *netlist, const std::string &name_pattern)
{
std::vector res;
+ if (! netlist) {
+ return res;
+ }
tl::GlobPattern glob (name_pattern);
+ glob.set_case_sensitive (netlist->is_case_sensitive ());
+
for (db::Netlist::circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
db::Circuit *circuit = c.operator-> ();
if (glob.match (circuit->name ())) {
@@ -1653,8 +1714,13 @@ static std::vector
circuits_by_name_const (const db::Netlist *netlist, const std::string &name_pattern)
{
std::vector res;
+ if (! netlist) {
+ return res;
+ }
tl::GlobPattern glob (name_pattern);
+ glob.set_case_sensitive (netlist->is_case_sensitive ());
+
for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
const db::Circuit *circuit = c.operator-> ();
if (glob.match (circuit->name ())) {
@@ -1666,6 +1732,14 @@ circuits_by_name_const (const db::Netlist *netlist, const std::string &name_patt
}
Class decl_dbNetlist ("db", "Netlist",
+ gsi::method ("is_case_sensitive?", &db::Netlist::is_case_sensitive,
+ "@brief Returns a value indicating whether the netlist names are case sensitive\n"
+ "This method has been added in version 0.27.3.\n"
+ ) +
+ gsi::method ("case_sensitive=", &db::Netlist::set_case_sensitive, gsi::arg ("cs"),
+ "@brief Sets a value indicating whether the netlist names are case sensitive\n"
+ "This method has been added in version 0.27.3.\n"
+ ) +
gsi::method_ext ("add", &gsi::add_circuit, gsi::arg ("circuit"),
"@brief Adds the circuit to the netlist\n"
"This method will add the given circuit object to the netlist. "
@@ -1709,7 +1783,7 @@ Class decl_dbNetlist ("db", "Netlist",
"This method will erase everything from inside the circuits matching the given pattern. It will only leave pins which are "
"not connected to any net. Hence, this method forms 'abstract' or black-box circuits which can be instantiated through "
"subcircuits like the former ones, but are empty shells.\n"
- "The name pattern is a glob expression. For example, 'flatten_circuit(\"np*\")' will blank out all circuits with names "
+ "The name pattern is a glob expression. For example, 'blank_circuit(\"np*\")' will blank out all circuits with names "
"starting with 'np'.\n"
"\n"
"For more details see \\Circuit#blank which is the corresponding method on the actual object."
diff --git a/src/db/db/gsiDeclDbNetlistCompare.cc b/src/db/db/gsiDeclDbNetlistCompare.cc
index 815790559..5a0696ee6 100644
--- a/src/db/db/gsiDeclDbNetlistCompare.cc
+++ b/src/db/db/gsiDeclDbNetlistCompare.cc
@@ -476,13 +476,32 @@ Class decl_dbNetlistComparer ("db", "NetlistComparer",
"The logger is a delegate or event receiver which the comparer will send compare events to. "
"See the class description for more details."
) +
- gsi::method ("same_nets", &db::NetlistComparer::same_nets, gsi::arg ("net_a"), gsi::arg ("net_b"),
+ gsi::method ("same_nets", (void (db::NetlistComparer::*) (const db::Net *, const db::Net *, bool)) &db::NetlistComparer::same_nets, gsi::arg ("net_a"), gsi::arg ("net_b"), gsi::arg ("must_match", false),
"@brief Marks two nets as identical.\n"
"This makes a net net_a in netlist a identical to the corresponding\n"
"net net_b in netlist b (see \\compare).\n"
"Otherwise, the algorithm will try to identify nets according to their topology. "
"This method can be used to supply hints to the compare algorithm. It will use "
- "these hints to derive further identities."
+ "these hints to derive further identities.\n"
+ "\n"
+ "If 'must_match' is true, the nets are required to match. If they don't, an error is reported.\n"
+ "\n"
+ "The 'must_match' optional argument has been added in version 0.27.3.\n"
+ ) +
+ gsi::method ("same_nets", (void (db::NetlistComparer::*) (const db::Circuit *, const db::Circuit *, const db::Net *, const db::Net *, bool)) &db::NetlistComparer::same_nets, gsi::arg ("circuit_a"), gsi::arg ("circuit_b"), gsi::arg ("net_a"), gsi::arg ("net_b"), gsi::arg ("must_match", false),
+ "@brief Marks two nets as identical.\n"
+ "This makes a net net_a in netlist a identical to the corresponding\n"
+ "net net_b in netlist b (see \\compare).\n"
+ "Otherwise, the algorithm will try to identify nets according to their topology. "
+ "This method can be used to supply hints to the compare algorithm. It will use "
+ "these hints to derive further identities.\n"
+ "\n"
+ "If 'must_match' is true, the nets are required to match. If they don't, an error is reported.\n"
+ "\n"
+ "This variant allows specifying nil for the nets indicating the nets are mismatched by definition. "
+ "with 'must_match' this will render a net mismatch error.\n"
+ "\n"
+ "This variant has been added in version 0.27.3.\n"
) +
gsi::method ("equivalent_pins", (void (db::NetlistComparer::*) (const db::Circuit *, size_t, size_t)) &db::NetlistComparer::equivalent_pins, gsi::arg ("circuit_b"), gsi::arg ("pin_id1"), gsi::arg ("pin_id2"),
"@brief Marks two pins of the given circuit as equivalent (i.e. they can be swapped).\n"
diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc
index 17f102883..12106ac5e 100644
--- a/src/db/unit_tests/dbNetlistCompareTests.cc
+++ b/src/db/unit_tests/dbNetlistCompareTests.cc
@@ -766,16 +766,18 @@ TEST(2_SimpleInverterWithForcedNetAssignment)
bool good = comp.compare (&nl1, &nl2);
EXPECT_EQ (logger.text (),
- "begin_circuit INV INV\n"
- "match_nets OUT OUT\n"
- "match_nets IN IN\n"
- "match_pins $0 $1\n"
- "match_pins $1 $3\n"
- "match_pins $2 $0\n"
- "match_pins $3 $2\n"
- "match_devices $2 $1\n"
- "match_devices $1 $2\n"
- "end_circuit INV INV MATCH"
+ "begin_circuit INV INV\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
+ "match_nets OUT OUT\n"
+ "match_nets IN IN\n"
+ "match_pins $0 $1\n"
+ "match_pins $1 $3\n"
+ "match_pins $2 $0\n"
+ "match_pins $3 $2\n"
+ "match_devices $2 $1\n"
+ "match_devices $1 $2\n"
+ "end_circuit INV INV MATCH"
);
EXPECT_EQ (good, true);
}
@@ -933,6 +935,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets INT $10\n"
"net_mismatch IN IN\n"
@@ -959,6 +963,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets IN IN\n"
"match_ambiguous_nets INT $10\n"
@@ -985,6 +991,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets INT $10\n"
"net_mismatch IN IN\n"
@@ -1011,6 +1019,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets INT $10\n"
"net_mismatch IN IN\n"
@@ -1037,6 +1047,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets IN IN\n"
"match_ambiguous_nets INT $10\n"
@@ -1064,6 +1076,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets IN IN\n"
"match_ambiguous_nets INT $10\n"
@@ -1091,6 +1105,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets INT $10\n"
"net_mismatch IN IN\n"
@@ -1156,6 +1172,8 @@ TEST(5_BufferTwoPathsDifferentDeviceClasses)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
"match_nets INT $10\n"
"match_nets IN IN\n"
"net_mismatch INT2 $11\n"
@@ -1222,6 +1240,8 @@ TEST(6_BufferTwoPathsAdditionalResistor)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
"net_mismatch INT $10\n"
"match_nets IN IN\n"
"net_mismatch INT2 $11\n"
@@ -1249,6 +1269,8 @@ TEST(6_BufferTwoPathsAdditionalResistor)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
+ "match_nets VDD VDD\n"
+ "match_nets VSS VSS\n"
"net_mismatch INT $10\n"
"match_nets OUT OUT\n"
"net_mismatch INT2 $11\n"
@@ -2704,6 +2726,7 @@ TEST(17_InherentlyAmbiguousDecoder)
"match_devices $4 $4\n"
"end_circuit NAND NAND MATCH\n"
"begin_circuit DECODER DECODER\n"
+ "match_nets A A\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets B B\n"
@@ -2755,6 +2778,7 @@ TEST(17_InherentlyAmbiguousDecoder)
"match_devices $4 $4\n"
"end_circuit NAND NAND MATCH\n"
"begin_circuit DECODER DECODER\n"
+ "match_nets A A\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets NA NA\n"
@@ -3822,24 +3846,24 @@ TEST(21_BusLikeAmbiguousConnections)
"match_pins VSS VSS\n"
"end_circuit INV8 INV8 MATCH\n"
"begin_circuit INV8_WRAP INV8_WRAP\n"
- "match_ambiguous_nets VDD VDD\n"
- "match_ambiguous_nets VSS VSS\n"
- "match_ambiguous_nets IN1 A1\n"
- "match_ambiguous_nets IN2 A2\n"
- "match_ambiguous_nets IN3 A3\n"
- "match_ambiguous_nets IN4 A4\n"
- "match_ambiguous_nets IN5 A5\n"
- "match_ambiguous_nets IN6 A6\n"
- "match_ambiguous_nets IN7 A7\n"
- "match_ambiguous_nets IN8 A8\n"
- "match_ambiguous_nets OUT1 Q1\n"
- "match_ambiguous_nets OUT2 Q2\n"
- "match_ambiguous_nets OUT3 Q3\n"
- "match_ambiguous_nets OUT4 Q4\n"
- "match_ambiguous_nets OUT5 Q5\n"
- "match_ambiguous_nets OUT6 Q6\n"
- "match_ambiguous_nets OUT7 Q7\n"
- "match_ambiguous_nets OUT8 Q8\n"
+ "match_nets VSS VSS\n"
+ "match_nets VDD VDD\n"
+ "match_nets OUT8 Q8\n"
+ "match_nets IN8 A8\n"
+ "match_nets OUT7 Q7\n"
+ "match_nets IN7 A7\n"
+ "match_nets OUT6 Q6\n"
+ "match_nets IN6 A6\n"
+ "match_nets OUT5 Q5\n"
+ "match_nets IN5 A5\n"
+ "match_nets OUT4 Q4\n"
+ "match_nets IN4 A4\n"
+ "match_nets OUT3 Q3\n"
+ "match_nets IN3 A3\n"
+ "match_nets OUT2 Q2\n"
+ "match_nets IN2 A2\n"
+ "match_nets OUT1 Q1\n"
+ "match_nets IN1 A1\n"
"match_pins IN1 A1\n"
"match_pins OUT1 Q1\n"
"match_pins IN2 A2\n"
diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb
index 978e6c723..1fa342e52 100644
--- a/src/drc/drc/built-in-macros/_drc_netter.rb
+++ b/src/drc/drc/built-in-macros/_drc_netter.rb
@@ -64,10 +64,8 @@ module DRC
def initialize(engine)
@engine = engine
- @connect_implicit = []
- @connect_implicit_per_cell = {}
- @connect_explicit = []
- @connect_explicit_per_cell = {}
+ @pre_extract_config = []
+ @post_extract_config = []
@l2n = nil
@lnum = 0
@device_scaling = 1.0
@@ -239,10 +237,8 @@ module DRC
# See \connect for more details.
def clear_connections
- @connect_implicit = []
- @connect_implicit_per_cell = {}
- @connect_explicit = []
- @connect_explicit_per_cell = {}
+ @pre_extract_config = []
+ @post_extract_config = []
_clear_data
end
@@ -277,11 +273,10 @@ module DRC
if arg2
(arg2.is_a?(String) && arg2 != "") || raise("The second argument has to be a non-empty string")
arg1.is_a?(String) || raise("The first argument has to be a string")
- @connect_implicit_per_cell[arg1] ||= []
- @connect_implicit_per_cell[arg1] << arg2
+ @pre_extract_config << lambda { |l2n| l2n.join_net_names(arg1, arg2) }
else
arg1.is_a?(String) || raise("The argument has to be a string")
- @connect_implicit << arg1
+ @pre_extract_config << lambda { |l2n| l2n.join_net_names(arg1) }
end
end
@@ -338,11 +333,10 @@ module DRC
arg2.is_a?(Array) || raise("The second argument has to be an array of strings")
arg2.find { |a| !a.is_a?(String) } && raise("The second argument has to be an array of strings")
arg1.is_a?(String) || raise("The first argument has to be a string")
- @connect_explicit_per_cell[arg1] ||= []
- @connect_explicit_per_cell[arg1] << arg2
+ @pre_extract_config << lambda { |l2n| l2n.join_nets(arg1, arg2) }
else
arg1.is_a?(String) || raise("The argument has to be a string")
- @connect_explicit << arg1
+ @pre_extract_config << lambda { |l2n| l2n.join_nets(arg1) }
end
end
@@ -563,30 +557,21 @@ module DRC
# run extraction in a timed environment
if ! @l2n.is_extracted?
- # configure implicit net connections
@l2n.clear_join_net_names
- @connect_implicit.each do |label_pattern|
- @l2n.join_net_names(label_pattern)
- end
- @connect_implicit_per_cell.each do |cell_pattern,label_pattern|
- label_pattern.each do |lp|
- @l2n.join_net_names(cell_pattern, lp)
- end
- end
-
- # configure explicit net connections
@l2n.clear_join_nets
- @connect_explicit.each do |names|
- @l2n.join_nets(names)
- end
- @connect_explicit_per_cell.each do |cell_pattern,name_lists|
- name_lists.each do |names|
- @l2n.join_nets(cell_pattern, names)
- end
+
+ # configure the netter
+ @pre_extract_config.each do |cfg|
+ cfg.call(@l2n)
end
@engine._cmd(@l2n, :extract_netlist)
+ # configure the netter, post-extraction
+ @post_extract_config.each do |cfg|
+ cfg.call(@l2n)
+ end
+
end
@l2n
diff --git a/src/lay/lay/doc/about/lvs_ref_global.xml b/src/lay/lay/doc/about/lvs_ref_global.xml
index f854e06e6..ab05ff346 100644
--- a/src/lay/lay/doc/about/lvs_ref_global.xml
+++ b/src/lay/lay/doc/about/lvs_ref_global.xml
@@ -28,6 +28,15 @@ For more details about the DRC functions see
See Netter#align for a description of that function.
+"blank_circuit" - Removes the content from the given circuits (blackboxing)
+
+Usage:
+
+- blank_circuit(circuit_filter)
+
+
+See Netter#blank_circuit for a description of that function.
+
"compare" - Compares the extracted netlist vs. the schematic
Usage:
@@ -152,12 +161,24 @@ See Netter#same_device_c
Usage:
-- same_nets(circuit, net_a, net_b)
+- same_nets(circuit_pattern, net_pattern)
+- same_nets(circuit_pattern, net_a, net_b)
- same_nets(circuit_a, net_a, circuit_b, net_b)
See Netter#same_nets for a description of that function.
+"same_nets!" - Establishes an equivalence between the nets (must match)
+
+Usage:
+
+- same_nets!(circuit_pattern, net_pattern)
+- same_nets!(circuit_pattern, net_a, net_b)
+- same_nets!(circuit_a, net_a, circuit_b, net_b)
+
+
+See Netter#same_nets! for a description of that function.
+
"schematic" - Reads the reference netlist
Usage:
diff --git a/src/lay/lay/doc/about/lvs_ref_netter.xml b/src/lay/lay/doc/about/lvs_ref_netter.xml
index 04244ff71..4b33f3fe5 100644
--- a/src/lay/lay/doc/about/lvs_ref_netter.xml
+++ b/src/lay/lay/doc/about/lvs_ref_netter.xml
@@ -68,6 +68,36 @@ are other (explicit) ways to flatten circuits.
Please note that flattening circuits has some side effects such
as loss of details in the cross reference and net layout.
+"blank_circuit" - Removes the content from the given circuits (blackboxing)
+
+Usage:
+
+- blank_circuit(circuit_filter)
+
+
+This method will erase all content from the circuits matching the filter.
+The filter is a glob expression.
+
+This has the following effects:
+
+
+- The circuits are no longer compared (netlist vs. schematic)
+- Named pins are required to match (use labels on the nets to name pins in the layout)
+- Unnamed pins are treated as equivalent and can be swapped
+- The selected circuits will not be purged on netlist simplification
+
+
+Using this method can be useful to reduce the verification overhead for
+blocks which are already verifified by other ways or for which no schematic
+is available - e.g. hard macros.
+
+Example:
+
+
+# skips all MEMORY* circuits from compare
+blank_circuit("MEMORY*")
+
+
"compare" - Compares the extracted netlist vs. the schematic
Usage:
@@ -289,7 +319,8 @@ Use this method andwhere in the script before the compare
Usage:
-- same_nets(circuit, net_a, net_b)
+- same_nets(circuit_pattern, net_pattern)
+- same_nets(circuit_pattern, net_a, net_b)
- same_nets(circuit_a, net_a, circuit_b, net_b)
@@ -297,8 +328,17 @@ This method will force an equivalence between the net_a and net_b from circuit_a
and circuit_b (circuit in the three-argument form is for both circuit_a and circuit_b).
In the four-argument form, the circuits can be either given by name or as Circuit
-objects. In the three-argument form, the circuit has to be given by name.
+objects. In the three-argument form, the circuits have to be given by name pattern.
Nets can be either given by name or as Net objects.
+In the two-argument form, the circuits and nets have to be given as name pattern.
+
+"name pattern" are glob-style pattern - e.g. the following will identify the
+all nets starting with "A" from the extracted netlist with the same net from
+the schematic netlist for all circuits starting with "INV":
+
+
+same_nets("INV*", "A*")
+
After using this function, the compare algorithm will consider these nets equivalent.
Use this method to provide hints for the comparer in cases which are difficult to
@@ -309,6 +349,18 @@ Names are case sensitive for layout-derived netlists and case-insensitive for SP
Use this method andwhere in the script before the compare call.
+"same_nets!" - Establishes an equivalence between the nets with matching requirement
+
+Usage:
+
+- same_nets!(circuit_pattern, net_pattern)
+- same_nets!(circuit_pattern, net_a, net_b)
+- same_nets!(circuit_a, net_a, circuit_b, net_b)
+
+
+This method is equivalent to same_nets, but requires identity of the given nets.
+If the specified nets do not match, an error is reported.
+
"schematic" - Gets, sets or reads the reference netlist
Usage:
diff --git a/src/lay/lay/doc/manual/lvs_compare.xml b/src/lay/lay/doc/manual/lvs_compare.xml
index d5de64f78..5b3fe3073 100644
--- a/src/lay/lay/doc/manual/lvs_compare.xml
+++ b/src/lay/lay/doc/manual/lvs_compare.xml
@@ -52,7 +52,44 @@
- For more information about "same_nets" see same_nets.
+ "same_nets" can also be used to require a matching between specific nets.
+ This is useful on top level to check for matching nets assigned to specific pads.
+ This allows checking correct pad assignment. For example to check whether the
+ same net is attached to the "VDD" pad, label the net "VDD" in the layout and
+ specify:
+
+
+ same_nets!("CHIP", "VDD", "VDD")
+
+
+ The exclamation-mark version will report a net mismatch if either there is no
+ "VDD" net in either layout or schematic or if these nets to not match.
+ The above specification can be abbreviated as layout and schematic net name are identical:
+
+
+ same_nets!("CHIP", "VDD")
+
+
+ It's also possible to specify pattern for circuit names or net names.
+ This example requires all nets starting with "PAD" to have a counterpart
+ in layout and schematic for circuit "TOP" and each of these pairs has to match:
+
+
+ same_nets!("TOP", "PAD*")
+
+
+ So it is an error if there is a PAD1 net in layout but none in the schematic.
+ It is also an error if a net called PAD2 is there is layout and schematic but they
+ do not match.
+
+
+
+ "same_nets" and "same_nets!" can appear anywhere in the LVS script.
+
+
+
+ For more information about "same_nets" see same_nets and
+ same_nets!.
Circuit equivalence hint
diff --git a/src/lay/lay/doc/manual/lvs_tweaks.xml b/src/lay/lay/doc/manual/lvs_tweaks.xml
index 12e4b0bf5..6a8d505f9 100644
--- a/src/lay/lay/doc/manual/lvs_tweaks.xml
+++ b/src/lay/lay/doc/manual/lvs_tweaks.xml
@@ -153,10 +153,11 @@
A useful method in this context is the "blank_circuit" method. It clears
- a circuit's innards and leaves only the pins. You can use this method to
- ensure abstracts in both the layout netlist and the schematic. After this,
+ a circuit's innards from a netlist. After this,
the compare algorithm will identify both circuits as identical, provided
- they feature the same number of pins.
+ they feature the same number of pins. Named pins are required to match exactly
+ unless declared equivalent. Unnamed pins are treated as equivalent. To name
+ pins use labels on the pin's nets inside the circuit's layout.
@@ -166,14 +167,20 @@
netlist.blank_circuit("CIRCUIT_NAME")
schematic.blank_circuit("CIRCUIT_NAME")
+ NOTE: In this version, use "blank_circuit" before "purge" or "simplify" (see below). "blank_circuit"
+ sets a flag () which prevents purging of abstract circuits.
+
- The argument to "blank_circuit" is a glob pattern (shell-like).
- For example, "MEMORY*" will blank out all circuits starting with "MEMORY".
+ There is a short form for this too (blank_circuit).
+ In contrast to netlist-based "blank_circuit", this method can be used anywhere in the LVS script:
- NOTE: Use "blank_circuit" before "purge" or "simplify" (see below). This method
- sets a flag () which prevents purging of abstract
- circuits.
+ blank_circuit("CIRCUIT_NAME")
+
+
+ The argument to "blank_circuit" in both cases is a glob pattern (shell-like).
+ For example, "MEMORY*" will blank out all circuits starting with the word "MEMORY".
+
Joining of symmetric nodes
@@ -201,8 +208,8 @@ schematic.blank_circuit("CIRCUIT_NAME")
- KLayout provides a feature which will add such connections after extraction
- of the netlist:
+ KLayout provides a feature (join_symmetric_nets)
+ which will add such connections after extraction of the netlist:
join_symmetric_nets("NAND2")
@@ -221,6 +228,10 @@ schematic.blank_circuit("CIRCUIT_NAME")
need it.
+
+ "join_symmetric_nets" can be used anywhere in the LVS script.
+
+
Purging (elimination of redundancy)
diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc
index b160ac73a..5def404a6 100644
--- a/src/laybasic/laybasic/layNetlistBrowserModel.cc
+++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc
@@ -233,11 +233,11 @@ static QString escaped (const std::string &s)
}
template
-static std::string str_from_expanded_name (const Obj *obj, bool dash_for_empty = false)
+static std::string str_from_expanded_name (const Obj *obj, bool indicate_empty = false)
{
if (obj) {
return obj->expanded_name ();
- } else if (dash_for_empty) {
+ } else if (indicate_empty) {
return std::string ("-");
} else {
return std::string ();
@@ -245,11 +245,11 @@ static std::string str_from_expanded_name (const Obj *obj, bool dash_for_empty =
}
template
-static std::string str_from_name (const Obj *obj, bool dash_for_empty = false)
+static std::string str_from_name (const Obj *obj, bool indicate_empty = false)
{
if (obj) {
return obj->name ();
- } else if (dash_for_empty) {
+ } else if (indicate_empty) {
return std::string ("-");
} else {
return std::string ();
@@ -264,7 +264,7 @@ static std::string str_from_expanded_names (const std::pair &ob
std::string s = str_from_name (objs.first, ! is_single);
if (! is_single) {
std::string t = str_from_name (objs.second, ! is_single);
- if (t != s) {
+ if (t != s || ! objs.first || ! objs.second) {
s += var_sep;
s += t;
}
diff --git a/src/lvs/lvs/built-in-macros/_lvs_engine.rb b/src/lvs/lvs/built-in-macros/_lvs_engine.rb
index f53bfcc72..3a0506516 100644
--- a/src/lvs/lvs/built-in-macros/_lvs_engine.rb
+++ b/src/lvs/lvs/built-in-macros/_lvs_engine.rb
@@ -100,6 +100,12 @@ module LVS
# @synopsis join_symmetric_nets(circuit_filter)
# See \Netter#join_symmetric_nets for a description of that function.
+ # %LVS%
+ # @name blank_circuit
+ # @brief Removes the content from the given circuits (blackboxing)
+ # @synopsis blank_circuit(circuit_filter)
+ # See \Netter#blank_circuit for a description of that function.
+
# %LVS%
# @name align
# @brief Aligns the extracted netlist vs. the schematic by flattening circuits where required
@@ -109,10 +115,19 @@ module LVS
# %LVS%
# @name same_nets
# @brief Establishes an equivalence between the nets
- # @synopsis same_nets(circuit, net_a, net_b)
+ # @synopsis same_nets(circuit_pattern, net_pattern)
+ # @synopsis same_nets(circuit_pattern, net_a, net_b)
# @synopsis same_nets(circuit_a, net_a, circuit_b, net_b)
# See \Netter#same_nets for a description of that function.
+ # %LVS%
+ # @name same_nets!
+ # @brief Establishes an equivalence between the nets (must match)
+ # @synopsis same_nets!(circuit_pattern, net_pattern)
+ # @synopsis same_nets!(circuit_pattern, net_a, net_b)
+ # @synopsis same_nets!(circuit_a, net_a, circuit_b, net_b)
+ # See \Netter#same_nets! for a description of that function.
+
# %LVS%
# @name same_circuits
# @brief Establishes an equivalence between the circuits
@@ -168,7 +183,7 @@ module LVS
# @synopsis tolerance(device_class_name, parameter_name [, :absolute => absolute_tolerance] [, :relative => relative_tolerance])
# See \Netter#tolerance for a description of that function.
- %w(schematic compare join_symmetric_nets tolerance align same_nets same_circuits same_device_classes equivalent_pins min_caps max_res max_depth max_branch_complexity consider_net_names).each do |f|
+ %w(schematic compare join_symmetric_nets tolerance blank_circuit align same_nets same_nets! same_circuits same_device_classes equivalent_pins min_caps max_res max_depth max_branch_complexity consider_net_names).each do |f|
eval <<"CODE"
def #{f}(*args)
_netter.#{f}(*args)
diff --git a/src/lvs/lvs/built-in-macros/_lvs_netter.rb b/src/lvs/lvs/built-in-macros/_lvs_netter.rb
index ca20ae82f..5c34685a3 100644
--- a/src/lvs/lvs/built-in-macros/_lvs_netter.rb
+++ b/src/lvs/lvs/built-in-macros/_lvs_netter.rb
@@ -49,6 +49,7 @@ module LVS
def initialize(engine)
super
@comparer_config = []
+ @comparer_miniconfig = []
end
def _make_data
@@ -140,7 +141,18 @@ module LVS
abs_tol ||= 0.0
rel_tol ||= 0.0
- dc = netlist.device_class_by_name(device_class_name)
+ if self._l2n_data
+ # already extracted
+ self._tolerance(self._l2n_data, device_class_name, parameter_name, abs_tol, rel_tol)
+ else
+ @post_extract_config << lambda { |l2n| self._tolerance(l2n, device_class_name, parameter_name, abs_tol, rel_tol) }
+ end
+
+ end
+
+ def _tolerance(l2n, device_class_name, parameter_name, abs_tol, rel_tol)
+
+ dc = l2n.netlist.device_class_by_name(device_class_name)
if dc && dc.has_parameter?(parameter_name)
ep = RBA::EqualDeviceParameters::new(dc.parameter_id(parameter_name), abs_tol, rel_tol)
if dc.equal_parameters == nil
@@ -250,13 +262,74 @@ module LVS
circuit_pattern.is_a?(String) || raise("Circuit pattern argument of 'join_symmetric_nets' must be a string")
- comparer = self._comparer
+ if self._l2n_data
+ # already extracted
+ self._join_symmetric_nets(self._l2n_data, circuit_pattern)
+ else
+ @post_extract_config << lambda { |l2n| self._join_symmetric_nets(l2n, circuit_pattern) }
+ end
- netlist || raise("No netlist present (not extracted?)")
- netlist.circuits_by_name(circuit_pattern).each do |c|
+ end
+
+ def _join_symmetric_nets(l2n, circuit_pattern)
+
+ comparer = self._comparer_mini
+
+ l2n.netlist.circuits_by_name(circuit_pattern).each do |c|
comparer.join_symmetric_nets(c)
end
+ comparer._destroy
+
+ end
+
+ # %LVS%
+ # @name blank_circuit
+ # @brief Removes the content from the given circuits (blackboxing)
+ # @synopsis blank_circuit(circuit_filter)
+ # This method will erase all content from the circuits matching the filter.
+ # The filter is a glob expression.
+ #
+ # This has the following effects:
+ #
+ # @ul
+ # @li The circuits are no longer compared (netlist vs. schematic) @/li
+ # @li Named pins are required to match (use labels on the nets to name pins in the layout) @/li
+ # @li Unnamed pins are treated as equivalent and can be swapped @/li
+ # @li The selected circuits will not be purged on netlist simplification @/li
+ # @/ul
+ #
+ # Using this method can be useful to reduce the verification overhead for
+ # blocks which are already verifified by other ways or for which no schematic
+ # is available - e.g. hard macros.
+ #
+ # Example:
+ #
+ # @code
+ # # skips all MEMORY* circuits from compare
+ # blank_circuit("MEMORY*")
+ # @/code
+
+ def blank_circuit(circuit_pattern)
+
+ circuit_pattern.is_a?(String) || raise("Circuit pattern argument of 'blank_circuit' must be a string")
+
+ if self._l2n_data
+ # already extracted
+ self._blank_circuit(self._l2n_data, circuit_pattern)
+ else
+ @post_extract_config << lambda { |l2n| self._blank_circuit(l2n, circuit_pattern) }
+ end
+
+ end
+
+ def _blank_circuit(l2n, circuit_pattern)
+
+ (n, s) = _ensure_two_netlists
+
+ n.blank_circuit(circuit_pattern)
+ s.blank_circuit(circuit_pattern)
+
end
def _comparer
@@ -272,6 +345,19 @@ module LVS
end
+ def _comparer_mini
+
+ comparer = RBA::NetlistComparer::new
+
+ # execute the configuration commands
+ @comparer_miniconfig.each do |cc|
+ cc.call(comparer)
+ end
+
+ return comparer
+
+ end
+
def _ensure_two_netlists
netlist || raise("No netlist present (not extracted?)")
@@ -284,14 +370,24 @@ module LVS
# %LVS%
# @name same_nets
# @brief Establishes an equivalence between the nets
- # @synopsis same_nets(circuit, net_a, net_b)
+ # @synopsis same_nets(circuit_pattern, net_pattern)
+ # @synopsis same_nets(circuit_pattern, net_a, net_b)
# @synopsis same_nets(circuit_a, net_a, circuit_b, net_b)
# This method will force an equivalence between the net_a and net_b from circuit_a
# and circuit_b (circuit in the three-argument form is for both circuit_a and circuit_b).
- #
+ #
# In the four-argument form, the circuits can be either given by name or as Circuit
- # objects. In the three-argument form, the circuit has to be given by name.
+ # objects. In the three-argument form, the circuits have to be given by name pattern.
# Nets can be either given by name or as Net objects.
+ # In the two-argument form, the circuits and nets have to be given as name pattern.
+ #
+ # "name pattern" are glob-style pattern - e.g. the following will identify the
+ # all nets starting with "A" from the extracted netlist with the same net from
+ # the schematic netlist for all circuits starting with "INV":
+ #
+ # @code
+ # same_nets("INV*", "A*")
+ # @/code
#
# After using this function, the compare algorithm will consider these nets equivalent.
# Use this method to provide hints for the comparer in cases which are difficult to
@@ -303,65 +399,127 @@ module LVS
# Use this method andwhere in the script before the \compare call.
def same_nets(*args)
+ _same_nets_impl(false, *args)
+ end
- if args.size < 3
- raise("Too few arguments to 'same_nets' (need at least 3)")
+ # %LVS%
+ # @name same_nets!
+ # @brief Establishes an equivalence between the nets with matching requirement
+ # @synopsis same_nets!(circuit_pattern, net_pattern)
+ # @synopsis same_nets!(circuit_pattern, net_a, net_b)
+ # @synopsis same_nets!(circuit_a, net_a, circuit_b, net_b)
+ # This method is equivalent to \same_nets, but requires identity of the given nets.
+ # If the specified nets do not match, an error is reported.
+
+ def same_nets!(*args)
+ _same_nets_impl(true, *args)
+ end
+
+ def _same_nets_impl(force, *args)
+
+ if args.size < 2
+ raise("Too few arguments to 'same_nets' (need at least 2)")
end
if args.size > 4
raise("Too many arguments to 'same_nets' (need max 4)")
end
if args.size == 3
- ( ca, a, b ) = args
- cb = ca
+ ( ca, a ) = args
+ cb = nil
ca.is_a?(String) || raise("Circuit argument of 'same_nets' must be a string")
+ b = nil
+ a.is_a?(String) || raise("Net argument of 'same_nets' must be a string")
+ elsif args.size == 3
+ ( ca, a, b ) = args
+ cb = nil
+ ca.is_a?(String) || raise("Circuit argument of 'same_nets' must be a string")
+ [ a, b ].each do |n|
+ n.is_a?(String) || n.is_a?(RBA::Net) || raise("Net arguments of 'same_nets' must be strings or Net objects")
+ end
else
( ca, a, cb, b ) = args
[ ca, cb ].each do |n|
- n.is_a?(String) || n.is_a?(RBA::Net) || raise("Circuit arguments of 'same_nets' must be strings or Net objects")
+ n.is_a?(String) || n.is_a?(RBA::Circuit) || raise("Circuit arguments of 'same_nets' must be strings or Circuit objects")
+ end
+ [ a, b ].each do |n|
+ n.is_a?(String) || n.is_a?(RBA::Net) || raise("Net arguments of 'same_nets' must be strings or Net objects")
end
end
- [ a, b ].each do |n|
- n.is_a?(String) || n.is_a?(RBA::Net) || raise("Net arguments of 'same_nets' must be strings or Net objects")
- end
-
- @comparer_config << lambda { |comparer| self._same_nets(comparer, ca, a, cb, b) }
+ @comparer_config << lambda { |comparer| self._same_nets(comparer, ca, a, cb, b, force) }
end
- def _same_nets(comparer, ca, a, cb, b)
+ def _same_nets(comparer, ca, a, cb, b, force)
( nl_a, nl_b ) = _ensure_two_netlists
- if ca.is_a?(String)
- circuit_a = nl_a.circuit_by_name(ca)
+ cs = !(nl_a.is_case_sensitive? && nl_b.is_case_sensitive?)
+
+ if ca.is_a?(String) && !cb
+
+ n2c = {}
+ nl_a.circuits_by_name(ca).each { |c| name = cs ? c.name.upcase : c.name; n2c[name] ||= [ nil, nil ]; n2c[name][0] = c }
+ nl_b.circuits_by_name(ca).each { |c| name = cs ? c.name.upcase : c.name; n2c[name] ||= [ nil, nil ]; n2c[name][1] = c }
+
+ circuits = []
+ n2c.keys.sort.each do |n|
+ if n2c[n][0] && n2c[n][1]
+ circuits << n2c[n]
+ end
+ end
+
else
- circuit_a = ca
- end
- if cb.is_a?(String)
- circuit_b = nl_b.circuit_by_name(cb)
- else
- circuit_b = cb
- end
+ circuit_a = ca.is_a?(String) ? nl_a.circuit_by_name(ca) : ca
+ circuit_b = cb.is_a?(String) ? nl_b.circuit_by_name(cb) : cb
- if circuit_a && circuit_b
-
- if a.is_a?(String)
- net_a = circuit_a.net_by_name(a) || raise("Not a valid net name in extracted netlist in 'same_nets': #{a} (for circuit #{circuit_a})")
- else
- net_a = a
+ circuits = []
+ if circuit_a && circuit_b
+ circuits << [ circuit_a, circuit_b ]
end
- if b.is_a?(String)
- net_b = circuit_b.net_by_name(b) || raise("Not a valid net name in extracted netlist in 'same_nets': #{b} (for circuit #{circuit_b})")
+ end
+
+ circuits.each do |circuit_a, circuit_b|
+
+ if a.is_a?(String) && !b
+
+ n2n = {}
+ circuit_a.nets_by_name(a).each { |n| name = cs ? n.name.upcase : n.name; n2n[name] ||= [ nil, nil ]; n2n[name][0] = n }
+ circuit_b.nets_by_name(a).each { |n| name = cs ? n.name.upcase : n.name; n2n[name] ||= [ nil, nil ]; n2n[name][1] = n }
+
+ nets = []
+ n2n.keys.sort.each do |n|
+ if force || (n2n[n][0] && n2n[n][1])
+ nets << n2n[n]
+ end
+ end
+
else
- net_b = b
+
+ if a.is_a?(String)
+ net_a = circuit_a.net_by_name(a) || raise("Not a valid net name in extracted netlist in 'same_nets': #{a} (for circuit #{circuit_a})")
+ else
+ net_a = a
+ end
+
+ if b.is_a?(String)
+ net_b = circuit_b.net_by_name(b) || raise("Not a valid net name in extracted netlist in 'same_nets': #{b} (for circuit #{circuit_b})")
+ else
+ net_b = b
+ end
+
+ nets = []
+ if net_a && net_b
+ nets << [ net_a, net_b ]
+ end
+
end
- if net_a && net_b
- comparer.same_nets(net_a, net_b)
+ nets.each do |net_a, net_b|
+ comparer.same_nets(circuit_a, circuit_b, net_a, net_b, force)
end
end
@@ -589,6 +747,7 @@ module LVS
def min_caps(value)
v = value.to_f
@comparer_config << lambda { |comparer| comparer.min_capacitance = v }
+ @comparer_miniconfig << lambda { |comparer| comparer.min_capacitance = v }
end
# %LVS%
@@ -601,6 +760,7 @@ module LVS
def max_res(value)
v = value.to_f
@comparer_config << lambda { |comparer| comparer.max_resistance = v }
+ @comparer_miniconfig << lambda { |comparer| comparer.max_resistance = v }
end
# %LVS%
diff --git a/src/lvs/unit_tests/lvsSimpleTests.cc b/src/lvs/unit_tests/lvsSimpleTests.cc
index 6d054e461..d6fdec334 100644
--- a/src/lvs/unit_tests/lvsSimpleTests.cc
+++ b/src/lvs/unit_tests/lvsSimpleTests.cc
@@ -86,6 +86,11 @@ TEST(1b_simple_with_tolerance)
run_test (_this, "ringo_simple_with_tol", "ringo.gds");
}
+TEST(1c_simple_with_tolerance_early)
+{
+ run_test (_this, "ringo_simple_with_tol_early", "ringo.gds");
+}
+
TEST(2_simple_io)
{
run_test (_this, "ringo_simple_io", "ringo.gds");
@@ -130,6 +135,11 @@ TEST(9_blackboxing)
run_test (_this, "ringo_simple_blackboxing", "ringo_for_blackboxing.gds");
}
+TEST(9b_blackboxing_netter)
+{
+ run_test (_this, "ringo_simple_blackboxing_netter", "ringo_for_blackboxing.gds");
+}
+
TEST(10_simplification_with_align)
{
run_test (_this, "ringo_simple_simplification_with_align", "ringo_for_simplification.gds");
@@ -200,6 +210,11 @@ TEST(22_split_gate)
run_test (_this, "nand2_split_gate", "nand2_split_gate.oas");
}
+TEST(22b_split_gate_early)
+{
+ run_test (_this, "nand2_split_gate_early", "nand2_split_gate.oas");
+}
+
// empty gds
TEST(23_issue709)
{
@@ -211,3 +226,12 @@ TEST(24_issue806)
{
run_test (_this, "custom_compare", "custom_compare.gds");
}
+
+TEST(25_blackbox)
+{
+ run_test (_this, "blackbox1", "blackbox.gds");
+ run_test (_this, "blackbox2", "blackbox_swapped.gds");
+ run_test (_this, "blackbox3", "blackbox_open.gds");
+ run_test (_this, "blackbox4", "blackbox_short.gds");
+ run_test (_this, "blackbox5", "blackbox_short_and_open.gds");
+}
diff --git a/testdata/drc/drcSimpleTests_au9a.cir b/testdata/drc/drcSimpleTests_au9a.cir
index 8d0e86af5..b106c0428 100644
--- a/testdata/drc/drcSimpleTests_au9a.cir
+++ b/testdata/drc/drcSimpleTests_au9a.cir
@@ -119,9 +119,9 @@ M$2 3 5 2 7 LVNMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
* cell TIE
* pin VDD
* pin BULK,VSS
-.SUBCKT TIE 2 3
-* net 2 VDD
-* net 3 BULK,VSS
+.SUBCKT TIE 1 2
+* net 1 VDD
+* net 2 BULK,VSS
.ENDS TIE
* cell EMPTY
diff --git a/testdata/lvs/blackbox.gds b/testdata/lvs/blackbox.gds
new file mode 100644
index 000000000..27ad3ab86
Binary files /dev/null and b/testdata/lvs/blackbox.gds differ
diff --git a/testdata/lvs/blackbox1.cir b/testdata/lvs/blackbox1.cir
new file mode 100644
index 000000000..f8fb8eeb8
--- /dev/null
+++ b/testdata/lvs/blackbox1.cir
@@ -0,0 +1,27 @@
+* Extracted by KLayout
+
+* cell TOP
+.SUBCKT TOP
+* net 1 3
+* net 2 4
+* net 3 2
+* net 4 1
+* net 5 8
+* net 6 7
+* net 7 5
+* net 8 6
+* cell instance $1 r0 *1 0,0
+X$1 1 2 7 3 4 5 8 6 CHIP
+.ENDS TOP
+
+* cell CHIP
+* pin pad3
+* pin pad4
+* pin pad5
+* pin pad2
+* pin pad1
+* pin pad8
+* pin pad6
+* pin pad7
+.SUBCKT CHIP 1 2 3 4 5 6 7 8
+.ENDS CHIP
diff --git a/testdata/lvs/blackbox1.lvs b/testdata/lvs/blackbox1.lvs
new file mode 100644
index 000000000..9b20bc4d6
--- /dev/null
+++ b/testdata/lvs/blackbox1.lvs
@@ -0,0 +1,22 @@
+source($lvs_test_source)
+report_lvs($lvs_test_target_lvsdb, true)
+target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
+
+schematic("blackbox_schematic.cir")
+
+deep
+
+same_nets!("TOP", "*", "*")
+
+m1 = input(1, 0)
+via = input(2, 0)
+m2 = input(3, 0)
+pad = input(10, 0)
+
+connect(m1, pad)
+connect(m1, via)
+connect(via, m2)
+
+blank_circuit("CHIP")
+
+compare
diff --git a/testdata/lvs/blackbox1.lvsdb b/testdata/lvs/blackbox1.lvsdb
new file mode 100644
index 000000000..a9012c999
--- /dev/null
+++ b/testdata/lvs/blackbox1.lvsdb
@@ -0,0 +1,196 @@
+#%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(l1 '1/0')
+ layer(l3 '2/0')
+ layer(l4 '3/0')
+ layer(l2 '10/0')
+
+ # Mask layer connectivity
+ connect(l1 l1 l3 l2)
+ connect(l3 l1 l3 l4)
+ connect(l4 l3 l4)
+ connect(l2 l1 l2)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(CHIP
+
+ # Circuit boundary
+ rect((-4000 -6000) (11000 9000))
+
+ # Outgoing pins and their connections to nets
+ pin(name(pad3))
+ pin(name(pad4))
+ pin(name(pad5))
+ pin(name(pad2))
+ pin(name(pad1))
+ pin(name(pad8))
+ pin(name(pad6))
+ pin(name(pad7))
+
+ )
+ circuit(TOP
+
+ # Circuit boundary
+ rect((-18500 -14000) (44500 28000))
+
+ # Nets with their geometries
+ net(1 name('3')
+ rect(l1 (-10500 2000) (7500 1000))
+ rect(l1 (-7500 0) (1000 4000))
+ rect(l1 (-6000 0) (6000 1000))
+ rect(l1 (-9000 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (12499 -5501) (1000 1000))
+ )
+ net(2 name('4')
+ rect(l1 (1000 2000) (1000 10000))
+ rect(l1 (-17500 0) (17500 1000))
+ rect(l1 (-20500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (17499 -10501) (1000 1000))
+ )
+ net(3 name('2')
+ rect(l1 (-15500 -2000) (12500 1000))
+ rect(l1 (-15500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (12499 -501) (1000 1000))
+ )
+ net(4 name('1')
+ rect(l1 (-15500 -13000) (6000 1000))
+ rect(l1 (-1000 0) (1000 6000))
+ rect(l1 (-9000 -8000) (3500 3000))
+ rect(l1 (4500 5000) (7500 1000))
+ rect(l1 (-13501 -7501) (2 2))
+ rect(l2 (12499 6499) (1000 1000))
+ )
+ net(5 name('8')
+ rect(l1 (1000 -13000) (22000 1000))
+ rect(l1 (-22000 0) (1000 7000))
+ rect(l1 (20500 -9000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (-23501 6499) (1000 1000))
+ )
+ net(6 name('7')
+ rect(l1 (6000 -6000) (7000 1000))
+ rect(l1 (-1000 0) (1000 12000))
+ rect(l1 (-1000 0) (11000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (-18501 -13501) (1000 1000))
+ )
+ net(7 name('5')
+ rect(l1 (6000 2000) (1000 10000))
+ rect(l1 (-1000 0) (17000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (-18501 -10501) (1000 1000))
+ )
+ net(8 name('6')
+ rect(l1 (16000 -2000) (7000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l1 (-18501 -501) (3500 1000))
+ rect(l3 (6500 -1000) (1000 1000))
+ rect(l3 (-8500 -1000) (1000 1000))
+ rect(l4 (-1000 -1000) (8500 1000))
+ rect(l2 (-11000 -1000) (1000 1000))
+ )
+
+ # Subcircuits and their connections
+ circuit(1 CHIP location(0 0)
+ pin(0 1)
+ pin(1 2)
+ pin(2 7)
+ pin(3 3)
+ pin(4 4)
+ pin(5 5)
+ pin(6 8)
+ pin(7 6)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(CHIP
+
+ # Outgoing pins and their connections to nets
+ pin(name(PAD1))
+ pin(name(PAD2))
+ pin(name(PAD3))
+ pin(name(PAD4))
+ pin(name(PAD5))
+ pin(name(PAD6))
+ pin(name(PAD7))
+ pin(name(PAD8))
+
+ )
+ circuit(TOP
+
+ # Nets
+ net(1 name('1'))
+ net(2 name('2'))
+ net(3 name('3'))
+ net(4 name('4'))
+ net(5 name('5'))
+ net(6 name('6'))
+ net(7 name('7'))
+ net(8 name('8'))
+
+ # Subcircuits and their connections
+ circuit(1 CHIP name('1')
+ pin(0 1)
+ pin(1 2)
+ pin(2 3)
+ pin(3 4)
+ pin(4 5)
+ pin(5 6)
+ pin(6 7)
+ pin(7 8)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(CHIP CHIP match
+ xref(
+ pin(4 0 match)
+ pin(3 1 match)
+ pin(0 2 match)
+ pin(1 3 match)
+ pin(2 4 match)
+ pin(6 5 match)
+ pin(7 6 match)
+ pin(5 7 match)
+ )
+ )
+ circuit(TOP TOP match
+ xref(
+ net(4 1 match)
+ net(3 2 match)
+ net(1 3 match)
+ net(2 4 match)
+ net(7 5 match)
+ net(8 6 match)
+ net(6 7 match)
+ net(5 8 match)
+ circuit(1 1 match)
+ )
+ )
+)
diff --git a/testdata/lvs/blackbox2.cir b/testdata/lvs/blackbox2.cir
new file mode 100644
index 000000000..6b3a67d15
--- /dev/null
+++ b/testdata/lvs/blackbox2.cir
@@ -0,0 +1,27 @@
+* Extracted by KLayout
+
+* cell TOP
+.SUBCKT TOP
+* net 1 4
+* net 2 3
+* net 3 2
+* net 4 1
+* net 5 8
+* net 6 7
+* net 7 5
+* net 8 6
+* cell instance $1 r0 *1 0,0
+X$1 1 2 7 3 4 5 8 6 CHIP
+.ENDS TOP
+
+* cell CHIP
+* pin pad3
+* pin pad4
+* pin pad5
+* pin pad2
+* pin pad1
+* pin pad8
+* pin pad6
+* pin pad7
+.SUBCKT CHIP 1 2 3 4 5 6 7 8
+.ENDS CHIP
diff --git a/testdata/lvs/blackbox2.lvs b/testdata/lvs/blackbox2.lvs
new file mode 100644
index 000000000..9b20bc4d6
--- /dev/null
+++ b/testdata/lvs/blackbox2.lvs
@@ -0,0 +1,22 @@
+source($lvs_test_source)
+report_lvs($lvs_test_target_lvsdb, true)
+target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
+
+schematic("blackbox_schematic.cir")
+
+deep
+
+same_nets!("TOP", "*", "*")
+
+m1 = input(1, 0)
+via = input(2, 0)
+m2 = input(3, 0)
+pad = input(10, 0)
+
+connect(m1, pad)
+connect(m1, via)
+connect(via, m2)
+
+blank_circuit("CHIP")
+
+compare
diff --git a/testdata/lvs/blackbox2.lvsdb b/testdata/lvs/blackbox2.lvsdb
new file mode 100644
index 000000000..4fa169913
--- /dev/null
+++ b/testdata/lvs/blackbox2.lvsdb
@@ -0,0 +1,196 @@
+#%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(l1 '1/0')
+ layer(l3 '2/0')
+ layer(l4 '3/0')
+ layer(l2 '10/0')
+
+ # Mask layer connectivity
+ connect(l1 l1 l3 l2)
+ connect(l3 l1 l3 l4)
+ connect(l4 l3 l4)
+ connect(l2 l1 l2)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(CHIP
+
+ # Circuit boundary
+ rect((-4000 -6000) (11000 9000))
+
+ # Outgoing pins and their connections to nets
+ pin(name(pad3))
+ pin(name(pad4))
+ pin(name(pad5))
+ pin(name(pad2))
+ pin(name(pad1))
+ pin(name(pad8))
+ pin(name(pad6))
+ pin(name(pad7))
+
+ )
+ circuit(TOP
+
+ # Circuit boundary
+ rect((-18500 -14000) (44500 28000))
+
+ # Nets with their geometries
+ net(1 name('4')
+ rect(l1 (-10500 2000) (7500 1000))
+ rect(l1 (-7500 0) (1000 4000))
+ rect(l1 (-6000 0) (6000 1000))
+ rect(l1 (-9000 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (12499 -5501) (1000 1000))
+ )
+ net(2 name('3')
+ rect(l1 (1000 2000) (1000 10000))
+ rect(l1 (-17500 0) (17500 1000))
+ rect(l1 (-20500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (17499 -10501) (1000 1000))
+ )
+ net(3 name('2')
+ rect(l1 (-15500 -2000) (12500 1000))
+ rect(l1 (-15500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (12499 -501) (1000 1000))
+ )
+ net(4 name('1')
+ rect(l1 (-15500 -13000) (6000 1000))
+ rect(l1 (-1000 0) (1000 6000))
+ rect(l1 (-9000 -8000) (3500 3000))
+ rect(l1 (4500 5000) (7500 1000))
+ rect(l1 (-13501 -7501) (2 2))
+ rect(l2 (12499 6499) (1000 1000))
+ )
+ net(5 name('8')
+ rect(l1 (1000 -13000) (22000 1000))
+ rect(l1 (-22000 0) (1000 7000))
+ rect(l1 (20500 -9000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (-23501 6499) (1000 1000))
+ )
+ net(6 name('7')
+ rect(l1 (6000 -6000) (7000 1000))
+ rect(l1 (-1000 0) (1000 12000))
+ rect(l1 (-1000 0) (11000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (-18501 -13501) (1000 1000))
+ )
+ net(7 name('5')
+ rect(l1 (6000 2000) (1000 10000))
+ rect(l1 (-1000 0) (17000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (-18501 -10501) (1000 1000))
+ )
+ net(8 name('6')
+ rect(l1 (16000 -2000) (7000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l1 (-18501 -501) (3500 1000))
+ rect(l3 (6500 -1000) (1000 1000))
+ rect(l3 (-8500 -1000) (1000 1000))
+ rect(l4 (-1000 -1000) (8500 1000))
+ rect(l2 (-11000 -1000) (1000 1000))
+ )
+
+ # Subcircuits and their connections
+ circuit(1 CHIP location(0 0)
+ pin(0 1)
+ pin(1 2)
+ pin(2 7)
+ pin(3 3)
+ pin(4 4)
+ pin(5 5)
+ pin(6 8)
+ pin(7 6)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(CHIP
+
+ # Outgoing pins and their connections to nets
+ pin(name(PAD1))
+ pin(name(PAD2))
+ pin(name(PAD3))
+ pin(name(PAD4))
+ pin(name(PAD5))
+ pin(name(PAD6))
+ pin(name(PAD7))
+ pin(name(PAD8))
+
+ )
+ circuit(TOP
+
+ # Nets
+ net(1 name('1'))
+ net(2 name('2'))
+ net(3 name('3'))
+ net(4 name('4'))
+ net(5 name('5'))
+ net(6 name('6'))
+ net(7 name('7'))
+ net(8 name('8'))
+
+ # Subcircuits and their connections
+ circuit(1 CHIP name('1')
+ pin(0 1)
+ pin(1 2)
+ pin(2 3)
+ pin(3 4)
+ pin(4 5)
+ pin(5 6)
+ pin(6 7)
+ pin(7 8)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(CHIP CHIP match
+ xref(
+ pin(4 0 match)
+ pin(3 1 match)
+ pin(0 2 match)
+ pin(1 3 match)
+ pin(2 4 match)
+ pin(6 5 match)
+ pin(7 6 match)
+ pin(5 7 match)
+ )
+ )
+ circuit(TOP TOP nomatch
+ xref(
+ net(4 1 match)
+ net(3 2 match)
+ net(2 3 mismatch)
+ net(1 4 mismatch)
+ net(7 5 match)
+ net(8 6 match)
+ net(6 7 match)
+ net(5 8 match)
+ circuit(1 1 mismatch)
+ )
+ )
+)
diff --git a/testdata/lvs/blackbox3.cir b/testdata/lvs/blackbox3.cir
new file mode 100644
index 000000000..40adb3c28
--- /dev/null
+++ b/testdata/lvs/blackbox3.cir
@@ -0,0 +1,27 @@
+* Extracted by KLayout
+
+* cell TOP
+.SUBCKT TOP
+* net 2 3
+* net 3 4
+* net 4 2
+* net 5 1
+* net 6 8
+* net 7 5
+* net 8 6
+* net 9 7
+* cell instance $1 r0 *1 0,0
+X$1 2 3 7 4 5 6 8 1 CHIP
+.ENDS TOP
+
+* cell CHIP
+* pin pad3
+* pin pad4
+* pin pad5
+* pin pad2
+* pin pad1
+* pin pad8
+* pin pad6
+* pin pad7
+.SUBCKT CHIP 1 2 3 4 5 6 7 8
+.ENDS CHIP
diff --git a/testdata/lvs/blackbox3.lvs b/testdata/lvs/blackbox3.lvs
new file mode 100644
index 000000000..9b20bc4d6
--- /dev/null
+++ b/testdata/lvs/blackbox3.lvs
@@ -0,0 +1,22 @@
+source($lvs_test_source)
+report_lvs($lvs_test_target_lvsdb, true)
+target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
+
+schematic("blackbox_schematic.cir")
+
+deep
+
+same_nets!("TOP", "*", "*")
+
+m1 = input(1, 0)
+via = input(2, 0)
+m2 = input(3, 0)
+pad = input(10, 0)
+
+connect(m1, pad)
+connect(m1, via)
+connect(via, m2)
+
+blank_circuit("CHIP")
+
+compare
diff --git a/testdata/lvs/blackbox3.lvsdb b/testdata/lvs/blackbox3.lvsdb
new file mode 100644
index 000000000..1dd6f3942
--- /dev/null
+++ b/testdata/lvs/blackbox3.lvsdb
@@ -0,0 +1,200 @@
+#%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(l1 '1/0')
+ layer(l3 '2/0')
+ layer(l4 '3/0')
+ layer(l2 '10/0')
+
+ # Mask layer connectivity
+ connect(l1 l1 l3 l2)
+ connect(l3 l1 l3 l4)
+ connect(l4 l3 l4)
+ connect(l2 l1 l2)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(CHIP
+
+ # Circuit boundary
+ rect((-4000 -6000) (11000 9000))
+
+ # Outgoing pins and their connections to nets
+ pin(name(pad3))
+ pin(name(pad4))
+ pin(name(pad5))
+ pin(name(pad2))
+ pin(name(pad1))
+ pin(name(pad8))
+ pin(name(pad6))
+ pin(name(pad7))
+
+ )
+ circuit(TOP
+
+ # Circuit boundary
+ rect((-18500 -14000) (44500 28000))
+
+ # Nets with their geometries
+ net(1
+ rect(l1 (6000 -6000) (7000 1000))
+ rect(l1 (-1000 0) (1000 12000))
+ rect(l1 (-1000 0) (5160 1000))
+ rect(l2 (-11160 -14000) (1000 1000))
+ )
+ net(2 name('3')
+ rect(l1 (-10500 2000) (7500 1000))
+ rect(l1 (-7500 0) (1000 4000))
+ rect(l1 (-6000 0) (6000 1000))
+ rect(l1 (-9000 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (12499 -5501) (1000 1000))
+ )
+ net(3 name('4')
+ rect(l1 (1000 2000) (1000 10000))
+ rect(l1 (-17500 0) (17500 1000))
+ rect(l1 (-20500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (17499 -10501) (1000 1000))
+ )
+ net(4 name('2')
+ rect(l1 (-15500 -2000) (12500 1000))
+ rect(l1 (-15500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (12499 -501) (1000 1000))
+ )
+ net(5 name('1')
+ rect(l1 (-15500 -13000) (6000 1000))
+ rect(l1 (-1000 0) (1000 6000))
+ rect(l1 (-9000 -8000) (3500 3000))
+ rect(l1 (4500 5000) (7500 1000))
+ rect(l1 (-13501 -7501) (2 2))
+ rect(l2 (12499 6499) (1000 1000))
+ )
+ net(6 name('8')
+ rect(l1 (1000 -13000) (22000 1000))
+ rect(l1 (-22000 0) (1000 7000))
+ rect(l1 (20500 -9000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (-23501 6499) (1000 1000))
+ )
+ net(7 name('5')
+ rect(l1 (6000 2000) (1000 10000))
+ rect(l1 (-1000 0) (17000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (-18501 -10501) (1000 1000))
+ )
+ net(8 name('6')
+ rect(l1 (16000 -2000) (7000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l1 (-18501 -501) (3500 1000))
+ rect(l3 (6500 -1000) (1000 1000))
+ rect(l3 (-8500 -1000) (1000 1000))
+ rect(l4 (-1000 -1000) (8500 1000))
+ rect(l2 (-11000 -1000) (1000 1000))
+ )
+ net(9 name('7')
+ rect(l1 (18080 7000) (4920 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ )
+
+ # Subcircuits and their connections
+ circuit(1 CHIP location(0 0)
+ pin(0 2)
+ pin(1 3)
+ pin(2 7)
+ pin(3 4)
+ pin(4 5)
+ pin(5 6)
+ pin(6 8)
+ pin(7 1)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(CHIP
+
+ # Outgoing pins and their connections to nets
+ pin(name(PAD1))
+ pin(name(PAD2))
+ pin(name(PAD3))
+ pin(name(PAD4))
+ pin(name(PAD5))
+ pin(name(PAD6))
+ pin(name(PAD7))
+ pin(name(PAD8))
+
+ )
+ circuit(TOP
+
+ # Nets
+ net(1 name('1'))
+ net(2 name('2'))
+ net(3 name('3'))
+ net(4 name('4'))
+ net(5 name('5'))
+ net(6 name('6'))
+ net(7 name('7'))
+ net(8 name('8'))
+
+ # Subcircuits and their connections
+ circuit(1 CHIP name('1')
+ pin(0 1)
+ pin(1 2)
+ pin(2 3)
+ pin(3 4)
+ pin(4 5)
+ pin(5 6)
+ pin(6 7)
+ pin(7 8)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(CHIP CHIP match
+ xref(
+ pin(4 0 match)
+ pin(3 1 match)
+ pin(0 2 match)
+ pin(1 3 match)
+ pin(2 4 match)
+ pin(6 5 match)
+ pin(7 6 match)
+ pin(5 7 match)
+ )
+ )
+ circuit(TOP TOP nomatch
+ xref(
+ net(() 7 mismatch)
+ net(1 () mismatch)
+ net(5 1 match)
+ net(4 2 match)
+ net(2 3 match)
+ net(3 4 match)
+ net(7 5 match)
+ net(8 6 match)
+ net(6 8 match)
+ circuit(1 1 mismatch)
+ )
+ )
+)
diff --git a/testdata/lvs/blackbox4.cir b/testdata/lvs/blackbox4.cir
new file mode 100644
index 000000000..84da4c047
--- /dev/null
+++ b/testdata/lvs/blackbox4.cir
@@ -0,0 +1,26 @@
+* Extracted by KLayout
+
+* cell TOP
+.SUBCKT TOP
+* net 1 3
+* net 2 4
+* net 3 2
+* net 4 1
+* net 5 8
+* net 6 5,7
+* net 7 6
+* cell instance $1 r0 *1 0,0
+X$1 1 2 6 3 4 5 7 6 CHIP
+.ENDS TOP
+
+* cell CHIP
+* pin pad3
+* pin pad4
+* pin pad5
+* pin pad2
+* pin pad1
+* pin pad8
+* pin pad6
+* pin pad7
+.SUBCKT CHIP 1 2 3 4 5 6 7 8
+.ENDS CHIP
diff --git a/testdata/lvs/blackbox4.lvs b/testdata/lvs/blackbox4.lvs
new file mode 100644
index 000000000..9b20bc4d6
--- /dev/null
+++ b/testdata/lvs/blackbox4.lvs
@@ -0,0 +1,22 @@
+source($lvs_test_source)
+report_lvs($lvs_test_target_lvsdb, true)
+target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
+
+schematic("blackbox_schematic.cir")
+
+deep
+
+same_nets!("TOP", "*", "*")
+
+m1 = input(1, 0)
+via = input(2, 0)
+m2 = input(3, 0)
+pad = input(10, 0)
+
+connect(m1, pad)
+connect(m1, via)
+connect(via, m2)
+
+blank_circuit("CHIP")
+
+compare
diff --git a/testdata/lvs/blackbox4.lvsdb b/testdata/lvs/blackbox4.lvsdb
new file mode 100644
index 000000000..fb865f98d
--- /dev/null
+++ b/testdata/lvs/blackbox4.lvsdb
@@ -0,0 +1,196 @@
+#%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(l1 '1/0')
+ layer(l3 '2/0')
+ layer(l4 '3/0')
+ layer(l2 '10/0')
+
+ # Mask layer connectivity
+ connect(l1 l1 l3 l2)
+ connect(l3 l1 l3 l4)
+ connect(l4 l3 l4)
+ connect(l2 l1 l2)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(CHIP
+
+ # Circuit boundary
+ rect((-4000 -6000) (11000 9000))
+
+ # Outgoing pins and their connections to nets
+ pin(name(pad3))
+ pin(name(pad4))
+ pin(name(pad5))
+ pin(name(pad2))
+ pin(name(pad1))
+ pin(name(pad8))
+ pin(name(pad6))
+ pin(name(pad7))
+
+ )
+ circuit(TOP
+
+ # Circuit boundary
+ rect((-18500 -14000) (44500 28000))
+
+ # Nets with their geometries
+ net(1 name('3')
+ rect(l1 (-10500 2000) (7500 1000))
+ rect(l1 (-7500 0) (1000 4000))
+ rect(l1 (-6000 0) (6000 1000))
+ rect(l1 (-9000 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (12499 -5501) (1000 1000))
+ )
+ net(2 name('4')
+ rect(l1 (1000 2000) (1000 10000))
+ rect(l1 (-17500 0) (17500 1000))
+ rect(l1 (-20500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (17499 -10501) (1000 1000))
+ )
+ net(3 name('2')
+ rect(l1 (-15500 -2000) (12500 1000))
+ rect(l1 (-15500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (12499 -501) (1000 1000))
+ )
+ net(4 name('1')
+ rect(l1 (-15500 -13000) (6000 1000))
+ rect(l1 (-1000 0) (1000 6000))
+ rect(l1 (-9000 -8000) (3500 3000))
+ rect(l1 (4500 5000) (7500 1000))
+ rect(l1 (-13501 -7501) (2 2))
+ rect(l2 (12499 6499) (1000 1000))
+ )
+ net(5 name('8')
+ rect(l1 (1000 -13000) (22000 1000))
+ rect(l1 (-22000 0) (1000 7000))
+ rect(l1 (20500 -9000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (-23501 6499) (1000 1000))
+ )
+ net(6 name('5,7')
+ rect(l1 (6000 -6000) (7000 1000))
+ rect(l1 (-1000 0) (1000 12000))
+ rect(l1 (-1000 0) (11000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-12200 -1500) (790 4500))
+ rect(l1 (-8590 -10000) (1000 10000))
+ rect(l1 (-1000 0) (17000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -6501) (2 2))
+ rect(l1 (-2 4998) (2 2))
+ rect(l2 (-18501 -18501) (1000 1000))
+ rect(l2 (-1000 7000) (1000 1000))
+ )
+ net(7 name('6')
+ rect(l1 (16000 -2000) (7000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l1 (-18501 -501) (3500 1000))
+ rect(l3 (6500 -1000) (1000 1000))
+ rect(l3 (-8500 -1000) (1000 1000))
+ rect(l4 (-1000 -1000) (8500 1000))
+ rect(l2 (-11000 -1000) (1000 1000))
+ )
+
+ # Subcircuits and their connections
+ circuit(1 CHIP location(0 0)
+ pin(0 1)
+ pin(1 2)
+ pin(2 6)
+ pin(3 3)
+ pin(4 4)
+ pin(5 5)
+ pin(6 7)
+ pin(7 6)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(CHIP
+
+ # Outgoing pins and their connections to nets
+ pin(name(PAD1))
+ pin(name(PAD2))
+ pin(name(PAD3))
+ pin(name(PAD4))
+ pin(name(PAD5))
+ pin(name(PAD6))
+ pin(name(PAD7))
+ pin(name(PAD8))
+
+ )
+ circuit(TOP
+
+ # Nets
+ net(1 name('1'))
+ net(2 name('2'))
+ net(3 name('3'))
+ net(4 name('4'))
+ net(5 name('5'))
+ net(6 name('6'))
+ net(7 name('7'))
+ net(8 name('8'))
+
+ # Subcircuits and their connections
+ circuit(1 CHIP name('1')
+ pin(0 1)
+ pin(1 2)
+ pin(2 3)
+ pin(3 4)
+ pin(4 5)
+ pin(5 6)
+ pin(6 7)
+ pin(7 8)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(CHIP CHIP match
+ xref(
+ pin(4 0 match)
+ pin(3 1 match)
+ pin(0 2 match)
+ pin(1 3 match)
+ pin(2 4 match)
+ pin(6 5 match)
+ pin(7 6 match)
+ pin(5 7 match)
+ )
+ )
+ circuit(TOP TOP nomatch
+ xref(
+ net(() 5 mismatch)
+ net(() 7 mismatch)
+ net(4 1 match)
+ net(3 2 match)
+ net(1 3 match)
+ net(2 4 match)
+ net(6 () mismatch)
+ net(7 6 match)
+ net(5 8 match)
+ circuit(1 1 mismatch)
+ )
+ )
+)
diff --git a/testdata/lvs/blackbox5.cir b/testdata/lvs/blackbox5.cir
new file mode 100644
index 000000000..4e2b43ed7
--- /dev/null
+++ b/testdata/lvs/blackbox5.cir
@@ -0,0 +1,26 @@
+* Extracted by KLayout
+
+* cell TOP
+.SUBCKT TOP
+* net 2 3
+* net 3 4
+* net 4 2
+* net 5 1
+* net 6 8
+* net 7 5,7
+* net 8 6
+* cell instance $1 r0 *1 0,0
+X$1 2 3 7 4 5 6 8 1 CHIP
+.ENDS TOP
+
+* cell CHIP
+* pin pad3
+* pin pad4
+* pin pad5
+* pin pad2
+* pin pad1
+* pin pad8
+* pin pad6
+* pin pad7
+.SUBCKT CHIP 1 2 3 4 5 6 7 8
+.ENDS CHIP
diff --git a/testdata/lvs/blackbox5.lvs b/testdata/lvs/blackbox5.lvs
new file mode 100644
index 000000000..9b20bc4d6
--- /dev/null
+++ b/testdata/lvs/blackbox5.lvs
@@ -0,0 +1,22 @@
+source($lvs_test_source)
+report_lvs($lvs_test_target_lvsdb, true)
+target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
+
+schematic("blackbox_schematic.cir")
+
+deep
+
+same_nets!("TOP", "*", "*")
+
+m1 = input(1, 0)
+via = input(2, 0)
+m2 = input(3, 0)
+pad = input(10, 0)
+
+connect(m1, pad)
+connect(m1, via)
+connect(via, m2)
+
+blank_circuit("CHIP")
+
+compare
diff --git a/testdata/lvs/blackbox5.lvsdb b/testdata/lvs/blackbox5.lvsdb
new file mode 100644
index 000000000..3c2726f5a
--- /dev/null
+++ b/testdata/lvs/blackbox5.lvsdb
@@ -0,0 +1,200 @@
+#%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(l1 '1/0')
+ layer(l3 '2/0')
+ layer(l4 '3/0')
+ layer(l2 '10/0')
+
+ # Mask layer connectivity
+ connect(l1 l1 l3 l2)
+ connect(l3 l1 l3 l4)
+ connect(l4 l3 l4)
+ connect(l2 l1 l2)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(CHIP
+
+ # Circuit boundary
+ rect((-4000 -6000) (11000 9000))
+
+ # Outgoing pins and their connections to nets
+ pin(name(pad3))
+ pin(name(pad4))
+ pin(name(pad5))
+ pin(name(pad2))
+ pin(name(pad1))
+ pin(name(pad8))
+ pin(name(pad6))
+ pin(name(pad7))
+
+ )
+ circuit(TOP
+
+ # Circuit boundary
+ rect((-18500 -14000) (44500 28000))
+
+ # Nets with their geometries
+ net(1
+ rect(l1 (6000 -6000) (7000 1000))
+ rect(l1 (-1000 0) (1000 12000))
+ rect(l1 (-1000 0) (4550 1000))
+ rect(l2 (-10550 -14000) (1000 1000))
+ )
+ net(2 name('3')
+ rect(l1 (-10500 2000) (7500 1000))
+ rect(l1 (-7500 0) (1000 4000))
+ rect(l1 (-6000 0) (6000 1000))
+ rect(l1 (-9000 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (12499 -5501) (1000 1000))
+ )
+ net(3 name('4')
+ rect(l1 (1000 2000) (1000 10000))
+ rect(l1 (-17500 0) (17500 1000))
+ rect(l1 (-20500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (17499 -10501) (1000 1000))
+ )
+ net(4 name('2')
+ rect(l1 (-15500 -2000) (12500 1000))
+ rect(l1 (-15500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (12499 -501) (1000 1000))
+ )
+ net(5 name('1')
+ rect(l1 (-15500 -13000) (6000 1000))
+ rect(l1 (-1000 0) (1000 6000))
+ rect(l1 (-9000 -8000) (3500 3000))
+ rect(l1 (4500 5000) (7500 1000))
+ rect(l1 (-13501 -7501) (2 2))
+ rect(l2 (12499 6499) (1000 1000))
+ )
+ net(6 name('8')
+ rect(l1 (1000 -13000) (22000 1000))
+ rect(l1 (-22000 0) (1000 7000))
+ rect(l1 (20500 -9000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l2 (-23501 6499) (1000 1000))
+ )
+ net(7 name('5,7')
+ rect(l1 (6000 2000) (1000 10000))
+ rect(l1 (-1000 0) (17000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-6960 -6450) (700 4950))
+ rect(l1 (-2270 -5500) (5530 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l1 (-2 4998) (2 2))
+ rect(l2 (-18501 -10501) (1000 1000))
+ )
+ net(8 name('6')
+ rect(l1 (16000 -2000) (7000 1000))
+ rect(l1 (-500 -2000) (3500 3000))
+ rect(l1 (-1501 -1501) (2 2))
+ rect(l1 (-18501 -501) (3500 1000))
+ rect(l3 (6500 -1000) (1000 1000))
+ rect(l3 (-8500 -1000) (1000 1000))
+ rect(l4 (-1000 -1000) (8500 1000))
+ rect(l2 (-11000 -1000) (1000 1000))
+ )
+
+ # Subcircuits and their connections
+ circuit(1 CHIP location(0 0)
+ pin(0 2)
+ pin(1 3)
+ pin(2 7)
+ pin(3 4)
+ pin(4 5)
+ pin(5 6)
+ pin(6 8)
+ pin(7 1)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(CHIP
+
+ # Outgoing pins and their connections to nets
+ pin(name(PAD1))
+ pin(name(PAD2))
+ pin(name(PAD3))
+ pin(name(PAD4))
+ pin(name(PAD5))
+ pin(name(PAD6))
+ pin(name(PAD7))
+ pin(name(PAD8))
+
+ )
+ circuit(TOP
+
+ # Nets
+ net(1 name('1'))
+ net(2 name('2'))
+ net(3 name('3'))
+ net(4 name('4'))
+ net(5 name('5'))
+ net(6 name('6'))
+ net(7 name('7'))
+ net(8 name('8'))
+
+ # Subcircuits and their connections
+ circuit(1 CHIP name('1')
+ pin(0 1)
+ pin(1 2)
+ pin(2 3)
+ pin(3 4)
+ pin(4 5)
+ pin(5 6)
+ pin(6 7)
+ pin(7 8)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(CHIP CHIP match
+ xref(
+ pin(4 0 match)
+ pin(3 1 match)
+ pin(0 2 match)
+ pin(1 3 match)
+ pin(2 4 match)
+ pin(6 5 match)
+ pin(7 6 match)
+ pin(5 7 match)
+ )
+ )
+ circuit(TOP TOP nomatch
+ xref(
+ net(() 5 mismatch)
+ net(() 7 mismatch)
+ net(1 () mismatch)
+ net(5 1 match)
+ net(4 2 match)
+ net(2 3 match)
+ net(3 4 match)
+ net(7 () mismatch)
+ net(8 6 match)
+ net(6 8 match)
+ circuit(1 1 mismatch)
+ )
+ )
+)
diff --git a/testdata/lvs/blackbox_open.gds b/testdata/lvs/blackbox_open.gds
new file mode 100644
index 000000000..3123ac4da
Binary files /dev/null and b/testdata/lvs/blackbox_open.gds differ
diff --git a/testdata/lvs/blackbox_schematic.cir b/testdata/lvs/blackbox_schematic.cir
new file mode 100644
index 000000000..3dcf769b4
--- /dev/null
+++ b/testdata/lvs/blackbox_schematic.cir
@@ -0,0 +1,9 @@
+
+.subckt chip pad1 pad2 pad3 pad4 pad5 pad6 pad7 pad8
+* This chip is an abstract
+.ends
+
+.subckt TOP
+X1 1 2 3 4 5 6 7 8 chip
+.ends
+
diff --git a/testdata/lvs/blackbox_short.gds b/testdata/lvs/blackbox_short.gds
new file mode 100644
index 000000000..ec78d962b
Binary files /dev/null and b/testdata/lvs/blackbox_short.gds differ
diff --git a/testdata/lvs/blackbox_short_and_open.gds b/testdata/lvs/blackbox_short_and_open.gds
new file mode 100644
index 000000000..49e96056c
Binary files /dev/null and b/testdata/lvs/blackbox_short_and_open.gds differ
diff --git a/testdata/lvs/blackbox_swapped.gds b/testdata/lvs/blackbox_swapped.gds
new file mode 100644
index 000000000..555ca2c8d
Binary files /dev/null and b/testdata/lvs/blackbox_swapped.gds differ
diff --git a/testdata/lvs/empty_subcells.lvsdb b/testdata/lvs/empty_subcells.lvsdb
index 81138e85d..5a0306ccb 100644
--- a/testdata/lvs/empty_subcells.lvsdb
+++ b/testdata/lvs/empty_subcells.lvsdb
@@ -158,8 +158,8 @@ xref(
)
circuit(empty_subcells EMPTY_SUBCELLS match
xref(
- net(1 1 warning)
- net(2 2 warning)
+ net(1 1 match)
+ net(2 2 match)
circuit(2 1 match)
circuit(1 2 match)
)
diff --git a/testdata/lvs/nand2_split_gate_early.cir.1 b/testdata/lvs/nand2_split_gate_early.cir.1
new file mode 100644
index 000000000..5c739a1a4
--- /dev/null
+++ b/testdata/lvs/nand2_split_gate_early.cir.1
@@ -0,0 +1,23 @@
+* Extracted by KLayout
+
+* cell NAND2_WITH_DIODES
+* pin B
+* pin A
+* pin OUT
+* pin VDD
+* pin VSS
+.SUBCKT NAND2_WITH_DIODES 1 2 4 5 6
+* net 1 B
+* net 2 A
+* net 4 OUT
+* net 5 VDD
+* net 6 VSS
+* device instance $1 r0 *1 1.025,4.95 PMOS
+M$1 5 1 4 5 PMOS L=0.25U W=1.5U AS=0.675P AD=0.375P PS=3.9U PD=2U
+* device instance $2 r0 *1 1.775,4.95 PMOS
+M$2 4 2 5 5 PMOS L=0.25U W=1.5U AS=0.375P AD=0.675P PS=2U PD=3.9U
+* device instance $3 r0 *1 1.025,2 NMOS
+M$3 6 1 3 6 NMOS L=0.25U W=1.8U AS=0.81P AD=0.45P PS=5.4U PD=2.8U
+* device instance $4 r0 *1 1.775,2 NMOS
+M$4 3 2 4 6 NMOS L=0.25U W=1.8U AS=0.45P AD=0.81P PS=2.8U PD=5.4U
+.ENDS NAND2_WITH_DIODES
diff --git a/testdata/lvs/nand2_split_gate_early.cir.2 b/testdata/lvs/nand2_split_gate_early.cir.2
new file mode 100644
index 000000000..6bceb7353
--- /dev/null
+++ b/testdata/lvs/nand2_split_gate_early.cir.2
@@ -0,0 +1,23 @@
+* Extracted by KLayout
+
+* cell NAND2_WITH_DIODES
+* pin B
+* pin A
+* pin OUT
+* pin VDD
+* pin VSS
+.SUBCKT NAND2_WITH_DIODES 1 2 4 5 6
+* net 1 B
+* net 2 A
+* net 4 OUT
+* net 5 VDD
+* net 6 VSS
+* device instance $1 r0 *1 1.025,4.95 PMOS
+M$1 5 1 4 5 PMOS L=0.25U W=1.5U AS=0.675P AD=0.375P PS=3.9U PD=2U
+* device instance $2 r0 *1 1.775,4.95 PMOS
+M$2 4 2 5 5 PMOS L=0.25U W=1.5U AS=0.375P AD=0.675P PS=2U PD=3.9U
+* device instance $3 r0 *1 1.025,0.65 NMOS
+M$3 6 1 3 6 NMOS L=0.25U W=1.8U AS=0.81P AD=0.45P PS=5.4U PD=2.8U
+* device instance $4 r0 *1 1.775,0.65 NMOS
+M$4 3 2 4 6 NMOS L=0.25U W=1.8U AS=0.45P AD=0.81P PS=2.8U PD=5.4U
+.ENDS NAND2_WITH_DIODES
diff --git a/testdata/lvs/nand2_split_gate_early.lvs b/testdata/lvs/nand2_split_gate_early.lvs
new file mode 100644
index 000000000..bf48ae960
--- /dev/null
+++ b/testdata/lvs/nand2_split_gate_early.lvs
@@ -0,0 +1,85 @@
+
+source($lvs_test_source, "NAND2_WITH_DIODES")
+
+report_lvs($lvs_test_target_lvsdb, true)
+
+target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
+
+schematic("nand2_split_gate_schematic.cir")
+
+join_symmetric_nets("*")
+
+deep
+
+# Reports generated
+
+# Drawing layers
+
+nwell = input(1, 0)
+active = input(2, 0)
+pplus = input(3, 0)
+nplus = input(4, 0)
+poly = input(5, 0)
+contact = input(6, 0)
+metal1 = input(7, 0)
+metal1_lbl = labels(7, 1)
+via1 = input(8, 0)
+metal2 = input(9, 0)
+metal2_lbl = labels(9, 1)
+
+# 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, metal1_lbl) # attaches labels
+connect(metal1, via1)
+connect(via1, metal2)
+connect(metal2, metal2_lbl) # attaches labels
+
+# Global
+connect_global(bulk, "SUBSTRATE")
+connect_global(ptie, "SUBSTRATE")
+
+# Extract, simplify
+
+netlist
+netlist.simplify
+
+# Compare section
+
+compare
+
diff --git a/testdata/lvs/nand2_split_gate_early.lvsdb.1 b/testdata/lvs/nand2_split_gate_early.lvsdb.1
new file mode 100644
index 000000000..e0d758a88
--- /dev/null
+++ b/testdata/lvs/nand2_split_gate_early.lvsdb.1
@@ -0,0 +1,407 @@
+#%lvsdb-klayout
+
+# Layout
+layout(
+ top(NAND2_WITH_DIODES)
+ unit(0.001)
+
+ # Layer section
+ # This section lists the mask layers (drawing or derived) and their connections.
+
+ # Mask layers
+ layer(l3 'NWELL (1/0)')
+ layer(l4 'POLY (5/0)')
+ layer(l8 'CONTACT (6/0)')
+ layer(l11 'METAL1 (7/0)')
+ layer(l12 'METAL1_LABEL (7/1)')
+ layer(l13 'VIA1 (8/0)')
+ layer(l14 'METAL2 (9/0)')
+ layer(l15 'METAL2_LABEL (9/1)')
+ 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 l13)
+ connect(l12 l11)
+ connect(l13 l11 l13 l14)
+ connect(l14 l13 l14 l15)
+ connect(l15 l14)
+ 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 (-575 -750) (450 1500))
+ )
+ terminal(G
+ rect(l4 (-125 -750) (250 1500))
+ )
+ terminal(D
+ rect(l2 (125 -750) (500 1500))
+ )
+ terminal(B
+ rect(l3 (-125 -750) (250 1500))
+ )
+ )
+ device(D$PMOS$1 PMOS
+ terminal(S
+ rect(l2 (-625 -750) (500 1500))
+ )
+ terminal(G
+ rect(l4 (-125 -750) (250 1500))
+ )
+ terminal(D
+ rect(l2 (125 -750) (450 1500))
+ )
+ terminal(B
+ rect(l3 (-125 -750) (250 1500))
+ )
+ )
+ device(D$NMOS NMOS
+ terminal(S
+ rect(l6 (-575 -450) (450 900))
+ )
+ terminal(G
+ rect(l4 (-125 -450) (250 900))
+ )
+ terminal(D
+ rect(l6 (125 -450) (500 900))
+ )
+ terminal(B
+ rect(l7 (-125 -450) (250 900))
+ )
+ )
+ device(D$NMOS$1 NMOS
+ terminal(S
+ rect(l6 (-625 -450) (500 900))
+ )
+ terminal(G
+ rect(l4 (-125 -450) (250 900))
+ )
+ terminal(D
+ rect(l6 (125 -450) (450 900))
+ )
+ terminal(B
+ rect(l7 (-125 -450) (250 900))
+ )
+ )
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(NAND2_WITH_DIODES
+
+ # Circuit boundary
+ rect((0 0) (3750 6150))
+
+ # Nets with their geometries
+ net(1 name(B)
+ rect(l4 (350 2750) (550 400))
+ rect(l4 (0 -2050) (250 3100))
+ rect(l4 (-250 0) (250 1650))
+ rect(l4 (-250 -5800) (250 1050))
+ rect(l4 (-250 300) (250 1050))
+ rect(l8 (-700 400) (200 200))
+ rect(l11 (-300 -300) (400 400))
+ text(l12 B (-200 -200))
+ )
+ net(2 name(A)
+ rect(l4 (1900 3400) (550 400))
+ rect(l4 (-800 -2700) (250 3100))
+ rect(l4 (-250 0) (250 1650))
+ rect(l4 (-250 -5800) (250 1050))
+ rect(l4 (-250 300) (250 1050))
+ rect(l8 (250 1050) (200 200))
+ rect(l11 (-300 -300) (400 400))
+ text(l12 A (-200 -200))
+ )
+ net(3
+ rect(l8 (1300 300) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l8 (-200 650) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l11 (-250 -2150) (300 900))
+ rect(l11 (-300 -900) (300 850))
+ rect(l11 (-300 500) (300 900))
+ rect(l11 (-300 -900) (300 850))
+ rect(l6 (-400 -2200) (500 900))
+ rect(l6 (-500 450) (500 900))
+ )
+ net(4 name(OUT)
+ rect(l8 (2050 300) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 650) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-950 2000) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l11 (500 -5350) (300 850))
+ rect(l11 (-300 -50) (300 1950))
+ rect(l11 (-300 -1400) (300 850))
+ rect(l11 (-300 300) (450 400))
+ rect(l11 (-1200 -300) (1050 300))
+ rect(l11 (-1050 1150) (300 1400))
+ rect(l11 (-300 -2700) (300 1950))
+ text(l12 OUT (700 -2000))
+ rect(l2 (-1100 1300) (500 1500))
+ rect(l6 (250 -5500) (450 900))
+ rect(l6 (-450 450) (450 900))
+ )
+ net(5 name(VDD)
+ rect(l3 (0 2950) (3750 3200))
+ rect(l8 (-3200 -1800) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (1300 -1200) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (700 -800) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l11 (-2650 -1200) (300 1600))
+ rect(l11 (1200 -1600) (300 1600))
+ rect(l11 (600 -1200) (300 1200))
+ rect(l13 (-2650 -800) (200 200))
+ rect(l13 (-200 300) (200 200))
+ rect(l13 (1300 -700) (200 200))
+ rect(l13 (-200 300) (200 200))
+ rect(l13 (700 -700) (200 200))
+ rect(l13 (-200 300) (200 200))
+ rect(l14 (-3150 -850) (3750 1000))
+ text(l15 VDD (-100 -850))
+ rect(l2 (-3200 -850) (450 1500))
+ rect(l2 (1000 -1500) (450 1500))
+ rect(l9 (400 -1200) (600 1200))
+ )
+ net(6 name(VSS)
+ rect(l8 (550 1650) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 -2050) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (2200 -550) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l11 (-2650 -50) (300 1350))
+ rect(l11 (-300 -2400) (300 1050))
+ rect(l11 (2100 -1050) (300 1200))
+ rect(l13 (-2650 -1100) (200 200))
+ rect(l13 (-200 300) (200 200))
+ rect(l13 (2200 -700) (200 200))
+ rect(l13 (-200 300) (200 200))
+ rect(l14 (-3150 -850) (3750 1000))
+ text(l15 VSS (-100 -850))
+ rect(l6 (-3200 1400) (450 900))
+ rect(l6 (-450 -2250) (450 900))
+ rect(l10 (1850 -900) (600 1200))
+ )
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(B))
+ pin(2 name(A))
+ pin(4 name(OUT))
+ pin(5 name(VDD))
+ pin(6 name(VSS))
+
+ # Devices and their connections
+ device(1 D$PMOS
+ location(1025 4950)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0.675)
+ param(AD 0.375)
+ param(PS 3.9)
+ param(PD 2)
+ terminal(S 5)
+ terminal(G 1)
+ terminal(D 4)
+ terminal(B 5)
+ )
+ device(2 D$PMOS$1
+ location(1775 4950)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0.375)
+ param(AD 0.675)
+ param(PS 2)
+ param(PD 3.9)
+ terminal(S 4)
+ terminal(G 2)
+ terminal(D 5)
+ terminal(B 5)
+ )
+ device(3 D$NMOS
+ device(D$NMOS location(0 -1350))
+ connect(0 S S)
+ connect(1 S S)
+ connect(0 G G)
+ connect(1 G G)
+ connect(0 D D)
+ connect(1 D D)
+ connect(0 B B)
+ connect(1 B B)
+ location(1025 2000)
+ param(L 0.25)
+ param(W 1.8)
+ param(AS 0.81)
+ param(AD 0.45)
+ param(PS 5.4)
+ param(PD 2.8)
+ terminal(S 6)
+ terminal(G 1)
+ terminal(D 3)
+ terminal(B 6)
+ )
+ device(4 D$NMOS$1
+ device(D$NMOS$1 location(0 -1350))
+ connect(0 S S)
+ connect(1 S S)
+ connect(0 G G)
+ connect(1 G G)
+ connect(0 D D)
+ connect(1 D D)
+ connect(0 B B)
+ connect(1 B B)
+ location(1775 2000)
+ param(L 0.25)
+ param(W 1.8)
+ param(AS 0.45)
+ param(AD 0.81)
+ param(PS 2.8)
+ param(PD 5.4)
+ terminal(S 3)
+ terminal(G 2)
+ terminal(D 4)
+ terminal(B 6)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Device class section
+ class(PMOS MOS4)
+ class(NMOS MOS4)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(NAND2_WITH_DIODES
+
+ # Nets
+ net(1 name(A))
+ net(2 name(B))
+ net(3 name(OUT))
+ net(4 name(VSS))
+ net(5 name(VDD))
+ net(6 name($1))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(A))
+ pin(2 name(B))
+ pin(3 name(OUT))
+ pin(4 name(VSS))
+ pin(5 name(VDD))
+
+ # Devices and their connections
+ device(1 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 5)
+ terminal(G 2)
+ terminal(D 3)
+ terminal(B 5)
+ )
+ device(2 PMOS
+ name('2')
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 5)
+ terminal(G 1)
+ terminal(D 3)
+ terminal(B 5)
+ )
+ device(3 NMOS
+ name('3')
+ param(L 0.25)
+ param(W 1.8)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 4)
+ terminal(G 2)
+ terminal(D 6)
+ terminal(B 4)
+ )
+ device(4 NMOS
+ name('4')
+ param(L 0.25)
+ param(W 1.8)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 6)
+ terminal(G 1)
+ terminal(D 3)
+ terminal(B 4)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(NAND2_WITH_DIODES NAND2_WITH_DIODES match
+ xref(
+ net(3 6 match)
+ net(2 1 match)
+ net(1 2 match)
+ net(4 3 match)
+ net(5 5 match)
+ net(6 4 match)
+ pin(1 0 match)
+ pin(0 1 match)
+ pin(2 2 match)
+ pin(3 4 match)
+ pin(4 3 match)
+ device(3 3 match)
+ device(4 4 match)
+ device(1 1 match)
+ device(2 2 match)
+ )
+ )
+)
diff --git a/testdata/lvs/nand2_split_gate_early.lvsdb.2 b/testdata/lvs/nand2_split_gate_early.lvsdb.2
new file mode 100644
index 000000000..4742977a2
--- /dev/null
+++ b/testdata/lvs/nand2_split_gate_early.lvsdb.2
@@ -0,0 +1,407 @@
+#%lvsdb-klayout
+
+# Layout
+layout(
+ top(NAND2_WITH_DIODES)
+ unit(0.001)
+
+ # Layer section
+ # This section lists the mask layers (drawing or derived) and their connections.
+
+ # Mask layers
+ layer(l3 'NWELL (1/0)')
+ layer(l4 'POLY (5/0)')
+ layer(l8 'CONTACT (6/0)')
+ layer(l11 'METAL1 (7/0)')
+ layer(l12 'METAL1_LABEL (7/1)')
+ layer(l13 'VIA1 (8/0)')
+ layer(l14 'METAL2 (9/0)')
+ layer(l15 'METAL2_LABEL (9/1)')
+ 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 l13)
+ connect(l12 l11)
+ connect(l13 l11 l13 l14)
+ connect(l14 l13 l14 l15)
+ connect(l15 l14)
+ 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 (-575 -750) (450 1500))
+ )
+ terminal(G
+ rect(l4 (-125 -750) (250 1500))
+ )
+ terminal(D
+ rect(l2 (125 -750) (500 1500))
+ )
+ terminal(B
+ rect(l3 (-125 -750) (250 1500))
+ )
+ )
+ device(D$PMOS$1 PMOS
+ terminal(S
+ rect(l2 (-625 -750) (500 1500))
+ )
+ terminal(G
+ rect(l4 (-125 -750) (250 1500))
+ )
+ terminal(D
+ rect(l2 (125 -750) (450 1500))
+ )
+ terminal(B
+ rect(l3 (-125 -750) (250 1500))
+ )
+ )
+ device(D$NMOS NMOS
+ terminal(S
+ rect(l6 (-575 -450) (450 900))
+ )
+ terminal(G
+ rect(l4 (-125 -450) (250 900))
+ )
+ terminal(D
+ rect(l6 (125 -450) (500 900))
+ )
+ terminal(B
+ rect(l7 (-125 -450) (250 900))
+ )
+ )
+ device(D$NMOS$1 NMOS
+ terminal(S
+ rect(l6 (-625 -450) (500 900))
+ )
+ terminal(G
+ rect(l4 (-125 -450) (250 900))
+ )
+ terminal(D
+ rect(l6 (125 -450) (450 900))
+ )
+ terminal(B
+ rect(l7 (-125 -450) (250 900))
+ )
+ )
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(NAND2_WITH_DIODES
+
+ # Circuit boundary
+ rect((0 0) (3750 6150))
+
+ # Nets with their geometries
+ net(1 name(B)
+ rect(l4 (350 2750) (550 400))
+ rect(l4 (0 -2050) (250 3100))
+ rect(l4 (-250 0) (250 1650))
+ rect(l4 (-250 -5800) (250 1050))
+ rect(l4 (-250 300) (250 1050))
+ rect(l8 (-700 400) (200 200))
+ rect(l11 (-300 -300) (400 400))
+ text(l12 B (-200 -200))
+ )
+ net(2 name(A)
+ rect(l4 (1900 3400) (550 400))
+ rect(l4 (-800 -2700) (250 3100))
+ rect(l4 (-250 0) (250 1650))
+ rect(l4 (-250 -5800) (250 1050))
+ rect(l4 (-250 300) (250 1050))
+ rect(l8 (250 1050) (200 200))
+ rect(l11 (-300 -300) (400 400))
+ text(l12 A (-200 -200))
+ )
+ net(3
+ rect(l8 (1300 300) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l8 (-200 650) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l11 (-250 -2150) (300 900))
+ rect(l11 (-300 -900) (300 850))
+ rect(l11 (-300 500) (300 900))
+ rect(l11 (-300 -900) (300 850))
+ rect(l6 (-400 -2200) (500 900))
+ rect(l6 (-500 450) (500 900))
+ )
+ net(4 name(OUT)
+ rect(l8 (2050 300) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 650) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-950 2000) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 -200) (200 200))
+ rect(l11 (500 -5350) (300 850))
+ rect(l11 (-300 -50) (300 1950))
+ rect(l11 (-300 -1400) (300 850))
+ rect(l11 (-300 300) (450 400))
+ rect(l11 (-1200 -300) (1050 300))
+ rect(l11 (-1050 1150) (300 1400))
+ rect(l11 (-300 -2700) (300 1950))
+ text(l12 OUT (700 -2000))
+ rect(l2 (-1100 1300) (500 1500))
+ rect(l6 (250 -5500) (450 900))
+ rect(l6 (-450 450) (450 900))
+ )
+ net(5 name(VDD)
+ rect(l3 (0 2950) (3750 3200))
+ rect(l8 (-3200 -1800) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (1300 -1200) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (700 -800) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l11 (-2650 -1200) (300 1600))
+ rect(l11 (1200 -1600) (300 1600))
+ rect(l11 (600 -1200) (300 1200))
+ rect(l13 (-2650 -800) (200 200))
+ rect(l13 (-200 300) (200 200))
+ rect(l13 (1300 -700) (200 200))
+ rect(l13 (-200 300) (200 200))
+ rect(l13 (700 -700) (200 200))
+ rect(l13 (-200 300) (200 200))
+ rect(l14 (-3150 -850) (3750 1000))
+ text(l15 VDD (-100 -850))
+ rect(l2 (-3200 -850) (450 1500))
+ rect(l2 (1000 -1500) (450 1500))
+ rect(l9 (400 -1200) (600 1200))
+ )
+ net(6 name(VSS)
+ rect(l8 (550 1650) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (-200 -2050) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l8 (2200 -550) (200 200))
+ rect(l8 (-200 300) (200 200))
+ rect(l11 (-2650 -50) (300 1350))
+ rect(l11 (-300 -2400) (300 1050))
+ rect(l11 (2100 -1050) (300 1200))
+ rect(l13 (-2650 -1100) (200 200))
+ rect(l13 (-200 300) (200 200))
+ rect(l13 (2200 -700) (200 200))
+ rect(l13 (-200 300) (200 200))
+ rect(l14 (-3150 -850) (3750 1000))
+ text(l15 VSS (-100 -850))
+ rect(l6 (-3200 1400) (450 900))
+ rect(l6 (-450 -2250) (450 900))
+ rect(l10 (1850 -900) (600 1200))
+ )
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(B))
+ pin(2 name(A))
+ pin(4 name(OUT))
+ pin(5 name(VDD))
+ pin(6 name(VSS))
+
+ # Devices and their connections
+ device(1 D$PMOS
+ location(1025 4950)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0.675)
+ param(AD 0.375)
+ param(PS 3.9)
+ param(PD 2)
+ terminal(S 5)
+ terminal(G 1)
+ terminal(D 4)
+ terminal(B 5)
+ )
+ device(2 D$PMOS$1
+ location(1775 4950)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0.375)
+ param(AD 0.675)
+ param(PS 2)
+ param(PD 3.9)
+ terminal(S 4)
+ terminal(G 2)
+ terminal(D 5)
+ terminal(B 5)
+ )
+ device(3 D$NMOS
+ device(D$NMOS location(0 1350))
+ connect(0 S S)
+ connect(1 S S)
+ connect(0 G G)
+ connect(1 G G)
+ connect(0 D D)
+ connect(1 D D)
+ connect(0 B B)
+ connect(1 B B)
+ location(1025 650)
+ param(L 0.25)
+ param(W 1.8)
+ param(AS 0.81)
+ param(AD 0.45)
+ param(PS 5.4)
+ param(PD 2.8)
+ terminal(S 6)
+ terminal(G 1)
+ terminal(D 3)
+ terminal(B 6)
+ )
+ device(4 D$NMOS$1
+ device(D$NMOS$1 location(0 1350))
+ connect(0 S S)
+ connect(1 S S)
+ connect(0 G G)
+ connect(1 G G)
+ connect(0 D D)
+ connect(1 D D)
+ connect(0 B B)
+ connect(1 B B)
+ location(1775 650)
+ param(L 0.25)
+ param(W 1.8)
+ param(AS 0.45)
+ param(AD 0.81)
+ param(PS 2.8)
+ param(PD 5.4)
+ terminal(S 3)
+ terminal(G 2)
+ terminal(D 4)
+ terminal(B 6)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Device class section
+ class(PMOS MOS4)
+ class(NMOS MOS4)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(NAND2_WITH_DIODES
+
+ # Nets
+ net(1 name(A))
+ net(2 name(B))
+ net(3 name(OUT))
+ net(4 name(VSS))
+ net(5 name(VDD))
+ net(6 name($1))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(A))
+ pin(2 name(B))
+ pin(3 name(OUT))
+ pin(4 name(VSS))
+ pin(5 name(VDD))
+
+ # Devices and their connections
+ device(1 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 5)
+ terminal(G 2)
+ terminal(D 3)
+ terminal(B 5)
+ )
+ device(2 PMOS
+ name('2')
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 5)
+ terminal(G 1)
+ terminal(D 3)
+ terminal(B 5)
+ )
+ device(3 NMOS
+ name('3')
+ param(L 0.25)
+ param(W 1.8)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 4)
+ terminal(G 2)
+ terminal(D 6)
+ terminal(B 4)
+ )
+ device(4 NMOS
+ name('4')
+ param(L 0.25)
+ param(W 1.8)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 6)
+ terminal(G 1)
+ terminal(D 3)
+ terminal(B 4)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(NAND2_WITH_DIODES NAND2_WITH_DIODES match
+ xref(
+ net(3 6 match)
+ net(2 1 match)
+ net(1 2 match)
+ net(4 3 match)
+ net(5 5 match)
+ net(6 4 match)
+ pin(1 0 match)
+ pin(0 1 match)
+ pin(2 2 match)
+ pin(3 4 match)
+ pin(4 3 match)
+ device(3 3 match)
+ device(4 4 match)
+ device(1 1 match)
+ device(2 2 match)
+ )
+ )
+)
diff --git a/testdata/lvs/ringo_simple_blackboxing.lvsdb b/testdata/lvs/ringo_simple_blackboxing.lvsdb
index 31b71eaba..ac20fdda6 100644
--- a/testdata/lvs/ringo_simple_blackboxing.lvsdb
+++ b/testdata/lvs/ringo_simple_blackboxing.lvsdb
@@ -516,8 +516,8 @@ xref(
net(8 4 match)
net(5 3 match)
net(7 5 match)
- net(6 2 warning)
- net(9 1 warning)
+ net(6 2 match)
+ net(9 1 match)
pin(3 3 match)
pin(0 2 match)
pin(2 4 match)
diff --git a/testdata/lvs/ringo_simple_blackboxing_netter.cir b/testdata/lvs/ringo_simple_blackboxing_netter.cir
new file mode 100644
index 000000000..e6a7e5bcc
--- /dev/null
+++ b/testdata/lvs/ringo_simple_blackboxing_netter.cir
@@ -0,0 +1,70 @@
+* Extracted by KLayout
+
+* cell RINGO
+* pin FB
+* pin VDD
+* pin OUT
+* pin ENABLE
+* pin VSS
+.SUBCKT RINGO 5 6 7 8 9
+* net 5 FB
+* net 6 VDD
+* net 7 OUT
+* net 8 ENABLE
+* net 9 VSS
+* cell instance $1 r0 *1 1.8,0
+X$1 6 1 9 6 5 8 9 ND2X1
+* cell instance $2 r0 *1 4.2,0
+X$2 6 2 9 6 1 9 INVX1
+* cell instance $3 r0 *1 6,0
+X$3 6 10 9 6 2 9 INVX1
+* cell instance $4 r0 *1 16.8,0
+X$4 6 3 9 6 11 9 INVX1
+* cell instance $5 r0 *1 18.6,0
+X$5 6 4 9 6 3 9 INVX1
+* cell instance $6 r0 *1 20.4,0
+X$6 6 5 9 6 4 9 INVX1
+* cell instance $7 r0 *1 22.2,0
+X$7 5 6 7 9 6 9 INVX2
+* cell instance $17 r0 *1 7.8,0
+X$17 6 12 9 6 10 9 INVX1
+* cell instance $18 r0 *1 9.6,0
+X$18 6 13 9 6 12 9 INVX1
+* cell instance $19 r0 *1 11.4,0
+X$19 6 14 9 6 13 9 INVX1
+* cell instance $20 r0 *1 13.2,0
+X$20 6 15 9 6 14 9 INVX1
+* cell instance $21 r0 *1 15,0
+X$21 6 11 9 6 15 9 INVX1
+.ENDS RINGO
+
+* cell INVX2
+* pin IN
+* pin VDD
+* pin OUT
+* pin VSS
+* pin
+* pin BULK
+.SUBCKT INVX2 1 2 3 4 5 6
+.ENDS INVX2
+
+* cell INVX1
+* pin VDD
+* pin OUT
+* pin VSS
+* pin
+* pin IN
+* pin BULK
+.SUBCKT INVX1 1 2 3 4 5 6
+.ENDS INVX1
+
+* cell ND2X1
+* pin VDD
+* pin OUT
+* pin VSS
+* pin
+* pin B
+* pin A
+* pin BULK
+.SUBCKT ND2X1 1 2 3 4 5 6 7
+.ENDS ND2X1
diff --git a/testdata/lvs/ringo_simple_blackboxing_netter.lvs b/testdata/lvs/ringo_simple_blackboxing_netter.lvs
new file mode 100644
index 000000000..4cbbc0591
--- /dev/null
+++ b/testdata/lvs/ringo_simple_blackboxing_netter.lvs
@@ -0,0 +1,87 @@
+
+source($lvs_test_source, "RINGO")
+
+report_lvs($lvs_test_target_lvsdb, true)
+
+target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
+
+schematic("ringo_for_blackboxing.cir")
+
+blank_circuit("INVX1")
+blank_circuit("INVX2")
+blank_circuit("ND2X1")
+
+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
+# and to provide the BULK labels for
+# the abstracts
+
+bulk = labels(13, 0)
+
+# 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.flatten_circuit("INVCHAIN")
+
+netlist.make_top_level_pins
+netlist.purge
+netlist.combine_devices
+netlist.purge_nets
+
+consider_net_names(false)
+
+compare
+
diff --git a/testdata/lvs/ringo_simple_blackboxing_netter.lvsdb b/testdata/lvs/ringo_simple_blackboxing_netter.lvsdb
new file mode 100644
index 000000000..ac20fdda6
--- /dev/null
+++ b/testdata/lvs/ringo_simple_blackboxing_netter.lvsdb
@@ -0,0 +1,540 @@
+#%lvsdb-klayout
+
+# Layout
+layout(
+ top(RINGO)
+ 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 '10/0')
+ layer(l13 '11/0')
+ layer(l7 '13/0')
+ 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(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)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(ND2X1
+
+ # Circuit boundary
+ rect((-100 250) (2600 7750))
+
+ # Outgoing pins and their connections to nets
+ pin(name(VDD))
+ pin(name(OUT))
+ pin(name(VSS))
+ pin()
+ pin(name(B))
+ pin(name(A))
+ pin(name(BULK))
+
+ )
+ circuit(INVX1
+
+ # Circuit boundary
+ rect((-100 250) (2000 7750))
+
+ # Outgoing pins and their connections to nets
+ pin(name(VDD))
+ pin(name(OUT))
+ pin(name(VSS))
+ pin()
+ pin(name(IN))
+ pin(name(BULK))
+
+ )
+ circuit(INVX2
+
+ # Circuit boundary
+ rect((-100 250) (2600 7750))
+
+ # Outgoing pins and their connections to nets
+ pin(name(IN))
+ pin(name(VDD))
+ pin(name(OUT))
+ pin(name(VSS))
+ pin()
+ pin(name(BULK))
+
+ )
+ circuit(RINGO
+
+ # Circuit boundary
+ rect((600 250) (25800 7750))
+
+ # Nets with their geometries
+ net(1
+ rect(l11 (4040 2950) (610 300))
+ )
+ net(2
+ rect(l11 (5550 2950) (900 300))
+ )
+ net(3
+ rect(l11 (18150 2950) (900 300))
+ )
+ net(4
+ rect(l11 (19950 2950) (900 300))
+ )
+ net(5 name(FB)
+ rect(l11 (21750 2950) (900 300))
+ rect(l11 (-19530 590) (320 320))
+ rect(l11 (17820 -320) (320 320))
+ rect(l12 (-18400 -260) (200 200))
+ rect(l12 (17940 -200) (200 200))
+ rect(l13 (-18040 -300) (17740 400))
+ rect(l13 (-17921 -201) (2 2))
+ rect(l13 (-221 -201) (400 400))
+ rect(l13 (17740 -400) (400 400))
+ )
+ net(6 name(VDD)
+ rect(l3 (1100 4500) (1400 3500))
+ rect(l3 (-1900 -3500) (600 3500))
+ rect(l3 (23300 -3500) (1400 3500))
+ rect(l3 (-100 -3500) (600 3500))
+ rect(l8 (-24690 -1240) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (23220 370) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l11 (-22341 859) (2 2))
+ rect(l11 (-1751 -451) (1200 800))
+ rect(l11 (-750 -1450) (300 1400))
+ rect(l11 (-101 -351) (2 2))
+ rect(l11 (-1251 -401) (600 800))
+ rect(l11 (23400 -800) (1200 800))
+ rect(l11 (-750 -1450) (300 1400))
+ rect(l11 (-101 -351) (2 2))
+ rect(l11 (549 -401) (600 800))
+ rect(l9 (-24850 -1500) (500 1500))
+ rect(l9 (22900 -1500) (500 1500))
+ )
+ net(7 name(OUT)
+ rect(l11 (23440 3840) (320 320))
+ rect(l12 (-260 -260) (200 200))
+ rect(l13 (-101 -101) (2 2))
+ rect(l13 (-201 -201) (400 400))
+ )
+ net(8 name(ENABLE)
+ rect(l11 (2440 2940) (320 320))
+ rect(l12 (-260 -260) (200 200))
+ rect(l13 (-101 -101) (2 2))
+ rect(l13 (-201 -201) (400 400))
+ )
+ net(9 name(VSS)
+ rect(l8 (1710 1610) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (23220 370) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l11 (-22341 -391) (2 2))
+ rect(l11 (-1301 -401) (300 1400))
+ rect(l11 (-750 -1450) (1200 800))
+ rect(l11 (-551 -401) (2 2))
+ rect(l11 (-1251 -401) (600 800))
+ rect(l11 (23850 -750) (300 1400))
+ rect(l11 (-750 -1450) (1200 800))
+ rect(l11 (-551 -401) (2 2))
+ rect(l11 (549 -401) (600 800))
+ rect(l10 (-24850 -800) (500 1500))
+ rect(l10 (22900 -1500) (500 1500))
+ )
+ net(10
+ rect(l11 (7350 2950) (900 300))
+ )
+ net(11
+ rect(l11 (16350 2950) (900 300))
+ )
+ net(12
+ rect(l11 (9150 2950) (900 300))
+ )
+ net(13
+ rect(l11 (10950 2950) (900 300))
+ )
+ net(14
+ rect(l11 (12750 2950) (900 300))
+ )
+ net(15
+ rect(l11 (14550 2950) (900 300))
+ )
+
+ # Outgoing pins and their connections to nets
+ pin(5 name(FB))
+ pin(6 name(VDD))
+ pin(7 name(OUT))
+ pin(8 name(ENABLE))
+ pin(9 name(VSS))
+
+ # Subcircuits and their connections
+ circuit(1 ND2X1 location(1800 0)
+ pin(0 6)
+ pin(1 1)
+ pin(2 9)
+ pin(3 6)
+ pin(4 5)
+ pin(5 8)
+ pin(6 9)
+ )
+ circuit(2 INVX1 location(4200 0)
+ pin(0 6)
+ pin(1 2)
+ pin(2 9)
+ pin(3 6)
+ pin(4 1)
+ pin(5 9)
+ )
+ circuit(3 INVX1 location(6000 0)
+ pin(0 6)
+ pin(1 10)
+ pin(2 9)
+ pin(3 6)
+ pin(4 2)
+ pin(5 9)
+ )
+ circuit(4 INVX1 location(16800 0)
+ pin(0 6)
+ pin(1 3)
+ pin(2 9)
+ pin(3 6)
+ pin(4 11)
+ pin(5 9)
+ )
+ circuit(5 INVX1 location(18600 0)
+ pin(0 6)
+ pin(1 4)
+ pin(2 9)
+ pin(3 6)
+ pin(4 3)
+ pin(5 9)
+ )
+ circuit(6 INVX1 location(20400 0)
+ pin(0 6)
+ pin(1 5)
+ pin(2 9)
+ pin(3 6)
+ pin(4 4)
+ pin(5 9)
+ )
+ circuit(7 INVX2 location(22200 0)
+ pin(0 5)
+ pin(1 6)
+ pin(2 7)
+ pin(3 9)
+ pin(4 6)
+ pin(5 9)
+ )
+ circuit(17 INVX1 location(7800 0)
+ pin(0 6)
+ pin(1 12)
+ pin(2 9)
+ pin(3 6)
+ pin(4 10)
+ pin(5 9)
+ )
+ circuit(18 INVX1 location(9600 0)
+ pin(0 6)
+ pin(1 13)
+ pin(2 9)
+ pin(3 6)
+ pin(4 12)
+ pin(5 9)
+ )
+ circuit(19 INVX1 location(11400 0)
+ pin(0 6)
+ pin(1 14)
+ pin(2 9)
+ pin(3 6)
+ pin(4 13)
+ pin(5 9)
+ )
+ circuit(20 INVX1 location(13200 0)
+ pin(0 6)
+ pin(1 15)
+ pin(2 9)
+ pin(3 6)
+ pin(4 14)
+ pin(5 9)
+ )
+ circuit(21 INVX1 location(15000 0)
+ pin(0 6)
+ pin(1 11)
+ pin(2 9)
+ pin(3 6)
+ pin(4 15)
+ pin(5 9)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Device class section
+ class(PMOS MOS4)
+ class(NMOS MOS4)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(ND2X1
+
+ # Outgoing pins and their connections to nets
+ pin(name(VDD))
+ pin(name(OUT))
+ pin(name(VSS))
+ pin(name(NWELL))
+ pin(name(B))
+ pin(name(A))
+ pin(name(BULK))
+
+ )
+ circuit(INVX1
+
+ # Outgoing pins and their connections to nets
+ pin(name(VDD))
+ pin(name(OUT))
+ pin(name(VSS))
+ pin(name(NWELL))
+ pin(name(IN))
+ pin(name(BULK))
+
+ )
+ circuit(INVX2
+
+ # Outgoing pins and their connections to nets
+ pin(name(VDD))
+ pin(name(OUT))
+ pin(name(VSS))
+ pin(name(NWELL))
+ pin(name(IN))
+ pin(name(BULK))
+
+ )
+ circuit(RINGO
+
+ # Nets
+ net(1 name(VSS))
+ net(2 name(VDD))
+ net(3 name(FB))
+ net(4 name(ENABLE))
+ net(5 name(OUT))
+ net(6 name('1'))
+ net(7 name('2'))
+ net(8 name('3'))
+ net(9 name('4'))
+ net(10 name('5'))
+ net(11 name('6'))
+ net(12 name('7'))
+ net(13 name('8'))
+ net(14 name('9'))
+ net(15 name('10'))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VSS))
+ pin(2 name(VDD))
+ pin(3 name(FB))
+ pin(4 name(ENABLE))
+ pin(5 name(OUT))
+
+ # Subcircuits and their connections
+ circuit(1 ND2X1 name($1)
+ pin(0 2)
+ pin(1 6)
+ pin(2 1)
+ pin(3 2)
+ pin(4 3)
+ pin(5 4)
+ pin(6 1)
+ )
+ circuit(2 INVX1 name($2)
+ pin(0 2)
+ pin(1 7)
+ pin(2 1)
+ pin(3 2)
+ pin(4 6)
+ pin(5 1)
+ )
+ circuit(3 INVX1 name($3)
+ pin(0 2)
+ pin(1 8)
+ pin(2 1)
+ pin(3 2)
+ pin(4 7)
+ pin(5 1)
+ )
+ circuit(4 INVX1 name($4)
+ pin(0 2)
+ pin(1 9)
+ pin(2 1)
+ pin(3 2)
+ pin(4 8)
+ pin(5 1)
+ )
+ circuit(5 INVX1 name($5)
+ pin(0 2)
+ pin(1 10)
+ pin(2 1)
+ pin(3 2)
+ pin(4 9)
+ pin(5 1)
+ )
+ circuit(6 INVX1 name($6)
+ pin(0 2)
+ pin(1 11)
+ pin(2 1)
+ pin(3 2)
+ pin(4 10)
+ pin(5 1)
+ )
+ circuit(7 INVX1 name($7)
+ pin(0 2)
+ pin(1 12)
+ pin(2 1)
+ pin(3 2)
+ pin(4 11)
+ pin(5 1)
+ )
+ circuit(8 INVX1 name($8)
+ pin(0 2)
+ pin(1 13)
+ pin(2 1)
+ pin(3 2)
+ pin(4 12)
+ pin(5 1)
+ )
+ circuit(9 INVX1 name($9)
+ pin(0 2)
+ pin(1 14)
+ pin(2 1)
+ pin(3 2)
+ pin(4 13)
+ pin(5 1)
+ )
+ circuit(10 INVX1 name($10)
+ pin(0 2)
+ pin(1 15)
+ pin(2 1)
+ pin(3 2)
+ pin(4 14)
+ pin(5 1)
+ )
+ circuit(11 INVX1 name($11)
+ pin(0 2)
+ pin(1 3)
+ pin(2 1)
+ pin(3 2)
+ pin(4 15)
+ pin(5 1)
+ )
+ circuit(12 INVX2 name($12)
+ pin(0 2)
+ pin(1 5)
+ pin(2 1)
+ pin(3 2)
+ pin(4 3)
+ pin(5 1)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(INVX1 INVX1 match
+ xref(
+ pin(3 3 match)
+ pin(5 5 match)
+ pin(4 4 match)
+ pin(1 1 match)
+ pin(0 0 match)
+ pin(2 2 match)
+ )
+ )
+ circuit(INVX2 INVX2 match
+ xref(
+ pin(4 3 match)
+ pin(5 5 match)
+ pin(0 4 match)
+ pin(2 1 match)
+ pin(1 0 match)
+ pin(3 2 match)
+ )
+ )
+ circuit(ND2X1 ND2X1 match
+ xref(
+ pin(3 3 match)
+ pin(5 5 match)
+ pin(4 4 match)
+ pin(6 6 match)
+ pin(1 1 match)
+ pin(0 0 match)
+ pin(2 2 match)
+ )
+ )
+ circuit(RINGO RINGO match
+ xref(
+ net(1 6 match)
+ net(4 15 match)
+ net(2 7 match)
+ net(10 8 match)
+ net(12 9 match)
+ net(13 10 match)
+ net(14 11 match)
+ net(15 12 match)
+ net(11 13 match)
+ net(3 14 match)
+ net(8 4 match)
+ net(5 3 match)
+ net(7 5 match)
+ net(6 2 match)
+ net(9 1 match)
+ pin(3 3 match)
+ pin(0 2 match)
+ pin(2 4 match)
+ pin(1 1 match)
+ pin(4 0 match)
+ circuit(2 2 match)
+ circuit(3 3 match)
+ circuit(17 4 match)
+ circuit(18 5 match)
+ circuit(19 6 match)
+ circuit(20 7 match)
+ circuit(21 8 match)
+ circuit(4 9 match)
+ circuit(5 10 match)
+ circuit(6 11 match)
+ circuit(7 12 match)
+ circuit(1 1 match)
+ )
+ )
+)
diff --git a/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvsdb.1 b/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvsdb.1
index a43d6f458..638555d57 100644
--- a/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvsdb.1
+++ b/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvsdb.1
@@ -881,6 +881,7 @@ xref(
net(7 12 match)
net(8 13 match)
net(9 14 match)
+ net(14 4 match)
net(11 3 match)
net(13 5 match)
net(12 2 match)
diff --git a/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvsdb.2 b/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvsdb.2
index 04e80f7d8..a2b8e370d 100644
--- a/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvsdb.2
+++ b/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvsdb.2
@@ -881,6 +881,7 @@ xref(
net(7 12 match)
net(8 13 match)
net(9 14 match)
+ net(14 4 match)
net(11 3 match)
net(13 5 match)
net(12 2 match)
diff --git a/testdata/lvs/ringo_simple_with_tol_early.cir b/testdata/lvs/ringo_simple_with_tol_early.cir
new file mode 100644
index 000000000..761afb771
--- /dev/null
+++ b/testdata/lvs/ringo_simple_with_tol_early.cir
@@ -0,0 +1,83 @@
+* Extracted by KLayout
+
+* cell RINGO
+* pin FB
+* pin VDD
+* pin OUT
+* pin ENABLE
+* pin VSS
+.SUBCKT RINGO 11 12 13 14 15
+* net 11 FB
+* net 12 VDD
+* net 13 OUT
+* net 14 ENABLE
+* net 15 VSS
+* cell instance $1 r0 *1 1.8,0
+X$1 12 1 15 12 11 14 15 ND2X1
+* cell instance $2 r0 *1 4.2,0
+X$2 12 2 15 12 1 15 INVX1
+* cell instance $3 r0 *1 6,0
+X$3 12 3 15 12 2 15 INVX1
+* cell instance $4 r0 *1 7.8,0
+X$4 12 4 15 12 3 15 INVX1
+* cell instance $5 r0 *1 9.6,0
+X$5 12 5 15 12 4 15 INVX1
+* cell instance $6 r0 *1 11.4,0
+X$6 12 6 15 12 5 15 INVX1
+* cell instance $7 r0 *1 13.2,0
+X$7 12 7 15 12 6 15 INVX1
+* cell instance $8 r0 *1 15,0
+X$8 12 8 15 12 7 15 INVX1
+* cell instance $9 r0 *1 16.8,0
+X$9 12 9 15 12 8 15 INVX1
+* cell instance $10 r0 *1 18.6,0
+X$10 12 10 15 12 9 15 INVX1
+* cell instance $11 r0 *1 20.4,0
+X$11 12 11 15 12 10 15 INVX1
+* cell instance $12 r0 *1 22.2,0
+X$12 12 13 15 12 11 15 INVX1
+.ENDS RINGO
+
+* cell INVX1
+* pin VDD
+* pin OUT
+* pin VSS
+* pin
+* pin IN
+* pin SUBSTRATE
+.SUBCKT INVX1 1 2 3 4 5 6
+* net 1 VDD
+* net 2 OUT
+* net 3 VSS
+* net 5 IN
+* net 6 SUBSTRATE
+* device instance $1 r0 *1 0.85,5.8 PMOS
+M$1 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
+* device instance $2 r0 *1 0.85,2.135 NMOS
+M$2 3 5 2 6 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
+.ENDS INVX1
+
+* cell ND2X1
+* pin VDD
+* pin OUT
+* pin VSS
+* pin
+* pin B
+* pin A
+* pin SUBSTRATE
+.SUBCKT ND2X1 1 2 3 4 5 6 7
+* net 1 VDD
+* net 2 OUT
+* net 3 VSS
+* net 5 B
+* net 6 A
+* net 7 SUBSTRATE
+* device instance $1 r0 *1 0.85,5.8 PMOS
+M$1 2 6 1 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.3375P PS=3.85U PD=1.95U
+* device instance $2 r0 *1 1.55,5.8 PMOS
+M$2 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.3375P AD=0.6375P PS=1.95U PD=3.85U
+* device instance $3 r0 *1 0.85,2.135 NMOS
+M$3 3 6 8 7 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.21375P PS=2.75U PD=1.4U
+* device instance $4 r0 *1 1.55,2.135 NMOS
+M$4 8 5 2 7 NMOS L=0.25U W=0.95U AS=0.21375P AD=0.40375P PS=1.4U PD=2.75U
+.ENDS ND2X1
diff --git a/testdata/lvs/ringo_simple_with_tol_early.lvs b/testdata/lvs/ringo_simple_with_tol_early.lvs
new file mode 100644
index 000000000..7f8fcef72
--- /dev/null
+++ b/testdata/lvs/ringo_simple_with_tol_early.lvs
@@ -0,0 +1,79 @@
+
+source($lvs_test_source, "RINGO")
+
+report_lvs($lvs_test_target_lvsdb, true)
+
+target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
+
+schematic("ringo_off_target.cir")
+
+tolerance("PMOS", "L", 0.001) # absolute
+tolerance("PMOS", "W", 0.01, 0.1) # relative + absolute
+tolerance("NMOS", "L", :absolute => 0.01)
+tolerance("NMOS", "W", :relative => 0.07)
+
+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
+
+compare
+
diff --git a/testdata/lvs/ringo_simple_with_tol_early.lvsdb.1 b/testdata/lvs/ringo_simple_with_tol_early.lvsdb.1
new file mode 100644
index 000000000..51c6fe9e2
--- /dev/null
+++ b/testdata/lvs/ringo_simple_with_tol_early.lvsdb.1
@@ -0,0 +1,908 @@
+#%lvsdb-klayout
+
+# Layout
+layout(
+ top(RINGO)
+ 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 '10/0')
+ layer(l13 '11/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) (450 1500))
+ )
+ terminal(B
+ rect(l3 (-125 -750) (250 1500))
+ )
+ )
+ device(D$PMOS$1 PMOS
+ terminal(S
+ rect(l2 (-575 -750) (450 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$PMOS$2 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) (450 950))
+ )
+ terminal(B
+ rect(l7 (-125 -475) (250 950))
+ )
+ )
+ device(D$NMOS$1 NMOS
+ terminal(S
+ rect(l6 (-575 -475) (450 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))
+ )
+ )
+ device(D$NMOS$2 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(ND2X1
+
+ # Circuit boundary
+ rect((-100 400) (2600 7600))
+
+ # Nets with their geometries
+ net(1 name(VDD)
+ rect(l8 (1110 5160) (180 180))
+ rect(l8 (-180 920) (180 180))
+ rect(l8 (-180 -730) (180 180))
+ rect(l11 (-240 -790) (300 1700))
+ rect(l11 (-1350 0) (2400 800))
+ rect(l11 (-1151 -401) (2 2))
+ rect(l2 (-276 -2151) (425 1500))
+ rect(l2 (-400 -1500) (425 1500))
+ )
+ net(2 name(OUT)
+ rect(l8 (1810 1770) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (-1580 3760) (180 180))
+ rect(l8 (-180 -730) (180 180))
+ rect(l8 (-180 -730) (180 180))
+ rect(l8 (1220 920) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (-180 370) (180 180))
+ polygon(l11 (-240 -4180) (0 1390) (490 0) (0 -300) (-190 0) (0 -1090))
+ rect(l11 (-110 1390) (300 1400))
+ polygon(l11 (-1890 0) (0 600) (300 0) (0 -300) (1590 0) (0 -300))
+ rect(l11 (-141 -501) (2 2))
+ rect(l11 (-1751 1099) (300 1400))
+ rect(l11 (1100 -1700) (300 300))
+ rect(l11 (-300 0) (300 1400))
+ rect(l2 (-1750 -1450) (425 1500))
+ rect(l2 (950 -1500) (425 1500))
+ rect(l6 (-425 -4890) (425 950))
+ )
+ net(3 name(VSS)
+ rect(l8 (410 1770) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l11 (-240 -1300) (300 1360))
+ rect(l11 (-650 -2160) (2400 800))
+ rect(l11 (-1151 -401) (2 2))
+ rect(l6 (-951 859) (425 950))
+ )
+ net(4
+ rect(l3 (-100 4500) (2600 3500))
+ )
+ net(5 name(B)
+ rect(l4 (1425 2860) (250 1940))
+ rect(l4 (-345 -950) (300 300))
+ rect(l4 (-205 650) (250 2000))
+ rect(l4 (-250 -2000) (250 2000))
+ rect(l4 (-250 -5390) (250 1450))
+ rect(l8 (-285 1050) (180 180))
+ rect(l11 (-71 -91) (2 2))
+ rect(l11 (-171 -151) (300 300))
+ )
+ net(6 name(A)
+ rect(l4 (725 2860) (250 1940))
+ rect(l4 (-325 -1850) (300 300))
+ rect(l4 (-225 1550) (250 2000))
+ rect(l4 (-250 -2000) (250 2000))
+ rect(l4 (-250 -5390) (250 1450))
+ rect(l8 (-265 150) (180 180))
+ rect(l11 (-91 -91) (2 2))
+ rect(l11 (-151 -151) (300 300))
+ )
+ net(7 name(SUBSTRATE))
+ net(8
+ rect(l6 (975 1660) (425 950))
+ rect(l6 (-400 -950) (425 950))
+ )
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VDD))
+ pin(2 name(OUT))
+ pin(3 name(VSS))
+ pin(4)
+ pin(5 name(B))
+ pin(6 name(A))
+ pin(7 name(SUBSTRATE))
+
+ # Devices and their connections
+ device(1 D$PMOS
+ location(850 5800)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0.6375)
+ param(AD 0.3375)
+ param(PS 3.85)
+ param(PD 1.95)
+ terminal(S 2)
+ terminal(G 6)
+ terminal(D 1)
+ terminal(B 4)
+ )
+ device(2 D$PMOS$1
+ location(1550 5800)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0.3375)
+ param(AD 0.6375)
+ param(PS 1.95)
+ param(PD 3.85)
+ terminal(S 1)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 4)
+ )
+ device(3 D$NMOS
+ location(850 2135)
+ param(L 0.25)
+ param(W 0.95)
+ param(AS 0.40375)
+ param(AD 0.21375)
+ param(PS 2.75)
+ param(PD 1.4)
+ terminal(S 3)
+ terminal(G 6)
+ terminal(D 8)
+ terminal(B 7)
+ )
+ device(4 D$NMOS$1
+ location(1550 2135)
+ param(L 0.25)
+ param(W 0.95)
+ param(AS 0.21375)
+ param(AD 0.40375)
+ param(PS 1.4)
+ param(PD 2.75)
+ terminal(S 8)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 7)
+ )
+
+ )
+ circuit(INVX1
+
+ # Circuit boundary
+ rect((-100 400) (2000 7600))
+
+ # Nets with their geometries
+ net(1 name(VDD)
+ rect(l8 (410 6260) (180 180))
+ rect(l8 (-180 -730) (180 180))
+ rect(l8 (-180 -730) (180 180))
+ rect(l11 (-240 -240) (300 1400))
+ rect(l11 (-650 300) (1800 800))
+ rect(l11 (-1450 -1100) (300 300))
+ rect(l11 (299 399) (2 2))
+ rect(l2 (-651 -2151) (425 1500))
+ )
+ net(2 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(3 name(VSS)
+ rect(l8 (410 1770) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l11 (-240 -1300) (300 1360))
+ rect(l11 (-650 -2160) (1800 800))
+ rect(l11 (-851 -401) (2 2))
+ rect(l6 (-651 859) (425 950))
+ )
+ net(4
+ rect(l3 (-100 4500) (2000 3500))
+ )
+ net(5 name(IN)
+ rect(l4 (725 2860) (250 1940))
+ rect(l4 (-525 -1850) (300 300))
+ rect(l4 (-25 1550) (250 2000))
+ rect(l4 (-250 -2000) (250 2000))
+ rect(l4 (-250 -5390) (250 1450))
+ rect(l8 (-465 150) (180 180))
+ rect(l11 (-91 -91) (2 2))
+ rect(l11 (-151 -151) (300 300))
+ )
+ net(6 name(SUBSTRATE))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VDD))
+ pin(2 name(OUT))
+ pin(3 name(VSS))
+ pin(4)
+ pin(5 name(IN))
+ pin(6 name(SUBSTRATE))
+
+ # Devices and their connections
+ device(1 D$PMOS$2
+ 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 1)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 4)
+ )
+ device(2 D$NMOS$2
+ 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 3)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 6)
+ )
+
+ )
+ circuit(RINGO
+
+ # Circuit boundary
+ rect((0 350) (25800 7650))
+
+ # Nets with their geometries
+ net(1
+ rect(l11 (4040 2950) (610 300))
+ )
+ net(2
+ rect(l11 (5550 2950) (900 300))
+ )
+ net(3
+ rect(l11 (7350 2950) (900 300))
+ )
+ net(4
+ rect(l11 (9150 2950) (900 300))
+ )
+ net(5
+ rect(l11 (10950 2950) (900 300))
+ )
+ net(6
+ rect(l11 (12750 2950) (900 300))
+ )
+ net(7
+ rect(l11 (14550 2950) (900 300))
+ )
+ net(8
+ rect(l11 (16350 2950) (900 300))
+ )
+ net(9
+ rect(l11 (18150 2950) (900 300))
+ )
+ net(10
+ rect(l11 (19950 2950) (900 300))
+ )
+ net(11 name(FB)
+ rect(l11 (21750 2950) (900 300))
+ rect(l11 (-19530 590) (320 320))
+ rect(l11 (17820 -320) (320 320))
+ rect(l12 (-18400 -260) (200 200))
+ rect(l12 (17940 -200) (200 200))
+ rect(l13 (-18040 -300) (17740 400))
+ rect(l13 (-17921 -201) (2 2))
+ rect(l13 (-221 -201) (400 400))
+ rect(l13 (17740 -400) (400 400))
+ )
+ net(12 name(VDD)
+ rect(l3 (500 4500) (1400 3500))
+ rect(l3 (-1900 -3500) (600 3500))
+ rect(l3 (23300 -3500) (1400 3500))
+ rect(l3 (-100 -3500) (600 3500))
+ rect(l8 (-24690 -1240) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (23220 370) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l11 (-21741 859) (2 2))
+ rect(l11 (-2351 -451) (1200 800))
+ rect(l11 (-750 -1450) (300 1400))
+ rect(l11 (-101 -351) (2 2))
+ rect(l11 (-1251 -401) (600 800))
+ rect(l11 (23400 -800) (1200 800))
+ rect(l11 (-750 -1450) (300 1400))
+ rect(l11 (-101 -351) (2 2))
+ rect(l11 (549 -401) (600 800))
+ rect(l9 (-24850 -1500) (500 1500))
+ rect(l9 (22900 -1500) (500 1500))
+ )
+ net(13 name(OUT)
+ rect(l11 (23440 3840) (320 320))
+ rect(l12 (-260 -260) (200 200))
+ rect(l13 (-101 -101) (2 2))
+ rect(l13 (-201 -201) (400 400))
+ )
+ net(14 name(ENABLE)
+ rect(l11 (2440 2940) (320 320))
+ rect(l12 (-260 -260) (200 200))
+ rect(l13 (-101 -101) (2 2))
+ rect(l13 (-201 -201) (400 400))
+ )
+ net(15 name(VSS)
+ rect(l8 (1110 1610) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (23220 370) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l11 (-21741 -391) (2 2))
+ rect(l11 (-1901 -401) (300 1400))
+ rect(l11 (-750 -1450) (1200 800))
+ rect(l11 (-551 -401) (2 2))
+ rect(l11 (-1251 -401) (600 800))
+ rect(l11 (23850 -750) (300 1400))
+ rect(l11 (-750 -1450) (1200 800))
+ rect(l11 (-551 -401) (2 2))
+ rect(l11 (549 -401) (600 800))
+ rect(l10 (-24850 -800) (500 1500))
+ rect(l10 (22900 -1500) (500 1500))
+ )
+
+ # Outgoing pins and their connections to nets
+ pin(11 name(FB))
+ pin(12 name(VDD))
+ pin(13 name(OUT))
+ pin(14 name(ENABLE))
+ pin(15 name(VSS))
+
+ # Subcircuits and their connections
+ circuit(1 ND2X1 location(1800 0)
+ pin(0 12)
+ pin(1 1)
+ pin(2 15)
+ pin(3 12)
+ pin(4 11)
+ pin(5 14)
+ pin(6 15)
+ )
+ circuit(2 INVX1 location(4200 0)
+ pin(0 12)
+ pin(1 2)
+ pin(2 15)
+ pin(3 12)
+ pin(4 1)
+ pin(5 15)
+ )
+ circuit(3 INVX1 location(6000 0)
+ pin(0 12)
+ pin(1 3)
+ pin(2 15)
+ pin(3 12)
+ pin(4 2)
+ pin(5 15)
+ )
+ circuit(4 INVX1 location(7800 0)
+ pin(0 12)
+ pin(1 4)
+ pin(2 15)
+ pin(3 12)
+ pin(4 3)
+ pin(5 15)
+ )
+ circuit(5 INVX1 location(9600 0)
+ pin(0 12)
+ pin(1 5)
+ pin(2 15)
+ pin(3 12)
+ pin(4 4)
+ pin(5 15)
+ )
+ circuit(6 INVX1 location(11400 0)
+ pin(0 12)
+ pin(1 6)
+ pin(2 15)
+ pin(3 12)
+ pin(4 5)
+ pin(5 15)
+ )
+ circuit(7 INVX1 location(13200 0)
+ pin(0 12)
+ pin(1 7)
+ pin(2 15)
+ pin(3 12)
+ pin(4 6)
+ pin(5 15)
+ )
+ circuit(8 INVX1 location(15000 0)
+ pin(0 12)
+ pin(1 8)
+ pin(2 15)
+ pin(3 12)
+ pin(4 7)
+ pin(5 15)
+ )
+ circuit(9 INVX1 location(16800 0)
+ pin(0 12)
+ pin(1 9)
+ pin(2 15)
+ pin(3 12)
+ pin(4 8)
+ pin(5 15)
+ )
+ circuit(10 INVX1 location(18600 0)
+ pin(0 12)
+ pin(1 10)
+ pin(2 15)
+ pin(3 12)
+ pin(4 9)
+ pin(5 15)
+ )
+ circuit(11 INVX1 location(20400 0)
+ pin(0 12)
+ pin(1 11)
+ pin(2 15)
+ pin(3 12)
+ pin(4 10)
+ pin(5 15)
+ )
+ circuit(12 INVX1 location(22200 0)
+ pin(0 12)
+ pin(1 13)
+ pin(2 15)
+ pin(3 12)
+ pin(4 11)
+ pin(5 15)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Device class section
+ class(PMOS MOS4)
+ class(NMOS MOS4)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(ND2X1
+
+ # Nets
+ net(1 name(VDD))
+ net(2 name(OUT))
+ net(3 name(VSS))
+ net(4 name(NWELL))
+ net(5 name(B))
+ net(6 name(A))
+ net(7 name(BULK))
+ net(8 name('1'))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VDD))
+ pin(2 name(OUT))
+ pin(3 name(VSS))
+ pin(4 name(NWELL))
+ pin(5 name(B))
+ pin(6 name(A))
+ pin(7 name(BULK))
+
+ # Devices and their connections
+ device(1 PMOS
+ name($1)
+ param(L 0.251)
+ param(W 1.6)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 2)
+ terminal(G 6)
+ terminal(D 1)
+ terminal(B 4)
+ )
+ device(2 PMOS
+ name($2)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 1)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 4)
+ )
+ device(3 NMOS
+ name($3)
+ param(L 0.26)
+ param(W 1)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 3)
+ terminal(G 6)
+ terminal(D 8)
+ terminal(B 7)
+ )
+ device(4 NMOS
+ name($4)
+ param(L 0.25)
+ param(W 0.95)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 8)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 7)
+ )
+
+ )
+ circuit(INVX1
+
+ # Nets
+ net(1 name(VDD))
+ net(2 name(OUT))
+ net(3 name(VSS))
+ net(4 name(NWELL))
+ net(5 name(IN))
+ net(6 name(BULK))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VDD))
+ pin(2 name(OUT))
+ pin(3 name(VSS))
+ pin(4 name(NWELL))
+ pin(5 name(IN))
+ pin(6 name(BULK))
+
+ # Devices and their connections
+ device(1 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 1)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 4)
+ )
+ device(2 NMOS
+ name($2)
+ param(L 0.25)
+ param(W 0.95)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 3)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 6)
+ )
+
+ )
+ circuit(RINGO
+
+ # Nets
+ net(1 name(VSS))
+ net(2 name(VDD))
+ net(3 name(FB))
+ net(4 name(ENABLE))
+ net(5 name(OUT))
+ net(6 name('1'))
+ net(7 name('2'))
+ net(8 name('3'))
+ net(9 name('4'))
+ net(10 name('5'))
+ net(11 name('6'))
+ net(12 name('7'))
+ net(13 name('8'))
+ net(14 name('9'))
+ net(15 name('10'))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VSS))
+ pin(2 name(VDD))
+ pin(3 name(FB))
+ pin(4 name(ENABLE))
+ pin(5 name(OUT))
+
+ # Subcircuits and their connections
+ circuit(1 ND2X1 name($1)
+ pin(0 2)
+ pin(1 6)
+ pin(2 1)
+ pin(3 2)
+ pin(4 3)
+ pin(5 4)
+ pin(6 1)
+ )
+ circuit(2 INVX1 name($2)
+ pin(0 2)
+ pin(1 7)
+ pin(2 1)
+ pin(3 2)
+ pin(4 6)
+ pin(5 1)
+ )
+ circuit(3 INVX1 name($3)
+ pin(0 2)
+ pin(1 8)
+ pin(2 1)
+ pin(3 2)
+ pin(4 7)
+ pin(5 1)
+ )
+ circuit(4 INVX1 name($4)
+ pin(0 2)
+ pin(1 9)
+ pin(2 1)
+ pin(3 2)
+ pin(4 8)
+ pin(5 1)
+ )
+ circuit(5 INVX1 name($5)
+ pin(0 2)
+ pin(1 10)
+ pin(2 1)
+ pin(3 2)
+ pin(4 9)
+ pin(5 1)
+ )
+ circuit(6 INVX1 name($6)
+ pin(0 2)
+ pin(1 11)
+ pin(2 1)
+ pin(3 2)
+ pin(4 10)
+ pin(5 1)
+ )
+ circuit(7 INVX1 name($7)
+ pin(0 2)
+ pin(1 12)
+ pin(2 1)
+ pin(3 2)
+ pin(4 11)
+ pin(5 1)
+ )
+ circuit(8 INVX1 name($8)
+ pin(0 2)
+ pin(1 13)
+ pin(2 1)
+ pin(3 2)
+ pin(4 12)
+ pin(5 1)
+ )
+ circuit(9 INVX1 name($9)
+ pin(0 2)
+ pin(1 14)
+ pin(2 1)
+ pin(3 2)
+ pin(4 13)
+ pin(5 1)
+ )
+ circuit(10 INVX1 name($10)
+ pin(0 2)
+ pin(1 15)
+ pin(2 1)
+ pin(3 2)
+ pin(4 14)
+ pin(5 1)
+ )
+ circuit(11 INVX1 name($11)
+ pin(0 2)
+ pin(1 3)
+ pin(2 1)
+ pin(3 2)
+ pin(4 15)
+ pin(5 1)
+ )
+ circuit(12 INVX1 name($12)
+ pin(0 2)
+ pin(1 5)
+ pin(2 1)
+ pin(3 2)
+ pin(4 3)
+ pin(5 1)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(INVX1 INVX1 match
+ xref(
+ net(4 4 match)
+ net(5 5 match)
+ net(2 2 match)
+ net(6 6 match)
+ net(1 1 match)
+ net(3 3 match)
+ pin(3 3 match)
+ pin(4 4 match)
+ pin(1 1 match)
+ pin(5 5 match)
+ pin(0 0 match)
+ pin(2 2 match)
+ device(2 2 match)
+ device(1 1 match)
+ )
+ )
+ circuit(ND2X1 ND2X1 match
+ xref(
+ net(8 8 match)
+ net(4 4 match)
+ net(6 6 match)
+ net(5 5 match)
+ net(2 2 match)
+ net(7 7 match)
+ net(1 1 match)
+ net(3 3 match)
+ pin(3 3 match)
+ pin(5 5 match)
+ pin(4 4 match)
+ pin(1 1 match)
+ pin(6 6 match)
+ pin(0 0 match)
+ pin(2 2 match)
+ device(3 3 match)
+ device(4 4 match)
+ device(1 1 match)
+ device(2 2 match)
+ )
+ )
+ circuit(RINGO RINGO match
+ xref(
+ net(1 6 match)
+ net(10 15 match)
+ net(2 7 match)
+ net(3 8 match)
+ net(4 9 match)
+ net(5 10 match)
+ net(6 11 match)
+ net(7 12 match)
+ net(8 13 match)
+ net(9 14 match)
+ net(14 4 match)
+ net(11 3 match)
+ net(13 5 match)
+ net(12 2 match)
+ net(15 1 match)
+ pin(3 3 match)
+ pin(0 2 match)
+ pin(2 4 match)
+ pin(1 1 match)
+ pin(4 0 match)
+ circuit(2 2 match)
+ circuit(3 3 match)
+ circuit(4 4 match)
+ circuit(5 5 match)
+ circuit(6 6 match)
+ circuit(7 7 match)
+ circuit(8 8 match)
+ circuit(9 9 match)
+ circuit(10 10 match)
+ circuit(11 11 match)
+ circuit(12 12 match)
+ circuit(1 1 match)
+ )
+ )
+)
diff --git a/testdata/lvs/ringo_simple_with_tol_early.lvsdb.2 b/testdata/lvs/ringo_simple_with_tol_early.lvsdb.2
new file mode 100644
index 000000000..372bf323d
--- /dev/null
+++ b/testdata/lvs/ringo_simple_with_tol_early.lvsdb.2
@@ -0,0 +1,908 @@
+#%lvsdb-klayout
+
+# Layout
+layout(
+ top(RINGO)
+ 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 '10/0')
+ layer(l13 '11/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) (450 1500))
+ )
+ terminal(B
+ rect(l3 (-125 -750) (250 1500))
+ )
+ )
+ device(D$PMOS$1 PMOS
+ terminal(S
+ rect(l2 (-575 -750) (450 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$PMOS$2 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) (450 950))
+ )
+ terminal(B
+ rect(l7 (-125 -475) (250 950))
+ )
+ )
+ device(D$NMOS$1 NMOS
+ terminal(S
+ rect(l6 (-575 -475) (450 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))
+ )
+ )
+ device(D$NMOS$2 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(ND2X1
+
+ # Circuit boundary
+ rect((-100 400) (2600 7600))
+
+ # Nets with their geometries
+ net(1 name(VDD)
+ rect(l8 (1110 5160) (180 180))
+ rect(l8 (-180 920) (180 180))
+ rect(l8 (-180 -730) (180 180))
+ rect(l11 (-240 -790) (300 1700))
+ rect(l11 (-1350 0) (2400 800))
+ rect(l11 (-1151 -401) (2 2))
+ rect(l2 (-276 -2151) (425 1500))
+ rect(l2 (-400 -1500) (425 1500))
+ )
+ net(2 name(OUT)
+ rect(l8 (1810 1770) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (-1580 3760) (180 180))
+ rect(l8 (-180 -730) (180 180))
+ rect(l8 (-180 -730) (180 180))
+ rect(l8 (1220 920) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (-180 370) (180 180))
+ polygon(l11 (-240 -4180) (0 1390) (490 0) (0 -300) (-190 0) (0 -1090))
+ rect(l11 (-110 1390) (300 1400))
+ polygon(l11 (-1890 0) (0 600) (300 0) (0 -300) (1590 0) (0 -300))
+ rect(l11 (-141 -501) (2 2))
+ rect(l11 (-1751 1099) (300 1400))
+ rect(l11 (1100 -1700) (300 300))
+ rect(l11 (-300 0) (300 1400))
+ rect(l2 (-375 -1450) (425 1500))
+ rect(l2 (-1800 -1500) (425 1500))
+ rect(l6 (950 -4890) (425 950))
+ )
+ net(3 name(VSS)
+ rect(l8 (410 1770) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l11 (-240 -1300) (300 1360))
+ rect(l11 (-650 -2160) (2400 800))
+ rect(l11 (-1151 -401) (2 2))
+ rect(l6 (-951 859) (425 950))
+ )
+ net(4
+ rect(l3 (-100 4500) (2600 3500))
+ )
+ net(5 name(B)
+ rect(l4 (1425 2860) (250 1940))
+ rect(l4 (-345 -950) (300 300))
+ rect(l4 (-205 650) (250 2000))
+ rect(l4 (-250 -2000) (250 2000))
+ rect(l4 (-250 -5390) (250 1450))
+ rect(l8 (-285 1050) (180 180))
+ rect(l11 (-71 -91) (2 2))
+ rect(l11 (-171 -151) (300 300))
+ )
+ net(6 name(A)
+ rect(l4 (725 2860) (250 1940))
+ rect(l4 (-325 -1850) (300 300))
+ rect(l4 (-225 1550) (250 2000))
+ rect(l4 (-250 -2000) (250 2000))
+ rect(l4 (-250 -5390) (250 1450))
+ rect(l8 (-265 150) (180 180))
+ rect(l11 (-91 -91) (2 2))
+ rect(l11 (-151 -151) (300 300))
+ )
+ net(7 name(SUBSTRATE))
+ net(8
+ rect(l6 (975 1660) (425 950))
+ rect(l6 (-400 -950) (425 950))
+ )
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VDD))
+ pin(2 name(OUT))
+ pin(3 name(VSS))
+ pin(4)
+ pin(5 name(B))
+ pin(6 name(A))
+ pin(7 name(SUBSTRATE))
+
+ # Devices and their connections
+ device(1 D$PMOS
+ location(850 5800)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0.6375)
+ param(AD 0.3375)
+ param(PS 3.85)
+ param(PD 1.95)
+ terminal(S 2)
+ terminal(G 6)
+ terminal(D 1)
+ terminal(B 4)
+ )
+ device(2 D$PMOS$1
+ location(1550 5800)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0.3375)
+ param(AD 0.6375)
+ param(PS 1.95)
+ param(PD 3.85)
+ terminal(S 1)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 4)
+ )
+ device(3 D$NMOS
+ location(850 2135)
+ param(L 0.25)
+ param(W 0.95)
+ param(AS 0.40375)
+ param(AD 0.21375)
+ param(PS 2.75)
+ param(PD 1.4)
+ terminal(S 3)
+ terminal(G 6)
+ terminal(D 8)
+ terminal(B 7)
+ )
+ device(4 D$NMOS$1
+ location(1550 2135)
+ param(L 0.25)
+ param(W 0.95)
+ param(AS 0.21375)
+ param(AD 0.40375)
+ param(PS 1.4)
+ param(PD 2.75)
+ terminal(S 8)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 7)
+ )
+
+ )
+ circuit(INVX1
+
+ # Circuit boundary
+ rect((-100 400) (2000 7600))
+
+ # Nets with their geometries
+ net(1 name(VDD)
+ rect(l8 (410 6260) (180 180))
+ rect(l8 (-180 -730) (180 180))
+ rect(l8 (-180 -730) (180 180))
+ rect(l11 (-240 -240) (300 1400))
+ rect(l11 (-650 300) (1800 800))
+ rect(l11 (-1450 -1100) (300 300))
+ rect(l11 (299 399) (2 2))
+ rect(l2 (-651 -2151) (425 1500))
+ )
+ net(2 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(3 name(VSS)
+ rect(l8 (410 1770) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l11 (-240 -1300) (300 1360))
+ rect(l11 (-650 -2160) (1800 800))
+ rect(l11 (-851 -401) (2 2))
+ rect(l6 (-651 859) (425 950))
+ )
+ net(4
+ rect(l3 (-100 4500) (2000 3500))
+ )
+ net(5 name(IN)
+ rect(l4 (725 2860) (250 1940))
+ rect(l4 (-525 -1850) (300 300))
+ rect(l4 (-25 1550) (250 2000))
+ rect(l4 (-250 -2000) (250 2000))
+ rect(l4 (-250 -5390) (250 1450))
+ rect(l8 (-465 150) (180 180))
+ rect(l11 (-91 -91) (2 2))
+ rect(l11 (-151 -151) (300 300))
+ )
+ net(6 name(SUBSTRATE))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VDD))
+ pin(2 name(OUT))
+ pin(3 name(VSS))
+ pin(4)
+ pin(5 name(IN))
+ pin(6 name(SUBSTRATE))
+
+ # Devices and their connections
+ device(1 D$PMOS$2
+ 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 1)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 4)
+ )
+ device(2 D$NMOS$2
+ 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 3)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 6)
+ )
+
+ )
+ circuit(RINGO
+
+ # Circuit boundary
+ rect((0 350) (25800 7650))
+
+ # Nets with their geometries
+ net(1
+ rect(l11 (4040 2950) (610 300))
+ )
+ net(2
+ rect(l11 (5550 2950) (900 300))
+ )
+ net(3
+ rect(l11 (7350 2950) (900 300))
+ )
+ net(4
+ rect(l11 (9150 2950) (900 300))
+ )
+ net(5
+ rect(l11 (10950 2950) (900 300))
+ )
+ net(6
+ rect(l11 (12750 2950) (900 300))
+ )
+ net(7
+ rect(l11 (14550 2950) (900 300))
+ )
+ net(8
+ rect(l11 (16350 2950) (900 300))
+ )
+ net(9
+ rect(l11 (18150 2950) (900 300))
+ )
+ net(10
+ rect(l11 (19950 2950) (900 300))
+ )
+ net(11 name(FB)
+ rect(l11 (21750 2950) (900 300))
+ rect(l11 (-19530 590) (320 320))
+ rect(l11 (17820 -320) (320 320))
+ rect(l12 (-18400 -260) (200 200))
+ rect(l12 (17940 -200) (200 200))
+ rect(l13 (-18040 -300) (17740 400))
+ rect(l13 (-17921 -201) (2 2))
+ rect(l13 (-221 -201) (400 400))
+ rect(l13 (17740 -400) (400 400))
+ )
+ net(12 name(VDD)
+ rect(l3 (500 4500) (1400 3500))
+ rect(l3 (-1900 -3500) (600 3500))
+ rect(l3 (23300 -3500) (1400 3500))
+ rect(l3 (-100 -3500) (600 3500))
+ rect(l8 (-24690 -1240) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (23220 370) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l11 (-21741 859) (2 2))
+ rect(l11 (-2351 -451) (1200 800))
+ rect(l11 (-750 -1450) (300 1400))
+ rect(l11 (-101 -351) (2 2))
+ rect(l11 (-1251 -401) (600 800))
+ rect(l11 (23400 -800) (1200 800))
+ rect(l11 (-750 -1450) (300 1400))
+ rect(l11 (-101 -351) (2 2))
+ rect(l11 (549 -401) (600 800))
+ rect(l9 (-24850 -1500) (500 1500))
+ rect(l9 (22900 -1500) (500 1500))
+ )
+ net(13 name(OUT)
+ rect(l11 (23440 3840) (320 320))
+ rect(l12 (-260 -260) (200 200))
+ rect(l13 (-101 -101) (2 2))
+ rect(l13 (-201 -201) (400 400))
+ )
+ net(14 name(ENABLE)
+ rect(l11 (2440 2940) (320 320))
+ rect(l12 (-260 -260) (200 200))
+ rect(l13 (-101 -101) (2 2))
+ rect(l13 (-201 -201) (400 400))
+ )
+ net(15 name(VSS)
+ rect(l8 (1110 1610) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l8 (23220 370) (180 180))
+ rect(l8 (-180 -1280) (180 180))
+ rect(l8 (-180 370) (180 180))
+ rect(l11 (-21741 -391) (2 2))
+ rect(l11 (-1901 -401) (300 1400))
+ rect(l11 (-750 -1450) (1200 800))
+ rect(l11 (-551 -401) (2 2))
+ rect(l11 (-1251 -401) (600 800))
+ rect(l11 (23850 -750) (300 1400))
+ rect(l11 (-750 -1450) (1200 800))
+ rect(l11 (-551 -401) (2 2))
+ rect(l11 (549 -401) (600 800))
+ rect(l10 (-24850 -800) (500 1500))
+ rect(l10 (22900 -1500) (500 1500))
+ )
+
+ # Outgoing pins and their connections to nets
+ pin(11 name(FB))
+ pin(12 name(VDD))
+ pin(13 name(OUT))
+ pin(14 name(ENABLE))
+ pin(15 name(VSS))
+
+ # Subcircuits and their connections
+ circuit(1 ND2X1 location(1800 0)
+ pin(0 12)
+ pin(1 1)
+ pin(2 15)
+ pin(3 12)
+ pin(4 11)
+ pin(5 14)
+ pin(6 15)
+ )
+ circuit(2 INVX1 location(4200 0)
+ pin(0 12)
+ pin(1 2)
+ pin(2 15)
+ pin(3 12)
+ pin(4 1)
+ pin(5 15)
+ )
+ circuit(3 INVX1 location(6000 0)
+ pin(0 12)
+ pin(1 3)
+ pin(2 15)
+ pin(3 12)
+ pin(4 2)
+ pin(5 15)
+ )
+ circuit(4 INVX1 location(7800 0)
+ pin(0 12)
+ pin(1 4)
+ pin(2 15)
+ pin(3 12)
+ pin(4 3)
+ pin(5 15)
+ )
+ circuit(5 INVX1 location(9600 0)
+ pin(0 12)
+ pin(1 5)
+ pin(2 15)
+ pin(3 12)
+ pin(4 4)
+ pin(5 15)
+ )
+ circuit(6 INVX1 location(11400 0)
+ pin(0 12)
+ pin(1 6)
+ pin(2 15)
+ pin(3 12)
+ pin(4 5)
+ pin(5 15)
+ )
+ circuit(7 INVX1 location(13200 0)
+ pin(0 12)
+ pin(1 7)
+ pin(2 15)
+ pin(3 12)
+ pin(4 6)
+ pin(5 15)
+ )
+ circuit(8 INVX1 location(15000 0)
+ pin(0 12)
+ pin(1 8)
+ pin(2 15)
+ pin(3 12)
+ pin(4 7)
+ pin(5 15)
+ )
+ circuit(9 INVX1 location(16800 0)
+ pin(0 12)
+ pin(1 9)
+ pin(2 15)
+ pin(3 12)
+ pin(4 8)
+ pin(5 15)
+ )
+ circuit(10 INVX1 location(18600 0)
+ pin(0 12)
+ pin(1 10)
+ pin(2 15)
+ pin(3 12)
+ pin(4 9)
+ pin(5 15)
+ )
+ circuit(11 INVX1 location(20400 0)
+ pin(0 12)
+ pin(1 11)
+ pin(2 15)
+ pin(3 12)
+ pin(4 10)
+ pin(5 15)
+ )
+ circuit(12 INVX1 location(22200 0)
+ pin(0 12)
+ pin(1 13)
+ pin(2 15)
+ pin(3 12)
+ pin(4 11)
+ pin(5 15)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Device class section
+ class(PMOS MOS4)
+ class(NMOS MOS4)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(ND2X1
+
+ # Nets
+ net(1 name(VDD))
+ net(2 name(OUT))
+ net(3 name(VSS))
+ net(4 name(NWELL))
+ net(5 name(B))
+ net(6 name(A))
+ net(7 name(BULK))
+ net(8 name('1'))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VDD))
+ pin(2 name(OUT))
+ pin(3 name(VSS))
+ pin(4 name(NWELL))
+ pin(5 name(B))
+ pin(6 name(A))
+ pin(7 name(BULK))
+
+ # Devices and their connections
+ device(1 PMOS
+ name($1)
+ param(L 0.251)
+ param(W 1.6)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 2)
+ terminal(G 6)
+ terminal(D 1)
+ terminal(B 4)
+ )
+ device(2 PMOS
+ name($2)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 1)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 4)
+ )
+ device(3 NMOS
+ name($3)
+ param(L 0.26)
+ param(W 1)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 3)
+ terminal(G 6)
+ terminal(D 8)
+ terminal(B 7)
+ )
+ device(4 NMOS
+ name($4)
+ param(L 0.25)
+ param(W 0.95)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 8)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 7)
+ )
+
+ )
+ circuit(INVX1
+
+ # Nets
+ net(1 name(VDD))
+ net(2 name(OUT))
+ net(3 name(VSS))
+ net(4 name(NWELL))
+ net(5 name(IN))
+ net(6 name(BULK))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VDD))
+ pin(2 name(OUT))
+ pin(3 name(VSS))
+ pin(4 name(NWELL))
+ pin(5 name(IN))
+ pin(6 name(BULK))
+
+ # Devices and their connections
+ device(1 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 1)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 4)
+ )
+ device(2 NMOS
+ name($2)
+ param(L 0.25)
+ param(W 0.95)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 3)
+ terminal(G 5)
+ terminal(D 2)
+ terminal(B 6)
+ )
+
+ )
+ circuit(RINGO
+
+ # Nets
+ net(1 name(VSS))
+ net(2 name(VDD))
+ net(3 name(FB))
+ net(4 name(ENABLE))
+ net(5 name(OUT))
+ net(6 name('1'))
+ net(7 name('2'))
+ net(8 name('3'))
+ net(9 name('4'))
+ net(10 name('5'))
+ net(11 name('6'))
+ net(12 name('7'))
+ net(13 name('8'))
+ net(14 name('9'))
+ net(15 name('10'))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(VSS))
+ pin(2 name(VDD))
+ pin(3 name(FB))
+ pin(4 name(ENABLE))
+ pin(5 name(OUT))
+
+ # Subcircuits and their connections
+ circuit(1 ND2X1 name($1)
+ pin(0 2)
+ pin(1 6)
+ pin(2 1)
+ pin(3 2)
+ pin(4 3)
+ pin(5 4)
+ pin(6 1)
+ )
+ circuit(2 INVX1 name($2)
+ pin(0 2)
+ pin(1 7)
+ pin(2 1)
+ pin(3 2)
+ pin(4 6)
+ pin(5 1)
+ )
+ circuit(3 INVX1 name($3)
+ pin(0 2)
+ pin(1 8)
+ pin(2 1)
+ pin(3 2)
+ pin(4 7)
+ pin(5 1)
+ )
+ circuit(4 INVX1 name($4)
+ pin(0 2)
+ pin(1 9)
+ pin(2 1)
+ pin(3 2)
+ pin(4 8)
+ pin(5 1)
+ )
+ circuit(5 INVX1 name($5)
+ pin(0 2)
+ pin(1 10)
+ pin(2 1)
+ pin(3 2)
+ pin(4 9)
+ pin(5 1)
+ )
+ circuit(6 INVX1 name($6)
+ pin(0 2)
+ pin(1 11)
+ pin(2 1)
+ pin(3 2)
+ pin(4 10)
+ pin(5 1)
+ )
+ circuit(7 INVX1 name($7)
+ pin(0 2)
+ pin(1 12)
+ pin(2 1)
+ pin(3 2)
+ pin(4 11)
+ pin(5 1)
+ )
+ circuit(8 INVX1 name($8)
+ pin(0 2)
+ pin(1 13)
+ pin(2 1)
+ pin(3 2)
+ pin(4 12)
+ pin(5 1)
+ )
+ circuit(9 INVX1 name($9)
+ pin(0 2)
+ pin(1 14)
+ pin(2 1)
+ pin(3 2)
+ pin(4 13)
+ pin(5 1)
+ )
+ circuit(10 INVX1 name($10)
+ pin(0 2)
+ pin(1 15)
+ pin(2 1)
+ pin(3 2)
+ pin(4 14)
+ pin(5 1)
+ )
+ circuit(11 INVX1 name($11)
+ pin(0 2)
+ pin(1 3)
+ pin(2 1)
+ pin(3 2)
+ pin(4 15)
+ pin(5 1)
+ )
+ circuit(12 INVX1 name($12)
+ pin(0 2)
+ pin(1 5)
+ pin(2 1)
+ pin(3 2)
+ pin(4 3)
+ pin(5 1)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(INVX1 INVX1 match
+ xref(
+ net(4 4 match)
+ net(5 5 match)
+ net(2 2 match)
+ net(6 6 match)
+ net(1 1 match)
+ net(3 3 match)
+ pin(3 3 match)
+ pin(4 4 match)
+ pin(1 1 match)
+ pin(5 5 match)
+ pin(0 0 match)
+ pin(2 2 match)
+ device(2 2 match)
+ device(1 1 match)
+ )
+ )
+ circuit(ND2X1 ND2X1 match
+ xref(
+ net(8 8 match)
+ net(4 4 match)
+ net(6 6 match)
+ net(5 5 match)
+ net(2 2 match)
+ net(7 7 match)
+ net(1 1 match)
+ net(3 3 match)
+ pin(3 3 match)
+ pin(5 5 match)
+ pin(4 4 match)
+ pin(1 1 match)
+ pin(6 6 match)
+ pin(0 0 match)
+ pin(2 2 match)
+ device(3 3 match)
+ device(4 4 match)
+ device(1 1 match)
+ device(2 2 match)
+ )
+ )
+ circuit(RINGO RINGO match
+ xref(
+ net(1 6 match)
+ net(10 15 match)
+ net(2 7 match)
+ net(3 8 match)
+ net(4 9 match)
+ net(5 10 match)
+ net(6 11 match)
+ net(7 12 match)
+ net(8 13 match)
+ net(9 14 match)
+ net(14 4 match)
+ net(11 3 match)
+ net(13 5 match)
+ net(12 2 match)
+ net(15 1 match)
+ pin(3 3 match)
+ pin(0 2 match)
+ pin(2 4 match)
+ pin(1 1 match)
+ pin(4 0 match)
+ circuit(2 2 match)
+ circuit(3 3 match)
+ circuit(4 4 match)
+ circuit(5 5 match)
+ circuit(6 6 match)
+ circuit(7 7 match)
+ circuit(8 8 match)
+ circuit(9 9 match)
+ circuit(10 10 match)
+ circuit(11 11 match)
+ circuit(12 12 match)
+ circuit(1 1 match)
+ )
+ )
+)
diff --git a/testdata/ruby/dbNetlist.rb b/testdata/ruby/dbNetlist.rb
index bb1d34570..392c9a3e8 100644
--- a/testdata/ruby/dbNetlist.rb
+++ b/testdata/ruby/dbNetlist.rb
@@ -63,6 +63,13 @@ class DBNetlist_TestClass < TestBase
assert_equal(nl.circuit_by_cell_index(17).inspect, "nil")
assert_equal(nl.circuit_by_name("DOESNOTEXIST").inspect, "nil")
+ assert_equal(nl.is_case_sensitive?, true)
+ assert_equal(nl.circuit_by_name("xyz").inspect, "nil")
+ nl.case_sensitive = false
+ assert_equal(nl.is_case_sensitive?, false)
+ assert_equal(nl.circuit_by_name("xyz").name, "XYZ")
+ nl.case_sensitive = true
+
cc = RBA::Circuit::new
assert_equal(cc.dont_purge, false)
cc.dont_purge = true
@@ -103,6 +110,11 @@ class DBNetlist_TestClass < TestBase
assert_equal(names, [ c.name, cc.name ])
assert_equal(nl.circuits_by_name("X*").collect { |x| x.name }, [ "XYZ" ])
+ assert_equal(nl.circuits_by_name("x*").collect { |x| x.name }, [])
+ nl.case_sensitive = false
+ assert_equal(nl.circuits_by_name("X*").collect { |x| x.name }, [ "XYZ" ])
+ assert_equal(nl.circuits_by_name("x*").collect { |x| x.name }, [ "XYZ" ])
+ nl.case_sensitive = true
assert_equal(nl.circuits_by_name("???").collect { |x| x.name }, [ "XYZ", "UVW" ])
assert_equal(nl.circuits_by_name("*").collect { |x| x.name }, [ "XYZ", "UVW" ])
assert_equal(nl.circuits_by_name("P*").collect { |x| x.name }, [])
@@ -698,7 +710,14 @@ class DBNetlist_TestClass < TestBase
assert_equal(c.net_by_cluster_id(17).name, "NET1")
assert_equal(c.net_by_cluster_id(42).inspect, "nil")
assert_equal(c.net_by_name("NET1").name, "NET1")
+ assert_equal(c.nets_by_name("NET*").collect(&:name), ["NET1"])
assert_equal(c.net_by_name("DOESNOTEXIST").inspect, "nil")
+ assert_equal(c.nets_by_name("DOESNOTEXIST").collect(&:name), [])
+
+ assert_equal(c.net_by_name("net1").inspect, "nil")
+ nl.case_sensitive = false
+ assert_equal(c.net_by_name("net1").name, "NET1")
+ nl.case_sensitive = true
net2 = c.create_net
net2.name = "NET2"
@@ -706,6 +725,12 @@ class DBNetlist_TestClass < TestBase
names = []
c.each_net { |n| names << n.name }
assert_equal(names, [ "NET1", "NET2" ])
+ assert_equal(c.nets_by_name("NET*").collect(&:name), ["NET1", "NET2"])
+ assert_equal(c.nets_by_name("net*").collect(&:name), [])
+ nl.case_sensitive = false
+ assert_equal(c.nets_by_name("NET*").collect(&:name), ["NET1", "NET2"])
+ assert_equal(c.nets_by_name("net*").collect(&:name), ["NET1", "NET2"])
+ nl.case_sensitive = true
assert_equal(net1.pin_count, 0)
c.connect_pin(pina1, net1)
diff --git a/testdata/ruby/dbNetlistCompare.rb b/testdata/ruby/dbNetlistCompare.rb
index 58b3339ca..9fe3b704d 100644
--- a/testdata/ruby/dbNetlistCompare.rb
+++ b/testdata/ruby/dbNetlistCompare.rb
@@ -333,6 +333,8 @@ END
assert_equal(logger.text(), <<"END")
begin_circuit INV INV
+match_nets VDD VDD
+match_nets VSS VSS
match_nets OUT OUT
match_nets IN IN
match_pins $0 $1
@@ -459,6 +461,8 @@ END
assert_equal(logger.text, <<"END")
begin_circuit BUF BUF
+match_nets VDD VDD
+match_nets VSS VSS
match_nets OUT OUT
match_nets INT $10
net_mismatch IN IN
@@ -487,6 +491,8 @@ END
assert_equal(logger.text, <<"END")
begin_circuit BUF BUF
+match_nets VDD VDD
+match_nets VSS VSS
match_nets OUT OUT
match_nets IN IN
match_ambiguous_nets INT $10
@@ -515,6 +521,8 @@ END
assert_equal(logger.text, <<"END")
begin_circuit BUF BUF
+match_nets VDD VDD
+match_nets VSS VSS
match_nets OUT OUT
match_nets INT $10
net_mismatch IN IN
@@ -545,6 +553,8 @@ END
assert_equal(logger.text, <<"END")
begin_circuit BUF BUF
+match_nets VDD VDD
+match_nets VSS VSS
match_nets OUT OUT
match_nets IN IN
match_ambiguous_nets INT $10
@@ -574,6 +584,8 @@ END
assert_equal(logger.text, <<"END")
begin_circuit BUF BUF
+match_nets VDD VDD
+match_nets VSS VSS
match_nets OUT OUT
match_nets IN IN
match_ambiguous_nets INT $10
@@ -636,17 +648,20 @@ END
# NOTE: adding this power hint makes the device class error harder to detect
ca = nl1.circuit_by_name("BUF")
cb = nl2.circuit_by_name("BUF")
- comp.same_nets(ca.net_by_name("VDD"), cb.net_by_name("VDD"))
- comp.same_nets(ca.net_by_name("VSS"), cb.net_by_name("VSS"))
+ comp.same_nets(ca.net_by_name("VDD"), cb.net_by_name("VDD"), false)
+ comp.same_nets(ca.net_by_name("VSS"), cb.net_by_name("VSS"), false)
+ comp.same_nets(ca.net_by_name("OUT"), cb.net_by_name("OUT"), false)
good = comp.compare(nl1, nl2)
assert_equal(logger.text, <<"END")
begin_circuit BUF BUF
+match_nets VDD VDD
+match_nets VSS VSS
+match_nets OUT OUT
match_nets INT $10
match_nets IN IN
net_mismatch INT2 $11
-net_mismatch OUT OUT
match_pins $0 $1
match_pins $1 $3
match_pins $2 $0
@@ -666,6 +681,157 @@ END
end
+ def test_6b
+
+ nls1 = <<"END"
+circuit BUF ($1=IN,$2=OUT,$3=VDD,$4=VSS);
+ device PMOS $1 (S=VDD,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $2 (S=VSS,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOS $3 (S=VDD,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $4 (S=VSS,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOS $5 (S=VDD,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $6 (S=VSS,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOSB $7 (S=VDD,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOSB $8 (S=VSS,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+end;
+END
+
+ nls2 = <<"END"
+circuit BUF ($1=VDD,$2=IN,$3=VSS,$4=OUT);
+ device PMOS $1 (S=VDD,G=IN,D=$10) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOS $2 (S=VDD,G=$10,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOS $3 (S=VDD,G=IN,D=$11) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOS $4 (S=VDD,G=$11,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $5 (S=$10,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $6 (S=OUT,G=$10,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $7 (S=$11,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOSB $8 (S=OUT,G=$11,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+end;
+END
+
+ nl1 = RBA::Netlist::new
+ nl2 = RBA::Netlist::new
+ prep_nl(nl1, nls1)
+ prep_nl(nl2, nls2)
+
+ logger = NetlistCompareTestLogger::new
+ comp = RBA::NetlistComparer::new(logger)
+
+ # NOTE: adding this power hint makes the device class error harder to detect
+ ca = nl1.circuit_by_name("BUF")
+ cb = nl2.circuit_by_name("BUF")
+ comp.same_nets(ca.net_by_name("VDD"), cb.net_by_name("VDD"), true)
+ comp.same_nets(ca.net_by_name("VSS"), cb.net_by_name("VSS"), true)
+ comp.same_nets(ca.net_by_name("OUT"), cb.net_by_name("OUT"), true)
+
+ good = comp.compare(nl1, nl2)
+
+ assert_equal(logger.text, <<"END")
+begin_circuit BUF BUF
+net_mismatch VDD VDD
+match_nets VSS VSS
+net_mismatch OUT OUT
+match_nets INT $10
+match_nets IN IN
+net_mismatch INT2 $11
+match_pins $0 $1
+match_pins $1 $3
+match_pins $2 $0
+match_pins $3 $2
+match_devices $1 $1
+match_devices $3 $2
+match_devices $5 $3
+match_devices_with_different_device_classes $7 $4
+match_devices $2 $5
+match_devices $4 $6
+match_devices $6 $7
+match_devices $8 $8
+end_circuit BUF BUF NOMATCH
+END
+
+ assert_equal(good, false)
+
+ end
+
+ def test_6c
+
+ nls1 = <<"END"
+circuit BUF ($1=IN,$2=OUT,$3=VDD,$4=VSS);
+ device PMOS $1 (S=VDD,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $2 (S=VSS,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOS $3 (S=VDD,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $4 (S=VSS,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOS $5 (S=VDD,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $6 (S=VSS,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOSB $7 (S=VDD,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOSB $8 (S=VSS,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+end;
+END
+
+ nls2 = <<"END"
+circuit BUF ($1=VDD,$2=IN,$3=VSS,$4=OUT);
+ device PMOS $1 (S=VDD,G=IN,D=$10) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOS $2 (S=VDD,G=$10,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOS $3 (S=VDD,G=IN,D=$11) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device PMOS $4 (S=VDD,G=$11,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $5 (S=$10,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $6 (S=OUT,G=$10,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOS $7 (S=$11,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+ device NMOSB $8 (S=OUT,G=$11,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
+end;
+END
+
+ nl1 = RBA::Netlist::new
+ nl2 = RBA::Netlist::new
+ prep_nl(nl1, nls1)
+ prep_nl(nl2, nls2)
+
+ logger = NetlistCompareTestLogger::new
+ comp = RBA::NetlistComparer::new(logger)
+
+ # NOTE: adding this power hint makes the device class error harder to detect
+ ca = nl1.circuit_by_name("BUF")
+ cb = nl2.circuit_by_name("BUF")
+ comp.same_nets(ca, cb, ca.net_by_name("VDD"), cb.net_by_name("VDD"), true)
+ comp.same_nets(ca, cb, ca.net_by_name("VSS"), nil, false)
+ comp.same_nets(ca, cb, ca.net_by_name("OUT"), nil, true)
+
+ good = comp.compare(nl1, nl2)
+
+ assert_equal(logger.text, <<"END")
+begin_circuit BUF BUF
+net_mismatch VDD VDD
+match_nets VSS (null)
+net_mismatch OUT (null)
+match_nets INT $10
+match_nets IN IN
+net_mismatch INT2 (null)
+net_mismatch (null) VSS
+net_mismatch (null) OUT
+net_mismatch (null) $11
+match_pins $0 $1
+match_pins $2 $0
+match_pins $1 (null)
+match_pins $3 (null)
+match_pins (null) $2
+match_pins (null) $3
+match_devices $1 $1
+device_mismatch $3 $2
+device_mismatch $5 $3
+device_mismatch (null) $4
+device_mismatch $6 $5
+device_mismatch $4 $6
+device_mismatch $2 $7
+device_mismatch (null) $8
+device_mismatch $7 (null)
+device_mismatch $8 (null)
+end_circuit BUF BUF NOMATCH
+END
+
+ assert_equal(good, false)
+
+ end
+
def test_7
nls1 = <<"END"
@@ -713,6 +879,8 @@ END
assert_equal(logger.text, <<"END")
begin_circuit BUF BUF
+match_nets VDD VDD
+match_nets VSS VSS
net_mismatch INT $10
match_nets IN IN
net_mismatch INT2 $11