diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc index 735f6116b..04c456a2a 100644 --- a/src/db/db/dbCircuit.cc +++ b/src/db/db/dbCircuit.cc @@ -575,7 +575,17 @@ 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) { @@ -587,29 +597,35 @@ void Circuit::purge_nets () std::set pins_to_delete; for (std::vector::const_iterator n = nets_to_be_purged.begin (); n != nets_to_be_purged.end (); ++n) { - for (db::Net::pin_iterator p = (*n)->begin_pins (); p != (*n)->end_pins (); ++p) { - pins_to_delete.insert (p->pin_id ()); + 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; } - // 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; + 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); + // 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 5fa298ea0..199aa8a8f 100644 --- a/src/db/db/dbCircuit.h +++ b/src/db/db/dbCircuit.h @@ -713,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 * @@ -786,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/dbNetlistSpiceReader.cc b/src/db/db/dbNetlistSpiceReader.cc index 9234570c7..855b39546 100644 --- a/src/db/db/dbNetlistSpiceReader.cc +++ b/src/db/db/dbNetlistSpiceReader.cc @@ -282,15 +282,37 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist) } } +/** + * @brief Removes dummy nets which are just there to define a pin for a subcircuit + */ +static void +remove_dummy_nets (db::Circuit &circuit) +{ + std::vector nets_to_be_purged; + for (db::Circuit::net_iterator n = circuit.begin_nets (); n != circuit.end_nets (); ++n) { + if (n->subcircuit_pin_count () == 1 && (n->terminal_count () + n->pin_count ()) == 0) { + nets_to_be_purged.push_back (n.operator-> ()); + } + } + + for (std::vector::const_iterator n = nets_to_be_purged.begin (); n != nets_to_be_purged.end (); ++n) { + delete *n; + } +} + void NetlistSpiceReader::finish () { while (! m_streams.empty ()) { pop_stream (); } - // purge nets with single connections (this way unconnected pins can be realized) if (mp_netlist) { - mp_netlist->purge_nets (); + // purge nets with single connections (this way unconnected pins can be realized) + // NOTE: we don't use Netlist::purge_nets as this method has too many side effects + db::NetlistLocker locker (mp_netlist); + for (db::Netlist::bottom_up_circuit_iterator c = mp_netlist->begin_bottom_up (); c != mp_netlist->end_bottom_up (); ++c) { + remove_dummy_nets (*c); + } } mp_stream.reset (0); diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index f6dd51ce8..59c5fa5e7 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -1316,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/testdata/algo/lvs_test2_au.lvsdb.1 b/testdata/algo/lvs_test2_au.lvsdb.1 index 40eb31bb7..eb5e0dbce 100644 --- a/testdata/algo/lvs_test2_au.lvsdb.1 +++ b/testdata/algo/lvs_test2_au.lvsdb.1 @@ -951,11 +951,8 @@ reference( net(4 name('4')) net(5 name('6')) net(6 name('5')) - net(7 name('101')) - net(8 name('8')) - net(9 name('102')) - net(10 name('7')) - net(11 name('103')) + net(7 name('8')) + net(8 name('7')) # Outgoing pins and their connections to nets pin(1 name('1')) @@ -986,26 +983,23 @@ reference( pin(0 4) pin(1 3) pin(2 4) - pin(3 7) pin(4 6) - pin(5 8) + pin(5 7) pin(6 3) ) circuit(4 INV2PAIR name($4) pin(0 4) pin(1 3) pin(2 4) - pin(3 9) - pin(4 8) - pin(5 10) + pin(4 7) + pin(5 8) pin(6 3) ) circuit(5 INV2PAIR name($5) pin(0 4) pin(1 3) pin(2 4) - pin(3 11) - pin(4 10) + pin(4 8) pin(5 5) pin(6 3) ) @@ -1090,11 +1084,8 @@ xref( ) circuit(RINGO RINGO nomatch xref( - net(() 7 mismatch) - net(() 9 mismatch) - net(() 11 mismatch) net(() 6 mismatch) - net(() 8 mismatch) + net(() 7 mismatch) net(5 () mismatch) net(6 () mismatch) net(7 () mismatch) @@ -1102,7 +1093,7 @@ xref( net(11 () mismatch) net(12 () mismatch) net(10 1 mismatch) - net(8 10 mismatch) + net(8 8 mismatch) net(1 5 mismatch) net(2 2 match) net(3 3 match) @@ -1120,7 +1111,7 @@ xref( circuit(3 () mismatch) circuit(4 () mismatch) circuit(5 () mismatch) - circuit(1 1 mismatch) + circuit(1 1 match) ) ) )