diff --git a/src/db/db/dbEdgePairFilters.cc b/src/db/db/dbEdgePairFilters.cc index 9b8d6ff9f..270c37fe2 100644 --- a/src/db/db/dbEdgePairFilters.cc +++ b/src/db/db/dbEdgePairFilters.cc @@ -112,7 +112,17 @@ InternalAngleEdgePairFilter::InternalAngleEdgePairFilter (double amin, bool incl bool InternalAngleEdgePairFilter::selected (const db::EdgePair &edge_pair) const { - return m_checker (edge_pair.first ().d (), -edge_pair.second ().d ()) != m_inverted; + db::Vector d1 = edge_pair.first ().d (); + db::Vector d2 = edge_pair.second ().d (); + + if (db::sprod_sign (d1, d2) < 0) { + d1 = -d1; + } + if (db::vprod_sign (d1, d2) < 0) { + std::swap (d1, d2); + } + + return m_checker (d1, d2) != m_inverted; } } 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/gsiDeclDbEdgePairs.cc b/src/db/db/gsiDeclDbEdgePairs.cc index f7d3073a0..fa41472e7 100644 --- a/src/db/db/gsiDeclDbEdgePairs.cc +++ b/src/db/db/gsiDeclDbEdgePairs.cc @@ -724,10 +724,7 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "edge pairs with the given angle are returned. If \"inverse\" is true, " "edge pairs not with the given angle are returned.\n" "\n" - "The angle is measured between the two edges. Antiparallel edges have an angle of 0, parallel ones an angle of 180 or -180 degree (whichever fits). " - "For other configurations, the angle is determined by thinking of the edges as emerging from the same point: if the second edge is rotated clockwise " - "against the first one, the angle is positive. If the second edge is rotated counterclockwise, the angle is negative. This way, the same angle " - "definition applies to edges at a corner of a polygon and the same edges appearing in an edge pair.\n" + "The angle is measured between the two edges. It is between 0 (parallel or anti-parallel edges) and 90 degree (perpendicular edges).\n" "\n" "This method has been added in version 0.27.2.\n" ) + @@ -737,10 +734,7 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "edge pairs with an angle between min_angle and max_angle (max_angle itself is excluded) are returned. If \"inverse\" is true, " "edge pairs not fulfilling this criterion are returned.\n" "\n" - "The angle is measured between the two edges. Antiparallel edges have an angle of 0, parallel ones an angle of 180 or -180 degree (whichever fits). " - "For other configurations, the angle is determined by thinking of the edges as emerging from the same point: if the second edge is rotated clockwise " - "against the first one, the angle is positive. If the second edge is rotated counterclockwise, the angle is negative. This way, the same angle " - "definition applies to edges at a corner of a polygon and the same edges appearing in an edge pair.\n" + "The angle is measured between the two edges. It is between 0 (parallel or anti-parallel edges) and 90 degree (perpendicular edges).\n" "\n" "With \"include_min_angle\" set to true (the default), the minimum angle is included in the criterion while with false, the " "minimum angle itself is not included. Same for \"include_max_angle\" where the default is false, meaning the maximum angle is not included in the range.\n" diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index d095c936a..96b6a8066 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -1391,6 +1391,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" @@ -1504,6 +1548,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." @@ -1794,8 +1850,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 ())) { @@ -1810,8 +1871,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 ())) { @@ -1823,6 +1889,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. " @@ -1866,7 +1940,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/dbEdgePairsTests.cc b/src/db/unit_tests/dbEdgePairsTests.cc index e20d543ee..8ec877c12 100644 --- a/src/db/unit_tests/dbEdgePairsTests.cc +++ b/src/db/unit_tests/dbEdgePairsTests.cc @@ -24,6 +24,7 @@ #include "tlUnitTest.h" #include "dbEdgePairs.h" +#include "dbEdgePairFilters.h" #include "dbEdges.h" #include "dbRegion.h" #include "dbTestSupport.h" @@ -160,3 +161,42 @@ TEST(4) db::Region r (db::RecursiveShapeIterator (ly, ly.cell (top_cell), l1)); EXPECT_EQ (db::compare (r, "(-10,-21;9,20;50,51;91,80);(-10,-21;9,20;110,121;91,80)"), true); } + +TEST(5_InternalAngleFilter) +{ + db::EdgePair ep0 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (0, 0))); + db::EdgePair ep45 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, 100))); + db::EdgePair ep180 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, 0))); + db::EdgePair ep90 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (0, 100))); + db::EdgePair epm90 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 100), db::Point (0, 0))); + + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep0), true); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep180), true); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep90), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (epm90), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep45), false); + + EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep0), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep180), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep90), true); + EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (epm90), true); + EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep45), false); + + EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep0), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep180), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep90), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (epm90), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep45), true); + + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep0), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep180), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep90), true); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (epm90), true); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep45), true); + + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep0), true); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep180), true); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep90), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (epm90), false); + EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep45), true); +} 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_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index 3442b3742..699fe5333 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -330,28 +330,30 @@ module DRC # %DRC% # @name with_area - # @brief Selects polygons by area + # @brief Selects polygons or edge pairs by area # @synopsis layer.with_area(min .. max) # @synopsis layer.with_area(value) # @synopsis layer.with_area(min, max) - # The first form will select all polygons with an area larger or + # The first form will select all polygons or edge pairs with an area larger or # equal to min and less (but not equal to) max. The second form - # will select the polygons with exactly the given area. + # will select the polygons or edge pairs with exactly the given area. # The third form basically is equivalent to the first form, but # allows specification of nil for min or max indicating no lower or # upper limit. + # + # This method is available for polygon or edge pair layers. # %DRC% # @name without_area - # @brief Selects polygons by area + # @brief Selects polygons or edge pairs by area # @synopsis layer.without_area(min .. max) # @synopsis layer.without_area(value) # @synopsis layer.without_area(min, max) # This method is the inverse of "with_area". It will select - # polygons without an area equal to the given one or outside + # polygons or edge pairs without an area equal to the given one or outside # the given interval. # - # This method is available for polygon layers only. + # This method is available for polygon or edge pair layers. %w(area).each do |f| [true, false].each do |inv| @@ -361,7 +363,8 @@ module DRC @engine._context("#{mn}") do - requires_region + self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::EdgePairs) || raise("Requires an edge pair or polygon layer") + if args.size == 1 a = args[0] if a.is_a?(Range) @@ -857,7 +860,7 @@ CODE # @synopsis layer.with_angle(min .. max) # @synopsis layer.with_angle(value) # @synopsis layer.with_angle(min, max) - # @synopsis edge_pairlayer.with_angle(min, max [, both]) + # @synopsis edge_pair_layer.with_angle(min, max [, both]) # # When called on an edge layer, the method selects edges by their angle, # measured against the horizontal axis in the mathematical sense. @@ -871,10 +874,6 @@ CODE # The second version selects edges with exactly the given angle. The third # version is identical to the first one. # - # When called on a polygon layer, this method selects corners which match the - # given angle or is within the given angle interval. The angle is measured between the edges forming the corner. - # For each corner, an edge pair containing the edges forming in the angle is returned. - # # When called on an edge pair layer, this method selects edge pairs with one or both edges # meeting the angle criterion. In this case an additional argument is accepted which can be # either "both" (plain word) to indicate that both edges have to be within the given interval. @@ -903,6 +902,9 @@ CODE # @td @img(/images/drc_with_angle4.png) @/td # @/tr # @/table + # + # Note that in former versions, with_angle could be used on polygon layers selecting corners with specific angles. + # This feature has been deprecated. Use \corners instead. # %DRC% # @name without_angle @@ -910,11 +912,12 @@ CODE # @synopsis layer.without_angle(min .. max) # @synopsis layer.without_angle(value) # @synopsis layer.without_angle(min, max) - # @synopsis edge_pairlayer.without_angle(min, max [, both]) + # @synopsis edge_pair_layer.without_angle(min, max [, both]) # # The method basically is the inverse of \with_angle. It selects all edges # of the edge layer or corners of the polygons which do not have the given angle (second form) or whose angle - # is not inside the given interval (first and third form). + # is not inside the given interval (first and third form). When called on edge pairs, it selects + # edge pairs by the angles of their edges. # # A note on the "both" modifier (without_angle called on edge pairs): "both" means that # both edges need to be "without_angle". For example @@ -925,8 +928,41 @@ CODE # ep = edge_pairs.without_angle(0, both) # @/code # + # See \with_internal_angle and \without_internal_angle to select edge pairs by the + # angle between the edges. - %w(angle).each do |f| + # %DRC% + # @name with_internal_angle + # @brief Selects edge pairs by their internal angle + # @synopsis edge_pair_layer.with_internal_angle(min .. max) + # @synopsis edge_pair_layer.with_internal_angle(value) + # @synopsis edge_pair_layer.with_internal_angle(min, max) + # + # This method selects edge pairs by the angle enclosed by their edges. + # The angle is between 0 (parallel or anti-parallel edges) and 90 degree (perpendicular edges). + # If an interval or two values are given, the angle is checked to be within the given + # range. + # + # Here are examples for "with_internal_angle" on edge pair layers: + # + # @code + # # selects edge pairs with parallel edges + # ep1 = edge_pairs.with_internal_angle(0) + # # selects edge pairs with perpendicular edges + # ep2 = edge_pairs.with_internal_angle(90) + # @/code + + # %DRC% + # @name without_internal_angle + # @brief Selects edge pairs by their internal angle + # @synopsis edge_pair_layer.without_internal_angle(min .. max) + # @synopsis edge_pair_layer.without_internal_angle(value) + # @synopsis edge_pair_layer.without_internal_angle(min, max) + # + # The method basically is the inverse of \with_internal_angle. It selects all + # edge pairs by the angle enclosed by their edges, applying the opposite criterion than \with_internal_angle. + + %w(angle internal_angle).each do |f| [true, false].each do |inv| mn = (inv ? "without" : "with") + "_" + f eval <<"CODE" @@ -935,16 +971,22 @@ CODE @engine._context("#{mn}") do f = :with_#{f} - args = args.select do |a| - if a.is_a?(DRCBothEdges) - if !self.data.is_a?(RBA::EdgePairs) - raise("'both' keyword only available for edge pair layers") + + if "#{f}" == "angle" + self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs) || raise("Requires an edge, edge pair or polygon layer") + args = args.select do |a| + if a.is_a?(DRCBothEdges) + if !self.data.is_a?(RBA::EdgePairs) + raise("'both' keyword only available for edge pair layers") + end + f = :with_#{f}_both + false + else + true end - f = :with_#{f}_both - false - else - true end + else + requires_edge_pairs end result_class = self.data.is_a?(RBA::Edges) ? RBA::Edges : RBA::EdgePairs diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb index fe87ee25a..3c10049bd 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 @@ -244,10 +242,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 @@ -282,11 +278,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 @@ -343,11 +338,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 @@ -568,30 +562,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/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 6b19de6d3..ad98a0644 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1283,12 +1283,12 @@ TEST(48d_drcWithFragments) run_test (_this, "48", true); } -TEST(49_drcWithFragments) +TEST(49_epAngle) { run_test (_this, "49", false); } -TEST(49d_drcWithFragments) +TEST(49d_epAngle) { run_test (_this, "49", true); } @@ -1298,3 +1298,8 @@ TEST(50_issue826) run_test (_this, "50", false); } +TEST(51_epInternalAngle) +{ + run_test (_this, "51", false); +} + diff --git a/src/klayout.pri b/src/klayout.pri index 550c0cba7..4268df503 100644 --- a/src/klayout.pri +++ b/src/klayout.pri @@ -156,6 +156,7 @@ msvc { win32 { QMAKE_LFLAGS += -Wl,--exclude-all-symbols + QMAKE_CXXFLAGS += -fdeclspec } else { QMAKE_CXXFLAGS += -fvisibility=hidden } diff --git a/src/lay/lay/doc/about/drc_ref_layer.xml b/src/lay/lay/doc/about/drc_ref_layer.xml index d41750cfc..b13360a9a 100644 --- a/src/lay/lay/doc/about/drc_ref_layer.xml +++ b/src/lay/lay/doc/about/drc_ref_layer.xml @@ -3157,7 +3157,7 @@ Shielding is enabled by default, but can be switched off with the "transparent"
  • layer.with_angle(min .. max)
  • layer.with_angle(value)
  • layer.with_angle(min, max)
  • -
  • edge_pairlayer.with_angle(min, max [, both])
  • +
  • edge_pair_layer.with_angle(min, max [, both])
  • When called on an edge layer, the method selects edges by their angle, @@ -3172,10 +3172,6 @@ edges with a angle larger or equal to min and less than max (but not equal). The second version selects edges with exactly the given angle. The third version is identical to the first one.

    -When called on a polygon layer, this method selects corners which match the -given angle or is within the given angle interval. The angle is measured between the edges forming the corner. -For each corner, an edge pair containing the edges forming in the angle is returned. -

    When called on an edge pair layer, this method selects edge pairs with one or both edges meeting the angle criterion. In this case an additional argument is accepted which can be either "both" (plain word) to indicate that both edges have to be within the given interval. @@ -3204,8 +3200,11 @@ The following images demonstrate some use cases of with_an +

    +Note that in former versions, with_angle could be used on polygon layers selecting corners with specific angles. +This feature has been deprecated. Use corners instead.

    -

    "with_area" - Selects polygons by area

    +

    "with_area" - Selects polygons or edge pairs by area

    Usage:

    -The first form will select all polygons with an area larger or +The first form will select all polygons or edge pairs with an area larger or equal to min and less (but not equal to) max. The second form -will select the polygons with exactly the given area. +will select the polygons or edge pairs with exactly the given area. The third form basically is equivalent to the first form, but allows specification of nil for min or max indicating no lower or upper limit. +

    +This method is available for polygon or edge pair layers.

    "with_area_ratio" - Selects polygons by the ratio of the bounding box area vs. polygon area

    @@ -3430,6 +3431,29 @@ This method is available for edge pair layers only. This method is available for polygon layers. It will select all polygons from the input layer which have the specified number of holes.

    +

    "with_internal_angle" - Selects edge pairs by their internal angle

    + +

    Usage:

    +
      +
    • edge_pair_layer.with_internal_angle(min .. max)
    • +
    • edge_pair_layer.with_internal_angle(value)
    • +
    • edge_pair_layer.with_internal_angle(min, max)
    • +
    +

    +This method selects edge pairs by the angle enclosed by their edges. +The angle is between 0 (parallel or anti-parallel edges) and 90 degree (perpendicular edges). +If an interval or two values are given, the angle is checked to be within the given +range. +

    +Here are examples for "with_internal_angle" on edge pair layers: +

    +

    +# selects edge pairs with parallel edges
    +ep1 = edge_pairs.with_internal_angle(0)
    +# selects edge pairs with perpendicular edges
    +ep2 = edge_pairs.with_internal_angle(90)
    +
    +

    "with_length" - Selects edges by their length

    Usage:

    @@ -3505,12 +3529,13 @@ This method is available for polygon layers only.
  • layer.without_angle(min .. max)
  • layer.without_angle(value)
  • layer.without_angle(min, max)
  • -
  • edge_pairlayer.without_angle(min, max [, both])
  • +
  • edge_pair_layer.without_angle(min, max [, both])
  • The method basically is the inverse of with_angle. It selects all edges of the edge layer or corners of the polygons which do not have the given angle (second form) or whose angle -is not inside the given interval (first and third form). +is not inside the given interval (first and third form). When called on edge pairs, it selects +edge pairs by the angles of their edges.

    A note on the "both" modifier (without_angle called on edge pairs): "both" means that both edges need to be "without_angle". For example @@ -3520,8 +3545,11 @@ both edges need to be "without_angle". For example # the edge pair is skipped if one edge is horizontal ep = edge_pairs.without_angle(0, both) +

    +See with_internal_angle and without_internal_angle to select edge pairs by the +angle between the edges.

    -

    "without_area" - Selects polygons by area

    +

    "without_area" - Selects polygons or edge pairs by area

    Usage:

      @@ -3531,10 +3559,10 @@ ep = edge_pairs.without_angle(0, both)

    This method is the inverse of "with_area". It will select -polygons without an area equal to the given one or outside +polygons or edge pairs without an area equal to the given one or outside the given interval.

    -This method is available for polygon layers only. +This method is available for polygon or edge pair layers.

    "without_area_ratio" - Selects polygons by the aspect ratio of their bounding box

    @@ -3647,6 +3675,18 @@ This method is available for edge pair layers only. This method is available for polygon layers. It will select all polygons from the input layer which do not have the specified number of holes.

    +

    "without_internal_angle" - Selects edge pairs by their internal angle

    + +

    Usage:

    +
      +
    • edge_pair_layer.without_internal_angle(min .. max)
    • +
    • edge_pair_layer.without_internal_angle(value)
    • +
    • edge_pair_layer.without_internal_angle(min, max)
    • +
    +

    +The method basically is the inverse of with_internal_angle. It selects all +edge pairs by the angle enclosed by their edges, applying the opposite criterion than with_internal_angle. +

    "without_length" - Selects edges by the their length

    Usage:

    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 70f94a7ed..e5e8daf3d 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -234,11 +234,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 (); @@ -246,11 +246,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 (); @@ -265,7 +265,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/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index 2a74de56c..e628cfcb8 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -1192,6 +1192,7 @@ NetlistBrowserPage::produce_highlights_for_net (const db::Net *net, size_t &n_ma while (! shapes.at_end ()) { if (shapes->type () != db::NetShape::Polygon) { + ++shapes; continue; } 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 304aa9dd5..c3dbe3ef1 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,7 +226,15 @@ TEST(24_issue806) run_test (_this, "custom_compare", "custom_compare.gds"); } -TEST(25_enableWandL) +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"); + +TEST(26_enableWandL) { run_test (_this, "enable_wl1", "resistor.gds"); run_test (_this, "enable_wl2", "resistor.gds"); diff --git a/src/rba/rba/rbaConvert.cc b/src/rba/rba/rbaConvert.cc index 6ac1a7877..17673a91a 100644 --- a/src/rba/rba/rbaConvert.cc +++ b/src/rba/rba/rbaConvert.cc @@ -224,7 +224,7 @@ object_to_ruby (void *obj, Proxy *self, const gsi::ClassBase *cls, bool pass_obj // a Ruby object. If it already has, we simply return a reference to this. ret = rba_data->self (); -#if HAVE_RUBY_VERSION_CODE >= 20200 +#if HAVE_RUBY_VERSION_CODE >= 20200 && HAVE_RUBY_VERSION_CODE < 30000 // Mark the returned object - the original one may have been already // scheduled for sweeping. This happens at least for Ruby 2.3 which // has a two-phase GC (mark and sweep in separate steps). If by chance diff --git a/testdata/drc/drcSimpleTests_51.drc b/testdata/drc/drcSimpleTests_51.drc new file mode 100644 index 000000000..ee43169dc --- /dev/null +++ b/testdata/drc/drcSimpleTests_51.drc @@ -0,0 +1,26 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +ep = input(1, 0).drc(sep(input(2, 0), angle_limit(91)) < 0.5) + +input(1, 0).output(1, 0) +input(2, 0).output(2, 0) + +ep.polygons(0).output(100, 0) + +ep.with_internal_angle(45.0).polygons(0).output(200, 0) +ep.with_internal_angle(0.0).polygons(0).output(201, 0) +ep.with_internal_angle(45.0..91.0).polygons(0).output(202, 0) + +ep.without_internal_angle(45.0).polygons(0).output(220, 0) +ep.without_internal_angle(0.0).polygons(0).output(221, 0) +ep.without_internal_angle(45.0..91.0).polygons(0).output(222, 0) + +ep.with_area(0 .. 0.1).polygons(0).output(300, 0) +ep.without_area(0 .. 0.1).polygons(0).output(301, 0) + diff --git a/testdata/drc/drcSimpleTests_51.gds b/testdata/drc/drcSimpleTests_51.gds new file mode 100644 index 000000000..ec9722ff6 Binary files /dev/null and b/testdata/drc/drcSimpleTests_51.gds differ diff --git a/testdata/drc/drcSimpleTests_au51.gds b/testdata/drc/drcSimpleTests_au51.gds new file mode 100644 index 000000000..2025e5c0d Binary files /dev/null and b/testdata/drc/drcSimpleTests_au51.gds differ 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/basic_testcore.rb b/testdata/ruby/basic_testcore.rb index 008a064d7..ab32c9156 100644 --- a/testdata/ruby/basic_testcore.rb +++ b/testdata/ruby/basic_testcore.rb @@ -894,8 +894,10 @@ class Basic_TestClass < TestBase end - # TODO: this class is going to be deprecated - class X < Data + if RUBY_VERSION < "3.0.0" + # TODO: this class is going to be deprecated + class X < Data + end end class Y < Object end @@ -907,12 +909,14 @@ class Basic_TestClass < TestBase end # Test, if this throws an error (object of class X passed to A argument): - begin - b = RBA::B.new - assert_equal( b.b4( X.new ), "b4_result: -6" ) - assert_equal( false, true ) # this must never hit - rescue - assert_equal( $!.to_s(), "allocator undefined for Basic_TestClass::X" ); + if RUBY_VERSION < "3.0.0" + begin + b = RBA::B.new + assert_equal( b.b4( X.new ), "b4_result: -6" ) + assert_equal( false, true ) # this must never hit + rescue + assert_equal( $!.to_s(), "allocator undefined for Basic_TestClass::X" ); + end end # Test, if this throws an error (object of class X passed to A argument): diff --git a/testdata/ruby/dbEdgePairsTest.rb b/testdata/ruby/dbEdgePairsTest.rb index 95ef504b5..e56de3be6 100644 --- a/testdata/ruby/dbEdgePairsTest.rb +++ b/testdata/ruby/dbEdgePairsTest.rb @@ -268,13 +268,9 @@ class DBEdgePairs_TestClass < TestBase assert_equal(r1.with_area(150, 150, false).to_s, "") assert_equal(r1.with_area(150, 151, true).to_s, "(0,0;0,10)/(10,0;10,20);(0,0;0,20)/(10,20;10,0);(0,0;0,10)/(10,0;10,10)") - assert_equal(r1.with_internal_angle(0, false).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,20)/(10,20;10,0)") + assert_equal(r1.with_internal_angle(0, false).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(10,0;10,20);(0,0;0,20)/(10,20;10,0);(0,0;0,10)/(10,0;10,10)") assert_equal(r1.with_internal_angle(0, 0, false).to_s, "") - assert_equal(r1.with_internal_angle(0, 180, false).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,20)/(10,20;10,0)") - assert_equal(r1.with_internal_angle(0, 180, false, true, true).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(10,0;10,20);(0,0;0,20)/(10,20;10,0);(0,0;0,10)/(10,0;10,10)") - assert_equal(r1.with_internal_angle(180, false).to_s, "(0,0;0,10)/(10,0;10,20);(0,0;0,10)/(10,0;10,10)") - assert_equal(r1.with_internal_angle(-180, false).to_s, "(0,0;0,10)/(10,0;10,20);(0,0;0,10)/(10,0;10,10)") - assert_equal(r1.with_internal_angle(0, true).to_s, "(0,0;0,10)/(10,0;10,20);(0,0;0,10)/(10,0;10,10)") + assert_equal(r1.with_internal_angle(0, true).to_s, "") ep1 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 10), RBA::Edge::new(10, 20, 10, 0)) ep2 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 10), RBA::Edge::new(20, 0, 30, 0)) @@ -286,8 +282,8 @@ class DBEdgePairs_TestClass < TestBase assert_equal(r1.with_distance(20, true).to_s, "(0,0;0,10)/(10,20;10,0)") assert_equal(r1.with_internal_angle(0, false).to_s, "(0,0;0,10)/(10,20;10,0)") - assert_equal(r1.with_internal_angle(90, false).to_s, "(0,0;0,10)/(20,0;30,0)") - assert_equal(r1.with_internal_angle(-90, false).to_s, "(0,0;0,10)/(-20,0;-30,0)") + assert_equal(r1.with_internal_angle(90, false).to_s, "(0,0;0,10)/(20,0;30,0);(0,0;0,10)/(-20,0;-30,0)") + assert_equal(r1.with_internal_angle(-90, false).to_s, "") assert_equal(r1.with_angle(90, false).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(20,0;30,0);(0,0;0,10)/(-20,0;-30,0)") assert_equal(r1.with_angle(0, false).to_s, "(0,0;0,10)/(20,0;30,0);(0,0;0,10)/(-20,0;-30,0)") @@ -295,6 +291,18 @@ class DBEdgePairs_TestClass < TestBase assert_equal(r1.with_angle_both(90, false).to_s, "(0,0;0,10)/(10,20;10,0)") assert_equal(r1.with_angle_both(0, false).to_s, "") + ep1 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 10), RBA::Edge::new(10, 20, 10, 0)) + ep2 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 10), RBA::Edge::new(20, 10, 30, 0)) + + r1 = RBA::EdgePairs::new([ ep1, ep2 ]) + + assert_equal(r1.with_internal_angle(0, false).to_s, "(0,0;0,10)/(10,20;10,0)") + assert_equal(r1.with_internal_angle(90, false).to_s, "") + assert_equal(r1.with_internal_angle(90, true).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(20,10;30,0)") + assert_equal(r1.with_internal_angle(45, false).to_s, "(0,0;0,10)/(20,10;30,0)") + assert_equal(r1.with_internal_angle(0, 45, false, true, true).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(20,10;30,0)") + assert_equal(r1.with_internal_angle(0, 45, true, true, true).to_s, "") + end end diff --git a/testdata/ruby/dbNetlist.rb b/testdata/ruby/dbNetlist.rb index 9f0081795..d5820f71f 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 }, []) @@ -700,7 +712,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" @@ -708,6 +727,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