From 3f3f4c917388cbd5927bf0d598a180d015bfd6d9 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 17 Jul 2021 22:03:22 +0200 Subject: [PATCH 01/12] Fixed some compiler warnings. --- src/db/db/dbBoxScanner.h | 8 ++++---- src/db/db/dbRegionUtils.cc | 2 +- src/db/db/dbRegionUtils.h | 2 +- src/lay/lay/layTechSetupDialog.cc | 2 +- src/lay/lay/layTechSetupDialog.h | 2 +- src/lay/lay/layTechnologyController.cc | 2 +- src/laybasic/laybasic/layLibrariesView.cc | 2 +- src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc | 2 +- .../tools/net_tracer/lay_plugin/layNetTracerDialog.cc | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/db/db/dbBoxScanner.h b/src/db/db/dbBoxScanner.h index 07b5c8319..8183396e4 100644 --- a/src/db/db/dbBoxScanner.h +++ b/src/db/db/dbBoxScanner.h @@ -122,7 +122,7 @@ struct box_scanner_receiver * The finish method is called when an object is no longer in the queue and can be * discarded. */ - virtual void finish (const Obj * /*obj*/, const Prop & /*prop*/) { } + virtual void finish (const Obj * /*obj*/, Prop /*prop*/) { } /** * @brief Callback for an interaction of o1 with o2. @@ -130,7 +130,7 @@ struct box_scanner_receiver * This method is called when the object o1 interacts with o2 within the current * definition. */ - virtual void add (const Obj * /*o1*/, const Prop & /*p1*/, const Obj * /*o2*/, const Prop & /*p2*/) { } + virtual void add (const Obj * /*o1*/, Prop /*p1*/, const Obj * /*o2*/, Prop /*p2*/) { } /** * @brief Indicates whether the scanner may stop @@ -1043,7 +1043,7 @@ public: /** * @brief Implementation of the box scanner receiver class */ - void finish (const Obj *obj, const Prop &prop) + void finish (const Obj *obj, Prop prop) { om_iterator_type omi = m_om.find (om_key_type (obj, prop)); if (omi != m_om.end ()) { @@ -1089,7 +1089,7 @@ public: /** * @brief Implementation of the box scanner receiver class */ - void add (const Obj *o1, const Prop &p1, const Obj *o2, const Prop &p2) + void add (const Obj *o1, Prop p1, const Obj *o2, Prop p2) { om_iterator_type om1 = m_om.find (om_key_type (o1, p1)); om_iterator_type om2 = m_om.find (om_key_type (o2, p2)); diff --git a/src/db/db/dbRegionUtils.cc b/src/db/db/dbRegionUtils.cc index ef0b5ac0a..e4e33e563 100644 --- a/src/db/db/dbRegionUtils.cc +++ b/src/db/db/dbRegionUtils.cc @@ -108,7 +108,7 @@ static inline bool shields (const db::EdgePair &ep, const db::Edge &q) } void -Edge2EdgeCheckBase::finish (const Edge *o, const size_t &p) +Edge2EdgeCheckBase::finish (const Edge *o, size_t p) { if (m_has_negative_edge_output && m_pass == 1 && m_pseudo_edges.find (std::make_pair (*o, p)) == m_pseudo_edges.end ()) { diff --git a/src/db/db/dbRegionUtils.h b/src/db/db/dbRegionUtils.h index cd759cb4f..62fca5cd3 100644 --- a/src/db/db/dbRegionUtils.h +++ b/src/db/db/dbRegionUtils.h @@ -611,7 +611,7 @@ public: /** * @brief Reimplementation of the box_scanner_receiver interface */ - void finish (const Edge *o, const size_t &); + void finish (const Edge *o, size_t); /** * @brief Gets a value indicating whether the check requires different layers diff --git a/src/lay/lay/layTechSetupDialog.cc b/src/lay/lay/layTechSetupDialog.cc index 6ab86f668..17c7ef644 100644 --- a/src/lay/lay/layTechSetupDialog.cc +++ b/src/lay/lay/layTechSetupDialog.cc @@ -708,7 +708,7 @@ TechSetupDialog::update () } int -TechSetupDialog::exec (db::Technologies &technologies) +TechSetupDialog::exec_dialog (db::Technologies &technologies) { if (s_first_show) { TipDialog td (this, diff --git a/src/lay/lay/layTechSetupDialog.h b/src/lay/lay/layTechSetupDialog.h index 03b608e4b..27bf8b3fb 100644 --- a/src/lay/lay/layTechSetupDialog.h +++ b/src/lay/lay/layTechSetupDialog.h @@ -149,7 +149,7 @@ public: TechSetupDialog (QWidget *parent); ~TechSetupDialog (); - int exec (db::Technologies &technologies); + int exec_dialog (db::Technologies &technologies); protected slots: void current_tech_changed (QTreeWidgetItem *current, QTreeWidgetItem *previous); diff --git a/src/lay/lay/layTechnologyController.cc b/src/lay/lay/layTechnologyController.cc index 441163065..883869709 100644 --- a/src/lay/lay/layTechnologyController.cc +++ b/src/lay/lay/layTechnologyController.cc @@ -436,7 +436,7 @@ TechnologyController::show_editor () { db::Technologies new_tech = *db::Technologies ().instance (); - if (mp_editor && mp_editor->exec (new_tech)) { + if (mp_editor && mp_editor->exec_dialog (new_tech)) { std::string err_msg; diff --git a/src/laybasic/laybasic/layLibrariesView.cc b/src/laybasic/laybasic/layLibrariesView.cc index 55cff7d47..e80568f15 100644 --- a/src/laybasic/laybasic/layLibrariesView.cc +++ b/src/laybasic/laybasic/layLibrariesView.cc @@ -669,7 +669,7 @@ LibrariesView::do_update_content (int lib_index) mp_cell_lists.pop_back (); } - for (size_t i = imin; i < m_libraries.size () && i < mp_selector->count () && i <= imax; ++i) { + for (size_t i = imin; i < m_libraries.size () && i < size_t (mp_selector->count ()) && i <= imax; ++i) { mp_selector->setItemText (int (i), tl::to_qstring (display_string (int (i)))); } while (mp_selector->count () < int (m_libraries.size ())) { diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc index 8b0d598af..56b5113c2 100644 --- a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc +++ b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc @@ -3037,7 +3037,7 @@ DXFReader::read_int64 () if (! ex.try_read (x) || ! ex.at_end ()) { error ("Expected an ASCII numerical value"); } - if (x < std::numeric_limits::min() || x > std::numeric_limits::max()) { + if (x < double (std::numeric_limits::min()) || x > double (std::numeric_limits::max())) { error ("Value is out of limits for a 64 bit signed integer"); } return (long long) x; diff --git a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc index 7b8b24dc8..3c7da9d8b 100644 --- a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc +++ b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc @@ -1428,7 +1428,7 @@ NetTracerDialog::get_trace_depth() QString depth = depth_le->text ().trimmed (); if (! depth.isEmpty ()) { tl::from_string (tl::to_string (depth), n); - if (n < 0 || n > std::numeric_limits::max ()) { + if (n < 0 || n > double (std::numeric_limits::max ())) { n = 0.0; } } From 2f3e113db04f505380818b84ca72223accae0f28 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 17 Jul 2021 22:06:06 +0200 Subject: [PATCH 02/12] Added missing subcircuit mismatch events to netlist compare --- src/db/db/dbNetlistCompare.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 2bd44b72b..ae5a3a32b 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -4243,12 +4243,12 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG bool mapped = true, valid = true; std::vector > k = compute_subcircuit_key_for_this (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, mapped, valid); - if (! mapped) { + if (! mapped || ! valid) { if (mp_logger) { mp_logger->subcircuit_mismatch (sc.operator-> (), 0); } good = false; - } else if (valid) { + } else { // TODO: report devices which cannot be distinguished topologically? subcircuit_map.insert (std::make_pair (k, std::make_pair (sc.operator-> (), sc_cat))); } From d018805c23374e6cd56183b782286d8d1eee3bb6 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 18 Jul 2021 16:54:27 +0200 Subject: [PATCH 03/12] Some refactoring. --- src/db/db/dbNetlistCompare.cc | 407 +++++++++++++++++----------------- 1 file changed, 201 insertions(+), 206 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index ae5a3a32b..51fbc5b2a 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -668,6 +668,40 @@ struct CompareData tl::RelativeProgress *progress; }; +// -------------------------------------------------------------------------------------------------------------------- +// A generic triplet of object category and two IDs +// Used as a key for device terminal edges and subcircuit edges + +class CatAndIds +{ +public: + CatAndIds (size_t cat, size_t id1, size_t id2) + : m_cat (cat), m_id1 (id1), m_id2 (id2) + { } + + bool operator== (const CatAndIds &other) const + { + return m_cat == other.m_cat && m_id1 == other.m_id1 && m_id2 == other.m_id2; + } + + bool operator< (const CatAndIds &other) const + { + if (m_cat != other.m_cat) { + return m_cat < other.m_cat; + } + if (m_id1 != other.m_id1) { + return m_id1 < other.m_id1; + } + if (m_id2 != other.m_id2) { + return m_id2 < other.m_id2; + } + return false; + } + +private: + size_t m_cat, m_id1, m_id2; +}; + // -------------------------------------------------------------------------------------------------------------------- // NetGraphNode definition and implementation @@ -676,6 +710,156 @@ static size_t translate_terminal_id (size_t tid, const db::Device *device) return device->device_class () ? device->device_class ()->normalize_terminal_id (tid) : tid; } +/** + * @brief Represents one transition within a net graph edge + * + * Each transition connects two pins of subcircuits or terminals of devices. + * An edge is basically a collection of transitions. + */ +class Transition +{ +public: + Transition (const db::Device *device, size_t device_category, size_t terminal1_id, size_t terminal2_id) + { + m_ptr = (void *) device; + m_cat = device_category; + m_id1 = terminal1_id; + m_id2 = terminal2_id; + } + + Transition (const db::SubCircuit *subcircuit, size_t subcircuit_category, size_t pin1_id, size_t pin2_id) + { + m_ptr = (void *) subcircuit; + m_cat = subcircuit_category; + m_id1 = std::numeric_limits::max () - pin1_id; + m_id2 = pin2_id; + } + + CatAndIds make_key () const + { + return CatAndIds (m_cat, m_id1, m_id2); + } + + bool operator< (const Transition &other) const + { + if (is_for_subcircuit () != other.is_for_subcircuit ()) { + return is_for_subcircuit () < other.is_for_subcircuit (); + } + + if (is_for_subcircuit ()) { + + if ((subcircuit () != 0) != (other.subcircuit () != 0)) { + return (subcircuit () != 0) < (other.subcircuit () != 0); + } + + if (subcircuit () != 0) { + SubCircuitCompare scc; + if (! scc.equals (std::make_pair (subcircuit (), cat ()), std::make_pair (other.subcircuit (), other.cat ()))) { + return scc (std::make_pair (subcircuit (), cat ()), std::make_pair (other.subcircuit (), other.cat ())); + } + } + + } else { + + if ((device () != 0) != (other.device () != 0)) { + return (device () != 0) < (other.device () != 0); + } + + if (device () != 0) { + DeviceCompare dc; + if (! dc.equals (std::make_pair (device (), cat ()), std::make_pair (other.device (), other.cat ()))) { + return dc (std::make_pair (device (), cat ()), std::make_pair (other.device (), other.cat ())); + } + } + + } + + if (m_id1 != other.m_id1) { + return m_id1 < other.m_id1; + } + return m_id2 < other.m_id2; + } + + bool operator== (const Transition &other) const + { + if (is_for_subcircuit () != other.is_for_subcircuit ()) { + return false; + } + + if (is_for_subcircuit ()) { + + if ((subcircuit () != 0) != (other.subcircuit () != 0)) { + return false; + } + + if (subcircuit () != 0) { + SubCircuitCompare scc; + if (! scc.equals (std::make_pair (subcircuit (), cat ()), std::make_pair (other.subcircuit (), other.cat ()))) { + return false; + } + } + + } else { + + if ((device () != 0) != (other.device () != 0)) { + return false; + } + + if (device () != 0) { + DeviceCompare dc; + if (! dc.equals (std::make_pair (device (), cat ()), std::make_pair (other.device (), other.cat ()))) { + return false; + } + } + + } + + return (m_id1 == other.m_id1 && m_id2 == other.m_id2); + } + + std::string to_string () const + { + if (is_for_subcircuit ()) { + const db::SubCircuit *sc = subcircuit (); + 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 () + " " + c->pin_by_id (pin_id)->expanded_name () + " (virtual)"; + } else { + size_t term_id1 = m_id1; + size_t term_id2 = m_id2; + const db::Device *d = device (); + const db::DeviceClass *dc = d->device_class (); + return std::string ("D") + d->expanded_name () + " " + dc->name () + " " + + "(" + dc->terminal_definitions () [term_id1].name () + ")->(" + dc->terminal_definitions () [term_id2].name () + ")"; + } + } + + inline bool is_for_subcircuit () const + { + return m_id1 > std::numeric_limits::max () / 2; + } + + const db::Device *device () const + { + return (const db::Device *) m_ptr; + } + + const db::SubCircuit *subcircuit () const + { + return (const db::SubCircuit *) m_ptr; + } + + size_t cat () const + { + return m_cat; + } + +private: + void *m_ptr; + size_t m_cat; + size_t m_id1, m_id2; +}; + /** * @brief A node within the net graph * @@ -691,166 +875,6 @@ static size_t translate_terminal_id (size_t tid, const db::Device *device) class NetGraphNode { public: - /** - * @brief Represents one transition within an edge_iterator - * - * Each transition connects two pins of subcircuits or terminals - * of devices. - * An edge is basically a collection of transitions. - */ - struct Transition - { - - Transition (const db::Device *device, size_t device_category, size_t terminal1_id, size_t terminal2_id) - { - device_pair ().first = device; - device_pair ().second = device_category; - m_id1 = terminal1_id; - m_id2 = terminal2_id; - } - - Transition (const db::SubCircuit *subcircuit, size_t subcircuit_category, size_t pin1_id, size_t pin2_id) - { - subcircuit_pair ().first = subcircuit; - subcircuit_pair ().second = subcircuit_category; - m_id1 = std::numeric_limits::max () - pin1_id; - m_id2 = pin2_id; - } - - size_t id1 () const - { - return m_id1; - } - - size_t id2 () const - { - return m_id2; - } - - bool operator< (const Transition &other) const - { - if (is_for_subcircuit () != other.is_for_subcircuit ()) { - return is_for_subcircuit () < other.is_for_subcircuit (); - } - - if (is_for_subcircuit ()) { - - if ((subcircuit_pair ().first != 0) != (other.subcircuit_pair ().first != 0)) { - return (subcircuit_pair ().first != 0) < (other.subcircuit_pair ().first != 0); - } - - if (subcircuit_pair ().first != 0) { - SubCircuitCompare scc; - if (! scc.equals (subcircuit_pair (), other.subcircuit_pair ())) { - return scc (subcircuit_pair (), other.subcircuit_pair ()); - } - } - - } else { - - if ((device_pair ().first != 0) != (other.device_pair ().first != 0)) { - return (device_pair ().first != 0) < (other.device_pair ().first != 0); - } - - if (device_pair ().first != 0) { - DeviceCompare dc; - if (! dc.equals (device_pair (), other.device_pair ())) { - return dc (device_pair (), other.device_pair ()); - } - } - - } - - if (m_id1 != other.m_id1) { - return m_id1 < other.m_id1; - } - return m_id2 < other.m_id2; - } - - bool operator== (const Transition &other) const - { - if (is_for_subcircuit () != other.is_for_subcircuit ()) { - return false; - } - - if (is_for_subcircuit ()) { - - if ((subcircuit_pair ().first != 0) != (other.subcircuit_pair ().first != 0)) { - return false; - } - - if (subcircuit_pair ().first != 0) { - SubCircuitCompare scc; - if (! scc.equals (subcircuit_pair (), other.subcircuit_pair ())) { - return false; - } - } - - } else { - - if ((device_pair ().first != 0) != (other.device_pair ().first != 0)) { - return false; - } - - if (device_pair ().first != 0) { - DeviceCompare dc; - if (! dc.equals (device_pair (), other.device_pair ())) { - return false; - } - } - - } - - return (m_id1 == other.m_id1 && m_id2 == other.m_id2); - } - - std::string to_string () const - { - 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 () + " " + c->pin_by_id (pin_id)->expanded_name () + " (virtual)"; - } else { - size_t term_id1 = m_id1; - size_t term_id2 = m_id2; - const db::Device *d = device_pair ().first; - const db::DeviceClass *dc = d->device_class (); - return std::string ("D") + d->expanded_name () + " " + dc->name () + " " - + "(" + dc->terminal_definitions () [term_id1].name () + ")->(" + dc->terminal_definitions () [term_id2].name () + ")"; - } - } - - inline bool is_for_subcircuit () const - { - return m_id1 > std::numeric_limits::max () / 2; - } - - std::pair &device_pair () - { - return *reinterpret_cast *> ((void *) &m_ref); - } - - const std::pair &device_pair () const - { - return *reinterpret_cast *> ((const void *) &m_ref); - } - - std::pair &subcircuit_pair () - { - return *reinterpret_cast *> ((void *) &m_ref); - } - - const std::pair &subcircuit_pair () const - { - return *reinterpret_cast *> ((const void *) &m_ref); - } - - private: - char m_ref [sizeof (std::pair)]; - size_t m_id1, m_id2; - }; - typedef std::pair, std::pair > edge_type; static void swap_edges (edge_type &e1, edge_type &e2) @@ -953,7 +977,7 @@ public: edge_iterator find_edge (const std::vector &edge) const { - edge_iterator res = std::lower_bound (begin (), end (), edge, NetGraphNode::EdgeToEdgeOnlyCompare ()); + edge_iterator res = std::lower_bound (begin (), end (), edge, EdgeToEdgeOnlyCompare ()); if (res == end () || res->first != edge) { return end (); } else { @@ -1373,9 +1397,9 @@ NetGraphNode::expand_subcircuit_nodes (NetGraph *graph) for (std::vector::const_iterator t = e->first.begin (); t != e->first.end (); ++t) { tl_assert (t->is_for_subcircuit ()); if (! sc) { - sc = t->subcircuit_pair ().first; + sc = t->subcircuit (); } else { - tl_assert (sc == t->subcircuit_pair ().first); + tl_assert (sc == t->subcircuit ()); } } @@ -1542,35 +1566,6 @@ struct NodeRange // -------------------------------------------------------------------------------------------------------------------- -struct CatAndIds -{ -public: - CatAndIds (size_t _cat, size_t _id1, size_t _id2) - : cat (_cat), id1 (_id1), id2 (_id2) - { } - - bool operator== (const CatAndIds &other) const - { - return cat == other.cat && id1 == other.id1 && id2 == other.id2; - } - - bool operator< (const CatAndIds &other) const - { - if (cat != other.cat) { - return cat < other.cat; - } - if (id1 != other.id1) { - return id1 < other.id1; - } - if (id2 != other.id2) { - return id2 < other.id2; - } - return false; - } - - size_t cat, id1, id2; -}; - template class generic_mapper_for_target_node { @@ -1659,9 +1654,9 @@ public: size_t ni = e.second.first; std::set > &dev = for_node_nc (ni); - for (std::vector::const_iterator j = e.first.begin (); j != e.first.end (); ++j) { + for (std::vector::const_iterator j = e.first.begin (); j != e.first.end (); ++j) { if (! j->is_for_subcircuit ()) { - dev.insert (std::make_pair (CatAndIds (j->device_pair ().second, j->id1 (), j->id2 ()), j->device_pair ().first)); + dev.insert (std::make_pair (j->make_key (), j->device ())); } } } @@ -1686,9 +1681,9 @@ public: size_t ni = e.second.first; std::set > &sc = for_node_nc (ni); - for (std::vector::const_iterator j = e.first.begin (); j != e.first.end (); ++j) { + for (std::vector::const_iterator j = e.first.begin (); j != e.first.end (); ++j) { if (j->is_for_subcircuit ()) { - sc.insert (std::make_pair (CatAndIds (j->subcircuit_pair ().second, j->id1 (), j->id2 ()), j->subcircuit_pair ().first)); + sc.insert (std::make_pair (j->make_key (), j->subcircuit ())); } } } @@ -1903,21 +1898,21 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci */ static bool edges_are_compatible (const NetGraphNode::edge_type &e, const NetGraphNode::edge_type &e_other, const DeviceEquivalenceTracker &device_eq, const SubCircuitEquivalenceTracker &sc_eq) { - std::vector::const_iterator t1 = e.first.begin (), tt1 = e.first.end (); - std::vector::const_iterator t2 = e_other.first.begin (), tt2 = e_other.first.end (); + std::vector::const_iterator t1 = e.first.begin (), tt1 = e.first.end (); + std::vector::const_iterator t2 = e_other.first.begin (), tt2 = e_other.first.end (); std::vector p1, p2; while (t1 != tt1 && t2 != tt2) { - std::vector::const_iterator t10 = t1, t20 = t2; + std::vector::const_iterator t10 = t1, t20 = t2; p1.clear (); while (t1 != tt1 && *t1 == *t10) { if (t1->is_for_subcircuit ()) { - p1.push_back ((void *) sc_eq.other (t1->subcircuit_pair ().first)); + p1.push_back ((void *) sc_eq.other (t1->subcircuit ())); } else { - p1.push_back ((void *) device_eq.other (t1->device_pair ().first)); + p1.push_back ((void *) device_eq.other (t1->device ())); } ++t1; } @@ -1925,9 +1920,9 @@ static bool edges_are_compatible (const NetGraphNode::edge_type &e, const NetGra p2.clear (); while (t2 != tt2 && *t2 == *t20) { if (t2->is_for_subcircuit ()) { - p2.push_back ((void *) (sc_eq.other (t2->subcircuit_pair ().first) ? t2->subcircuit_pair ().first : 0)); + p2.push_back ((void *) (sc_eq.other (t2->subcircuit ()) ? t2->subcircuit () : 0)); } else { - p2.push_back ((void *) (device_eq.other (t2->device_pair ().first) ? t2->device_pair ().first : 0)); + p2.push_back ((void *) (device_eq.other (t2->device ()) ? t2->device () : 0)); } ++t2; } @@ -2004,7 +1999,7 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr first = false; } tl::info << indent (depth) << " " << (nn->net () ? nn->net ()->expanded_name ().c_str() : "(null)") << " via: " << tl::noendl; - for (std::vector::const_iterator t = i->second->first.begin (); t != i->second->first.end(); ++t) { + for (std::vector::const_iterator t = i->second->first.begin (); t != i->second->first.end(); ++t) { tl::info << (t != i->second->first.begin () ? "; " : "") << t->to_string() << tl::noendl; } tl::info << ""; @@ -2019,7 +2014,7 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr first = false; } tl::info << indent(depth) << " " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via: " << tl::noendl; - for (std::vector::const_iterator t = i->second->first.begin (); t != i->second->first.end(); ++t) { + for (std::vector::const_iterator t = i->second->first.begin (); t != i->second->first.end(); ++t) { tl::info << (t != i->second->first.begin () ? "; " : "") << t->to_string() << tl::noendl; } tl::info << ""; @@ -2079,7 +2074,7 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr static bool has_subcircuits (db::NetGraphNode::edge_iterator e, db::NetGraphNode::edge_iterator ee) { while (e != ee) { - for (std::vector::const_iterator t = e->first.begin (); t != e->first.end (); ++t) { + for (std::vector::const_iterator t = e->first.begin (); t != e->first.end (); ++t) { if (t->is_for_subcircuit ()) { return true; } From 23bea5dc07c88289e4286655add44768c5dc249e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 18 Jul 2021 17:39:32 +0200 Subject: [PATCH 04/12] Using real pin IDs for printing nodes in netlist compare debug output --- src/db/db/dbNetlistCompare.cc | 84 ++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 51fbc5b2a..8bc56779e 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -723,6 +723,7 @@ public: { m_ptr = (void *) device; m_cat = device_category; + tl_assert (terminal1_id < std::numeric_limits::max () / 2); m_id1 = terminal1_id; m_id2 = terminal2_id; } @@ -731,13 +732,19 @@ public: { m_ptr = (void *) subcircuit; m_cat = subcircuit_category; + // m_id1 between max/2 and max indicates subcircuit + tl_assert (pin1_id < std::numeric_limits::max () / 2); m_id1 = std::numeric_limits::max () - pin1_id; m_id2 = pin2_id; } CatAndIds make_key () const { - return CatAndIds (m_cat, m_id1, m_id2); + if (is_for_subcircuit ()) { + return CatAndIds (m_cat, m_id1, size_t (0)); + } else { + return CatAndIds (m_cat, m_id1, m_id2); + } } bool operator< (const Transition &other) const @@ -759,6 +766,8 @@ public: } } + return m_id1 < other.m_id1; + } else { if ((device () != 0) != (other.device () != 0)) { @@ -772,12 +781,12 @@ public: } } - } + if (m_id1 != other.m_id1) { + return m_id1 < other.m_id1; + } + return m_id2 < other.m_id2; - if (m_id1 != other.m_id1) { - return m_id1 < other.m_id1; } - return m_id2 < other.m_id2; } bool operator== (const Transition &other) const @@ -799,6 +808,8 @@ public: } } + return (m_id1 == other.m_id1); + } else { if ((device () != 0) != (other.device () != 0)) { @@ -812,18 +823,17 @@ public: } } - } + return (m_id1 == other.m_id1 && m_id2 == other.m_id2); - return (m_id1 == other.m_id1 && m_id2 == other.m_id2); + } } std::string to_string () const { if (is_for_subcircuit ()) { const db::SubCircuit *sc = subcircuit (); - 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 () + " " + c->pin_by_id (pin_id)->expanded_name () + " (virtual)"; + return std::string ("X") + sc->expanded_name () + " " + c->name () + " " + c->pin_by_id (m_id2)->expanded_name () + " (virtual)"; } else { size_t term_id1 = m_id1; size_t term_id2 = m_id2; @@ -1238,25 +1248,31 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego const CircuitMapper *cm = & icm->second; - // A pin assignment may be missing because there is no net for a pin -> skip this + // A pin assignment may be missing because there is no (real) net for a pin -> skip this pin + + size_t original_pin_id = pin_id; if (! cm->has_other_pin_for_this_pin (pin_id)) { + continue; + + } else { + + // NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit. + // For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper. + + pin_id = cm->other_pin_from_this_pin (pin_id); + + // realize pin swapping by normalization of pin ID + + pin_id = pin_map->normalize_pin_id (cm->other (), pin_id); + } - // NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit. - // For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper. - - pin_id = cm->other_pin_from_this_pin (pin_id); - - // realize pin swapping by normalization of pin ID - - pin_id = pin_map->normalize_pin_id (cm->other (), pin_id); - // Subcircuits are routed to a null node and descend from a virtual node inside the subcircuit. // The reasoning is that this way we don't need #pins*(#pins-1) edges but rather #pins. - Transition ed (sc, circuit_cat, pin_id, pin_id); + Transition ed (sc, circuit_cat, pin_id, original_pin_id); std::map::const_iterator in = n2entry.find ((const void *) sc); if (in == n2entry.end ()) { @@ -1338,24 +1354,30 @@ NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circui continue; } - // A pin assignment may be missing because there is no net for a pin -> skip this + // A pin assignment may be missing because there is no (real) net for a pin -> skip this pin + + size_t original_pin_id = pin_id; if (! cm->has_other_pin_for_this_pin (pin_id)) { + continue; + + } else { + + // NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit. + // For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper. + + pin_id = cm->other_pin_from_this_pin (pin_id); + + // realize pin swapping by normalization of pin ID + + pin_id = pin_map->normalize_pin_id (cm->other (), pin_id); + } - // NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit. - // For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper. - - pin_id = cm->other_pin_from_this_pin (pin_id); - - // realize pin swapping by normalization of pin ID - - pin_id = pin_map->normalize_pin_id (cm->other (), pin_id); - // Make the other endpoint - Transition ed (sc, circuit_cat, pin_id, pin_id); + Transition ed (sc, circuit_cat, pin_id, original_pin_id); std::map::const_iterator in = n2entry.find (net_at_pin); if (in == n2entry.end ()) { From 05386668b4a38a88399c94634de5cb0f67ed6cdf Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 18 Jul 2021 20:20:23 +0200 Subject: [PATCH 05/12] Re-introducing pin name mapping for net assignment --- src/db/db/dbNetlistCompare.cc | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 8bc56779e..7fc8edadf 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -1543,11 +1543,16 @@ NetGraphNode::net_less (const db::Net *a, const db::Net *b) if ((a != 0) != (b != 0)) { return (a != 0) < (b != 0); } - if (a != 0) { - return a->pin_count () < b->pin_count (); - } else { + if (a == 0) { return false; } + if (a->pin_count () != b->pin_count ()) { + return a->pin_count () < b->pin_count (); + } + if (a->pin_count () == 0) { + return true; + } + return db::Netlist::name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), a->begin_pins ()->pin ()->name (), b->begin_pins ()->pin ()->name ()) < 0; } bool @@ -1556,11 +1561,16 @@ NetGraphNode::edge_equal (const db::Net *a, const db::Net *b) if ((a != 0) != (b != 0)) { return false; } - if (a != 0) { - return a->pin_count () == b->pin_count (); - } else { + if (a == 0) { return true; } + if (a->pin_count () != b->pin_count ()) { + return false; + } + if (a->pin_count () == 0) { + return true; + } + return db::Netlist::name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), a->begin_pins ()->pin ()->name (), b->begin_pins ()->pin ()->name ()) == 0; } // -------------------------------------------------------------------------------------------------------------------- From 51d117e37959d78081216f02ab640b7ff886cbf0 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 18 Jul 2021 20:39:19 +0200 Subject: [PATCH 06/12] Refined black box pin heuristics Pins are required to match if they are passive inside the subcircuit but connected to a non-trivial net in the calling circuit. --- src/db/db/dbNetlistCompare.cc | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 7fc8edadf..862d86cb0 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -738,6 +738,11 @@ public: m_id2 = pin2_id; } + static size_t first_unique_pin_id () + { + return std::numeric_limits::max () / 4; + } + CatAndIds make_key () const { if (is_for_subcircuit ()) { @@ -912,12 +917,12 @@ public: /** * @brief Builds a node for a net */ - NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map); + NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id); /** * @brief Builds a virtual node for a subcircuit */ - NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map); + NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id); void expand_subcircuit_nodes (NetGraph *graph); @@ -1218,7 +1223,7 @@ private: // -------------------------------------------------------------------------------------------------------------------- -NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map) +NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id) : mp_net (net), m_other_net_index (invalid_id) { if (! net) { @@ -1254,7 +1259,12 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego if (! cm->has_other_pin_for_this_pin (pin_id)) { - continue; + // isolated pins are ignored, others are considered for the matching + if (net->pin_count () == 0 && net->terminal_count () == 0 && net->subcircuit_pin_count () == 1) { + continue; + } else { + pin_id = unique_pin_id++; + } } else { @@ -1330,7 +1340,7 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego } } -NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map) +NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id) : mp_net (0), m_other_net_index (invalid_id) { std::map n2entry; @@ -1360,7 +1370,12 @@ NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circui if (! cm->has_other_pin_for_this_pin (pin_id)) { - continue; + // isolated pins are ignored, others are considered for the matching + if (net_at_pin->pin_count () == 0 && net_at_pin->terminal_count () == 0 && net_at_pin->subcircuit_pin_count () == 1) { + continue; + } else { + pin_id = unique_pin_id++; + } } else { @@ -1865,8 +1880,10 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci m_nodes.clear (); m_net_index.clear (); + size_t unique_pin_id = Transition::first_unique_pin_id (); + // create a dummy node for a null net - m_nodes.push_back (NetGraphNode (0, device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper)); + m_nodes.push_back (NetGraphNode (0, device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper, unique_pin_id)); size_t nets = 0; for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { @@ -1875,7 +1892,7 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci m_nodes.reserve (nets); for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { - NetGraphNode node (n.operator-> (), device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper); + NetGraphNode node (n.operator-> (), device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper, unique_pin_id); if (! node.empty () || n->pin_count () > 0) { m_nodes.push_back (node); } @@ -1910,7 +1927,7 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci continue; } - m_virtual_nodes.insert (std::make_pair (i.operator-> (), NetGraphNode (i.operator-> (), circuit_categorizer, circuit_and_pin_mapping, circuit_pin_mapper))); + m_virtual_nodes.insert (std::make_pair (i.operator-> (), NetGraphNode (i.operator-> (), circuit_categorizer, circuit_and_pin_mapping, circuit_pin_mapper, unique_pin_id))); } From 2c8d065eb3a49caae4d1c2fcc5486bd8cdd93678 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 18 Jul 2021 22:34:02 +0200 Subject: [PATCH 07/12] Some enhancments + test update 1. Be more careful with net names Net names are used now for sorting the graph nodes, but not for strict compare. This is useful to derive swappable pins for blackbox circuits. 2. Be more careful with pins from schematic netlist Pins from schematic netlist without a corresponding pin on the layer side are treated as mandatory unless connected to a trivial net. Pins connecting to non-trivial nets inside the subcircuit are always considered mandatory. This way schematic pins enforce corresponding layout pins. On the other hand, layout pins connecting to trivial nets inside the subcircuit are considered non-mandatory. --- src/db/db/dbNetlistCompare.cc | 84 +++--- src/db/unit_tests/dbLayoutToNetlistTests.cc | 18 +- src/db/unit_tests/dbNetlistCompareTests.cc | 268 +++++++++++++++----- 3 files changed, 260 insertions(+), 110 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 862d86cb0..d7ca56d48 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -917,12 +917,12 @@ public: /** * @brief Builds a node for a net */ - NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id); + NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id); /** * @brief Builds a virtual node for a subcircuit */ - NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id); + NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id); void expand_subcircuit_nodes (NetGraph *graph); @@ -970,8 +970,18 @@ public: void apply_net_index (const std::map &ni); - bool operator< (const NetGraphNode &node) const; - bool operator== (const NetGraphNode &node) const; + bool less (const NetGraphNode &node, bool with_name) const; + bool equal (const NetGraphNode &node, bool with_name) const; + + bool operator== (const NetGraphNode &node) const + { + return equal (node, false); + } + + bool operator< (const NetGraphNode &node) const + { + return less (node, false); + } void swap (NetGraphNode &other) { @@ -1009,13 +1019,13 @@ private: * @brief Compares edges as "less" * Edge comparison is based on the pins attached (name of the first pin). */ - static bool net_less (const db::Net *a, const db::Net *b); + static bool net_less (const db::Net *a, const db::Net *b, bool with_name); /** * @brief Compares edges as "equal" * See edge_less for the comparison details. */ - static bool edge_equal (const db::Net *a, const db::Net *b); + static bool net_equal (const db::Net *a, const db::Net *b, bool with_name); }; // -------------------------------------------------------------------------------------------------------------------- @@ -1038,7 +1048,7 @@ struct CompareNodePtr { bool operator() (const std::pair &a, const std::pair &b) const { - return *a.first < *b.first; + return a.first->less (*b.first, true); } }; @@ -1072,7 +1082,7 @@ public: /** * @brief Builds the net graph */ - void build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper); + void build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper, size_t *unique_pin_id); /** * @brief Gets the node index for the given net @@ -1223,7 +1233,7 @@ private: // -------------------------------------------------------------------------------------------------------------------- -NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id) +NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id) : mp_net (net), m_other_net_index (invalid_id) { if (! net) { @@ -1262,8 +1272,10 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego // isolated pins are ignored, others are considered for the matching if (net->pin_count () == 0 && net->terminal_count () == 0 && net->subcircuit_pin_count () == 1) { continue; + } else if (! unique_pin_id) { + continue; } else { - pin_id = unique_pin_id++; + pin_id = (*unique_pin_id)++; } } else { @@ -1340,7 +1352,7 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego } } -NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id) +NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id) : mp_net (0), m_other_net_index (invalid_id) { std::map n2entry; @@ -1373,8 +1385,10 @@ NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circui // isolated pins are ignored, others are considered for the matching if (net_at_pin->pin_count () == 0 && net_at_pin->terminal_count () == 0 && net_at_pin->subcircuit_pin_count () == 1) { continue; + } else if (! unique_pin_id) { + continue; } else { - pin_id = unique_pin_id++; + pin_id = (*unique_pin_id)++; } } else { @@ -1517,7 +1531,7 @@ NetGraphNode::apply_net_index (const std::map &ni) } bool -NetGraphNode::operator< (const NetGraphNode &node) const +NetGraphNode::less (const NetGraphNode &node, bool with_name) const { if (m_edges.size () != node.m_edges.size ()) { return m_edges.size () < node.m_edges.size (); @@ -1529,13 +1543,13 @@ NetGraphNode::operator< (const NetGraphNode &node) const } if (m_edges.empty ()) { // do a more detailed analysis on the nets involved - return net_less (net (), node.net ()); + return net_less (net (), node.net (), with_name); } return false; } bool -NetGraphNode::operator== (const NetGraphNode &node) const +NetGraphNode::equal (const NetGraphNode &node, bool with_name) const { if (m_edges.size () != node.m_edges.size ()) { return false; @@ -1547,13 +1561,13 @@ NetGraphNode::operator== (const NetGraphNode &node) const } if (m_edges.empty ()) { // do a more detailed analysis on the edges - return edge_equal (net (), node.net ()); + return net_equal (net (), node.net (), with_name); } return true; } bool -NetGraphNode::net_less (const db::Net *a, const db::Net *b) +NetGraphNode::net_less (const db::Net *a, const db::Net *b, bool with_name) { if ((a != 0) != (b != 0)) { return (a != 0) < (b != 0); @@ -1564,14 +1578,11 @@ NetGraphNode::net_less (const db::Net *a, const db::Net *b) if (a->pin_count () != b->pin_count ()) { return a->pin_count () < b->pin_count (); } - if (a->pin_count () == 0) { - return true; - } - return db::Netlist::name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), a->begin_pins ()->pin ()->name (), b->begin_pins ()->pin ()->name ()) < 0; + return with_name ? name_compare (a, b) < 0 : false; } bool -NetGraphNode::edge_equal (const db::Net *a, const db::Net *b) +NetGraphNode::net_equal (const db::Net *a, const db::Net *b, bool with_name) { if ((a != 0) != (b != 0)) { return false; @@ -1582,10 +1593,7 @@ NetGraphNode::edge_equal (const db::Net *a, const db::Net *b) if (a->pin_count () != b->pin_count ()) { return false; } - if (a->pin_count () == 0) { - return true; - } - return db::Netlist::name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), a->begin_pins ()->pin ()->name (), b->begin_pins ()->pin ()->name ()) == 0; + return with_name ? name_compare (a, b) == 0 : true; } // -------------------------------------------------------------------------------------------------------------------- @@ -1871,7 +1879,7 @@ private: // NetGraph implementation void -NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper) +NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper, size_t *unique_pin_id) { tl::SelfTimer timer (tl::verbosity () >= 31, tl::to_string (tr ("Building net graph for circuit: ")) + c->name ()); @@ -1880,8 +1888,6 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci m_nodes.clear (); m_net_index.clear (); - size_t unique_pin_id = Transition::first_unique_pin_id (); - // create a dummy node for a null net m_nodes.push_back (NetGraphNode (0, device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper, unique_pin_id)); @@ -3613,16 +3619,21 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::NetGraph g1, g2; + size_t unique_pin_id = Transition::first_unique_pin_id (); + // 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); + g1.build (c1, device_categorizer, circuit_categorizer, device_filter, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, (size_t *)0); + 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); + // NOTE: the second netlist graph is the reference (schematic). We treat it a little more carefully by using pins from subcircuits which + // lead to passive nets but connect to non-trivial nets on the outside. This is done by specifying a unique_pin_id counter for the last argument. + g2.build (c2, device_categorizer, circuit_categorizer, device_filter, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, &unique_pin_id); // Match dummy nodes for null nets g1.identify (0, 0); @@ -4287,14 +4298,19 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG bool mapped = true, valid = true; std::vector > k = compute_subcircuit_key_for_this (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, mapped, valid); - if (! mapped || ! valid) { + if (! mapped) { if (mp_logger) { mp_logger->subcircuit_mismatch (sc.operator-> (), 0); } good = false; - } else { + } else if (valid) { // TODO: report devices which cannot be distinguished topologically? subcircuit_map.insert (std::make_pair (k, std::make_pair (sc.operator-> (), sc_cat))); + } else { + // emit a mismatch event but do not consider that an error - this may happen if the circuit has been dropped intentionally (e.g. via cells) + if (mp_logger) { + mp_logger->subcircuit_mismatch (sc.operator-> (), 0); + } } } @@ -4584,7 +4600,7 @@ NetlistComparer::join_symmetric_nets (db::Circuit *circuit) db::NetGraph graph; db::CircuitCategorizer circuit_categorizer; db::DeviceCategorizer device_categorizer; - graph.build (circuit, device_categorizer, circuit_categorizer, device_filter, &circuit_and_pin_mapping, &circuit_pin_mapper); + graph.build (circuit, device_categorizer, circuit_categorizer, device_filter, &circuit_and_pin_mapping, &circuit_pin_mapper, (size_t *) 0); // 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/unit_tests/dbLayoutToNetlistTests.cc b/src/db/unit_tests/dbLayoutToNetlistTests.cc index 155a371fd..7acad9839 100644 --- a/src/db/unit_tests/dbLayoutToNetlistTests.cc +++ b/src/db/unit_tests/dbLayoutToNetlistTests.cc @@ -1140,17 +1140,17 @@ TEST(3_GlobalNetConnections) CHECKPOINT (); db::compare_netlist (_this, *l2n.netlist (), "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" - " subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" - " subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" - " subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n" - " subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n" - " subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n" + " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" + " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" + " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n" + " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n" + " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n" "end;\n" - "circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n" - " subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);\n" - " subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);\n" + "circuit INV2PAIR ($2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n" + " subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6);\n" + " subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6);\n" "end;\n" - "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 081351a47..9d10f8b88 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -1984,6 +1984,7 @@ TEST(13_MismatchingSubcircuitsAdditionalHierarchy) "match_pins $1 $0\n" "match_pins $2 $2\n" "match_pins $3 $3\n" + "subcircuit_mismatch $2 (null)\n" "match_subcircuits $3 $1\n" "match_subcircuits $1 $2\n" "end_circuit TOP TOP MATCH" @@ -3931,25 +3932,6 @@ TEST(21_BusLikeAmbiguousConnections) TEST(22_NodesRemoved) { const char *nls1 = - "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" - " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n" - " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n" - " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n" - " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n" - " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" - "end;\n" - "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" - " subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" - " subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" - "end;\n" - "circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" - " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" - " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" - " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" - " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" - "end;\n"; - - const char *nls2 = "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" " subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" " subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" @@ -3968,6 +3950,25 @@ TEST(22_NodesRemoved) " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" "end;\n"; + const char *nls2 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n" + " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n" + " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n" + " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n" + " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" + "end;\n" + "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" + " subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" + " subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" + "end;\n" + "circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + db::Netlist nl1, nl2; prep_nl (nl1, nls1); prep_nl (nl2, nls2); @@ -3980,6 +3981,79 @@ TEST(22_NodesRemoved) std::string txt = logger.text (); + EXPECT_EQ (txt, + "begin_circuit INV2 INV2\n" + "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets $3 $3\n" + "match_nets IN IN\n" + "match_nets VSS VSS\n" + "match_nets $1 (null)\n" + "match_nets BULK (null)\n" + "match_pins IN IN\n" + "match_pins $2 $1\n" + "match_pins OUT OUT\n" + "match_pins VSS VSS\n" + "match_pins VDD VDD\n" + "match_pins $0 (null)\n" + "match_pins BULK (null)\n" + "match_devices $1 $1\n" + "match_devices $2 $2\n" + "match_devices $3 $3\n" + "match_devices $4 $4\n" + "end_circuit INV2 INV2 MATCH\n" + "begin_circuit INV2PAIR INV2PAIR\n" + "match_nets $I2 $I2\n" + "match_nets $I6 $I5\n" + "match_nets $I5 $I4\n" + "match_nets $I4 $I6\n" + "match_nets $I3 $I3\n" + "match_nets $I7 $I7\n" + "match_nets $I8 $I8\n" + "match_nets BULK (null)\n" + "match_nets $I1 (null)\n" + "match_pins $1 $0\n" + "match_pins $2 $1\n" + "match_pins $3 $2\n" + "match_pins $4 $3\n" + "match_pins $5 $4\n" + "match_pins BULK (null)\n" + "match_pins $6 (null)\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "end_circuit INV2PAIR INV2PAIR MATCH\n" + "begin_circuit RINGO RINGO\n" + "match_nets OSC OSC\n" + "match_nets $I7 $I7\n" + "match_nets $I6 $I6\n" + "match_nets $I5 $I5\n" + "match_nets $I13 $I21\n" + "match_nets FB FB\n" + "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets $I22 $I22\n" + "match_nets $I23 $I23\n" + "match_nets $I24 $I24\n" + "match_nets $I25 $I25\n" + "match_pins FB FB\n" + "match_pins OSC OSC\n" + "match_pins VDD VDD\n" + "match_pins VSS VSS\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "match_subcircuits $3 $3\n" + "match_subcircuits $4 $4\n" + "match_subcircuits $5 $5\n" + "end_circuit RINGO RINGO MATCH" + ); + EXPECT_EQ (good, true); + + logger.clear (); + good = comp.compare (&nl2, &nl1); + + txt = logger.text (); + + // additional nodes are not ignored when they come from the reference side (second) EXPECT_EQ (txt, "begin_circuit INV2 INV2\n" "match_nets VDD VDD\n" @@ -4028,24 +4102,28 @@ TEST(22_NodesRemoved) "match_nets $I5 $I5\n" "match_nets $I21 $I13\n" "match_nets FB FB\n" - "match_nets VSS VSS\n" - "match_nets VDD VDD\n" "match_nets $I22 $I22\n" "match_nets $I23 $I23\n" "match_nets $I24 $I24\n" "match_nets $I25 $I25\n" + "net_mismatch VDD (null)\n" + "net_mismatch VSS (null)\n" + "net_mismatch (null) VDD\n" + "net_mismatch (null) VSS\n" "match_pins FB FB\n" "match_pins OSC OSC\n" - "match_pins VDD VDD\n" - "match_pins VSS VSS\n" - "match_subcircuits $1 $1\n" - "match_subcircuits $2 $2\n" - "match_subcircuits $3 $3\n" - "match_subcircuits $4 $4\n" - "match_subcircuits $5 $5\n" - "end_circuit RINGO RINGO MATCH" + "match_pins VDD (null)\n" + "match_pins VSS (null)\n" + "match_pins (null) VDD\n" + "match_pins (null) VSS\n" + "subcircuit_mismatch $1 $1\n" + "subcircuit_mismatch $2 $2\n" + "subcircuit_mismatch $3 $3\n" + "subcircuit_mismatch $4 $4\n" + "subcircuit_mismatch $5 $5\n" + "end_circuit RINGO RINGO NOMATCH" ); - EXPECT_EQ (good, true); + EXPECT_EQ (good, false); } TEST(23_NodesRemovedWithError) @@ -4150,25 +4228,6 @@ TEST(23_NodesRemovedWithError) TEST(24_NodesRemovedButConnectedInOther) { const char *nls1 = - "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" - " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n" - " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n" - " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n" - " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n" - " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" - "end;\n" - "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" - " subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" - " subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" - "end;\n" - "circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" - " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" - " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" - " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" - " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" - "end;\n"; - - const char *nls2 = "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" " subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" " subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" @@ -4189,6 +4248,25 @@ TEST(24_NodesRemovedButConnectedInOther) " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" "end;\n"; + const char *nls2 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n" + " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n" + " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n" + " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n" + " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" + "end;\n" + "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" + " subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" + " subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" + "end;\n" + "circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + db::Netlist nl1, nl2; prep_nl (nl1, nls1); prep_nl (nl2, nls2); @@ -4208,15 +4286,15 @@ TEST(24_NodesRemovedButConnectedInOther) "match_nets $3 $3\n" "match_nets IN IN\n" "match_nets VSS VSS\n" - "match_nets (null) $1\n" - "match_nets (null) BULK\n" + "match_nets $1 (null)\n" + "match_nets BULK (null)\n" "match_pins IN IN\n" - "match_pins $1 $2\n" + "match_pins $2 $1\n" "match_pins OUT OUT\n" "match_pins VSS VSS\n" "match_pins VDD VDD\n" - "match_pins (null) $0\n" - "match_pins (null) BULK\n" + "match_pins $0 (null)\n" + "match_pins BULK (null)\n" "match_devices $1 $1\n" "match_devices $2 $2\n" "match_devices $3 $3\n" @@ -4224,21 +4302,21 @@ TEST(24_NodesRemovedButConnectedInOther) "end_circuit INV2 INV2 MATCH\n" "begin_circuit INV2PAIR INV2PAIR\n" "match_nets $I2 $I2\n" - "match_nets $I5 $I6\n" - "match_nets $I4 $I5\n" - "match_nets $I6 $I4\n" + "match_nets $I6 $I5\n" + "match_nets $I5 $I4\n" + "match_nets $I4 $I6\n" "match_nets $I3 $I3\n" "match_nets $I7 $I7\n" "match_nets $I8 $I8\n" - "match_nets (null) BULK\n" - "match_nets (null) $I1\n" - "match_pins $0 $1\n" - "match_pins $1 $2\n" - "match_pins $2 $3\n" - "match_pins $3 $4\n" - "match_pins $4 $5\n" - "match_pins (null) BULK\n" - "match_pins (null) $6\n" + "match_nets BULK (null)\n" + "match_nets $I1 (null)\n" + "match_pins $1 $0\n" + "match_pins $2 $1\n" + "match_pins $3 $2\n" + "match_pins $4 $3\n" + "match_pins $5 $4\n" + "match_pins BULK (null)\n" + "match_pins $6 (null)\n" "match_subcircuits $1 $1\n" "match_subcircuits $2 $2\n" "end_circuit INV2PAIR INV2PAIR MATCH\n" @@ -4247,7 +4325,7 @@ TEST(24_NodesRemovedButConnectedInOther) "match_nets $I7 $I7\n" "match_nets $I6 $I6\n" "match_nets $I5 $I5\n" - "match_nets $I21 $I13\n" + "match_nets $I13 $I21\n" "match_nets FB FB\n" "match_nets VSS VSS\n" "match_nets VDD VDD\n" @@ -4267,6 +4345,62 @@ TEST(24_NodesRemovedButConnectedInOther) "end_circuit RINGO RINGO MATCH" ); EXPECT_EQ (good, true); + + + logger.clear (); + good = comp.compare (&nl2, &nl1); + + txt = logger.text (); + + // NOTE: additional nets are ignored in the first netlist but not from the second + EXPECT_EQ (txt, + "begin_circuit INV2 INV2\n" + "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets $3 $3\n" + "match_nets IN IN\n" + "match_nets VSS VSS\n" + "match_nets (null) $1\n" + "match_nets (null) BULK\n" + "match_pins IN IN\n" + "match_pins $1 $2\n" + "match_pins OUT OUT\n" + "match_pins VSS VSS\n" + "match_pins VDD VDD\n" + "match_pins (null) $0\n" + "match_pins (null) BULK\n" + "match_devices $1 $1\n" + "match_devices $2 $2\n" + "match_devices $3 $3\n" + "match_devices $4 $4\n" + "end_circuit INV2 INV2 MATCH\n" + "begin_circuit INV2PAIR INV2PAIR\n" + "match_nets $I2 $I2\n" + "match_nets $I5 $I6\n" + "match_nets $I8 $I8\n" + "match_nets $I7 $I7\n" + "net_mismatch $I6 $I4\n" + "net_mismatch $I4 (null)\n" + "net_mismatch $I3 (null)\n" + "net_mismatch (null) BULK\n" + "net_mismatch (null) $I5\n" + "net_mismatch (null) $I3\n" + "net_mismatch (null) $I1\n" + "match_pins $0 $1\n" + "match_pins $1 $2\n" + "match_pins $4 $5\n" + "pin_mismatch $2 (null)\n" + "pin_mismatch $3 (null)\n" + "pin_mismatch (null) BULK\n" + "pin_mismatch (null) $3\n" + "pin_mismatch (null) $4\n" + "pin_mismatch (null) $6\n" + "subcircuit_mismatch $1 $1\n" + "subcircuit_mismatch $2 $2\n" + "end_circuit INV2PAIR INV2PAIR NOMATCH\n" + "circuit_skipped RINGO RINGO" + ); + EXPECT_EQ (good, false); } TEST(25_JoinSymmetricNets) From 70f4c7e2b59d748164f61a29a5ae41adb45798bb Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 18 Jul 2021 23:09:51 +0200 Subject: [PATCH 08/12] A small refactoring. --- src/db/db/dbNetlistCompare.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index d7ca56d48..fd9458d10 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -1233,6 +1233,11 @@ private: // -------------------------------------------------------------------------------------------------------------------- +static bool is_non_trivial_net (const db::Net *net) +{ + return net->pin_count () == 0 && net->terminal_count () == 0 && net->subcircuit_pin_count () == 1; +} + NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id) : mp_net (net), m_other_net_index (invalid_id) { @@ -1270,9 +1275,7 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego if (! cm->has_other_pin_for_this_pin (pin_id)) { // isolated pins are ignored, others are considered for the matching - if (net->pin_count () == 0 && net->terminal_count () == 0 && net->subcircuit_pin_count () == 1) { - continue; - } else if (! unique_pin_id) { + if (! unique_pin_id || is_non_trivial_net (net)) { continue; } else { pin_id = (*unique_pin_id)++; @@ -1383,9 +1386,7 @@ NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circui if (! cm->has_other_pin_for_this_pin (pin_id)) { // isolated pins are ignored, others are considered for the matching - if (net_at_pin->pin_count () == 0 && net_at_pin->terminal_count () == 0 && net_at_pin->subcircuit_pin_count () == 1) { - continue; - } else if (! unique_pin_id) { + if (! unique_pin_id || is_non_trivial_net (net_at_pin)) { continue; } else { pin_id = (*unique_pin_id)++; From bc74f189f80e1ef60793f0e20fcbdb80e66144c2 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 18 Jul 2021 23:33:01 +0200 Subject: [PATCH 09/12] Introducing asymmetric ambiguity groups for better matching of black box circuits with optional pins. --- src/db/db/dbNetlistCompare.cc | 82 ++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index fd9458d10..86016c64b 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -1604,19 +1604,22 @@ NetGraphNode::net_equal (const db::Net *a, const db::Net *b, bool with_name) */ struct NodeRange { - NodeRange (size_t _num, std::vector >::iterator _n1, std::vector >::iterator _nn1, - std::vector >::iterator _n2, std::vector >::iterator _nn2) - : num (_num), n1 (_n1), nn1 (_nn1), n2 (_n2), nn2 (_nn2) + NodeRange (size_t _num1, std::vector >::iterator _n1, std::vector >::iterator _nn1, + size_t _num2, std::vector >::iterator _n2, std::vector >::iterator _nn2) + : num1 (_num1), num2 (_num2), n1 (_n1), nn1 (_nn1), n2 (_n2), nn2 (_nn2) { // .. nothing yet .. } bool operator< (const NodeRange &other) const { - return num < other.num; + if (num1 != other.num1) { + return num1 < other.num1; + } + return num2 < other.num2; } - size_t num; + size_t num1, num2; std::vector >::iterator n1, nn1, n2, nn2; }; @@ -2399,7 +2402,7 @@ NetGraph::derive_node_identities_from_ambiguity_group (const NodeRange &nr, Devi } size_t new_nodes = 0; - size_t complexity = nr.num; + size_t complexity = std::max (nr.num1, nr.num2); // sort the ambiguity group such that net names match best @@ -2802,30 +2805,32 @@ NetGraph::derive_node_identities_from_node_set (std::vector >::iterator nn1 = n1, nn2 = n2; - size_t num = 1; ++nn1; ++nn2; - while (nn1 != nodes.end () && nn2 != other_nodes.end ()) { - if (nn1->first->has_other ()) { - ++nn1; - } else if (nn2->first->has_other ()) { - ++nn2; - } else if (! (*nn1->first == *n1->first) || ! (*nn2->first == *n2->first)) { - break; - } else { - ++num; - ++nn1; - ++nn2; + + size_t num1 = 1; + while (nn1 != nodes.end () && *nn1->first == *n1->first) { + if (! nn1->first->has_other ()) { + ++num1; } + ++nn1; } - if (num == 1 || data->with_ambiguous) { - node_ranges.push_back (NodeRange (num, n1, nn1, n2, nn2)); + size_t num2 = 1; + while (nn2 != other_nodes.end () && *nn2->first == *n2->first) { + if (! nn2->first->has_other ()) { + ++num2; + } + ++nn2; + } + + if ((num1 == 1 && num2 == 1) || data->with_ambiguous) { + node_ranges.push_back (NodeRange (num1, n1, nn1, num2, n2, nn2)); } // in tentative mode ambiguous nodes don't make a match without // with_ambiguous - if (num > 1 && tentative && ! data->with_ambiguous) { + if ((num1 > 1 || num2 > 1) && tentative && ! data->with_ambiguous) { return failed_match; } @@ -2852,26 +2857,25 @@ NetGraph::derive_node_identities_from_node_set (std::vectornum = 0; - std::vector >::const_iterator i1 = nr->n1, i2 = nr->n2; - - while (i1 != nr->nn1 && i2 != nr->nn2) { - if (i1->first->has_other ()) { - ++i1; - } else if (i2->first->has_other ()) { - ++i2; - } else { - ++nr->num; - ++i1; - ++i2; + nr->num1 = 0; + for (std::vector >::const_iterator i = nr->n1; i != nr->nn1; ++i) { + if (! i->first->has_other ()) { + ++nr->num1; } } - if (nr->num < 1) { + nr->num2 = 0; + for (std::vector >::const_iterator i = nr->n2; i != nr->nn2; ++i) { + if (! i->first->has_other ()) { + ++nr->num2; + } + } + + if (nr->num1 < 1 || nr->num2 < 1) { // ignore this - it got obsolete. - } else if (nr->num == 1) { + } else if (nr->num1 == 1 && nr->num2 == 1) { size_t n = derive_node_identities_from_singular_match (nr->n1->first, nr->n1->second, nr->n2->first, nr->n2->second, dm, dm_other, scm, scm_other, depth, n_branch, tentative, data, ! data->dont_consider_net_names); if (n == failed_match) { @@ -2880,17 +2884,17 @@ NetGraph::derive_node_identities_from_node_set (std::vectormax_n_branch != std::numeric_limits::max () && double (nr->num) * double (n_branch) > double (data->max_n_branch)) { + } else if (data->max_n_branch != std::numeric_limits::max () && double (std::max (nr->num1, nr->num2)) * double (n_branch) > double (data->max_n_branch)) { if (options ()->debug_netcompare) { - tl::info << indent_s << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << data->max_n_branch << ") - mismatch."; + tl::info << indent_s << "max. complexity exhausted (" << std::max (nr->num1, nr->num2) << "*" << n_branch << ">" << data->max_n_branch << ") - mismatch."; } return failed_match; } else { if (options ()->debug_netcompare) { - tl::info << indent_s << "analyzing ambiguity group with " << nr->num << " members"; + tl::info << indent_s << "analyzing ambiguity group with " << nr->num1 << "/" << nr->num2 << " members"; } size_t n = derive_node_identities_from_ambiguity_group (*nr, dm, dm_other, scm, scm_other, depth, n_branch, tentative, data); @@ -2901,7 +2905,7 @@ NetGraph::derive_node_identities_from_node_set (std::vectordebug_netcompare) { - tl::info << indent_s << "finished analysis of ambiguity group with " << nr->num << " members"; + tl::info << indent_s << "finished analysis of ambiguity group with " << nr->num1 << "/" << nr->num2 << " members"; } } From 722b45b72104c012c0822a93c1aa4512c3d996e7 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 19 Jul 2021 07:47:41 +0200 Subject: [PATCH 10/12] Fixed tests --- src/db/unit_tests/dbNetlistCompareTests.cc | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 9d10f8b88..7ef82e780 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -939,8 +939,8 @@ TEST(5_BufferTwoPathsDifferentParameters) "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" + "match_nets INT $10\n" "net_mismatch INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" @@ -995,8 +995,8 @@ TEST(5_BufferTwoPathsDifferentParameters) "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" + "match_nets INT $10\n" "net_mismatch INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" @@ -1023,8 +1023,8 @@ TEST(5_BufferTwoPathsDifferentParameters) "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" + "match_nets INT $10\n" "net_mismatch INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" @@ -1109,8 +1109,8 @@ TEST(5_BufferTwoPathsDifferentParameters) "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" + "match_nets INT $10\n" "net_mismatch INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" @@ -1557,15 +1557,15 @@ TEST(8_DiodesDontMatchOnSwappedPins) EXPECT_EQ (logger.text (), "begin_circuit TRIANGLE TRIANGLE\n" - "match_nets P1 P3\n" - "net_mismatch P2 P1\n" - "net_mismatch P3 P2\n" - "match_pins $0 $2\n" - "match_pins $1 $0\n" - "match_pins $2 $1\n" - "match_devices $1 $1\n" - "match_devices $3 $3\n" - "device_mismatch $2 $2\n" + "match_nets P3 P3\n" + "net_mismatch P1 P1\n" + "net_mismatch P2 P2\n" + "match_pins $0 $0\n" + "match_pins $1 $1\n" + "match_pins $2 $2\n" + "match_devices $3 $1\n" + "match_devices $2 $3\n" + "device_mismatch $1 $2\n" "end_circuit TRIANGLE TRIANGLE NOMATCH" ); EXPECT_EQ (good, false); @@ -4181,12 +4181,12 @@ TEST(23_NodesRemovedWithError) EXPECT_EQ (txt, "begin_circuit INV2 INV2\n" - "match_nets $1 $1\n" "match_nets VDD VDD\n" "match_nets OUT OUT\n" "match_nets $3 $3\n" "match_nets IN IN\n" "match_nets VSS VSS\n" + "match_ambiguous_nets $1 $1\n" "match_nets (null) BULK\n" "match_pins $0 $0\n" "match_pins IN IN\n" From 2e21498422a0e10e821d80baa6394bbb0f5f850e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 19 Jul 2021 07:58:42 +0200 Subject: [PATCH 11/12] Updated unit tests --- testdata/ruby/dbNetlistCompare.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testdata/ruby/dbNetlistCompare.rb b/testdata/ruby/dbNetlistCompare.rb index 9fe3b704d..9c05c6c8a 100644 --- a/testdata/ruby/dbNetlistCompare.rb +++ b/testdata/ruby/dbNetlistCompare.rb @@ -464,8 +464,8 @@ begin_circuit BUF BUF match_nets VDD VDD match_nets VSS VSS match_nets OUT OUT -match_nets INT $10 net_mismatch IN IN +match_nets INT $10 net_mismatch INT2 $11 match_pins $0 $1 match_pins $1 $3 @@ -524,8 +524,8 @@ begin_circuit BUF BUF match_nets VDD VDD match_nets VSS VSS match_nets OUT OUT -match_nets INT $10 net_mismatch IN IN +match_nets INT $10 net_mismatch INT2 $11 match_pins $0 $1 match_pins $1 $3 From 23d0fcae8d58fcda1a751fc5fde52583240fc54a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 19 Jul 2021 08:32:55 +0200 Subject: [PATCH 12/12] Added new tests --- src/lvs/unit_tests/lvsSimpleTests.cc | 20 ++ testdata/lvs/bbdevices.net | 32 ++ testdata/lvs/bbdevices1.cir | 75 ++++ testdata/lvs/bbdevices1.gds | Bin 0 -> 8192 bytes testdata/lvs/bbdevices1.lvs | 74 ++++ testdata/lvs/bbdevices1.lvsdb | 464 +++++++++++++++++++++++++ testdata/lvs/bbdevices1b.cir | 57 +++ testdata/lvs/bbdevices1b.lvs | 75 ++++ testdata/lvs/bbdevices1b.lvsdb | 340 ++++++++++++++++++ testdata/lvs/bbdevices2.cir | 79 +++++ testdata/lvs/bbdevices2.gds | Bin 0 -> 6382 bytes testdata/lvs/bbdevices2.lvs | 74 ++++ testdata/lvs/bbdevices2.lvsdb | 496 +++++++++++++++++++++++++++ testdata/lvs/bbdevices2b.cir | 61 ++++ testdata/lvs/bbdevices2b.lvs | 75 ++++ testdata/lvs/bbdevices2b.lvsdb | 372 ++++++++++++++++++++ testdata/lvs/bbdevices3.cir | 75 ++++ testdata/lvs/bbdevices3.gds | Bin 0 -> 6162 bytes testdata/lvs/bbdevices3.lvs | 74 ++++ testdata/lvs/bbdevices3.lvsdb | 465 +++++++++++++++++++++++++ testdata/lvs/bbdevices3b.cir | 57 +++ testdata/lvs/bbdevices3b.lvs | 75 ++++ testdata/lvs/bbdevices3b.lvsdb | 329 ++++++++++++++++++ testdata/lvs/bbdevices4.cir | 72 ++++ testdata/lvs/bbdevices4.gds | Bin 0 -> 6072 bytes testdata/lvs/bbdevices4.lvs | 74 ++++ testdata/lvs/bbdevices4.lvsdb | 459 +++++++++++++++++++++++++ testdata/lvs/bbdevices4b.cir | 54 +++ testdata/lvs/bbdevices4b.lvs | 75 ++++ testdata/lvs/bbdevices4b.lvsdb | 324 +++++++++++++++++ testdata/lvs/bbdevices5.cir | 75 ++++ testdata/lvs/bbdevices5.gds | Bin 0 -> 6200 bytes testdata/lvs/bbdevices5.lvs | 74 ++++ testdata/lvs/bbdevices5.lvsdb | 469 +++++++++++++++++++++++++ testdata/lvs/bbdevices5b.cir | 57 +++ testdata/lvs/bbdevices5b.lvs | 75 ++++ testdata/lvs/bbdevices5b.lvsdb | 345 +++++++++++++++++++ testdata/lvs/bbdevices6.cir | 75 ++++ testdata/lvs/bbdevices6.gds | Bin 0 -> 6190 bytes testdata/lvs/bbdevices6.lvs | 74 ++++ testdata/lvs/bbdevices6.lvsdb | 463 +++++++++++++++++++++++++ testdata/lvs/bbdevices6b.cir | 57 +++ testdata/lvs/bbdevices6b.lvs | 75 ++++ testdata/lvs/bbdevices6b.lvsdb | 339 ++++++++++++++++++ 44 files changed, 6605 insertions(+) create mode 100644 testdata/lvs/bbdevices.net create mode 100644 testdata/lvs/bbdevices1.cir create mode 100644 testdata/lvs/bbdevices1.gds create mode 100644 testdata/lvs/bbdevices1.lvs create mode 100644 testdata/lvs/bbdevices1.lvsdb create mode 100644 testdata/lvs/bbdevices1b.cir create mode 100644 testdata/lvs/bbdevices1b.lvs create mode 100644 testdata/lvs/bbdevices1b.lvsdb create mode 100644 testdata/lvs/bbdevices2.cir create mode 100644 testdata/lvs/bbdevices2.gds create mode 100644 testdata/lvs/bbdevices2.lvs create mode 100644 testdata/lvs/bbdevices2.lvsdb create mode 100644 testdata/lvs/bbdevices2b.cir create mode 100644 testdata/lvs/bbdevices2b.lvs create mode 100644 testdata/lvs/bbdevices2b.lvsdb create mode 100644 testdata/lvs/bbdevices3.cir create mode 100644 testdata/lvs/bbdevices3.gds create mode 100644 testdata/lvs/bbdevices3.lvs create mode 100644 testdata/lvs/bbdevices3.lvsdb create mode 100644 testdata/lvs/bbdevices3b.cir create mode 100644 testdata/lvs/bbdevices3b.lvs create mode 100644 testdata/lvs/bbdevices3b.lvsdb create mode 100644 testdata/lvs/bbdevices4.cir create mode 100644 testdata/lvs/bbdevices4.gds create mode 100644 testdata/lvs/bbdevices4.lvs create mode 100644 testdata/lvs/bbdevices4.lvsdb create mode 100644 testdata/lvs/bbdevices4b.cir create mode 100644 testdata/lvs/bbdevices4b.lvs create mode 100644 testdata/lvs/bbdevices4b.lvsdb create mode 100644 testdata/lvs/bbdevices5.cir create mode 100644 testdata/lvs/bbdevices5.gds create mode 100644 testdata/lvs/bbdevices5.lvs create mode 100644 testdata/lvs/bbdevices5.lvsdb create mode 100644 testdata/lvs/bbdevices5b.cir create mode 100644 testdata/lvs/bbdevices5b.lvs create mode 100644 testdata/lvs/bbdevices5b.lvsdb create mode 100644 testdata/lvs/bbdevices6.cir create mode 100644 testdata/lvs/bbdevices6.gds create mode 100644 testdata/lvs/bbdevices6.lvs create mode 100644 testdata/lvs/bbdevices6.lvsdb create mode 100644 testdata/lvs/bbdevices6b.cir create mode 100644 testdata/lvs/bbdevices6b.lvs create mode 100644 testdata/lvs/bbdevices6b.lvsdb diff --git a/src/lvs/unit_tests/lvsSimpleTests.cc b/src/lvs/unit_tests/lvsSimpleTests.cc index 2ce66d2b2..bb8e3b4c6 100644 --- a/src/lvs/unit_tests/lvsSimpleTests.cc +++ b/src/lvs/unit_tests/lvsSimpleTests.cc @@ -241,3 +241,23 @@ TEST(26_enableWandL) run_test (_this, "enable_wl2", "resistor.gds"); run_test (_this, "enable_wl3", "resistor.gds"); } + +TEST(27_BlackBoxDevicesWithAlign) +{ + run_test (_this, "bbdevices1", "bbdevices1.gds"); + run_test (_this, "bbdevices2", "bbdevices2.gds"); + run_test (_this, "bbdevices3", "bbdevices3.gds"); + run_test (_this, "bbdevices4", "bbdevices4.gds"); + run_test (_this, "bbdevices5", "bbdevices5.gds"); + run_test (_this, "bbdevices6", "bbdevices6.gds"); +} + +TEST(28_BlackBoxDevicesWithBlank) +{ + run_test (_this, "bbdevices1b", "bbdevices1.gds"); + run_test (_this, "bbdevices2b", "bbdevices2.gds"); + run_test (_this, "bbdevices3b", "bbdevices3.gds"); + run_test (_this, "bbdevices4b", "bbdevices4.gds"); + run_test (_this, "bbdevices5b", "bbdevices5.gds"); + run_test (_this, "bbdevices6b", "bbdevices6.gds"); +} diff --git a/testdata/lvs/bbdevices.net b/testdata/lvs/bbdevices.net new file mode 100644 index 000000000..5c07dde5c --- /dev/null +++ b/testdata/lvs/bbdevices.net @@ -0,0 +1,32 @@ +.SUBCKT TESTALL + +XUFBGA A1 B1 FBGATEST +XUFWB C1 G1 FWBTEST +XUFDP B1 C1 FDPTEST +XUDP C1 D1 DPTEST +XUBDP D1 E1 BDPTEST +XUBWB D1 H1 BWBTEST +XUBBGA E1 F1 BBGATEST + +.SUBCKT FBGATEST A B +.ENDS + +.SUBCKT FWBTEST A B +.ENDS + +.SUBCKT FDPTEST A B +.ENDS + +.SUBCKT DPTEST A B +.ENDS + +.SUBCKT BDPTEST A B +.ENDS + +.SUBCKT BWBTEST A B +.ENDS + +.SUBCKT BBGATEST A B +.ENDS + +.ENDS diff --git a/testdata/lvs/bbdevices1.cir b/testdata/lvs/bbdevices1.cir new file mode 100644 index 000000000..80ce62dca --- /dev/null +++ b/testdata/lvs/bbdevices1.cir @@ -0,0 +1,75 @@ +* Extracted by KLayout + +* cell testall +.SUBCKT testall +* cell instance $2 r0 *1 0,0 +X$2 1 2 FDPTEST +* cell instance $3 r0 *1 0,0 +X$3 1 FWBTEST +* cell instance $7 r0 *1 0,0 +X$7 3 1 DPTEST +* cell instance $8 r0 *1 0,0 +X$8 2 FBGATEST +* cell instance $9 r0 *1 0,0 +X$9 3 4 BDPTEST +* cell instance $10 r0 *1 0,0 +X$10 3 BWBTEST +* cell instance $14 r0 *1 0,0 +X$14 4 BBGATEST +.ENDS testall + +* cell FDPTEST +* pin B +* pin A +.SUBCKT FDPTEST 1 2 +* net 1 B +* net 2 A +.ENDS FDPTEST + +* cell DPTEST +* pin B +* pin A +.SUBCKT DPTEST 1 2 +* net 1 B +* net 2 A +.ENDS DPTEST + +* cell BDPTEST +* pin A +* pin B +.SUBCKT BDPTEST 1 2 +* net 1 A +* net 2 B +.ENDS BDPTEST + +* cell BBGATEST +* pin A +.SUBCKT BBGATEST 2 +* net 1 B +* net 2 A +* net 3 BBGATEST +.ENDS BBGATEST + +* cell FBGATEST +* pin B +.SUBCKT FBGATEST 1 +* net 1 B +* net 2 A +* net 3 FBGATEST +.ENDS FBGATEST + +* cell FWBTEST +* pin A +.SUBCKT FWBTEST 2 +* net 1 B +* net 2 A +* net 3 FWBTEST +.ENDS FWBTEST + +* cell BWBTEST +* pin A +.SUBCKT BWBTEST 2 +* net 1 B +* net 2 A +* net 3 BWBTEST +.ENDS BWBTEST diff --git a/testdata/lvs/bbdevices1.gds b/testdata/lvs/bbdevices1.gds new file mode 100644 index 0000000000000000000000000000000000000000..221cc5514211092f1675152225d03b545a3145f5 GIT binary patch literal 8192 zcmeHLZERCj7=C(hdwW;9F~^i4iwvA*3kABh$S{+zri?9oEm~z5LM1{nk`Yk01(N-e z#Xz!zsgQs!x&$ImA>0^=R{N{{ zD+4S2K(XptS9g5PrmxT6T^k-;)%V`Z5tOBcNldvQFsYXi#&e|hjQYg7+a&I7AY^f;z+|A1FrFi|PwBnF|HqjB+Cm3h&>nZt zXYXQHsDdK<^U}E7Uwx7!mhXYKNDEQVnfE!UlPiKGvE(9C*X6FBJkdj9Yn$PvV~gCe z8Mu)(*Wo53)go6LQ?Z6);bxX2XkQ){m^==H=QurATP3~oY6FS4UxM}=&6SCXn`K}; zN5;!*MbVMCdoM|>DNU0rJ8IYQ36iKhm?l>= zc3H<(M-P+astO}lBK9_OwLN6bl~kATehyX-C|FV}Fwx#?@EoVtg{;@V9VhWXGdwMY z0u!$dfbkreUCxzMm+;npM`9yGDCn&fnE1ZM;5jmTCcWO_B(cl4;CcU&z{GVQ7|)T} zBz@iU0g`n)PC526^u)B>uyj@_NZqmmW^^ zk4jaA*f<>9?m|0XCeV3m6pZJ{>~f?xNqXmRgHX0zp|LwHP(A4c<2f>WCcWeEIFtik zDA&3Ks@*{_o+Go%nWE!o&6Mkn3MhY!rHQf~wNfzzCDA8G+3deGc3H<(ceKKp7ldb# zh`ha;tQY;(+$(*lNRxQqAhb;pLKYnpsDGdvJV$D`L|WEQmX||&o$iyn+63w!UL%a> zNbMH=3Tgbr;$dim10?wg?R6&VC1JvNj+D=+pF9(Rb}vZoPy8ZKucYHso+GteGEL{7 zE!sx!cek%hlW9BZ$+IQMYZ_)1or=Cx(RP00eq$-zJ-O5*Jr~uBer@KuJ{4~5fq<1Eop?y?rR3%5fcqbUok@1=Ij_yuq!>v%RToI^yyTN#l z%q~|Y9Y0&HKzBR1chPk`<6L7$t@zHt-9l$J<6J{ymvwBlYY+618%Cx@>}}Si==C$} zlAhgqp&gw-{+~?(-NOwA&ym^XSkqO-&%n@!XkDCXL*7p`XC}G_dkmf<<7K^6mza0? zBwW7^qhQCVKz$1go+Gno((9`Rpp}Q=slOqRaq@@RSK+Qy#6U4>Tr19-YMVdKf?DXq_O$ja+&)QS>IGcNK*~)={FqZXT}-4?7MXG5V5f} zer~>tyjM%UKWyIrv)EmfY=0La`@4X*J2}eFj5BySXS8~G zugfiGX0Kf;>vI|3zTef+z?9!X$?s+IxDQaL4?J(v?n++d$9kr#((YSXRcSlEq+&Oz z-^Ztql|`l0?1ZXz3YE7gb>dC^_S73MKwD0CY3M%f#b98y(0GdY{b_c^GeSW}3GuVt z?3y(e4ZnBIuBnkV;}lv8&DNY*L-gb?YWSYNoZPwDfCZm9 zIl>bjBb4W8@PY@r%(0Ab)B00yG^Fa#RPin|Q)Sd3RavUnRPo+2Q>7<|;9ll~tK*=7vR|21?Axx! zt{hcL*=@M%T1n#007FX*`RQ)v4CyVE#DClg*QtI3o1As iCIdyEq5G-R$t!ja=OQo{fw>6GMPM!ha}oI8MBs130}3Dj literal 0 HcmV?d00001 diff --git a/testdata/lvs/bbdevices1.lvs b/testdata/lvs/bbdevices1.lvs new file mode 100644 index 000000000..cb4938f40 --- /dev/null +++ b/testdata/lvs/bbdevices1.lvs @@ -0,0 +1,74 @@ +source($lvs_test_source) +report_lvs($lvs_test_target_lvsdb, true) +target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout") + +schematic("bbdevices.net") + +deep + +class Layers + attr_accessor :selected, :fdpPad, :fdp, :fsm, :ftp, :fm7, :fv7, :fm6, :fv6, :fm5, :fv5, :fm4, :fv4, :fm3, :fv3, :fm2, :fv2, :fm1, :fv1, :dpPad, :dp, :package, :tsv, :bv1, :bm1, :bv2, :bm2, :bv3, :bm3, :bv4, :bm4, :bv5, :bm5, :bv6, :bm6, :bv7, :bm7, :btp, :bsm, :bdpPad, :bdp, :text, :fm, :fv, :bm, :bv +end + +layer = Layers.new +layer.package = input(20,0) +layer.fdp = input(70,0) +layer.fdpPad = input(73,0) +layer.fsm = input(45,0) +layer.ftp = input(44,0) +layer.fm7 = input(43,0) +layer.fv7 = input(42,0) +layer.fm6 = input(41,0) +layer.fv6 = input(40,0) +layer.fm5 = input(39,0) +layer.fv5 = input(38,0) +layer.fm4 = input(37,0) +layer.fv4 = input(36,0) +layer.fm3 = input(35,0) +layer.fv3 = input(34,0) +layer.fm2 = input(33,0) +layer.fv2 = input(32,0) +layer.fm1 = input(31,0) +layer.fv1 = input(30,0) +layer.dpPad = input(75,0) +layer.dp = input(21,0) +layer.tsv = input(19,0) +layer.bv1 = input(50,0) +layer.bm1 = input(51,0) +layer.bv2 = input(52,0) +layer.bm2 = input(53,0) +layer.bv3 = input(54,0) +layer.bm3 = input(55,0) +layer.bv4 = input(56,0) +layer.bm4 = input(57,0) +layer.bv5 = input(58,0) +layer.bm5 = input(59,0) +layer.bv6 = input(60,0) +layer.bm6 = input(61,0) +layer.bv7 = input(62,0) +layer.bm7 = input(63,0) +layer.btp = input(64,0) +layer.bsm = input(65,0) +layer.bdpPad = input(78,0) +layer.bdp = input(71,0) +layer.text = input(230,0) + +connect(layer.fdpPad, layer.fm4) +connect(layer.ftp, layer.fm4) +connect(layer.fm4, layer.fv4) +connect(layer.fv4, layer.fm3) +connect(layer.fm3, layer.fv3) +connect(layer.fv3, layer.fm2) +connect(layer.fm2, layer.fv2) +connect(layer.fv2, layer.fm1) +connect(layer.fm1, layer.fv1) +connect(layer.dpPad, layer.fv1) +connect(layer.fv1, layer.tsv) +connect(layer.tsv, layer.bv1) +connect(layer.bv1, layer.bm1) +connect(layer.btp, layer.bm1) +connect(layer.bdpPad, layer.bm1) + +align + +compare diff --git a/testdata/lvs/bbdevices1.lvsdb b/testdata/lvs/bbdevices1.lvsdb new file mode 100644 index 000000000..cb3ae8cc0 --- /dev/null +++ b/testdata/lvs/bbdevices1.lvsdb @@ -0,0 +1,464 @@ +#%lvsdb-klayout + +# Layout +layout( + top(testall) + unit(0.001) + + # Layer section + # This section lists the mask layers (drawing or derived) and their connections. + + # Mask layers + layer(l1 '73/0') + layer(l3 '44/0') + layer(l2 '37/0') + layer(l4 '36/0') + layer(l5 '35/0') + layer(l6 '34/0') + layer(l7 '33/0') + layer(l8 '32/0') + layer(l9 '31/0') + layer(l10 '30/0') + layer(l11 '75/0') + layer(l12 '19/0') + layer(l13 '50/0') + layer(l14 '51/0') + layer(l15 '64/0') + layer(l16 '78/0') + + # Mask layer connectivity + connect(l1 l1 l2) + connect(l3 l3 l2) + connect(l2 l1 l3 l2 l4) + connect(l4 l2 l4 l5) + connect(l5 l4 l5 l6) + connect(l6 l5 l6 l7) + connect(l7 l6 l7 l8) + connect(l8 l7 l8 l9) + connect(l9 l8 l9 l10) + connect(l10 l9 l10 l11 l12) + connect(l11 l10 l11) + connect(l12 l10 l12 l13) + connect(l13 l12 l13 l14) + connect(l14 l13 l14 l15 l16) + connect(l15 l14 l15) + connect(l16 l14 l16) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(BWBTEST + + # Circuit boundary + rect((554500 -276000) (403000 162001)) + + # Nets with their geometries + net(1 name(B) + rect(l15 (832000 -242000) (93500 75500)) + rect(l15 (-46751 -37751) (2 2)) + ) + net(2 name(A) + rect(l15 (576500 -249000) (105500 81500)) + rect(l15 (-52751 -40751) (2 2)) + ) + net(3 name(BWBTEST) + rect(l15 (754499 -114001) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(2 name(A)) + + ) + circuit(FWBTEST + + # Circuit boundary + rect((536500 386500) (404000 179001)) + + # Nets with their geometries + net(1 name(B) + rect(l3 (793500 427000) (120500 82000)) + rect(l3 (-60251 -41001) (2 2)) + ) + net(2 name(A) + rect(l3 (572500 432500) (74500 73500)) + rect(l3 (-37251 -36751) (2 2)) + ) + net(3 name(FWBTEST) + rect(l3 (797999 565499) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(2 name(A)) + + ) + circuit(FBGATEST + + # Circuit boundary + rect((-449500 412500) (390500 198001)) + + # Nets with their geometries + net(1 name(B) + rect(l3 (-221000 412500) (162000 152500)) + rect(l3 (-81001 -76251) (2 2)) + ) + net(2 name(A) + rect(l3 (-449500 422500) (146000 144500)) + rect(l3 (-71001 -71251) (2 2)) + ) + net(3 name(FBGATEST) + rect(l3 (-417001 610499) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(B)) + + ) + circuit(BBGATEST + + # Circuit boundary + rect((-468000 -313001) (442500 226001)) + + # Nets with their geometries + net(1 name(B) + rect(l15 (-468000 -280000) (177000 189000)) + rect(l15 (-88501 -94501) (2 2)) + ) + net(2 name(A) + rect(l15 (-218500 -290000) (193000 203000)) + rect(l15 (-94001 -101501) (2 2)) + ) + net(3 name(BBGATEST) + rect(l15 (-422001 -313001) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(2 name(A)) + + ) + circuit(BDPTEST + + # Circuit boundary + rect((71500 -290000) (371500 194000)) + + # Nets with their geometries + net(1 name(A) + rect(l16 (317000 -232000) (92000 92000)) + rect(l16 (-46001 -46001) (2 2)) + ) + net(2 name(B) + rect(l16 (95500 -231000) (116000 97000)) + rect(l16 (-58001 -48501) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(DPTEST + + # Circuit boundary + rect((64500 86000) (371500 214500)) + + # Nets with their geometries + net(1 name(B) + rect(l11 (323000 151500) (76000 83000)) + rect(l11 (-38001 -41501) (2 2)) + ) + net(2 name(A) + rect(l11 (96500 159500) (90000 73000)) + rect(l11 (-45001 -36501) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(B)) + pin(2 name(A)) + + ) + circuit(FDPTEST + + # Circuit boundary + rect((59500 359500) (375500 241000)) + + # Nets with their geometries + net(1 name(B) + rect(l1 (327000 436500) (72000 93000)) + rect(l1 (-36001 -46501) (2 2)) + ) + net(2 name(A) + rect(l1 (101500 443500) (82000 84000)) + rect(l1 (-41001 -42001) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(B)) + pin(2 name(A)) + + ) + circuit(testall + + # Circuit boundary + rect((-577500 -1123000) (1868000 1796000)) + + # Nets with their geometries + net(1 + rect(l2 (345500 455000) (256500 25000)) + rect(l2 (-256500 -146000) (25000 146000)) + rect(l2 (-47000 -183500) (75000 75000)) + rect(l4 (-50000 -50000) (25000 25000)) + rect(l5 (-134000 -25000) (134000 25000)) + rect(l5 (-50000 -50000) (75000 75000)) + rect(l5 (-184000 -78500) (75000 75000)) + rect(l6 (-50000 -50000) (25000 25000)) + rect(l7 (-133500 -21500) (134500 25000)) + rect(l7 (-51000 -53500) (75000 75000)) + rect(l7 (-183500 -73000) (75000 75000)) + rect(l8 (-50000 -50000) (25000 25000)) + rect(l9 (-25000 -152000) (25000 152000)) + rect(l9 (-50000 -50000) (75000 75000)) + rect(l9 (-80500 -217500) (90000 90000)) + rect(l10 (-57500 -57500) (25000 25000)) + rect(l11 (-25000 -25000) (25000 25000)) + ) + net(2 + rect(l2 (-148000 463000) (300000 25000)) + ) + net(3 + rect(l9 (348500 26500) (25000 179000)) + rect(l9 (-57500 -58000) (90000 90000)) + rect(l9 (-86000 -288500) (90000 90000)) + rect(l10 (-61500 141000) (25000 25000)) + rect(l10 (-21000 -223500) (25000 25000)) + rect(l11 (-29000 173500) (25000 25000)) + rect(l12 (-58500 -261000) (100000 100000)) + rect(l12 (-100000 -100000) (100000 100000)) + rect(l13 (-62500 -62500) (25000 25000)) + rect(l14 (-24000 -225500) (269500 25000)) + rect(l14 (-270500 7500) (25000 193000)) + rect(l14 (-87500 -87500) (150000 150000)) + ) + net(4 + rect(l14 (-126000 -195000) (292000 25000)) + ) + + # Subcircuits and their connections + circuit(2 FDPTEST location(0 0) + pin(0 1) + pin(1 2) + ) + circuit(3 FWBTEST location(0 0) pin(0 1)) + circuit(7 DPTEST location(0 0) + pin(0 3) + pin(1 1) + ) + circuit(8 FBGATEST location(0 0) pin(0 2)) + circuit(9 BDPTEST location(0 0) + pin(0 3) + pin(1 4) + ) + circuit(10 BWBTEST location(0 0) pin(0 3)) + circuit(14 BBGATEST location(0 0) pin(0 4)) + + ) +) + +# Reference netlist +reference( + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(FBGATEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(FWBTEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(FDPTEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(DPTEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(BDPTEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(BWBTEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(BBGATEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(TESTALL + + # Nets + net(1 name(A1)) + net(2 name(B1)) + net(3 name(C1)) + net(4 name(G1)) + net(5 name(D1)) + net(6 name(E1)) + net(7 name(H1)) + net(8 name(F1)) + + # Subcircuits and their connections + circuit(1 FBGATEST name(UFBGA) + pin(0 1) + pin(1 2) + ) + circuit(2 FWBTEST name(UFWB) + pin(0 3) + pin(1 4) + ) + circuit(3 FDPTEST name(UFDP) + pin(0 2) + pin(1 3) + ) + circuit(4 DPTEST name(UDP) + pin(0 3) + pin(1 5) + ) + circuit(5 BDPTEST name(UBDP) + pin(0 5) + pin(1 6) + ) + circuit(6 BWBTEST name(UBWB) + pin(0 5) + pin(1 7) + ) + circuit(7 BBGATEST name(UBBGA) + pin(0 6) + pin(1 8) + ) + + ) +) + +# Cross reference +xref( + circuit(BBGATEST BBGATEST match + xref( + net(() 2 match) + net(2 1 match) + pin(() 1 match) + pin(0 0 match) + ) + ) + circuit(BDPTEST BDPTEST match + xref( + net(1 1 match) + net(2 2 match) + pin(0 0 match) + pin(1 1 match) + ) + ) + circuit(BWBTEST BWBTEST match + xref( + net(() 2 match) + net(2 1 match) + pin(() 1 match) + pin(0 0 match) + ) + ) + circuit(DPTEST DPTEST match + xref( + net(2 1 match) + net(1 2 match) + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(FBGATEST FBGATEST match + xref( + net(() 1 match) + net(1 2 match) + pin(() 0 match) + pin(0 1 match) + ) + ) + circuit(FDPTEST FDPTEST match + xref( + net(2 1 match) + net(1 2 match) + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(FWBTEST FWBTEST match + xref( + net(() 2 match) + net(2 1 match) + pin(() 1 match) + pin(0 0 match) + ) + ) + circuit(testall TESTALL match + xref( + net(2 2 match) + net(1 3 match) + net(3 5 match) + net(4 6 match) + circuit(14 7 match) + circuit(9 5 match) + circuit(10 6 match) + circuit(7 4 match) + circuit(8 1 match) + circuit(2 3 match) + circuit(3 2 match) + ) + ) +) diff --git a/testdata/lvs/bbdevices1b.cir b/testdata/lvs/bbdevices1b.cir new file mode 100644 index 000000000..82dcb589b --- /dev/null +++ b/testdata/lvs/bbdevices1b.cir @@ -0,0 +1,57 @@ +* Extracted by KLayout + +* cell testall +.SUBCKT testall +* cell instance $2 r0 *1 0,0 +X$2 1 2 FDPTEST +* cell instance $3 r0 *1 0,0 +X$3 1 FWBTEST +* cell instance $7 r0 *1 0,0 +X$7 3 1 DPTEST +* cell instance $8 r0 *1 0,0 +X$8 2 FBGATEST +* cell instance $9 r0 *1 0,0 +X$9 3 4 BDPTEST +* cell instance $10 r0 *1 0,0 +X$10 3 BWBTEST +* cell instance $14 r0 *1 0,0 +X$14 4 BBGATEST +.ENDS testall + +* cell FDPTEST +* pin B +* pin A +.SUBCKT FDPTEST 1 2 +.ENDS FDPTEST + +* cell DPTEST +* pin B +* pin A +.SUBCKT DPTEST 1 2 +.ENDS DPTEST + +* cell BDPTEST +* pin A +* pin B +.SUBCKT BDPTEST 1 2 +.ENDS BDPTEST + +* cell BBGATEST +* pin A +.SUBCKT BBGATEST 1 +.ENDS BBGATEST + +* cell FBGATEST +* pin B +.SUBCKT FBGATEST 1 +.ENDS FBGATEST + +* cell FWBTEST +* pin A +.SUBCKT FWBTEST 1 +.ENDS FWBTEST + +* cell BWBTEST +* pin A +.SUBCKT BWBTEST 1 +.ENDS BWBTEST diff --git a/testdata/lvs/bbdevices1b.lvs b/testdata/lvs/bbdevices1b.lvs new file mode 100644 index 000000000..cba829291 --- /dev/null +++ b/testdata/lvs/bbdevices1b.lvs @@ -0,0 +1,75 @@ +source($lvs_test_source) +report_lvs($lvs_test_target_lvsdb, true) +target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout") + +schematic("bbdevices.net") + +deep + +class Layers + attr_accessor :selected, :fdpPad, :fdp, :fsm, :ftp, :fm7, :fv7, :fm6, :fv6, :fm5, :fv5, :fm4, :fv4, :fm3, :fv3, :fm2, :fv2, :fm1, :fv1, :dpPad, :dp, :package, :tsv, :bv1, :bm1, :bv2, :bm2, :bv3, :bm3, :bv4, :bm4, :bv5, :bm5, :bv6, :bm6, :bv7, :bm7, :btp, :bsm, :bdpPad, :bdp, :text, :fm, :fv, :bm, :bv +end + +layer = Layers.new +layer.package = input(20,0) +layer.fdp = input(70,0) +layer.fdpPad = input(73,0) +layer.fsm = input(45,0) +layer.ftp = input(44,0) +layer.fm7 = input(43,0) +layer.fv7 = input(42,0) +layer.fm6 = input(41,0) +layer.fv6 = input(40,0) +layer.fm5 = input(39,0) +layer.fv5 = input(38,0) +layer.fm4 = input(37,0) +layer.fv4 = input(36,0) +layer.fm3 = input(35,0) +layer.fv3 = input(34,0) +layer.fm2 = input(33,0) +layer.fv2 = input(32,0) +layer.fm1 = input(31,0) +layer.fv1 = input(30,0) +layer.dpPad = input(75,0) +layer.dp = input(21,0) +layer.tsv = input(19,0) +layer.bv1 = input(50,0) +layer.bm1 = input(51,0) +layer.bv2 = input(52,0) +layer.bm2 = input(53,0) +layer.bv3 = input(54,0) +layer.bm3 = input(55,0) +layer.bv4 = input(56,0) +layer.bm4 = input(57,0) +layer.bv5 = input(58,0) +layer.bm5 = input(59,0) +layer.bv6 = input(60,0) +layer.bm6 = input(61,0) +layer.bv7 = input(62,0) +layer.bm7 = input(63,0) +layer.btp = input(64,0) +layer.bsm = input(65,0) +layer.bdpPad = input(78,0) +layer.bdp = input(71,0) +layer.text = input(230,0) + +connect(layer.fdpPad, layer.fm4) +connect(layer.ftp, layer.fm4) +connect(layer.fm4, layer.fv4) +connect(layer.fv4, layer.fm3) +connect(layer.fm3, layer.fv3) +connect(layer.fv3, layer.fm2) +connect(layer.fm2, layer.fv2) +connect(layer.fv2, layer.fm1) +connect(layer.fm1, layer.fv1) +connect(layer.dpPad, layer.fv1) +connect(layer.fv1, layer.tsv) +connect(layer.tsv, layer.bv1) +connect(layer.bv1, layer.bm1) +connect(layer.btp, layer.bm1) +connect(layer.bdpPad, layer.bm1) + +blank_circuit("*TEST") +netlist.simplify + +compare diff --git a/testdata/lvs/bbdevices1b.lvsdb b/testdata/lvs/bbdevices1b.lvsdb new file mode 100644 index 000000000..30d688cef --- /dev/null +++ b/testdata/lvs/bbdevices1b.lvsdb @@ -0,0 +1,340 @@ +#%lvsdb-klayout + +# Layout +layout( + top(testall) + unit(0.001) + + # Layer section + # This section lists the mask layers (drawing or derived) and their connections. + + # Mask layers + layer(l1 '73/0') + layer(l3 '44/0') + layer(l2 '37/0') + layer(l4 '36/0') + layer(l5 '35/0') + layer(l6 '34/0') + layer(l7 '33/0') + layer(l8 '32/0') + layer(l9 '31/0') + layer(l10 '30/0') + layer(l11 '75/0') + layer(l12 '19/0') + layer(l13 '50/0') + layer(l14 '51/0') + layer(l15 '64/0') + layer(l16 '78/0') + + # Mask layer connectivity + connect(l1 l1 l2) + connect(l3 l3 l2) + connect(l2 l1 l3 l2 l4) + connect(l4 l2 l4 l5) + connect(l5 l4 l5 l6) + connect(l6 l5 l6 l7) + connect(l7 l6 l7 l8) + connect(l8 l7 l8 l9) + connect(l9 l8 l9 l10) + connect(l10 l9 l10 l11 l12) + connect(l11 l10 l11) + connect(l12 l10 l12 l13) + connect(l13 l12 l13 l14) + connect(l14 l13 l14 l15 l16) + connect(l15 l14 l15) + connect(l16 l14 l16) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(BWBTEST + + # Circuit boundary + rect((554500 -276000) (403000 162001)) + + # Outgoing pins and their connections to nets + pin(name(A)) + + ) + circuit(FWBTEST + + # Circuit boundary + rect((536500 386500) (404000 179001)) + + # Outgoing pins and their connections to nets + pin(name(A)) + + ) + circuit(FBGATEST + + # Circuit boundary + rect((-449500 412500) (390500 198001)) + + # Outgoing pins and their connections to nets + pin(name(B)) + + ) + circuit(BBGATEST + + # Circuit boundary + rect((-468000 -313001) (442500 226001)) + + # Outgoing pins and their connections to nets + pin(name(A)) + + ) + circuit(BDPTEST + + # Circuit boundary + rect((71500 -290000) (371500 194000)) + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(DPTEST + + # Circuit boundary + rect((64500 86000) (371500 214500)) + + # Outgoing pins and their connections to nets + pin(name(B)) + pin(name(A)) + + ) + circuit(FDPTEST + + # Circuit boundary + rect((59500 359500) (375500 241000)) + + # Outgoing pins and their connections to nets + pin(name(B)) + pin(name(A)) + + ) + circuit(testall + + # Circuit boundary + rect((-577500 -1123000) (1868000 1796000)) + + # Nets with their geometries + net(1 + rect(l2 (345500 455000) (256500 25000)) + rect(l2 (-256500 -146000) (25000 146000)) + rect(l2 (-47000 -183500) (75000 75000)) + rect(l4 (-50000 -50000) (25000 25000)) + rect(l5 (-134000 -25000) (134000 25000)) + rect(l5 (-50000 -50000) (75000 75000)) + rect(l5 (-184000 -78500) (75000 75000)) + rect(l6 (-50000 -50000) (25000 25000)) + rect(l7 (-133500 -21500) (134500 25000)) + rect(l7 (-51000 -53500) (75000 75000)) + rect(l7 (-183500 -73000) (75000 75000)) + rect(l8 (-50000 -50000) (25000 25000)) + rect(l9 (-25000 -152000) (25000 152000)) + rect(l9 (-50000 -50000) (75000 75000)) + rect(l9 (-80500 -217500) (90000 90000)) + rect(l10 (-57500 -57500) (25000 25000)) + rect(l11 (-25000 -25000) (25000 25000)) + ) + net(2 + rect(l2 (-148000 463000) (300000 25000)) + ) + net(3 + rect(l9 (348500 26500) (25000 179000)) + rect(l9 (-57500 -58000) (90000 90000)) + rect(l9 (-86000 -288500) (90000 90000)) + rect(l10 (-61500 141000) (25000 25000)) + rect(l10 (-21000 -223500) (25000 25000)) + rect(l11 (-29000 173500) (25000 25000)) + rect(l12 (-58500 -261000) (100000 100000)) + rect(l12 (-100000 -100000) (100000 100000)) + rect(l13 (-62500 -62500) (25000 25000)) + rect(l14 (-24000 -225500) (269500 25000)) + rect(l14 (-270500 7500) (25000 193000)) + rect(l14 (-87500 -87500) (150000 150000)) + ) + net(4 + rect(l14 (-126000 -195000) (292000 25000)) + ) + + # Subcircuits and their connections + circuit(2 FDPTEST location(0 0) + pin(0 1) + pin(1 2) + ) + circuit(3 FWBTEST location(0 0) pin(0 1)) + circuit(7 DPTEST location(0 0) + pin(0 3) + pin(1 1) + ) + circuit(8 FBGATEST location(0 0) pin(0 2)) + circuit(9 BDPTEST location(0 0) + pin(0 3) + pin(1 4) + ) + circuit(10 BWBTEST location(0 0) pin(0 3)) + circuit(14 BBGATEST location(0 0) pin(0 4)) + + ) +) + +# Reference netlist +reference( + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(FBGATEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(FWBTEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(FDPTEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(DPTEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(BDPTEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(BWBTEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(BBGATEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(TESTALL + + # Nets + net(1 name(A1)) + net(2 name(B1)) + net(3 name(C1)) + net(4 name(G1)) + net(5 name(D1)) + net(6 name(E1)) + net(7 name(H1)) + net(8 name(F1)) + + # Subcircuits and their connections + circuit(1 FBGATEST name(UFBGA) + pin(0 1) + pin(1 2) + ) + circuit(2 FWBTEST name(UFWB) + pin(0 3) + pin(1 4) + ) + circuit(3 FDPTEST name(UFDP) + pin(0 2) + pin(1 3) + ) + circuit(4 DPTEST name(UDP) + pin(0 3) + pin(1 5) + ) + circuit(5 BDPTEST name(UBDP) + pin(0 5) + pin(1 6) + ) + circuit(6 BWBTEST name(UBWB) + pin(0 5) + pin(1 7) + ) + circuit(7 BBGATEST name(UBBGA) + pin(0 6) + pin(1 8) + ) + + ) +) + +# Cross reference +xref( + circuit(BBGATEST BBGATEST match + xref( + pin(() 1 match) + pin(0 0 match) + ) + ) + circuit(BDPTEST BDPTEST match + xref( + pin(0 0 match) + pin(1 1 match) + ) + ) + circuit(BWBTEST BWBTEST match + xref( + pin(() 1 match) + pin(0 0 match) + ) + ) + circuit(DPTEST DPTEST match + xref( + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(FBGATEST FBGATEST match + xref( + pin(() 0 match) + pin(0 1 match) + ) + ) + circuit(FDPTEST FDPTEST match + xref( + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(FWBTEST FWBTEST match + xref( + pin(() 1 match) + pin(0 0 match) + ) + ) + circuit(testall TESTALL match + xref( + net(2 2 match) + net(1 3 match) + net(3 5 match) + net(4 6 match) + circuit(14 7 match) + circuit(9 5 match) + circuit(10 6 match) + circuit(7 4 match) + circuit(8 1 match) + circuit(2 3 match) + circuit(3 2 match) + ) + ) +) diff --git a/testdata/lvs/bbdevices2.cir b/testdata/lvs/bbdevices2.cir new file mode 100644 index 000000000..bac395789 --- /dev/null +++ b/testdata/lvs/bbdevices2.cir @@ -0,0 +1,79 @@ +* Extracted by KLayout + +* cell testall +.SUBCKT testall +* cell instance $2 r0 *1 0,0 +X$2 1 2 FDPTEST +* cell instance $3 r0 *1 0,0 +X$3 4 1 FWBTEST +* cell instance $7 r0 *1 0,0 +X$7 5 1 DPTEST +* cell instance $8 r0 *1 0,0 +X$8 2 3 FBGATEST +* cell instance $9 r0 *1 0,0 +X$9 5 6 BDPTEST +* cell instance $10 r0 *1 0,0 +X$10 8 5 BWBTEST +* cell instance $14 r0 *1 0,0 +X$14 7 6 BBGATEST +.ENDS testall + +* cell FDPTEST +* pin B +* pin A +.SUBCKT FDPTEST 1 2 +* net 1 B +* net 2 A +.ENDS FDPTEST + +* cell DPTEST +* pin B +* pin A +.SUBCKT DPTEST 1 2 +* net 1 B +* net 2 A +.ENDS DPTEST + +* cell BDPTEST +* pin A +* pin B +.SUBCKT BDPTEST 1 2 +* net 1 A +* net 2 B +.ENDS BDPTEST + +* cell BBGATEST +* pin B +* pin A +.SUBCKT BBGATEST 1 2 +* net 1 B +* net 2 A +* net 3 BBGATEST +.ENDS BBGATEST + +* cell FBGATEST +* pin B +* pin A +.SUBCKT FBGATEST 1 2 +* net 1 B +* net 2 A +* net 3 FBGATEST +.ENDS FBGATEST + +* cell FWBTEST +* pin B +* pin A +.SUBCKT FWBTEST 1 2 +* net 1 B +* net 2 A +* net 3 FWBTEST +.ENDS FWBTEST + +* cell BWBTEST +* pin B +* pin A +.SUBCKT BWBTEST 1 2 +* net 1 B +* net 2 A +* net 3 BWBTEST +.ENDS BWBTEST diff --git a/testdata/lvs/bbdevices2.gds b/testdata/lvs/bbdevices2.gds new file mode 100644 index 0000000000000000000000000000000000000000..45c7268ad2f607e82290534cafd0c20457870e2a GIT binary patch literal 6382 zcmd6re{2**6vyA~-R*757Hg@}+6xq{rVR&NdxwBQLN7;Y!>>k9DTZ(oOHz^=P}&BQ z{$Zq1NNT7G32K9l5U7MGDt|PlCPW(pkpwjjsR05plJpNmG!3-ekMYgy&fIM8&f6>h z*kto*-pzMs-kW)EW(QPIlos$h6wfX2z#Py(fuQ_9cont1Yj3n;=iZL!hPC0QNVLvh z=U)<7;s+>ox>wg9T)zItQ+HQ}hn5a}@^S>c?(FX>Q`P5pz8YnQ(SYH1Q1W}hO#3zCwoum3!0#Ey-M-(o(K^HLfaLdldEEKL+w{9q*3ZE2 z8OJ?`-`>3*Wlb$}bxCmi^{Uf~W^Bk7-B>;!$WAGCou=;hM* z>7J6uJBrkM;HkoDRIY|lnWws7;}!7KC{$f1Qi-*B|YXm5@jR3Q^jtX)+ zr5rz5uPr?XYE>90=~LKnO_19unLbC3)42{eTj#n#8Y_&qgS&eJP!`l+zsFYyayz9Q zDb(kjD`!tDXqT_Cxf1(|bX= zbV-ogDPvE{S(qfh@B$~dBQ5ch@{&w_gmvwH zkWs4{BM&D308Va48u}b_U8t&NTJV{EOv(s|O@L$bU7&Ow83pxJr69Lc$}1Z6IajoE zD`r7K5DLph?@~@ldp)@R90FzYB}V6A7t2XbZfDG*ckG)0Ww#EL&fXv>V?Bc0PAPkU z{pa++{dP4de~)KaYj)I1^)M)j0ePL|m?x~Cq3L_&8fm8VuYtrjodwE7XFtrIzeU!g1j~C&n*jm7RAKwH+hz z-=EG9Ydh+Kj};RCHB(O3%kf+FGl^Xu1|6CBr445HWBg2VJEa^yS+8}uNbKTGpiEr# zLE*9Ug4|BY^fu;N>{aGmt&_&;n7e_*KJ)`+@*sfv{XRi%r4UPR zpCp!hGprRmYTRi_qGnH?c`0^_^t>XIS8tNow`&-a{Rc?wP$S{wcBExp;i?vQ8u8QJ zbgl_y@=P@${jGxBK7FojWCeM!>@Z0zYRwQQJL=@(AW6(WBge@+``S@Y9qJ>ol`U+Y ziP%Z&M9M2N6`7=UjWMZ}k(e?_IJtd#U6b{R)wfAp$2E#f28s!(z&M)ZcBI|Bq<307 z+S>tKg#cwGneV3PHv-)s++}9HwYIg~=g_v!u~)!7%Vmtg+SYOhLfb0-UT~L;iniX= z7}D+y*f`$5K*)IC^!6FQH~*tOy?>+cw|twk_H-Zo3r`1h{&4Km#*@}wS+NbA&Ti3O zFG+nD(D(5_brF8ufaX(Q3vd6vX~ z+Xn6^Ddp2?itjx;<> z*Mok0k8#pLvXf5vJwaLt`0w(l`OQ^&glL|^(H54k^gL%zMYGVk5YKROHkz}sz^vZs zeX-V96P(u?Q?D66 zx4~22P7-&{QCen>_r+%Z#)R?Rf@I$-C+7*W?-t|tYlxLb7|HcY6fceUSM( m^VM8ArP5w{-(N-UTyG>uC=8FooUdG*+)ioqk7qQO3;qSNrfZ!5 literal 0 HcmV?d00001 diff --git a/testdata/lvs/bbdevices2.lvs b/testdata/lvs/bbdevices2.lvs new file mode 100644 index 000000000..cb4938f40 --- /dev/null +++ b/testdata/lvs/bbdevices2.lvs @@ -0,0 +1,74 @@ +source($lvs_test_source) +report_lvs($lvs_test_target_lvsdb, true) +target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout") + +schematic("bbdevices.net") + +deep + +class Layers + attr_accessor :selected, :fdpPad, :fdp, :fsm, :ftp, :fm7, :fv7, :fm6, :fv6, :fm5, :fv5, :fm4, :fv4, :fm3, :fv3, :fm2, :fv2, :fm1, :fv1, :dpPad, :dp, :package, :tsv, :bv1, :bm1, :bv2, :bm2, :bv3, :bm3, :bv4, :bm4, :bv5, :bm5, :bv6, :bm6, :bv7, :bm7, :btp, :bsm, :bdpPad, :bdp, :text, :fm, :fv, :bm, :bv +end + +layer = Layers.new +layer.package = input(20,0) +layer.fdp = input(70,0) +layer.fdpPad = input(73,0) +layer.fsm = input(45,0) +layer.ftp = input(44,0) +layer.fm7 = input(43,0) +layer.fv7 = input(42,0) +layer.fm6 = input(41,0) +layer.fv6 = input(40,0) +layer.fm5 = input(39,0) +layer.fv5 = input(38,0) +layer.fm4 = input(37,0) +layer.fv4 = input(36,0) +layer.fm3 = input(35,0) +layer.fv3 = input(34,0) +layer.fm2 = input(33,0) +layer.fv2 = input(32,0) +layer.fm1 = input(31,0) +layer.fv1 = input(30,0) +layer.dpPad = input(75,0) +layer.dp = input(21,0) +layer.tsv = input(19,0) +layer.bv1 = input(50,0) +layer.bm1 = input(51,0) +layer.bv2 = input(52,0) +layer.bm2 = input(53,0) +layer.bv3 = input(54,0) +layer.bm3 = input(55,0) +layer.bv4 = input(56,0) +layer.bm4 = input(57,0) +layer.bv5 = input(58,0) +layer.bm5 = input(59,0) +layer.bv6 = input(60,0) +layer.bm6 = input(61,0) +layer.bv7 = input(62,0) +layer.bm7 = input(63,0) +layer.btp = input(64,0) +layer.bsm = input(65,0) +layer.bdpPad = input(78,0) +layer.bdp = input(71,0) +layer.text = input(230,0) + +connect(layer.fdpPad, layer.fm4) +connect(layer.ftp, layer.fm4) +connect(layer.fm4, layer.fv4) +connect(layer.fv4, layer.fm3) +connect(layer.fm3, layer.fv3) +connect(layer.fv3, layer.fm2) +connect(layer.fm2, layer.fv2) +connect(layer.fv2, layer.fm1) +connect(layer.fm1, layer.fv1) +connect(layer.dpPad, layer.fv1) +connect(layer.fv1, layer.tsv) +connect(layer.tsv, layer.bv1) +connect(layer.bv1, layer.bm1) +connect(layer.btp, layer.bm1) +connect(layer.bdpPad, layer.bm1) + +align + +compare diff --git a/testdata/lvs/bbdevices2.lvsdb b/testdata/lvs/bbdevices2.lvsdb new file mode 100644 index 000000000..5a782379a --- /dev/null +++ b/testdata/lvs/bbdevices2.lvsdb @@ -0,0 +1,496 @@ +#%lvsdb-klayout + +# Layout +layout( + top(testall) + unit(0.001) + + # Layer section + # This section lists the mask layers (drawing or derived) and their connections. + + # Mask layers + layer(l1 '73/0') + layer(l3 '44/0') + layer(l2 '37/0') + layer(l4 '36/0') + layer(l5 '35/0') + layer(l6 '34/0') + layer(l7 '33/0') + layer(l8 '32/0') + layer(l9 '31/0') + layer(l10 '30/0') + layer(l11 '75/0') + layer(l12 '19/0') + layer(l13 '50/0') + layer(l14 '51/0') + layer(l15 '64/0') + layer(l16 '78/0') + + # Mask layer connectivity + connect(l1 l1 l2) + connect(l3 l3 l2) + connect(l2 l1 l3 l2 l4) + connect(l4 l2 l4 l5) + connect(l5 l4 l5 l6) + connect(l6 l5 l6 l7) + connect(l7 l6 l7 l8) + connect(l8 l7 l8 l9) + connect(l9 l8 l9 l10) + connect(l10 l9 l10 l11 l12) + connect(l11 l10 l11) + connect(l12 l10 l12 l13) + connect(l13 l12 l13 l14) + connect(l14 l13 l14 l15 l16) + connect(l15 l14 l15) + connect(l16 l14 l16) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(BWBTEST + + # Circuit boundary + rect((554500 -276000) (403000 162001)) + + # Nets with their geometries + net(1 name(B) + rect(l15 (832000 -242000) (93500 75500)) + rect(l15 (-46751 -37751) (2 2)) + ) + net(2 name(A) + rect(l15 (576500 -249000) (105500 81500)) + rect(l15 (-52751 -40751) (2 2)) + ) + net(3 name(BWBTEST) + rect(l15 (754499 -114001) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(B)) + pin(2 name(A)) + + ) + circuit(FWBTEST + + # Circuit boundary + rect((536500 386500) (404000 179001)) + + # Nets with their geometries + net(1 name(B) + rect(l3 (793500 427000) (120500 82000)) + rect(l3 (-60251 -41001) (2 2)) + ) + net(2 name(A) + rect(l3 (572500 432500) (74500 73500)) + rect(l3 (-37251 -36751) (2 2)) + ) + net(3 name(FWBTEST) + rect(l3 (797999 565499) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(B)) + pin(2 name(A)) + + ) + circuit(FBGATEST + + # Circuit boundary + rect((-449500 412500) (390500 198001)) + + # Nets with their geometries + net(1 name(B) + rect(l3 (-221000 412500) (162000 152500)) + rect(l3 (-81001 -76251) (2 2)) + ) + net(2 name(A) + rect(l3 (-449500 422500) (146000 144500)) + rect(l3 (-71001 -71251) (2 2)) + ) + net(3 name(FBGATEST) + rect(l3 (-417001 610499) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(B)) + pin(2 name(A)) + + ) + circuit(BBGATEST + + # Circuit boundary + rect((-468000 -313001) (442500 226001)) + + # Nets with their geometries + net(1 name(B) + rect(l15 (-468000 -280000) (177000 189000)) + rect(l15 (-88501 -94501) (2 2)) + ) + net(2 name(A) + rect(l15 (-218500 -290000) (193000 203000)) + rect(l15 (-94001 -101501) (2 2)) + ) + net(3 name(BBGATEST) + rect(l15 (-422001 -313001) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(B)) + pin(2 name(A)) + + ) + circuit(BDPTEST + + # Circuit boundary + rect((71500 -290000) (371500 194000)) + + # Nets with their geometries + net(1 name(A) + rect(l16 (317000 -232000) (92000 92000)) + rect(l16 (-46001 -46001) (2 2)) + ) + net(2 name(B) + rect(l16 (95500 -231000) (116000 97000)) + rect(l16 (-58001 -48501) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(DPTEST + + # Circuit boundary + rect((64500 86000) (371500 214500)) + + # Nets with their geometries + net(1 name(B) + rect(l11 (323000 151500) (76000 83000)) + rect(l11 (-38001 -41501) (2 2)) + ) + net(2 name(A) + rect(l11 (96500 159500) (90000 73000)) + rect(l11 (-45001 -36501) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(B)) + pin(2 name(A)) + + ) + circuit(FDPTEST + + # Circuit boundary + rect((59500 359500) (375500 241000)) + + # Nets with their geometries + net(1 name(B) + rect(l1 (327000 436500) (72000 93000)) + rect(l1 (-36001 -46501) (2 2)) + ) + net(2 name(A) + rect(l1 (101500 443500) (82000 84000)) + rect(l1 (-41001 -42001) (2 2)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(B)) + pin(2 name(A)) + + ) + circuit(testall + + # Circuit boundary + rect((-577500 -1123000) (1868000 1796000)) + + # Nets with their geometries + net(1 + rect(l2 (345500 455000) (256500 25000)) + rect(l2 (-256500 -146000) (25000 146000)) + rect(l2 (-47000 -183500) (75000 75000)) + rect(l4 (-50000 -50000) (25000 25000)) + rect(l5 (-134000 -25000) (134000 25000)) + rect(l5 (-50000 -50000) (75000 75000)) + rect(l5 (-184000 -78500) (75000 75000)) + rect(l6 (-50000 -50000) (25000 25000)) + rect(l7 (-133500 -21500) (134500 25000)) + rect(l7 (-51000 -53500) (75000 75000)) + rect(l7 (-183500 -73000) (75000 75000)) + rect(l8 (-50000 -50000) (25000 25000)) + rect(l9 (-25000 -152000) (25000 152000)) + rect(l9 (-50000 -50000) (75000 75000)) + rect(l9 (-80500 -217500) (90000 90000)) + rect(l10 (-57500 -57500) (25000 25000)) + rect(l11 (-25000 -25000) (25000 25000)) + ) + net(2 + rect(l2 (-148000 463000) (300000 25000)) + ) + net(3 + rect(l2 (-401420 456500) (50730 78500)) + ) + net(4 + rect(l2 (822690 427000) (63970 82000)) + ) + net(5 + rect(l9 (348500 26500) (25000 179000)) + rect(l9 (-57500 -58000) (90000 90000)) + rect(l9 (-86000 -288500) (90000 90000)) + rect(l10 (-61500 141000) (25000 25000)) + rect(l10 (-21000 -223500) (25000 25000)) + rect(l11 (-29000 173500) (25000 25000)) + rect(l12 (-58500 -261000) (100000 100000)) + rect(l12 (-100000 -100000) (100000 100000)) + rect(l13 (-62500 -62500) (25000 25000)) + rect(l14 (-24000 -225500) (269500 25000)) + rect(l14 (-270500 7500) (25000 193000)) + rect(l14 (-87500 -87500) (150000 150000)) + ) + net(6 + rect(l14 (-126000 -195000) (292000 25000)) + ) + net(7 + rect(l14 (-410240 -216150) (83240 87150)) + ) + net(8 + rect(l14 (846960 -242000) (77190 75500)) + ) + + # Subcircuits and their connections + circuit(2 FDPTEST location(0 0) + pin(0 1) + pin(1 2) + ) + circuit(3 FWBTEST location(0 0) + pin(0 4) + pin(1 1) + ) + circuit(7 DPTEST location(0 0) + pin(0 5) + pin(1 1) + ) + circuit(8 FBGATEST location(0 0) + pin(0 2) + pin(1 3) + ) + circuit(9 BDPTEST location(0 0) + pin(0 5) + pin(1 6) + ) + circuit(10 BWBTEST location(0 0) + pin(0 8) + pin(1 5) + ) + circuit(14 BBGATEST location(0 0) + pin(0 7) + pin(1 6) + ) + + ) +) + +# Reference netlist +reference( + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(FBGATEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(FWBTEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(FDPTEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(DPTEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(BDPTEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(BWBTEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(BBGATEST + + # Nets + net(1 name(A)) + net(2 name(B)) + + # Outgoing pins and their connections to nets + pin(1 name(A)) + pin(2 name(B)) + + ) + circuit(TESTALL + + # Nets + net(1 name(A1)) + net(2 name(B1)) + net(3 name(C1)) + net(4 name(G1)) + net(5 name(D1)) + net(6 name(E1)) + net(7 name(H1)) + net(8 name(F1)) + + # Subcircuits and their connections + circuit(1 FBGATEST name(UFBGA) + pin(0 1) + pin(1 2) + ) + circuit(2 FWBTEST name(UFWB) + pin(0 3) + pin(1 4) + ) + circuit(3 FDPTEST name(UFDP) + pin(0 2) + pin(1 3) + ) + circuit(4 DPTEST name(UDP) + pin(0 3) + pin(1 5) + ) + circuit(5 BDPTEST name(UBDP) + pin(0 5) + pin(1 6) + ) + circuit(6 BWBTEST name(UBWB) + pin(0 5) + pin(1 7) + ) + circuit(7 BBGATEST name(UBBGA) + pin(0 6) + pin(1 8) + ) + + ) +) + +# Cross reference +xref( + circuit(BBGATEST BBGATEST match + xref( + net(2 1 match) + net(1 2 match) + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(BDPTEST BDPTEST match + xref( + net(1 1 match) + net(2 2 match) + pin(0 0 match) + pin(1 1 match) + ) + ) + circuit(BWBTEST BWBTEST match + xref( + net(2 1 match) + net(1 2 match) + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(DPTEST DPTEST match + xref( + net(2 1 match) + net(1 2 match) + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(FBGATEST FBGATEST match + xref( + net(2 1 match) + net(1 2 match) + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(FDPTEST FDPTEST match + xref( + net(2 1 match) + net(1 2 match) + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(FWBTEST FWBTEST match + xref( + net(2 1 match) + net(1 2 match) + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(testall TESTALL match + xref( + net(3 1 match) + net(2 2 match) + net(1 3 match) + net(5 5 match) + net(6 6 match) + net(7 8 match) + net(4 4 match) + net(8 7 match) + circuit(14 7 match) + circuit(9 5 match) + circuit(10 6 match) + circuit(7 4 match) + circuit(8 1 match) + circuit(2 3 match) + circuit(3 2 match) + ) + ) +) diff --git a/testdata/lvs/bbdevices2b.cir b/testdata/lvs/bbdevices2b.cir new file mode 100644 index 000000000..c47a97097 --- /dev/null +++ b/testdata/lvs/bbdevices2b.cir @@ -0,0 +1,61 @@ +* Extracted by KLayout + +* cell testall +.SUBCKT testall +* cell instance $2 r0 *1 0,0 +X$2 1 2 FDPTEST +* cell instance $3 r0 *1 0,0 +X$3 4 1 FWBTEST +* cell instance $7 r0 *1 0,0 +X$7 5 1 DPTEST +* cell instance $8 r0 *1 0,0 +X$8 2 3 FBGATEST +* cell instance $9 r0 *1 0,0 +X$9 5 6 BDPTEST +* cell instance $10 r0 *1 0,0 +X$10 8 5 BWBTEST +* cell instance $14 r0 *1 0,0 +X$14 7 6 BBGATEST +.ENDS testall + +* cell FDPTEST +* pin B +* pin A +.SUBCKT FDPTEST 1 2 +.ENDS FDPTEST + +* cell DPTEST +* pin B +* pin A +.SUBCKT DPTEST 1 2 +.ENDS DPTEST + +* cell BDPTEST +* pin A +* pin B +.SUBCKT BDPTEST 1 2 +.ENDS BDPTEST + +* cell BBGATEST +* pin B +* pin A +.SUBCKT BBGATEST 1 2 +.ENDS BBGATEST + +* cell FBGATEST +* pin B +* pin A +.SUBCKT FBGATEST 1 2 +.ENDS FBGATEST + +* cell FWBTEST +* pin B +* pin A +.SUBCKT FWBTEST 1 2 +.ENDS FWBTEST + +* cell BWBTEST +* pin B +* pin A +.SUBCKT BWBTEST 1 2 +.ENDS BWBTEST diff --git a/testdata/lvs/bbdevices2b.lvs b/testdata/lvs/bbdevices2b.lvs new file mode 100644 index 000000000..cba829291 --- /dev/null +++ b/testdata/lvs/bbdevices2b.lvs @@ -0,0 +1,75 @@ +source($lvs_test_source) +report_lvs($lvs_test_target_lvsdb, true) +target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout") + +schematic("bbdevices.net") + +deep + +class Layers + attr_accessor :selected, :fdpPad, :fdp, :fsm, :ftp, :fm7, :fv7, :fm6, :fv6, :fm5, :fv5, :fm4, :fv4, :fm3, :fv3, :fm2, :fv2, :fm1, :fv1, :dpPad, :dp, :package, :tsv, :bv1, :bm1, :bv2, :bm2, :bv3, :bm3, :bv4, :bm4, :bv5, :bm5, :bv6, :bm6, :bv7, :bm7, :btp, :bsm, :bdpPad, :bdp, :text, :fm, :fv, :bm, :bv +end + +layer = Layers.new +layer.package = input(20,0) +layer.fdp = input(70,0) +layer.fdpPad = input(73,0) +layer.fsm = input(45,0) +layer.ftp = input(44,0) +layer.fm7 = input(43,0) +layer.fv7 = input(42,0) +layer.fm6 = input(41,0) +layer.fv6 = input(40,0) +layer.fm5 = input(39,0) +layer.fv5 = input(38,0) +layer.fm4 = input(37,0) +layer.fv4 = input(36,0) +layer.fm3 = input(35,0) +layer.fv3 = input(34,0) +layer.fm2 = input(33,0) +layer.fv2 = input(32,0) +layer.fm1 = input(31,0) +layer.fv1 = input(30,0) +layer.dpPad = input(75,0) +layer.dp = input(21,0) +layer.tsv = input(19,0) +layer.bv1 = input(50,0) +layer.bm1 = input(51,0) +layer.bv2 = input(52,0) +layer.bm2 = input(53,0) +layer.bv3 = input(54,0) +layer.bm3 = input(55,0) +layer.bv4 = input(56,0) +layer.bm4 = input(57,0) +layer.bv5 = input(58,0) +layer.bm5 = input(59,0) +layer.bv6 = input(60,0) +layer.bm6 = input(61,0) +layer.bv7 = input(62,0) +layer.bm7 = input(63,0) +layer.btp = input(64,0) +layer.bsm = input(65,0) +layer.bdpPad = input(78,0) +layer.bdp = input(71,0) +layer.text = input(230,0) + +connect(layer.fdpPad, layer.fm4) +connect(layer.ftp, layer.fm4) +connect(layer.fm4, layer.fv4) +connect(layer.fv4, layer.fm3) +connect(layer.fm3, layer.fv3) +connect(layer.fv3, layer.fm2) +connect(layer.fm2, layer.fv2) +connect(layer.fv2, layer.fm1) +connect(layer.fm1, layer.fv1) +connect(layer.dpPad, layer.fv1) +connect(layer.fv1, layer.tsv) +connect(layer.tsv, layer.bv1) +connect(layer.bv1, layer.bm1) +connect(layer.btp, layer.bm1) +connect(layer.bdpPad, layer.bm1) + +blank_circuit("*TEST") +netlist.simplify + +compare diff --git a/testdata/lvs/bbdevices2b.lvsdb b/testdata/lvs/bbdevices2b.lvsdb new file mode 100644 index 000000000..5e44f84c1 --- /dev/null +++ b/testdata/lvs/bbdevices2b.lvsdb @@ -0,0 +1,372 @@ +#%lvsdb-klayout + +# Layout +layout( + top(testall) + unit(0.001) + + # Layer section + # This section lists the mask layers (drawing or derived) and their connections. + + # Mask layers + layer(l1 '73/0') + layer(l3 '44/0') + layer(l2 '37/0') + layer(l4 '36/0') + layer(l5 '35/0') + layer(l6 '34/0') + layer(l7 '33/0') + layer(l8 '32/0') + layer(l9 '31/0') + layer(l10 '30/0') + layer(l11 '75/0') + layer(l12 '19/0') + layer(l13 '50/0') + layer(l14 '51/0') + layer(l15 '64/0') + layer(l16 '78/0') + + # Mask layer connectivity + connect(l1 l1 l2) + connect(l3 l3 l2) + connect(l2 l1 l3 l2 l4) + connect(l4 l2 l4 l5) + connect(l5 l4 l5 l6) + connect(l6 l5 l6 l7) + connect(l7 l6 l7 l8) + connect(l8 l7 l8 l9) + connect(l9 l8 l9 l10) + connect(l10 l9 l10 l11 l12) + connect(l11 l10 l11) + connect(l12 l10 l12 l13) + connect(l13 l12 l13 l14) + connect(l14 l13 l14 l15 l16) + connect(l15 l14 l15) + connect(l16 l14 l16) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(BWBTEST + + # Circuit boundary + rect((554500 -276000) (403000 162001)) + + # Outgoing pins and their connections to nets + pin(name(B)) + pin(name(A)) + + ) + circuit(FWBTEST + + # Circuit boundary + rect((536500 386500) (404000 179001)) + + # Outgoing pins and their connections to nets + pin(name(B)) + pin(name(A)) + + ) + circuit(FBGATEST + + # Circuit boundary + rect((-449500 412500) (390500 198001)) + + # Outgoing pins and their connections to nets + pin(name(B)) + pin(name(A)) + + ) + circuit(BBGATEST + + # Circuit boundary + rect((-468000 -313001) (442500 226001)) + + # Outgoing pins and their connections to nets + pin(name(B)) + pin(name(A)) + + ) + circuit(BDPTEST + + # Circuit boundary + rect((71500 -290000) (371500 194000)) + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(DPTEST + + # Circuit boundary + rect((64500 86000) (371500 214500)) + + # Outgoing pins and their connections to nets + pin(name(B)) + pin(name(A)) + + ) + circuit(FDPTEST + + # Circuit boundary + rect((59500 359500) (375500 241000)) + + # Outgoing pins and their connections to nets + pin(name(B)) + pin(name(A)) + + ) + circuit(testall + + # Circuit boundary + rect((-577500 -1123000) (1868000 1796000)) + + # Nets with their geometries + net(1 + rect(l2 (345500 455000) (256500 25000)) + rect(l2 (-256500 -146000) (25000 146000)) + rect(l2 (-47000 -183500) (75000 75000)) + rect(l4 (-50000 -50000) (25000 25000)) + rect(l5 (-134000 -25000) (134000 25000)) + rect(l5 (-50000 -50000) (75000 75000)) + rect(l5 (-184000 -78500) (75000 75000)) + rect(l6 (-50000 -50000) (25000 25000)) + rect(l7 (-133500 -21500) (134500 25000)) + rect(l7 (-51000 -53500) (75000 75000)) + rect(l7 (-183500 -73000) (75000 75000)) + rect(l8 (-50000 -50000) (25000 25000)) + rect(l9 (-25000 -152000) (25000 152000)) + rect(l9 (-50000 -50000) (75000 75000)) + rect(l9 (-80500 -217500) (90000 90000)) + rect(l10 (-57500 -57500) (25000 25000)) + rect(l11 (-25000 -25000) (25000 25000)) + ) + net(2 + rect(l2 (-148000 463000) (300000 25000)) + ) + net(3 + rect(l2 (-401420 456500) (50730 78500)) + ) + net(4 + rect(l2 (822690 427000) (63970 82000)) + ) + net(5 + rect(l9 (348500 26500) (25000 179000)) + rect(l9 (-57500 -58000) (90000 90000)) + rect(l9 (-86000 -288500) (90000 90000)) + rect(l10 (-61500 141000) (25000 25000)) + rect(l10 (-21000 -223500) (25000 25000)) + rect(l11 (-29000 173500) (25000 25000)) + rect(l12 (-58500 -261000) (100000 100000)) + rect(l12 (-100000 -100000) (100000 100000)) + rect(l13 (-62500 -62500) (25000 25000)) + rect(l14 (-24000 -225500) (269500 25000)) + rect(l14 (-270500 7500) (25000 193000)) + rect(l14 (-87500 -87500) (150000 150000)) + ) + net(6 + rect(l14 (-126000 -195000) (292000 25000)) + ) + net(7 + rect(l14 (-410240 -216150) (83240 87150)) + ) + net(8 + rect(l14 (846960 -242000) (77190 75500)) + ) + + # Subcircuits and their connections + circuit(2 FDPTEST location(0 0) + pin(0 1) + pin(1 2) + ) + circuit(3 FWBTEST location(0 0) + pin(0 4) + pin(1 1) + ) + circuit(7 DPTEST location(0 0) + pin(0 5) + pin(1 1) + ) + circuit(8 FBGATEST location(0 0) + pin(0 2) + pin(1 3) + ) + circuit(9 BDPTEST location(0 0) + pin(0 5) + pin(1 6) + ) + circuit(10 BWBTEST location(0 0) + pin(0 8) + pin(1 5) + ) + circuit(14 BBGATEST location(0 0) + pin(0 7) + pin(1 6) + ) + + ) +) + +# Reference netlist +reference( + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(FBGATEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(FWBTEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(FDPTEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(DPTEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(BDPTEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(BWBTEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(BBGATEST + + # Outgoing pins and their connections to nets + pin(name(A)) + pin(name(B)) + + ) + circuit(TESTALL + + # Nets + net(1 name(A1)) + net(2 name(B1)) + net(3 name(C1)) + net(4 name(G1)) + net(5 name(D1)) + net(6 name(E1)) + net(7 name(H1)) + net(8 name(F1)) + + # Subcircuits and their connections + circuit(1 FBGATEST name(UFBGA) + pin(0 1) + pin(1 2) + ) + circuit(2 FWBTEST name(UFWB) + pin(0 3) + pin(1 4) + ) + circuit(3 FDPTEST name(UFDP) + pin(0 2) + pin(1 3) + ) + circuit(4 DPTEST name(UDP) + pin(0 3) + pin(1 5) + ) + circuit(5 BDPTEST name(UBDP) + pin(0 5) + pin(1 6) + ) + circuit(6 BWBTEST name(UBWB) + pin(0 5) + pin(1 7) + ) + circuit(7 BBGATEST name(UBBGA) + pin(0 6) + pin(1 8) + ) + + ) +) + +# Cross reference +xref( + circuit(BBGATEST BBGATEST match + xref( + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(BDPTEST BDPTEST match + xref( + pin(0 0 match) + pin(1 1 match) + ) + ) + circuit(BWBTEST BWBTEST match + xref( + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(DPTEST DPTEST match + xref( + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(FBGATEST FBGATEST match + xref( + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(FDPTEST FDPTEST match + xref( + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(FWBTEST FWBTEST match + xref( + pin(1 0 match) + pin(0 1 match) + ) + ) + circuit(testall TESTALL match + xref( + net(3 1 match) + net(2 2 match) + net(1 3 match) + net(5 5 match) + net(6 6 match) + net(7 8 match) + net(4 4 match) + net(8 7 match) + circuit(14 7 match) + circuit(9 5 match) + circuit(10 6 match) + circuit(7 4 match) + circuit(8 1 match) + circuit(2 3 match) + circuit(3 2 match) + ) + ) +) diff --git a/testdata/lvs/bbdevices3.cir b/testdata/lvs/bbdevices3.cir new file mode 100644 index 000000000..82abe4cee --- /dev/null +++ b/testdata/lvs/bbdevices3.cir @@ -0,0 +1,75 @@ +* Extracted by KLayout + +* cell testall +.SUBCKT testall +* cell instance $2 r0 *1 0,0 +X$2 1 2 FDPTEST +* cell instance $3 r0 *1 0,0 +X$3 1 FWBTEST +* cell instance $7 r0 *1 0,0 +X$7 3 1 DPTEST +* cell instance $8 r0 *1 0,0 +X$8 2 FBGATEST +* cell instance $9 r0 *1 0,0 +X$9 3 4 BDPTEST +* cell instance $10 r0 *1 0,0 +X$10 3 BWBTEST +* cell instance $14 r0 *1 0,0 +X$14 4 BBGATEST +.ENDS testall + +* cell FDPTEST +* pin B +* pin A +.SUBCKT FDPTEST 1 2 +* net 1 B +* net 2 A +.ENDS FDPTEST + +* cell DPTEST +* pin B +* pin A +.SUBCKT DPTEST 1 2 +* net 1 B +* net 2 A +.ENDS DPTEST + +* cell BDPTEST +* pin A +* pin B +.SUBCKT BDPTEST 1 2 +* net 1 A +* net 2 B +.ENDS BDPTEST + +* cell BBGATEST +* pin A +.SUBCKT BBGATEST 2 +* net 1 B +* net 2 A +* net 3 BBGATEST +.ENDS BBGATEST + +* cell FBGATEST +* pin B +.SUBCKT FBGATEST 1 +* net 1 B +* net 2 A +* net 3 FBGATEST +.ENDS FBGATEST + +* cell FWBTEST +* pin A +.SUBCKT FWBTEST 2 +* net 1 B +* net 2 A +* net 3 FWBTEST +.ENDS FWBTEST + +* cell BWBTEST +* pin B +.SUBCKT BWBTEST 1 +* net 1 B +* net 2 A +* net 3 BWBTEST +.ENDS BWBTEST diff --git a/testdata/lvs/bbdevices3.gds b/testdata/lvs/bbdevices3.gds new file mode 100644 index 0000000000000000000000000000000000000000..07ea60b330bdce772722cbec2c09a2dcd4376b1d GIT binary patch literal 6162 zcmd6re`r%z6vt0q@?KtJT3zjCyM|d^H(HFEHgW23VneJgRxMjL>ky-?fg2)4(I#sJ?GwY?|m0EP?R?CITZIDaKmEI>HmfDZ}2HvM^9(0Yky}~tYvegIU1`E z)CX1tR|Npdoa)Ag<7>BmfBydZ$k^(kPhO9LPtES@>0?&e0q5yz@k&}=&`}hO!QLp@PI}%(^fY4XV`fGkdQV&32QhvA{Y0*C? z>kDb$4R+(Mj|Ee4horcd&9_}MZ_8!VwN@1MNZ?Aoa4{^zEkwxt%eG-qGI++C&E+b#Ff? zSFZ|kJ5r8;wx2f!_4o|9_l#wkD|Xb1{~Wjv(4M8|ijA=fZ)sqI#m`w%U6I5P?aS6E zqyDK*NX0SWPtXcH9S~>(nG@=c@#{9VyRfs?R&4 zox5li6otT3AzGJeO4{qe_4^noJFYT1Pr6u5a&kLk4!z^Z15gfm0qN`yfil%6$n8iu z0@{Aw2-J6LK>2ez%UrXgR%*sUF^1%Ml4qRg`Wc?PS8kF<>QXYVFK zZbz~>%{eLSy%z%{5o`mb@zyAmG`0wGJ5tUQ)m!s)bk1JsQ^TWd*G%o33qDAYWOxKC zEFFtfVTHc0=)z|t@$2(h#-PwQ6(8A1521shv7edaxkc)$V@V5%e;fd0@;HF@?GZt4N6O<# z_15vk^Uj>Jk8_f~XLSu5L(#red)uWxxUM&mME5s<#I;#_X;_fk8FT0z-CmM-XBd#i zg8^{9=ojR6q#OfnKW_}m&Ou_V^<|kicGPq?CPwYy0&7?7D4DfKW^UXj@vk>ACI^p^ z_=zUM$?cSuc|~Wqxc5k0?8UJr$mFFOLI&Ffxqa?fXH-b$Sd&Lq>|>*B)3!AtxLT3+Skzm;PL>JmuA1e!tV&&L)3C}O}6@4?tIYKIkgwm z1+G*dtiG0e67*F9{h*dk3SVEk4;gn0tREjG3M$mRQj@TG4K z^HnUD_gafLpNqM?%^MFICH6X>w|Pc0z4`v01wN8199W<9Wy*t5t7XiB`<=^ny zG6fXS7t$>58-_BPO?u`fiJy0adTNBxmWm`J=hzy`*HT+5Q0YuF+FBXKj5B-4Z_8sbpZ`~Aai^ZFQ zO~I9+l|g_Cr+Y*5u{B$MICpzPn-y89kSNHD?#l!LD-kt;T z)$vAfX#i@80?&Y2ssKQs%t^?b1N;H_pkIEt9SN?-LFnsb{j~rg=?5S
qfwCJCe z^~H?u0lRTG#Y5@1!&2O}3mwlYBaCHL)X2}wTy zUtN|TZbzoaFD~}z{(b4#X(B|QZh6GH|IcHO(EY739?YzJqZIq2u6xrX<}M`ZQ#UkX zKH#XEl^M8M0FLQ#vA_&?@67(u* z{&=Po@s1MpAMn)C-Ka{9P-T&7@3!mUX;4tzY^u%uZH1J-MORLM`_2R)wQT^UyCwy> z9VzEe)@!RSf?5{^BtE{Dn}XbqWcmUgN@J)GBtm)S%a$0U z_Nhil)luN&c1lZK$@;lE`qlMzCqZhTO_9VN+M_19ozjvg8+}QPTQ%V6U6~_KcGPoc zD#6=6!74>WUtC|3hi!iF4814kI=e54Q9S|b*hNOIGD=ck`hk<%DJ}Vv`jX6@qWju| zFr(HmMIO%n4xHRhnbsFrYoDr`ZNXRi38^C>F$0br_W|kpXcE+OHGp+i}fTYw=?F^I}Xo)azF>9b1)3b)PNwjBjpI_ z_yr?yzgrK=U(-2i&5l~B9|y%4k?W+uI???zGXJdHD6N$K4Upva3xG6whoN-odO>bS zvN+9}l=a$=Gb9$@cR}ee&7VnbN6Pt=^;(~cB(B^Bq;Vqv zzSEZkxgE*$Hr864Rpwf4mgeeMvXvx03<5HB3_$(vupqZ1<+Y;vf@|fRr0-c(&(=ze zFZI=SX%4RItt8od36Qw&sxOWTayw%ly`xtr$#+HpY0M0P^M!yQwFN)pFg2`9HxTIz~cwYbwre$kI> zO^~Vc^@I#}3Ud4WwYJd}$BTshJsTE;jEIlvh$^7=UqnL4|1u%dL-YM}{@(l#f4qOg_gj9OGk-h>|D<0BxPEl*^X8M~udLk-PG`UH*UK}% z3-EpXPhC!b-GCNQUkQg+3vXXJ|6a)F`@Ha_Z;tR?ET8upi#M;ueBS1528|MDUC7(~ z{xZG!*_Y?tVRN@mdyA7YpEtc1!F+px-GTDo=W4A23TThfEbbkJ3VI`&ik@Y=A>S2k zslZKZ#^`8g6t!cH#qWT!#$pu@Cp#GN%Saw8zY6Qwxr}}d$#rdxRcr2p*<&$p+Fj0@ zt(h(}Rs3c$TgCc}sw}-}s`x!_wn|HlgJ)R)+z(A(WMP^3z!xeK1=ZerZK oh)n0uJXI>BQ{h3dj@-M|N+`h>orc9O1Aync>Mlu7+wqUY< zl*K@@gsGSeU2q9RrXh-Ee=KHy5M2mF64WeY2_q6C$^Jk@v&gpg^?J|kySMjkt*;#} zx%rI4{l0sC+;iXE0}T|V8T<~#eHYxY6m;-GmHa#S6|JrFXuSR4(f0U`t5<*tcJeuTo z%Cz1MwzZBnu~Lg#ZOixyj%7QrR*b2WH2>cpBb?kmw^medS1WLi(dSfEuzZR2rF`v@ zd~n@tAjyu)fHZEGf%f8{Ah$E-&^tPOB>B!DAdRVBaJ~=_e7qwDj+!$drer|=u{WO0jxg9B=YqDPNbdkihJAgE91;BguvLLr3nck+>UQILG zf}gIhlyI5q{!VILr!Jz-GBy9K!&DOZ~6Z7Z$5 zR{_djlUb^ik6Ni10mT@|Ql%%P*dZ|mj@=Ic>H2sKvVrer+Qo8oqOBBKe&6d_2gP9f5wVY z(1wQyQZJ?F$X9+rZl|>5Pu9nxQ#l0MxedU{?MQiNQoUWRz}ejb`i%*eZLz-8*^QD9E~6Q=FG>KZm+YfY?-S&9 z#vFP_PZwyTZGhB$J)m5_F39ajIR?7EZ4C5n2k!l}7v|l~@=+^+^Wbi!o@MT4dDKe0 zYv%VQy*u`Uc6^%AJ=y?8e>VXqw(4sZR0Ah#o#-lo=mO?&C!8}Z1ihYnQ7gYnqW&Ujr%`{8(Xyjt98 zmu7l|kWH8P0QjLv9^8(!_+BIHZv+TQ4}jp9Jh&Zc(T5~`>XuH-0gm!%d2lK z>_HlE^w7a{?DQWZ_Lb7wq-g^&2f)`?<-zSpi|-1L^YuzH#AhG%7c zA$hlno8GVSo7RE0HhLHL0+bfBvmW=oB@gub58z)PYN>f{TjyH#3eI(ozYgjmS9;G| z=UVy+=PJP-P>aXJTz|#~JaaAQ4)f!KtAtGU&Yhq2{q!I6`MG8})7gCdE9=jxxzEoz zU)it^oX##W-&d^F^Lr#dkN;?E=vyE3fc8o_R4ZnCi}~L}x#m7E=F%re?4G>dGMoSH zloSLvw{aIX%4+IfUgUMsf>XRD3f1*(*?d*H5XBgXw9q$MtX{>}H0 zbpegbInj{mGBYmzwwSNNEI?l~%LaZKkmJg&!nK^M>DK_c^URY*x=DfBGC`7qCm0QH z5Ztvrgp=EmY}G7!_mx?uN21R2Zl56P`2WjZ^Y!P&N>b7D?0X>pE|`}JRC-z%%}tEr l)G&Q5kxtcz!E$o{b_1aVZ*&rte&gcgc4RtMdaAly@GrO0Gd}k>pi#c-rl#i_I3Q@ zl9$hNa=!20bM86!zFyEkQQE-gP~5k{4GTesVyKk=2cM#K_8g3L?LF8P+p;mz5{)$k z8UibVD*^!JPIZ0b(bb!OID2nxWMt*gC$B`or{;cFg{Hl*_qABl%lq~OW1(1Mch~;d zs#ra^bO5bbfu}$#Q2@YS>LlciKK=lF&?`UOjs(}EAoMk|{;Hpl)B_M0mmh9NTJ%rL z`a;HcgWb3rV!>40At~-9^BvdB+frFSkGSWZcl&YI#~M;`2c@_d%kwTI-)7v^vVI*o=>CHJjs2uVEv zUtN+PZbzoZFD&-RzP+i~X(B|QZhpwQ|IcF&)BUYJ7D%sqy%hVyu6x5n<}N7dlh<`( zKH#XCksoeH+FEz7rZw#dM>oD0P4CD4^jP4n8U*d|45NFj8H)dI1x{{9%KN#j*GHqE zebfa=_s9Tverprtb|lk#Q|AfQKaS^#w#Wf0Xiqrk|K2J!TuX_6-cl!cmj^%}N`SXg znm?W?1-zqJ`v=@LbT_Kh!cq`noPWaqdb zwsnj(d8IAh#ps zOi_K_wQ}~ggMM|At(6#GI{#awIk=2A&^|8*q+Y&@zWt;iw=?F@JNkP;8|wt5?(GNV z$`wIwN6InK@$<%@9-RUA?vX6DVn?m`&w#sw&MaLkHr6V+lfF;*!e`oj8>JZSNOd*EF;*O`4ujH)rvMlLYw6%msB(g&Q}PHD-X)R$!TBf78M z4>9U>6Xe0nE#TyK%9K9OS{G@W*%o}IACo!);?v;Reh-kY6XT$rtrp~Vq+HQdpSPl& zJ82hqLQqsGMwfa@I_tsp#|S9fuP{1~yI4N~Zd{56%O*6gU2+EGx9A-PWStP|Zo!*kEd4bn<^zX6iib{>#M_aKxkUMI-y zNEWAAld@j_ahfE8bl;;i-lThdN2wsUBjr3%ecn7RI85t1Oy@<=g4~W|dK+sk&MI@QHc4}JEZRci9|i!KJPM$FcSw-ik@8wmecrWlj??$7tYvE@ z#+UkPn=}X4wPup&z6eO%ceUq-1-YFuhu+ccC5g9(0clJRfb%)OAh#ps80h$UV^DSs z5@WS5ORd;Z)037Mbq5OUOL1Cc_7$1Aev`z%-N2X}JVN5fnh7VjQ(EeZR<*d(NPN+Y zYfX^JbG3vFwhMCm+_kpR739IHu+&*_-ll8{>J0#(yHA;!NX0aTP_znj9}2zWlI73O|x^|jpRps#b{RZthWQgg8STJAv5R|)ikS~f0xed#%5 z+#9fYynl(1se!rvS$}W-hdj^Rq9Gv#2{JIO& z6XzLisYo(%hV7wzFSVrtl~$V3*2*X<&fF3C4E zZ=NzE#6E+QZLHt$d(55+yU4keeuK%~WM*@Tx%+00#k^@xJ13jdy=|)aeQ2hNbvIR6 zb_7$!Z;vxodU6!pOZ}ks9AK2=%B@0gwWY5>l~R2N+>M>YxO)Ma%AvV(<