diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc index 1ca2d79c7..04c456a2a 100644 --- a/src/db/db/dbCircuit.cc +++ b/src/db/db/dbCircuit.cc @@ -105,6 +105,14 @@ Circuit &Circuit::operator= (const Circuit &other) m_cell_index = other.m_cell_index; m_pins = other.m_pins; + m_pin_by_id.clear (); + for (pin_list::iterator p = m_pins.begin (); p != m_pins.end (); ++p) { + if (m_pin_by_id.size () <= p->id ()) { + m_pin_by_id.resize (p->id () + 1, pin_list::iterator ()); + } + m_pin_by_id [p->id ()] = p; + } + std::map device_table; for (const_device_iterator i = other.begin_devices (); i != other.end_devices (); ++i) { Device *d = new Device (*i); @@ -157,17 +165,22 @@ void Circuit::set_netlist (Netlist *netlist) const Pin *Circuit::pin_by_id (size_t id) const { - if (id >= m_pins.size ()) { + if (id >= m_pin_by_id.size ()) { return 0; } else { - return &m_pins [id]; + pin_list::iterator pi = m_pin_by_id [id]; + if (pi == pin_list::iterator ()) { + return 0; + } else { + return pi.operator-> (); + } } } void Circuit::rename_pin (size_t id, const std::string &name) { - if (id < m_pins.size ()) { - m_pins [id].set_name (name); + if (id < m_pin_by_id.size () && m_pin_by_id [id] != pin_list::iterator ()) { + m_pin_by_id [id]->set_name (name); } } @@ -207,6 +220,7 @@ void Circuit::clear () { m_name.clear (); m_pins.clear (); + m_pin_by_id.clear (); m_devices.clear (); m_nets.clear (); m_subcircuits.clear (); @@ -290,22 +304,33 @@ Circuit::const_child_circuit_iterator Circuit::end_parents () const void Circuit::clear_pins () { m_pins.clear (); + m_pin_by_id.clear (); } const Pin &Circuit::add_pin (const Pin &pin) { m_pins.push_back (pin); - m_pins.back ().set_id (m_pins.size () - 1); + m_pins.back ().set_id (m_pin_by_id.size ()); + m_pin_by_id.push_back (--m_pins.end ()); return m_pins.back (); } const Pin &Circuit::add_pin (const std::string &name) { m_pins.push_back (Pin (name)); - m_pins.back ().set_id (m_pins.size () - 1); + m_pins.back ().set_id (m_pin_by_id.size ()); + m_pin_by_id.push_back (--m_pins.end ()); return m_pins.back (); } +void Circuit::remove_pin (size_t id) +{ + if (id < m_pin_by_id.size () && m_pin_by_id [id] != pin_list::iterator ()) { + m_pins.erase (m_pin_by_id [id]); + m_pin_by_id [id] = pin_list::iterator (); + } +} + void Circuit::add_net (Net *net) { m_nets.push_back (net); @@ -550,17 +575,58 @@ void Circuit::connect_pin (size_t pin_id, Net *net) } } +void Circuit::purge_nets_keep_pins () +{ + do_purge_nets (true); +} + void Circuit::purge_nets () +{ + do_purge_nets (false); +} + +void Circuit::do_purge_nets (bool keep_pins) { std::vector nets_to_be_purged; for (net_iterator n = begin_nets (); n != end_nets (); ++n) { - if (n->is_floating ()) { + if (n->is_passive ()) { nets_to_be_purged.push_back (n.operator-> ()); } } + + std::set pins_to_delete; + for (std::vector::const_iterator n = nets_to_be_purged.begin (); n != nets_to_be_purged.end (); ++n) { + if (! keep_pins) { + for (db::Net::pin_iterator p = (*n)->begin_pins (); p != (*n)->end_pins (); ++p) { + pins_to_delete.insert (p->pin_id ()); + } + } delete *n; } + + if (! pins_to_delete.empty ()) { + + // remove the pin references of the pins we're going to delete + for (refs_iterator r = begin_refs (); r != end_refs (); ++r) { + db::SubCircuit *subcircuit = r.operator-> (); + for (std::set::const_iterator p = pins_to_delete.begin (); p != pins_to_delete.end (); ++p) { + db::Net *net = subcircuit->net_for_pin (*p); + for (db::Net::subcircuit_pin_iterator sp = net->begin_subcircuit_pins (); sp != net->end_subcircuit_pins (); ++sp) { + if (sp->pin_id () == *p && sp->subcircuit () == subcircuit) { + net->erase_subcircuit_pin (sp); + break; + } + } + } + } + + // and actually remove those pins + for (std::set::const_iterator p = pins_to_delete.begin (); p != pins_to_delete.end (); ++p) { + remove_pin (*p); + } + + } } /** diff --git a/src/db/db/dbCircuit.h b/src/db/db/dbCircuit.h index c8bcac695..199aa8a8f 100644 --- a/src/db/db/dbCircuit.h +++ b/src/db/db/dbCircuit.h @@ -89,7 +89,7 @@ class DB_PUBLIC Circuit : public db::NetlistObject, public gsi::ObjectBase { public: - typedef tl::vector pin_list; + typedef std::list pin_list; typedef pin_list::const_iterator const_pin_iterator; typedef pin_list::iterator pin_iterator; typedef tl::shared_collection device_list; @@ -330,6 +330,11 @@ public: */ const Pin &add_pin (const Pin &pin); + /** + * @brief Removes the pin with the given ID + */ + void remove_pin (size_t id); + /** * @brief Begin iterator for the pins of the circuit (non-const version) */ @@ -708,10 +713,19 @@ public: /** * @brief Purge unused nets * - * This method will purge all nets which return "floating". + * This method will purge all nets which return "is_passive". + * Pins on these nets will also be removed. */ void purge_nets (); + /** + * @brief Purge unused nets but + * + * This method will purge all nets which return "is_passive". + * Pins on these nets will be kept but their net will be 0. + */ + void purge_nets_keep_pins (); + /** * @brief Combine devices * @@ -751,6 +765,7 @@ private: db::cell_index_type m_cell_index; net_list m_nets; pin_list m_pins; + std::vector m_pin_by_id; device_list m_devices; subcircuit_list m_subcircuits; Netlist *mp_netlist; @@ -780,6 +795,7 @@ private: void set_netlist (Netlist *netlist); bool combine_parallel_devices (const db::DeviceClass &cls); bool combine_serial_devices (const db::DeviceClass &cls); + void do_purge_nets (bool keep_pins); void devices_changed (); void subcircuits_changed (); diff --git a/src/db/db/dbNetlist.cc b/src/db/db/dbNetlist.cc index 62056542c..1f7ab2fe8 100644 --- a/src/db/db/dbNetlist.cc +++ b/src/db/db/dbNetlist.cc @@ -472,7 +472,7 @@ void Netlist::remove_device_abstract (DeviceAbstract *device_abstract) void Netlist::purge_nets () { - for (circuit_iterator c = begin_circuits (); c != end_circuits (); ++c) { + for (bottom_up_circuit_iterator c = begin_bottom_up (); c != end_bottom_up (); ++c) { c->purge_nets (); } } diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index a95f6fba2..5dad8cd22 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -2951,14 +2951,34 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, // Report missing net assignment for (db::NetGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) { - if (! i->has_other () && mp_logger) { - mp_logger->net_mismatch (i->net (), 0); + if (! i->has_other ()) { + if (mp_logger) { + if (good) { + mp_logger->match_nets (i->net (), 0); + } else { + mp_logger->net_mismatch (i->net (), 0); + } + } + if (good) { + // in the "good" case, match the nets against 0 + g1.identify (g1.node_index_for_net (i->net ()), 0); + } } } for (db::NetGraph::node_iterator i = g2.begin (); i != g2.end (); ++i) { - if (! i->has_other () && mp_logger) { - mp_logger->net_mismatch (0, i->net ()); + if (! i->has_other ()) { + if (mp_logger) { + if (good) { + mp_logger->match_nets (0, i->net ()); + } else { + mp_logger->net_mismatch (0, i->net ()); + } + } + if (good) { + // in the "good" case, match the nets against 0 + g2.identify (g2.node_index_for_net (i->net ()), 0); + } } } @@ -2969,22 +2989,34 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, return good; } -void -NetlistComparer::handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1, const db::Circuit *c2, const db::Pin *pin2, bool &good, bool &pin_mismatch) const +bool +NetlistComparer::handle_pin_mismatch (const db::NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const db::NetGraph &g2, const db::Circuit *c2, const db::Pin *pin2) const { const db::Circuit *c = pin1 ? c1 : c2; const db::Pin *pin = pin1 ? pin1 : pin2; + const db::NetGraph *graph = pin1 ? &g1 : &g2; + const db::Net *net = c->net_for_pin (pin->id ()); - // If the pin isn't connected internally inside the circuit we can ignore it - if (c->net_for_pin (pin->id ()) && c->net_for_pin (pin->id ())->is_passive ()) { - if (mp_logger) { - mp_logger->match_pins (pin1, pin2); + // Nets which are paired with "null" are "safely to be ignored" and + // pin matching against "null" is valid. + if (net) { + const db::NetGraphNode &n = graph->node (graph->node_index_for_net (net)); + if (n.has_other () && n.other_net_index () == 0) { + if (mp_logger) { + mp_logger->match_pins (pin1, pin2); + } + return true; } - return; } // Determine whether the pin in question is used - only in this case we will report an error. // Otherwise, the report will be "match" against 0. + // "used" follows a heuristic criterion derived from the subcircuits which make use of this circuit: + // if one of these connects the pin to a net with either connections upwards, other subcircuits or + // devices, the pin is regarded "used". + // TODO: it would be better probably to have a global concept of "used pins" which considers all + // devices and propagates their presence as "used" property upwards, then downwards to the subcircuit + // pins. bool is_not_connected = true; for (db::Circuit::const_refs_iterator r = c->begin_refs (); r != c->end_refs () && is_not_connected; ++r) { @@ -2999,12 +3031,12 @@ NetlistComparer::handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1 if (mp_logger) { mp_logger->match_pins (pin1, pin2); } + return true; } else { if (mp_logger) { mp_logger->pin_mismatch (pin1, pin2); } - good = false; - pin_mismatch = true; + return false; } } @@ -3042,18 +3074,21 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g } } - std::vector abstract_pins; - std::multimap net2pin; + std::vector abstract_pins2; + std::multimap net2pin2; for (db::Circuit::const_pin_iterator p = c2->begin_pins (); p != c2->end_pins (); ++p) { const db::Net *net = c2->net_for_pin (p->id ()); if (net) { - net2pin.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ())); + net2pin2.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ())); } else if (abstract_pin_name_mapping.find (p.operator-> ()) == abstract_pin_name_mapping.end ()) { - abstract_pins.push_back (p.operator-> ()); + abstract_pins2.push_back (p.operator-> ()); } } - std::vector::iterator next_abstract = abstract_pins.begin (); + // collect missing assignment for circuit 1 + std::multimap net2pin1; + + std::vector::iterator next_abstract = abstract_pins2.begin (); CircuitMapper &c12_pin_mapping = c12_circuit_and_pin_mapping [c1]; c12_pin_mapping.set_other (c2); @@ -3078,7 +3113,7 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g c12_pin_mapping.map_pin (p->id (), fp->second->id ()); c22_pin_mapping.map_pin (fp->second->id (), p->id ()); - } else if (next_abstract != abstract_pins.end ()) { + } else if (next_abstract != abstract_pins2.end ()) { // assign an abstract pin - this is a dummy assignment which is mitigated // by declaring the pins equivalent in derive_pin_equivalence @@ -3093,7 +3128,10 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g } else { // otherwise this is an error for subcircuits or worth a report for top-level circuits - handle_pin_mismatch (c1, p.operator-> (), c2, 0, good, pin_mismatch); + if (! handle_pin_mismatch (g1, c1, p.operator-> (), g2, c2, 0)) { + good = false; + pin_mismatch = true; + } } @@ -3104,14 +3142,15 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g const db::NetGraphNode &n = *(g1.begin () + g1.node_index_for_net (net)); if (! n.has_other ()) { - handle_pin_mismatch (c1, p.operator-> (), c2, 0, good, pin_mismatch); + // remember and handle later when we know which pins are not mapped + net2pin1.insert (std::make_pair (g1.node_index_for_net (net), p.operator-> ())); continue; } - std::multimap::iterator np = net2pin.find (n.other_net_index ()); + std::multimap::iterator np = net2pin2.find (n.other_net_index ()); for (db::Net::const_pin_iterator pi = net->begin_pins (); pi != net->end_pins (); ++pi) { - if (np != net2pin.end () && np->first == n.other_net_index ()) { + if (np != net2pin2.end () && np->first == n.other_net_index ()) { if (mp_logger) { mp_logger->match_pins (pi->pin (), np->second); @@ -3122,11 +3161,12 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g std::multimap::iterator np_delete = np; ++np; - net2pin.erase (np_delete); + net2pin2.erase (np_delete); } else { - handle_pin_mismatch (c1, pi->pin (), c2, 0, good, pin_mismatch); + // remember and handle later when we know which pins are not mapped + net2pin1.insert (std::make_pair (g1.node_index_for_net (net), p.operator-> ())); } @@ -3134,16 +3174,28 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g } - for (std::multimap::iterator np = net2pin.begin (); np != net2pin.end (); ++np) { - handle_pin_mismatch (c1, 0, c2, np->second, good, pin_mismatch); + for (std::multimap::iterator np = net2pin1.begin (); np != net2pin1.end (); ++np) { + if (! handle_pin_mismatch (g1, c1, np->second, g2, c2, 0)) { + good = false; + pin_mismatch = true; + } + } + + for (std::multimap::iterator np = net2pin2.begin (); np != net2pin2.end (); ++np) { + if (! handle_pin_mismatch (g1, c1, 0, g2, c2, np->second)) { + good = false; + pin_mismatch = true; + } } // abstract pins must match. - while (next_abstract != abstract_pins.end ()) { - handle_pin_mismatch (c1, 0, c2, *next_abstract, good, pin_mismatch); + while (next_abstract != abstract_pins2.end ()) { + if (! handle_pin_mismatch (g1, c1, 0, g2, c2, *next_abstract)) { + good = false; + pin_mismatch = true; + } ++next_abstract; } - } void @@ -3384,7 +3436,7 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG bool mapped = true; for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { - if (! g1.begin () [i->second].has_other ()) { + if (! g2.begin () [i->second].has_other ()) { mapped = false; } else { i->second = g2.begin () [i->second].other_net_index (); diff --git a/src/db/db/dbNetlistCompare.h b/src/db/db/dbNetlistCompare.h index bcb6b9f56..f1a7b2ff6 100644 --- a/src/db/db/dbNetlistCompare.h +++ b/src/db/db/dbNetlistCompare.h @@ -314,7 +314,7 @@ protected: void do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, bool &pin_mismatch, bool &good) const; void do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, DeviceCategorizer &device_categorizer, bool &good) const; void do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const db::CircuitPinMapper &circuit_pin_mapper, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, bool &good) const; - void handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1, const db::Circuit *c2, const db::Pin *p2, bool &good, bool &pin_mismatch) const; + bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const; mutable NetlistCompareLogger *mp_logger; std::map, std::vector > > m_same_nets; diff --git a/src/db/db/dbNetlistCrossReference.cc b/src/db/db/dbNetlistCrossReference.cc index 344969908..4ef99f9bf 100644 --- a/src/db/db/dbNetlistCrossReference.cc +++ b/src/db/db/dbNetlistCrossReference.cc @@ -508,8 +508,7 @@ NetlistCrossReference::build_pin_refs (const std::pair::const_iterator ipb = m_other_pin.find (pa); if (ipb != m_other_pin.end () && ipb->second) { - const db::Pin *pb = ipb->second; - std::map::iterator b = p2r_b.find (pb); + std::map::iterator b = p2r_b.find (ipb->second); if (b != p2r_b.end ()) { prb = b->second; // remove the entry so we won't find it again @@ -558,7 +557,7 @@ NetlistCrossReference::build_subcircuit_pin_refs (const std::paircircuit_ref ()->pin_by_id (a->first.second); std::map::const_iterator ipb = m_other_pin.find (pa); - if (ipb != m_other_pin.end ()) { + if (ipb != m_other_pin.end () && ipb->second) { std::map, const db::NetSubcircuitPinRef *>::iterator b = s2t_b.find (std::make_pair (sb, ipb->second->id ())); if (b != s2t_b.end ()) { diff --git a/src/db/db/dbNetlistSpiceReader.cc b/src/db/db/dbNetlistSpiceReader.cc index 9234570c7..c54a7e352 100644 --- a/src/db/db/dbNetlistSpiceReader.cc +++ b/src/db/db/dbNetlistSpiceReader.cc @@ -288,11 +288,6 @@ void NetlistSpiceReader::finish () pop_stream (); } - // purge nets with single connections (this way unconnected pins can be realized) - if (mp_netlist) { - mp_netlist->purge_nets (); - } - mp_stream.reset (0); mp_netlist = 0; mp_circuit = 0; diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 6d2ca28cd..59c5fa5e7 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -1131,6 +1131,11 @@ Class decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit", "to the outside through such a pin. The pin is added after all existing " "pins. For more details see the \\Pin class." ) + + gsi::method ("remove_pin", &db::Circuit::remove_pin, gsi::arg ("id"), + "@brief Removes the pin with the given ID from the circuit\n" + "\n" + "This method has been introduced in version 0.26.2.\n" + ) + gsi::iterator ("each_child", (db::Circuit::child_circuit_iterator (db::Circuit::*) ()) &db::Circuit::begin_children, (db::Circuit::child_circuit_iterator (db::Circuit::*) ()) &db::Circuit::end_children, "@brief Iterates over the child circuits of this circuit\n" "Child circuits are the ones that are referenced from this circuit via subcircuits." @@ -1311,8 +1316,16 @@ Class decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit", ) + gsi::method ("purge_nets", &db::Circuit::purge_nets, "@brief Purges floating nets.\n" - "Floating nets can be created as effect of reconnections of devices or pins. " - "This method will eliminate all nets that make less than two connections." + "Floating nets are nets with no device or subcircuit attached to. Such floating " + "nets are removed in this step. If these nets are connected outward to a circuit pin, this " + "circuit pin is also removed." + ) + + gsi::method ("purge_nets_keep_pins", &db::Circuit::purge_nets_keep_pins, + "@brief Purges floating nets but keep pins.\n" + "This method will remove floating nets like \\purge_nets, but if these nets are attached " + "to a pin, the pin will be left disconnected from any net.\n" + "\n" + "This method has been introduced in version 0.26.2.\n" ), "@brief Circuits are the basic building blocks of the netlist\n" "A circuit has pins by which it can connect to the outside. Pins are " diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 820b61b1f..2e32cd4a2 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -2055,11 +2055,11 @@ TEST(14_Subcircuit2NandMismatchNoSwap) "net_mismatch INT IN1\n" "net_mismatch IN1 INT\n" "net_mismatch IN2 IN2\n" - "match_pins $0 (null)\n" "match_pins $1 $1\n" "match_pins $2 $2\n" "match_pins $3 $3\n" "match_pins $4 $4\n" + "match_pins $0 (null)\n" "match_pins (null) $0\n" "match_subcircuits $2 $1\n" "subcircuit_mismatch $1 $2\n" @@ -3366,3 +3366,340 @@ TEST(21_BusLikeAmbiguousConnections) EXPECT_EQ (good, true); } +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" + " 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" + "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" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\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); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + + bool good = comp.compare (&nl1, &nl2); + + 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 (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 $I4 $I5\n" + "match_nets $I6 $I4\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_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 $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" + "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); +} + +TEST(23_NodesRemovedWithError) +{ + 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" + // NOTE: $1 pin should not be connected to different nets, although it's not functional + " subcircuit INV2 $1 ($1=$3,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" + " subcircuit INV2 $2 ($1=$6,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" + "end;\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" + " 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" + " 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" + "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" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\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); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + + bool good = comp.compare (&nl1, &nl2); + + std::string txt = logger.text (); + + 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_nets (null) BULK\n" + "match_pins $0 $0\n" + "match_pins IN IN\n" + "match_pins $2 $2\n" + "match_pins OUT OUT\n" + "match_pins VSS VSS\n" + "match_pins VDD VDD\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 $I4 $I5\n" + "match_nets $I6 $I4\n" + "match_nets $I3 $I3\n" + "match_nets $I7 $I7\n" + "net_mismatch $3 $I1\n" + "match_nets $I8 $I8\n" + "net_mismatch $6 BULK\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" + "pin_mismatch (null) BULK\n" + "pin_mismatch (null) $6\n" + "match_subcircuits $1 $1\n" + "subcircuit_mismatch $2 $2\n" + "end_circuit INV2PAIR INV2PAIR NOMATCH\n" + "circuit_skipped RINGO RINGO" + ); + EXPECT_EQ (good, false); +} + +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" + " 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" + "end;\n" + // rewired here: BULK->VSS (pin $4), $1->$I3/$I4 (both rewired pins are deleted in the first netlist) + // This proves that we can basically do everything with the dropped pins. + "circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n" + " subcircuit INV2 $1 ($1=$I3,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=$I5);\n" + " subcircuit INV2 $2 ($1=$I4,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=$I5);\n" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\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); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + + bool good = comp.compare (&nl1, &nl2); + + 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 (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 $I4 $I5\n" + "match_nets $I6 $I4\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_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 $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" + "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); +} diff --git a/src/db/unit_tests/dbNetlistExtractorTests.cc b/src/db/unit_tests/dbNetlistExtractorTests.cc index fd64adaa0..d1bad5e47 100644 --- a/src/db/unit_tests/dbNetlistExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistExtractorTests.cc @@ -2573,3 +2573,134 @@ TEST(12_FloatingSubcircuitExtraction) ); } +TEST(13_RemoveDummyPins) +{ + db::Layout ly; + db::LayerMap lmap; + + unsigned int nwell = define_layer (ly, lmap, 1); + unsigned int active = define_layer (ly, lmap, 2); + unsigned int poly = define_layer (ly, lmap, 3); + unsigned int poly_lbl = define_layer (ly, lmap, 3, 1); + unsigned int diff_cont = define_layer (ly, lmap, 4); + unsigned int poly_cont = define_layer (ly, lmap, 5); + unsigned int metal1 = define_layer (ly, lmap, 6); + unsigned int metal1_lbl = define_layer (ly, lmap, 6, 1); + unsigned int via1 = define_layer (ly, lmap, 7); + unsigned int metal2 = define_layer (ly, lmap, 8); + unsigned int metal2_lbl = define_layer (ly, lmap, 8, 1); + + { + db::LoadLayoutOptions options; + options.get_options ().layer_map = lmap; + options.get_options ().create_other_layers = false; + + std::string fn (tl::testsrc ()); + fn = tl::combine_path (fn, "testdata"); + fn = tl::combine_path (fn, "algo"); + fn = tl::combine_path (fn, "issue-425.gds"); + + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly, options); + } + + db::Cell &tc = ly.cell (*ly.begin_top_down ()); + + db::DeepShapeStore dss; + dss.set_text_enlargement (1); + dss.set_text_property_name (tl::Variant ("LABEL")); + + // original layers + db::Region rnwell (db::RecursiveShapeIterator (ly, tc, nwell), dss); + db::Region ractive (db::RecursiveShapeIterator (ly, tc, active), dss); + db::Region rpoly (db::RecursiveShapeIterator (ly, tc, poly), dss); + db::Region rpoly_lbl (db::RecursiveShapeIterator (ly, tc, poly_lbl), dss); + db::Region rdiff_cont (db::RecursiveShapeIterator (ly, tc, diff_cont), dss); + db::Region rpoly_cont (db::RecursiveShapeIterator (ly, tc, poly_cont), dss); + db::Region rmetal1 (db::RecursiveShapeIterator (ly, tc, metal1), dss); + db::Region rmetal1_lbl (db::RecursiveShapeIterator (ly, tc, metal1_lbl), dss); + db::Region rvia1 (db::RecursiveShapeIterator (ly, tc, via1), dss); + db::Region rmetal2 (db::RecursiveShapeIterator (ly, tc, metal2), dss); + db::Region rmetal2_lbl (db::RecursiveShapeIterator (ly, tc, metal2_lbl), dss); + + // derived regions + + db::Region rpactive = ractive & rnwell; + db::Region rpgate = rpactive & rpoly; + db::Region rpsd = rpactive - rpgate; + + db::Region rnactive = ractive - rnwell; + db::Region rngate = rnactive & rpoly; + db::Region rnsd = rnactive - rngate; + + // perform the extraction + + db::Netlist nl; + db::hier_clusters cl; + + db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); + db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); + + db::NetlistDeviceExtractor::input_layers dl; + + dl["SD"] = &rpsd; + dl["G"] = &rpgate; + dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes + pmos_ex.extract (dss, 0, dl, nl, cl); + + dl["SD"] = &rnsd; + dl["G"] = &rngate; + dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes + nmos_ex.extract (dss, 0, dl, nl, cl); + + // perform the net extraction + + db::Connectivity conn; + // Intra-layer + conn.connect (rpsd); + conn.connect (rnsd); + conn.connect (rpoly); + conn.connect (rdiff_cont); + conn.connect (rpoly_cont); + conn.connect (rmetal1); + conn.connect (rvia1); + conn.connect (rmetal2); + // Inter-layer + conn.connect (rpsd, rdiff_cont); + conn.connect (rnsd, rdiff_cont); + conn.connect (rpoly, rpoly_cont); + conn.connect (rpoly_cont, rmetal1); + conn.connect (rdiff_cont, rmetal1); + conn.connect (rmetal1, rvia1); + conn.connect (rvia1, rmetal2); + conn.connect (rpoly, rpoly_lbl); // attaches labels + conn.connect (rmetal1, rmetal1_lbl); // attaches labels + conn.connect (rmetal2, rmetal2_lbl); // attaches labels + + // extract the nets + + db::NetlistExtractor net_ex; + net_ex.set_include_floating_subcircuits (true); + net_ex.extract_nets (dss, 0, conn, nl, cl); + + nl.simplify (); + + // compare netlist as string + CHECKPOINT (); + db::compare_netlist (_this, nl, + "circuit RINGO (FB=FB,VSS=VSS,VDD=VDD);\n" + " subcircuit INV2 $1 (IN=FB,OUT=$I25,$3=VSS,$4=VDD);\n" + " subcircuit INV2 $2 (IN=$I25,OUT=$I1,$3=VSS,$4=VDD);\n" + " subcircuit INV2 $3 (IN=$I1,OUT=$I2,$3=VSS,$4=VDD);\n" + " subcircuit INV2 $4 (IN=$I2,OUT=$I3,$3=VSS,$4=VDD);\n" + "end;\n" + "circuit INV2 (IN=IN,OUT=OUT,$3=$4,$4=$5);\n" + " device PMOS $1 (S=$2,G=IN,D=$5) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=$5,G=$2,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=$2,G=IN,D=$4) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n" + ); +} + diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index c3056e4aa..c6bc770cf 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -360,6 +360,17 @@ TEST(3_CircuitBasic) EXPECT_EQ (c2.pin_by_id (0)->name (), "p1"); EXPECT_EQ (c2.pin_by_id (1)->name (), "p2"); EXPECT_EQ (c2.pin_by_id (2), 0); + + c2.remove_pin (1); + EXPECT_EQ (c2.pin_by_id (0)->name (), "p1"); + EXPECT_EQ (c2.pin_by_id (1), 0); + EXPECT_EQ (c2.pin_by_id (2), 0); + + db::Pin p3 = c2.add_pin ("p3"); + EXPECT_EQ (c2.pin_by_id (0)->name (), "p1"); + EXPECT_EQ (c2.pin_by_id (1), 0); + EXPECT_EQ (c2.pin_by_id (2)->name (), "p3"); + EXPECT_EQ (c2.pin_by_id (3), 0); } TEST(4_CircuitDevices) @@ -1393,7 +1404,7 @@ TEST(22_BlankCircuit) nl2.purge (); EXPECT_EQ (nl2.to_string (), - "circuit RINGO (IN=IN,OSC=OSC,VSS=VSS,VDD=VDD);\n" + "circuit RINGO (OSC=OSC,VSS=VSS,VDD=VDD);\n" " subcircuit INV2 INV2_SC1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);\n" " subcircuit INV2 INV2_SC2 (IN=FB,$2=(null),OUT=$I8,$4=VSS,$5=VDD);\n" "end;\n" diff --git a/src/lvs/unit_tests/lvsTests.cc b/src/lvs/unit_tests/lvsTests.cc index d4fc23a89..02d6f5280 100644 --- a/src/lvs/unit_tests/lvsTests.cc +++ b/src/lvs/unit_tests/lvsTests.cc @@ -30,22 +30,14 @@ #include "lymMacro.h" #include "tlFileUtils.h" -void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string &suffix, const std::string &layout) +void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string &au_netlist, const std::string &layout, bool priv = false) { - std::string rs = tl::testsrc (); - rs += "/testdata/lvs/" + lvs_rs; + std::string testsrc = priv ? tl::testsrc_private () : tl::testsrc (); + testsrc = tl::combine_path (tl::combine_path (testsrc, "testdata"), "lvs"); - std::string src = tl::testsrc (); - src += "/testdata/lvs/" + layout; - - std::string au_lvsdb = tl::testsrc (); - au_lvsdb += "/testdata/lvs/" + suffix + ".lvsdb.gz"; - - std::string au_cir = tl::testsrc (); - au_cir += "/testdata/lvs/" + suffix + ".cir.gz"; - - std::string au_l2n = tl::testsrc (); - au_l2n += "/testdata/lvs/" + suffix + ".l2n.gz"; + std::string rs = tl::combine_path (testsrc, lvs_rs); + std::string ly = tl::combine_path (testsrc, layout); + std::string au_cir = tl::combine_path (testsrc, au_netlist); std::string output_lvsdb = _this->tmp_file ("tmp.lvsdb"); std::string output_cir = _this->tmp_file ("tmp.cir"); @@ -59,7 +51,7 @@ void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string "$lvs_test_target_lvsdb = '%s'\n" "$lvs_test_target_cir = '%s'\n" "$lvs_test_target_l2n = '%s'\n" - , src, output_lvsdb, output_cir, output_l2n) + , ly, output_lvsdb, output_cir, output_l2n) ); config.set_interpreter (lym::Macro::Ruby); EXPECT_EQ (config.run (), 0); @@ -101,11 +93,53 @@ void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string TEST(1_full) { test_is_long_runner (); - run_test (_this, "vexriscv.lvs", "vexriscv", "vexriscv.oas.gz"); + run_test (_this, "vexriscv.lvs", "vexriscv.cir.gz", "vexriscv.oas.gz"); } TEST(2_fullWithAlign) { test_is_long_runner (); - run_test (_this, "vexriscv_align.lvs", "vexriscv", "vexriscv.oas.gz"); + run_test (_this, "vexriscv_align.lvs", "vexriscv.cir.gz", "vexriscv.oas.gz"); +} + +TEST(10_private) +{ + // test_is_long_runner (); + run_test (_this, "test_10.lvs", "test_10.cir.gz", "test_10.gds.gz", true); +} + +TEST(11_private) +{ + // test_is_long_runner (); + run_test (_this, "test_11.lvs", "test_11.cir.gz", "test_11.gds.gz", true); +} + +TEST(12_private) +{ + // test_is_long_runner (); + run_test (_this, "test_12.lvs", "test_12.cir.gz", "test_12.gds.gz", true); +} + +TEST(13_private) +{ + // test_is_long_runner (); + run_test (_this, "test_13.lvs", "test_13.cir.gz", "test_13.gds.gz", true); +} + +TEST(14_private) +{ + test_is_long_runner (); + run_test (_this, "test_14.lvs", "test_14.cir.gz", "test_14.gds.gz", true); +} + +TEST(15_private) +{ + // test_is_long_runner (); + run_test (_this, "test_15.lvs", "test_15.cir.gz", "test_15.gds.gz", true); +} + +TEST(16_private) +{ + // test_is_long_runner (); + run_test (_this, "test_16.lvs", "test_16.cir.gz", "test_16.gds.gz", true); } diff --git a/testdata/algo/issue-425.gds b/testdata/algo/issue-425.gds new file mode 100644 index 000000000..e2e675e8f Binary files /dev/null and b/testdata/algo/issue-425.gds differ diff --git a/testdata/algo/lvs_test2_au.lvsdb.1 b/testdata/algo/lvs_test2_au.lvsdb.1 index 40eb31bb7..b78d22e71 100644 --- a/testdata/algo/lvs_test2_au.lvsdb.1 +++ b/testdata/algo/lvs_test2_au.lvsdb.1 @@ -1120,7 +1120,7 @@ xref( circuit(3 () mismatch) circuit(4 () mismatch) circuit(5 () mismatch) - circuit(1 1 mismatch) + circuit(1 1 match) ) ) ) diff --git a/testdata/algo/lvs_test2b_au.lvsdb.1 b/testdata/algo/lvs_test2b_au.lvsdb.1 index 2b3360370..74daf3f76 100644 --- a/testdata/algo/lvs_test2b_au.lvsdb.1 +++ b/testdata/algo/lvs_test2b_au.lvsdb.1 @@ -1120,7 +1120,7 @@ xref( circuit(3 () mismatch) circuit(4 () mismatch) circuit(5 () mismatch) - circuit(1 1 mismatch) + circuit(1 1 match) ) ) ) diff --git a/testdata/lvs/invchain_cheat.cir.1 b/testdata/lvs/invchain_cheat.cir.1 index ebb1e0e31..f4bef3947 100644 --- a/testdata/lvs/invchain_cheat.cir.1 +++ b/testdata/lvs/invchain_cheat.cir.1 @@ -1,30 +1,25 @@ * Extracted by KLayout -.SUBCKT INVCHAIN -X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3 -X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2 -X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV +.SUBCKT INVCHAIN IN OUT VSS VDD +X$1 IN \$2 \$3 \$2 \$3 \$4 VDD VSS INV3 +X$2 \$5 \$6 \$4 \$5 VDD VSS INV2 +X$3 VSS VDD \$6 OUT INV .ENDS INVCHAIN -.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2 -X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV -X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV -X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV +.SUBCKT INV3 3 5 7 4 6 8 \$I4 \$I2 +X$1 \$I2 \$I4 3 4 INV +X$2 \$I2 \$I4 5 6 INV +X$3 \$I2 \$I4 7 8 INV .ENDS INV3 -.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5 -+ \$I4 \$I2 -X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV -X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV +.SUBCKT INV2 \$I8 \$I7 \$I6 \$I5 \$I4 \$I2 +X$1 \$I2 \$I4 \$I6 \$I8 INV +X$2 \$I2 \$I4 \$I5 \$I7 INV .ENDS INV2 -.SUBCKT INV \$1 \$2 \$3 \$4 \$5 \$9 \$I8 \$I7 -M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U -+ PD=1.5U -M$2 \$2 \$I8 \$5 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -M$3 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U -+ PD=1.5U -M$4 \$1 \$I7 \$9 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U +.SUBCKT INV \$1 \$2 \$3 \$4 +M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U ++ PD=3.45U +M$2 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U ++ PD=3.45U .ENDS INV diff --git a/testdata/lvs/invchain_cheat.cir.2 b/testdata/lvs/invchain_cheat.cir.2 deleted file mode 100644 index 559a90f2a..000000000 --- a/testdata/lvs/invchain_cheat.cir.2 +++ /dev/null @@ -1,30 +0,0 @@ -* Extracted by KLayout - -.SUBCKT INVCHAIN -X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3 -X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2 -X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV -.ENDS INVCHAIN - -.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2 -X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV -X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV -X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV -.ENDS INV3 - -.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5 -+ \$I4 \$I2 -X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV -X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV -.ENDS INV2 - -.SUBCKT INV \$1 \$2 \$3 \$4 \$5 \$8 \$I8 \$I7 -M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U -+ PD=1.5U -M$2 \$2 \$I8 \$5 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -M$3 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U -+ PD=1.5U -M$4 \$1 \$I7 \$8 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -.ENDS INV diff --git a/testdata/lvs/invchain_cheat.cir.3 b/testdata/lvs/invchain_cheat.cir.3 deleted file mode 100644 index be921871d..000000000 --- a/testdata/lvs/invchain_cheat.cir.3 +++ /dev/null @@ -1,30 +0,0 @@ -* Extracted by KLayout - -.SUBCKT INVCHAIN -X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3 -X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2 -X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV -.ENDS INVCHAIN - -.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2 -X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV -X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV -X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV -.ENDS INV3 - -.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5 -+ \$I4 \$I2 -X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV -X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV -.ENDS INV2 - -.SUBCKT INV \$1 \$2 \$3 \$4 \$7 \$10 \$I8 \$I7 -M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U -+ PD=1.5U -M$2 \$2 \$I8 \$7 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -M$3 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U -+ PD=1.5U -M$4 \$1 \$I7 \$10 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -.ENDS INV diff --git a/testdata/lvs/invchain_cheat.cir.4 b/testdata/lvs/invchain_cheat.cir.4 deleted file mode 100644 index f6fcce0cb..000000000 --- a/testdata/lvs/invchain_cheat.cir.4 +++ /dev/null @@ -1,30 +0,0 @@ -* Extracted by KLayout - -.SUBCKT INVCHAIN -X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3 -X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2 -X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV -.ENDS INVCHAIN - -.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2 -X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV -X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV -X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV -.ENDS INV3 - -.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5 -+ \$I4 \$I2 -X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV -X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV -.ENDS INV2 - -.SUBCKT INV \$1 \$2 \$3 \$4 \$6 \$9 \$I8 \$I7 -M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U -+ PD=1.5U -M$2 \$2 \$I8 \$6 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -M$3 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U -+ PD=1.5U -M$4 \$1 \$I7 \$9 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -.ENDS INV diff --git a/testdata/lvs/invchain_cheat.lvs b/testdata/lvs/invchain_cheat.lvs index 34ff10e5c..d0fd20237 100644 --- a/testdata/lvs/invchain_cheat.lvs +++ b/testdata/lvs/invchain_cheat.lvs @@ -6,7 +6,52 @@ report_lvs($lvs_test_target_lvsdb) writer = write_spice(true, false) target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout") -schematic("invchain_for_cheat.cir") +# needs this delegate because we use MOS3 which is not available in Spice +class SpiceReaderDelegate < RBA::NetlistSpiceReaderDelegate + + # says we want to catch these subcircuits as devices + def wants_subcircuit(name) + name == "HVNMOS" || name == "HVPMOS" + end + + # translate the element + def element(circuit, el, name, model, value, nets, params) + + if el != "M" + # all other elements are left to the standard implementation + return super + end + + if nets.size != 4 + error("Device #{model} needs four nodes") + end + + # provide a device class + cls = circuit.netlist.device_class_by_name(model) + if ! cls + cls = RBA::DeviceClassMOS3Transistor::new + cls.name = model + circuit.netlist.add(cls) + end + + # create a device + device = circuit.create_device(cls, name) + + # and configure the device + [ "S", "G", "D" ].each_with_index do |t,index| + device.connect_terminal(t, nets[index]) + end + device.set_parameter("W", params["W"] * 1e6) + device.set_parameter("L", params["L"] * 1e6) + + device + + end + +end + +reader = RBA::NetlistSpiceReader::new(SpiceReaderDelegate::new) +schematic("invchain_for_cheat.cir", reader) deep @@ -15,32 +60,38 @@ deep nwell = input(1, 0) active = input(2, 0) poly = input(3, 0) +poly_lbl = input(3, 1) diff_cont = input(4, 0) poly_cont = input(5, 0) metal1 = input(6, 0) +metal1_lbl = input(6, 1) via1 = input(7, 0) metal2 = input(8, 0) +metal2_lbl = input(8, 1) # Bulk layer for terminal provisioning bulk = polygon_layer -# Computed layers - -active_in_nwell = active & nwell -pactive = active_in_nwell -pgate = pactive & poly -psd = pactive - pgate - -active_outside_nwell = active - nwell -nactive = active_outside_nwell -ngate = nactive & poly -nsd = nactive - ngate - -# Device extraction +psd = nil +nsd = nil cheat("INV") do + # Computed layers + + active_in_nwell = active & nwell + pactive = active_in_nwell + pgate = pactive & poly + psd = pactive - pgate + + active_outside_nwell = active - nwell + nactive = active_outside_nwell + ngate = nactive & poly + nsd = nactive - ngate + + # Device extraction + # PMOS transistor device extraction extract_devices(mos3("PMOS"), { "SD" => psd, "G" => pgate, "tS" => psd, "tD" => psd, "tG" => poly }) @@ -62,12 +113,18 @@ connect(poly_cont, metal1) connect(metal1, via1) connect(via1, metal2) +# attach labels +connect(poly, poly_lbl) +connect(metal1, metal1_lbl) +connect(metal2, metal2_lbl) + # Global connect_global(bulk, "SUBSTRATE") # Compare section netlist.simplify +align compare diff --git a/testdata/lvs/invchain_cheat.lvsdb b/testdata/lvs/invchain_cheat.lvsdb index 7f128c691..5b854ca93 100644 --- a/testdata/lvs/invchain_cheat.lvsdb +++ b/testdata/lvs/invchain_cheat.lvsdb @@ -3,66 +3,50 @@ J( W(INVCHAIN) U(0.001) L(l3 '3/0') + L(l11 '3/1') L(l6 '4/0') - L(l7 '2/0') + L(l7 '5/0') L(l8 '6/0') + L(l12 '6/1') L(l9 '7/0') L(l10 '8/0') - L(l11) + L(l13 '8/1') + L(l14) L(l2) L(l5) - C(l3 l3 l7) + C(l3 l3 l11 l7) + C(l11 l3 l11) C(l6 l6 l8 l2 l5) C(l7 l3 l7 l8) - C(l8 l6 l7 l8 l9) + C(l8 l6 l7 l8 l12 l9) + C(l12 l8 l12) C(l9 l8 l9 l10) - C(l10 l9 l10) - C(l11 l11) + C(l10 l9 l10 l13) + C(l13 l10 l13) + C(l14 l14) C(l2 l6 l2) C(l5 l6 l5) - G(l11 SUBSTRATE) + G(l14 SUBSTRATE) D(D$PMOS PMOS T(S - R(l2 (-960 -475) (835 950)) + R(l2 (-900 -475) (775 950)) ) T(G R(l3 (-125 -475) (250 950)) ) T(D - R(l2 (125 -475) (550 950)) - ) - ) - D(D$PMOS$1 PMOS - T(S - R(l2 (-675 -475) (550 950)) - ) - T(G - R(l3 (-125 -475) (250 950)) - ) - T(D - R(l2 (125 -475) (35 950)) + R(l2 (125 -475) (775 950)) ) ) D(D$NMOS NMOS T(S - R(l5 (-960 -475) (835 950)) + R(l5 (-900 -475) (775 950)) ) T(G R(l3 (-125 -475) (250 950)) ) T(D - R(l5 (125 -475) (550 950)) - ) - ) - D(D$NMOS$1 NMOS - T(S - R(l5 (-675 -475) (550 950)) - ) - T(G - R(l3 (-125 -475) (250 950)) - ) - T(D - R(l5 (125 -475) (35 950)) + R(l5 (125 -475) (775 950)) ) ) X(INV @@ -74,7 +58,7 @@ J( R(l9 (-305 -705) (250 250)) R(l9 (-250 150) (250 250)) R(l10 (-2025 -775) (3000 900)) - R(l5 (-1375 -925) (550 950)) + R(l5 (-1375 -925) (775 950)) ) N(2 R(l6 (290 2490) (220 220)) @@ -83,7 +67,7 @@ J( R(l9 (-305 -705) (250 250)) R(l9 (-250 150) (250 250)) R(l10 (-2025 -775) (3000 900)) - R(l2 (-1375 -925) (550 950)) + R(l2 (-1375 -925) (775 950)) ) N(3 R(l3 (-125 -250) (250 2500)) @@ -98,99 +82,55 @@ J( R(l8 (-290 -3530) (360 2840)) R(l8 (-360 -2800) (360 760)) R(l8 (-360 2040) (360 760)) - R(l2 (-740 -855) (835 950)) - R(l5 (-835 -3750) (835 950)) + R(l2 (-680 -855) (775 950)) + R(l5 (-775 -3750) (775 950)) ) - N(5 - R(l2 (925 2325) (35 950)) - ) - N(6 - R(l5 (925 -475) (35 950)) - ) - N(7) - N(8) P(1) P(2) P(3) P(4) - P(5) - P(6) - P(7) - P(8) D(1 D$PMOS Y(0 2800) E(L 0.25) E(W 0.95) - E(AS 0.79325) - E(AD 0.26125) - E(PS 3.57) - E(PD 1.5) + E(AS 0.73625) + E(AD 0.73625) + E(PS 3.45) + E(PD 3.45) T(S 4) T(G 3) T(D 2) ) - D(2 D$PMOS$1 - Y(800 2800) - E(L 0.25) - E(W 0.95) - E(AS 0.26125) - E(AD 0.03325) - E(PS 1.5) - E(PD 1.97) - T(S 2) - T(G 7) - T(D 5) - ) - D(3 D$NMOS + D(2 D$NMOS Y(0 0) E(L 0.25) E(W 0.95) - E(AS 0.79325) - E(AD 0.26125) - E(PS 3.57) - E(PD 1.5) + E(AS 0.73625) + E(AD 0.73625) + E(PS 3.45) + E(PD 3.45) T(S 4) T(G 3) T(D 1) ) - D(4 D$NMOS$1 - Y(800 0) - E(L 0.25) - E(W 0.95) - E(AS 0.26125) - E(AD 0.03325) - E(PS 1.5) - E(PD 1.97) - T(S 1) - T(G 8) - T(D 6) - ) ) X(INV2 R((0 0) (5500 4600)) - N(1) - N(2) - N(3) - N(4) - N(5) - N(6) - N(7) - N(8) - N(9) - N(10) - N(11 + N(1 R(l6 (1790 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) ) - N(12 + N(2 R(l6 (3490 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) ) - N(13 + N(3) + N(4) + N(5 R(l6 (990 3290) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (3080 -620) (220 220)) @@ -198,7 +138,7 @@ J( R(l8 (-3590 -690) (360 760)) R(l8 (2940 -760) (360 760)) ) - N(14 + N(6 R(l6 (990 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (3080 -620) (220 220)) @@ -212,63 +152,52 @@ J( P(4) P(5) P(6) - P(7) - P(8) - P(9) - P(10) - P(11) - P(12) - P(13) - P(14) X(1 INV M O(180) Y(1500 800) - P(0 14) - P(1 13) + P(0 6) + P(1 5) P(2 3) - P(3 11) - P(4 9) - P(5 7) - P(6 1) - P(7 5) + P(3 1) ) X(2 INV Y(4000 800) - P(0 14) - P(1 13) + P(0 6) + P(1 5) P(2 4) - P(3 12) - P(4 10) - P(5 8) - P(6 2) - P(7 6) + P(3 2) ) ) X(INV3 R((0 0) (6300 4600)) - N(1) - N(2 + N(1 I('3') + R(l11 (1509 1929) (2 2)) + ) + N(2 I('5') + R(l11 (2319 1909) (2 2)) + ) + N(3 I('7') + R(l11 (4829 1889) (2 2)) + ) + N(4 I('4') R(l6 (990 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) + R(l12 (-121 -1941) (2 2)) ) - N(3) - N(4) - N(5) - N(6) - N(7) - N(8) - N(9 + N(5 I('6') R(l6 (2590 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) + R(l12 (-131 -1971) (2 2)) ) - N(10 + N(6 I('8') R(l6 (4290 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) + R(l12 (-101 -1991) (2 2)) ) - N(11 + N(7 R(l6 (1790 3290) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 -620) (220 220)) @@ -279,7 +208,7 @@ J( R(l8 (-360 -760) (360 760)) R(l8 (2940 -760) (360 760)) ) - N(12 + N(8 R(l6 (1790 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 -620) (220 220)) @@ -290,136 +219,92 @@ J( R(l8 (-360 -760) (360 760)) R(l8 (2940 -760) (360 760)) ) - P(1) - P(2) - P(3) - P(4) - P(5) - P(6) + P(1 I('3')) + P(2 I('5')) + P(3 I('7')) + P(4 I('4')) + P(5 I('6')) + P(6 I('8')) P(7) P(8) - P(9) - P(10) - P(11) - P(12) X(1 INV Y(1500 800) - P(0 12) - P(1 11) - P(2 5) - P(3 2) - P(4 9) - P(5 9) - P(6 1) - P(7 1) + P(0 8) + P(1 7) + P(2 1) + P(3 4) ) X(2 INV M O(180) Y(2300 800) - P(0 12) - P(1 11) - P(2 1) - P(3 9) - P(4 2) - P(5 2) - P(6 5) - P(7 5) + P(0 8) + P(1 7) + P(2 2) + P(3 5) ) X(3 INV Y(4800 800) - P(0 12) - P(1 11) - P(2 4) - P(3 10) - P(4 8) - P(5 7) - P(6 3) - P(7 6) + P(0 8) + P(1 7) + P(2 3) + P(3 6) ) ) X(INVCHAIN R((-1500 -800) (10400 4600)) - N(1 - R(l6 (490 990) (220 220)) - R(l6 (-1220 -1520) (220 220)) - R(l6 (-220 180) (220 220)) - R(l6 (-220 2180) (220 220)) - R(l6 (-220 180) (220 220)) - R(l8 (-65 -2185) (1105 350)) + N(1 I(IN) + R(l3 (-1295 925) (1235 350)) + R(l11 (-911 -151) (2 2)) ) N(2 - R(l6 (3790 990) (220 220)) - R(l6 (-1220 -1520) (220 220)) + R(l3 (445 805) (480 550)) + R(l6 (-1435 -1665) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) - R(l8 (-65 -2185) (1105 350)) + R(l7 (780 -2120) (220 220)) + R(l8 (-1065 -285) (1105 350)) ) N(3 - R(l6 (1405 990) (220 220)) - R(l6 (-535 -1520) (220 220)) + R(l3 (1345 925) (1945 350)) + R(l6 (-2200 -1585) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) - R(l8 (20 -2270) (440 520)) + R(l7 (95 -2120) (220 220)) + R(l8 (-295 -370) (440 520)) ) N(4 - R(l6 (7090 990) (220 220)) - R(l6 (-1220 -1520) (220 220)) + R(l3 (3745 805) (480 550)) + R(l6 (-1435 -1665) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) - R(l8 (-65 -2185) (1105 350)) + R(l7 (780 -2120) (220 220)) + R(l8 (-1065 -285) (1105 350)) ) N(5 - R(l6 (4705 990) (220 220)) - R(l6 (-535 -1520) (220 220)) + R(l3 (4645 925) (1945 350)) + R(l6 (-2200 -1585) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) - R(l8 (20 -2270) (440 520)) + R(l7 (95 -2120) (220 220)) + R(l8 (-295 -370) (440 520)) ) N(6 - R(l3 (-1295 925) (1235 350)) - ) - N(7 - R(l3 (445 805) (480 550)) - ) - N(8 - R(l3 (1345 925) (1945 350)) - ) - N(9 - R(l3 (3745 805) (480 550)) - ) - N(10 - R(l3 (4645 925) (1945 350)) - ) - N(11 R(l3 (7045 805) (480 550)) + R(l6 (-1435 -1665) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + R(l7 (780 -2120) (220 220)) + R(l8 (-1065 -285) (1105 350)) ) - N(12 + N(7 I(OUT) R(l6 (7690 -310) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) + R(l12 (-121 -2011) (2 2)) ) - N(13 - R(l6 (6890 2490) (220 220)) - R(l6 (-220 180) (220 220)) - R(l6 (-3520 -620) (220 220)) - R(l6 (-220 180) (220 220)) - R(l6 (3080 -620) (220 220)) - R(l6 (-220 180) (220 220)) - R(l6 (-6820 -620) (220 220)) - R(l6 (-220 180) (220 220)) - R(l6 (-220 -620) (220 220)) - R(l6 (-220 180) (220 220)) - R(l6 (3080 -620) (220 220)) - R(l6 (-220 180) (220 220)) - R(l8 (3010 -690) (360 760)) - R(l8 (-3660 -760) (360 760)) - R(l8 (2940 -760) (360 760)) - R(l8 (-6960 -760) (360 760)) - R(l8 (-360 -760) (360 760)) - R(l8 (2940 -760) (360 760)) - ) - N(14 + N(8 I(VSS) R(l6 (6890 -310) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-3520 -620) (220 220)) @@ -438,136 +323,96 @@ J( R(l8 (-6960 -760) (360 760)) R(l8 (-360 -760) (360 760)) R(l8 (2940 -760) (360 760)) + R(l13 (2719 -381) (2 2)) + R(l13 (-3302 -2) (2 2)) + R(l13 (-3302 -2) (2 2)) ) + N(9 I(VDD) + R(l6 (6890 2490) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-3520 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (3080 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-6820 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (3080 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (3010 -690) (360 760)) + R(l8 (-3660 -760) (360 760)) + R(l8 (2940 -760) (360 760)) + R(l8 (-6960 -760) (360 760)) + R(l8 (-360 -760) (360 760)) + R(l8 (2940 -760) (360 760)) + R(l13 (-581 -381) (2 2)) + R(l13 (3298 -2) (2 2)) + R(l13 (-6602 -2) (2 2)) + ) + P(1 I(IN)) + P(7 I(OUT)) + P(8 I(VSS)) + P(9 I(VDD)) X(1 INV3 Y(-1500 -800) - P(0 7) - P(1 1) - P(2 9) - P(3 8) - P(4 6) - P(5 9) - P(6 5) - P(7 5) - P(8 3) - P(9 2) - P(10 13) - P(11 14) + P(0 1) + P(1 2) + P(2 3) + P(3 2) + P(4 3) + P(5 4) + P(6 9) + P(7 8) ) X(2 INV2 Y(2600 -800) - P(0 8) - P(1 11) - P(2 9) - P(3 10) - P(4 8) - P(5 11) - P(6 2) - P(7 12) - P(8 2) - P(9 12) - P(10 5) - P(11 4) - P(12 13) - P(13 14) + P(0 5) + P(1 6) + P(2 4) + P(3 5) + P(4 9) + P(5 8) ) X(3 INV M O(180) Y(7400 0) - P(0 14) - P(1 13) - P(2 11) - P(3 12) - P(4 4) - P(5 4) - P(6 10) - P(7 10) + P(0 8) + P(1 9) + P(2 6) + P(3 7) ) ) ) H( - X(TRANS - N(1 I('1')) - N(2 I('2')) - N(3 I('3')) - P(1 I('1')) - P(2 I('2')) - P(3 I('3')) - ) X(INV N(1 I('1')) N(2 I('2')) N(3 I('3')) N(4 I('4')) - N(5 I('5')) - N(6 I('6')) - N(7 I('7')) - N(8 I('8')) P(1 I('1')) P(2 I('2')) P(3 I('3')) P(4 I('4')) - P(5 I('5')) - P(6 I('6')) - P(7 I('7')) - P(8 I('8')) D(1 PMOS I($1) E(L 0.25) E(W 0.95) - E(AS 0.79325) - E(AD 0.26125) - E(PS 3.57) - E(PD 1.5) - T(S 4) + E(AS 0) + E(AD 0) + E(PS 0) + E(PD 0) + T(S 1) T(G 3) - T(D 2) - T(B 4) + T(D 4) ) - D(2 PMOS - I($2) - E(L 0.25) - E(W 0.95) - E(AS 0.26125) - E(AD 0.03325) - E(PS 1.5) - E(PD 1.97) - T(S 2) - T(G 7) - T(D 5) - T(B 2) - ) - D(3 NMOS + D(2 NMOS I($3) E(L 0.25) E(W 0.95) - E(AS 0.79325) - E(AD 0.26125) - E(PS 3.57) - E(PD 1.5) - T(S 4) + E(AS 0) + E(AD 0) + E(PS 0) + E(PD 0) + T(S 2) T(G 3) - T(D 1) - T(B 4) - ) - D(4 NMOS - I($4) - E(L 0.25) - E(W 0.95) - E(AS 0.26125) - E(AD 0.03325) - E(PS 1.5) - E(PD 1.97) - T(S 1) - T(G 8) - T(D 6) - T(B 1) - ) - X(1 TRANS I($1) - P(0 4) - P(1 1) - P(2 3) - ) - X(2 TRANS I($2) - P(0 4) - P(1 2) - P(2 3) + T(D 4) ) ) X(INV3 @@ -579,10 +424,6 @@ H( N(6 I('6')) N(7 I('7')) N(8 I('8')) - N(9 I('9')) - N(10 I('10')) - N(11 I('11')) - N(12 I('12')) P(1 I('1')) P(2 I('2')) P(3 I('3')) @@ -591,39 +432,23 @@ H( P(6 I('6')) P(7 I('7')) P(8 I('8')) - P(9 I('9')) - P(10 I('10')) - P(11 I('11')) - P(12 I('12')) X(1 INV I($1) - P(0 12) - P(1 11) + P(0 1) + P(1 2) P(2 3) - P(3 10) - P(4 8) - P(5 6) - P(6 1) - P(7 5) + P(3 4) ) X(2 INV I($2) - P(0 12) - P(1 11) - P(2 4) - P(3 7) - P(4 9) - P(5 9) - P(6 2) - P(7 2) + P(0 1) + P(1 2) + P(2 5) + P(3 6) ) X(3 INV I($3) - P(0 12) - P(1 11) - P(2 2) - P(3 9) - P(4 7) - P(5 7) - P(6 4) - P(7 4) + P(0 1) + P(1 2) + P(2 7) + P(3 8) ) ) X(INV2 @@ -633,125 +458,135 @@ H( N(4 I('4')) N(5 I('5')) N(6 I('6')) - N(7 I('7')) - N(8 I('8')) - N(9 I('9')) - N(10 I('10')) - N(11 I('11')) - N(12 I('12')) - N(13 I('13')) - N(14 I('14')) P(1 I('1')) P(2 I('2')) P(3 I('3')) P(4 I('4')) P(5 I('5')) P(6 I('6')) - P(7 I('7')) - P(8 I('8')) - P(9 I('9')) - P(10 I('10')) - P(11 I('11')) - P(12 I('12')) - P(13 I('13')) - P(14 I('14')) X(1 INV I($1) - P(0 14) - P(1 13) + P(0 1) + P(1 2) P(2 3) - P(3 11) - P(4 9) - P(5 7) - P(6 1) - P(7 5) + P(3 4) ) X(2 INV I($2) - P(0 14) - P(1 13) - P(2 4) - P(3 12) - P(4 10) - P(5 8) - P(6 2) - P(7 6) + P(0 1) + P(1 2) + P(2 5) + P(3 6) ) ) X(INVCHAIN - N(1 I('9')) - N(2 I('7')) - N(3 I('8')) - N(4 I('6')) + N(1 I('1')) + N(2 I('2')) + N(3 I('3')) + N(4 I('4')) N(5 I('5')) - N(6 I('1')) - N(7 I('3')) - N(8 I('2')) - N(9 I('13')) - N(10 I('14')) - N(11 I('11')) - N(12 I('10')) - N(13 I('12')) - N(14 I('4')) + N(6 I('6')) + N(7 I('7')) + N(8 I('8')) + N(9 I('9')) X(1 INV3 I($1) P(0 1) P(1 2) P(2 3) P(3 4) - P(4 1) + P(4 4) P(5 5) - P(6 6) - P(7 5) - P(8 7) - P(9 8) - P(10 9) - P(11 10) + P(6 5) + P(7 6) ) X(2 INV2 I($2) - P(0 3) - P(1 11) - P(2 1) - P(3 12) - P(4 3) - P(5 11) - P(6 8) - P(7 13) - P(8 8) - P(9 13) - P(10 5) - P(11 14) - P(12 9) - P(13 10) + P(0 1) + P(1 2) + P(2 6) + P(3 7) + P(4 7) + P(5 8) ) X(3 INV I($3) - P(0 10) - P(1 9) - P(2 11) - P(3 13) - P(4 14) - P(5 14) - P(6 12) - P(7 12) + P(0 1) + P(1 2) + P(2 8) + P(3 9) ) ) ) Z( - X(() TRANS 0 + X(INV INV 1 Z( + N(2 1 1) + N(1 2 1) + N(3 3 1) + N(4 4 1) + P(1 0 1) + P(0 1 1) + P(2 2 1) + P(3 3 1) + D(2 2 1) + D(1 1 1) ) ) - X(INV INV S + X(INV2 INV2 1 Z( + N(5 1 1) + N(6 2 1) + N(3 3 1) + N(1 4 W) + N(4 5 1) + N(2 6 W) + P(4 0 1) + P(5 1 1) + P(2 2 1) + P(0 3 1) + P(3 4 1) + P(1 5 1) + X(1 1 1) + X(2 2 1) ) ) - X(INV2 INV2 S + X(INV3 INV3 1 Z( + N(7 1 1) + N(8 2 1) + N(1 3 1) + N(4 4 W) + N(2 5 1) + N(5 6 W) + N(3 7 1) + N(6 8 W) + P(6 0 1) + P(7 1 1) + P(0 2 1) + P(3 3 1) + P(1 4 1) + P(4 5 1) + P(2 6 1) + P(5 7 1) + X(1 1 1) + X(2 2 1) + X(3 3 1) ) ) - X(INV3 INV3 S - Z( - ) - ) - X(INVCHAIN INVCHAIN S + X(INVCHAIN INVCHAIN 1 Z( + N(2 4 1) + N(3 5 1) + N(4 6 1) + N(5 7 1) + N(6 8 1) + N(1 3 1) + N(7 9 1) + N(9 1 1) + N(8 2 1) + P(0 () 1) + P(1 () 1) + P(3 () 1) + P(2 () 1) + X(3 3 1) + X(2 2 1) + X(1 1 1) ) ) ) diff --git a/testdata/lvs/invchain_for_cheat.cir b/testdata/lvs/invchain_for_cheat.cir index 1aae680d3..d37bd4cee 100644 --- a/testdata/lvs/invchain_for_cheat.cir +++ b/testdata/lvs/invchain_for_cheat.cir @@ -1,85 +1,27 @@ * cell INVCHAIN .SUBCKT INVCHAIN -* cell instance $1 r0 *1 -1.5,-0.8 -X$1 9 7 8 6 9 5 1 5 3 2 13 14 INV3 -* cell instance $2 r0 *1 2.6,-0.8 -X$2 8 11 9 10 8 11 2 12 2 12 5 4 13 14 INV2 -* cell instance $3 m90 *1 7.4,0 -X$3 14 13 11 12 4 4 10 10 INV +X$1 1 2 3 4 4 5 5 6 INV3 +X$2 1 2 6 7 7 8 INV2 +X$3 1 2 8 9 INV .ENDS INVCHAIN * cell INV3 -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -.SUBCKT INV3 1 2 3 4 5 6 7 8 9 10 11 12 -* cell instance $1 r0 *1 4.8,0.8 -X$1 12 11 3 10 8 6 1 5 INV -* cell instance $2 r0 *1 1.5,0.8 -X$2 12 11 4 7 9 9 2 2 INV -* cell instance $3 m90 *1 2.3,0.8 -X$3 12 11 2 9 7 7 4 4 INV +.SUBCKT INV3 1 2 3 4 5 6 7 8 +X$1 1 2 3 4 INV +X$2 1 2 5 6 INV +X$3 1 2 7 8 INV .ENDS INV3 * cell INV2 -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -.SUBCKT INV2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 -* cell instance $1 m90 *1 1.5,0.8 -X$1 14 13 3 11 9 7 1 5 INV -* cell instance $2 r0 *1 4,0.8 -X$2 14 13 4 12 10 8 2 6 INV +.SUBCKT INV2 1 2 3 4 5 6 +X$1 1 2 3 4 INV +X$2 1 2 5 6 INV .ENDS INV2 * cell INV -* pin -* pin -* pin -* pin -* pin -* pin -* pin -* pin -.SUBCKT INV 1 2 3 4 5 6 7 8 -* cell instance $1 r0 *1 0,0 -X$1 4 1 3 TRANS -* cell instance $2 r0 *1 0,2.8 -X$2 4 2 3 TRANS -* device instance $1 r0 *1 0,2.8 PMOS -M$1 4 3 2 4 PMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U PD=1.5U -* device instance $2 r0 *1 0.8,2.8 PMOS -M$2 2 7 5 2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U PD=1.97U -* device instance $3 r0 *1 0,0 NMOS -M$3 4 3 1 4 NMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U PD=1.5U -* device instance $4 r0 *1 0.8,0 NMOS -M$4 1 8 6 1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U PD=1.97U +.SUBCKT INV 1 2 3 4 +M$1 1 3 4 1 PMOS L=0.25U W=0.95U +M$3 2 3 4 2 NMOS L=0.25U W=0.95U .ENDS INV -* cell TRANS -* pin -* pin -* pin -.SUBCKT TRANS 1 2 3 -.ENDS TRANS diff --git a/testdata/lvs/invchain_for_cheat.gds b/testdata/lvs/invchain_for_cheat.gds index 43446a79f..5856c8f19 100644 Binary files a/testdata/lvs/invchain_for_cheat.gds and b/testdata/lvs/invchain_for_cheat.gds differ diff --git a/testdata/ruby/dbNetlist.rb b/testdata/ruby/dbNetlist.rb index 695eb4e38..879939444 100644 --- a/testdata/ruby/dbNetlist.rb +++ b/testdata/ruby/dbNetlist.rb @@ -170,6 +170,21 @@ class DBNetlist_TestClass < TestBase c.each_pin { |p| names << p.name } assert_equal(names, [ "A", "B" ]) + assert_equal(c.pin_by_id(0) == nil, false) + assert_equal(c.pin_by_id(1) == nil, false) + assert_equal(c.pin_by_id(0).name, "A") + assert_equal(c.pin_by_id(1).name, "B") + + c.remove_pin(0) + + names = [] + c.each_pin { |p| names << p.name } + assert_equal(names, [ "B" ]) + + assert_equal(c.pin_by_id(0) == nil, true) + assert_equal(c.pin_by_id(1) == nil, false) + assert_equal(c.pin_by_id(1).name, "B") + end def test_4_Device