diff --git a/src/db/db/dbNetlistSpiceReader.cc b/src/db/db/dbNetlistSpiceReader.cc index 269a85bb5..129fc248d 100644 --- a/src/db/db/dbNetlistSpiceReader.cc +++ b/src/db/db/dbNetlistSpiceReader.cc @@ -256,6 +256,7 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist) mp_stream.reset (new tl::TextInputStream (stream)); mp_netlist = &netlist; mp_circuit = 0; + mp_anonymous_top_circuit = 0; mp_nets_by_name.reset (0); m_global_nets.clear (); m_circuits_read.clear (); @@ -268,6 +269,8 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist) read_card (); } + build_global_nets (); + mp_delegate->finish (&netlist); finish (); @@ -287,6 +290,48 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist) } } +void NetlistSpiceReader::build_global_nets () +{ + for (std::vector::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) { + + for (db::Netlist::bottom_up_circuit_iterator c = mp_netlist->begin_bottom_up (); c != mp_netlist->end_bottom_up (); ++c) { + + if (c.operator-> () == mp_anonymous_top_circuit) { + // no pins for the anonymous top circuit + continue; + } + + db::Net *net = c->net_by_name (*gn); + if (! net || net->pin_count () > 0) { + // only add a pin for a global net if there is a net with this name + // don't add a pin if it already has one + continue; + } + + const db::Pin &pin = c->add_pin (*gn); + c->connect_pin (pin.id (), net); + + for (db::Circuit::refs_iterator r = c->begin_refs (); r != c->end_refs (); ++r) { + + db::SubCircuit &sc = *r; + + db::Net *pnet = sc.circuit ()->net_by_name (*gn); + if (! pnet) { + pnet = new db::Net (); + pnet->set_name (*gn); + sc.circuit ()->add_net (pnet); + } + + sc.connect_pin (pin.id (), pnet); + + } + + } + + } +} + + void NetlistSpiceReader::finish () { while (! m_streams.empty ()) { @@ -577,12 +622,9 @@ void NetlistSpiceReader::ensure_circuit () mp_circuit = new db::Circuit (); // TODO: make top name configurable mp_circuit->set_name (".TOP"); + mp_anonymous_top_circuit = mp_circuit; mp_netlist->add_circuit (mp_circuit); - for (std::vector::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) { - make_net (*gn); - } - } } @@ -828,13 +870,10 @@ void NetlistSpiceReader::read_subcircuit (const std::string &sc_name, const std: for (std::vector::const_iterator i = nets.begin (); i != nets.end (); ++i) { cc->add_pin (std::string ()); } - for (std::vector::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) { - cc->add_pin (std::string ()); - } } else { - if (cc->pin_count () != nets.size () + m_global_nets.size ()) { + if (cc->pin_count () != nets.size ()) { error (tl::sprintf (tl::to_string (tr ("Pin count mismatch between circuit definition and circuit call: %d expected, got %d")), int (cc->pin_count ()), int (nets.size ()))); } @@ -846,11 +885,6 @@ void NetlistSpiceReader::read_subcircuit (const std::string &sc_name, const std: for (std::vector::const_iterator i = nets.begin (); i != nets.end (); ++i) { sc->connect_pin (i - nets.begin (), *i); } - - for (std::vector::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) { - db::Net *net = make_net (*gn); - sc->connect_pin (gn - m_global_nets.begin () + nets.size (), net); - } } void NetlistSpiceReader::skip_circuit (tl::Extractor & /*ex*/) @@ -892,13 +926,10 @@ void NetlistSpiceReader::read_circuit (tl::Extractor &ex, const std::string &nc) for (std::vector::const_iterator i = nn.begin (); i != nn.end (); ++i) { cc->add_pin (std::string ()); } - for (std::vector::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) { - cc->add_pin (std::string ()); - } } else { - if (cc->pin_count () != nn.size () + m_global_nets.size ()) { + if (cc->pin_count () != nn.size ()) { error (tl::sprintf (tl::to_string (tr ("Pin count mismatch between implicit (through call) and explicit circuit definition: %d expected, got %d in circuit %s")), int (cc->pin_count ()), int (nn.size ()), nc)); } @@ -925,14 +956,6 @@ void NetlistSpiceReader::read_circuit (tl::Extractor &ex, const std::string &nc) mp_circuit->connect_pin (pin_id, net); } - // produce pins for the global nets - for (std::vector::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) { - db::Net *net = make_net (*gn); - size_t pin_id = gn - m_global_nets.begin () + nn.size (); - mp_circuit->rename_pin (pin_id, net->name ()); - mp_circuit->connect_pin (pin_id, net); - } - while (! at_end ()) { if (read_card ()) { break; diff --git a/src/db/db/dbNetlistSpiceReader.h b/src/db/db/dbNetlistSpiceReader.h index 088400258..59f65d802 100644 --- a/src/db/db/dbNetlistSpiceReader.h +++ b/src/db/db/dbNetlistSpiceReader.h @@ -124,6 +124,7 @@ public: private: db::Netlist *mp_netlist; db::Circuit *mp_circuit; + db::Circuit *mp_anonymous_top_circuit; std::auto_ptr mp_stream; tl::weak_ptr mp_delegate; std::vector > m_streams; @@ -157,6 +158,7 @@ private: db::Net *make_net (const std::string &name); void ensure_circuit (); bool subcircuit_captured (const std::string &nc_name); + void build_global_nets (); }; } diff --git a/src/db/unit_tests/dbNetlistReaderTests.cc b/src/db/unit_tests/dbNetlistReaderTests.cc index 75ff3bf80..12f0a97f6 100644 --- a/src/db/unit_tests/dbNetlistReaderTests.cc +++ b/src/db/unit_tests/dbNetlistReaderTests.cc @@ -443,3 +443,47 @@ TEST(12_IgnoreDuplicateGlobals) ); } +TEST(13_NoGlobalNetsIfNotUsed) +{ + db::Netlist nl; + + std::string path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nreader13.cir"); + + db::NetlistSpiceReader reader; + tl::InputStream is (path); + reader.read (is, nl); + + EXPECT_EQ (nl.to_string (), + "circuit .TOP ();\n" + " device RES $1 (A=VDD,B=NC) (R=1000,L=0,W=0,A=0,P=0);\n" + " subcircuit C10 '1' (VDD=VDD,GND=GND);\n" + "end;\n" + "circuit C10 (VDD=VDD,GND=GND);\n" + " subcircuit C1 '1' (VDD=VDD,GND=GND);\n" + " subcircuit C2 '2' ();\n" + " subcircuit C3 '3' (VDD=VDD,GND=GND);\n" + " subcircuit C4 '4' (VDD=VDD,GND=GND);\n" + "end;\n" + "circuit FILLER_CAP (VDD=VDD,GND=GND);\n" + " device NMOS '1' (S=GND,G=VDD,D=GND,B=GND) (L=10,W=10,AS=0,AD=0,PS=0,PD=0);\n" + "end;\n" + "circuit DUMMY ();\n" + " device NMOS '1' (S=A,G=A,D=A,B=B) (L=1,W=1,AS=0,AD=0,PS=0,PD=0);\n" + "end;\n" + "circuit C1 (VDD=VDD,GND=GND);\n" + " subcircuit FILLER_CAP '1' (VDD=VDD,GND=GND);\n" + " subcircuit DUMMY '2' ();\n" + "end;\n" + "circuit C2 ();\n" + " subcircuit DUMMY '1' ();\n" + "end;\n" + "circuit C3 (VDD=VDD,GND=GND);\n" + " device NMOS '1' (S=GND,G=VDD,D=GND,B=GND) (L=10,W=10,AS=0,AD=0,PS=0,PD=0);\n" + " subcircuit FILLER_CAP '1' (VDD=VDD,GND=GND);\n" + "end;\n" + "circuit C4 (VDD=VDD,GND=GND);\n" + " subcircuit C1 '3' (VDD=VDD,GND=GND);\n" + "end;\n" + ); +} + diff --git a/testdata/algo/nreader13.cir b/testdata/algo/nreader13.cir new file mode 100644 index 000000000..313ab64e5 --- /dev/null +++ b/testdata/algo/nreader13.cir @@ -0,0 +1,42 @@ + +.global vdd gnd + +X1 C10 +R$1 vdd nc 1k + +.subckt FILLER_CAP +M1 gnd vdd gnd gnd NMOS W=10u L=10u +.ends FILLER_CAP + +.subckt DUMMY +M1 a a a b NMOS W=1u L=1u +.ends DUMMY + +.subckt C10 +X1 C1 +X2 C2 +X3 C3 +X4 C4 +.ends C10 + +.subckt C4 +X3 C1 +.ends C4 + +.subckt C1 +* generates gnd and vdd +X1 FILLER_CAP +X2 DUMMY +.ends C1 + +.subckt C2 +* does not generate gnd or vdd +X1 DUMMY +.ends C2 + +.subckt C3 +* generates gnd and vdd too +X1 FILLER_CAP +M1 gnd vdd gnd gnd NMOS W=10u L=10u +.ends C3 + diff --git a/testdata/lvs/floating.lvsdb b/testdata/lvs/floating.lvsdb index 8dddf3ead..e57702118 100644 --- a/testdata/lvs/floating.lvsdb +++ b/testdata/lvs/floating.lvsdb @@ -266,14 +266,14 @@ reference( # Nets net(1 name(A)) net(2 name(Z)) - net(3 name(VDD)) - net(4 name(VSS)) + net(3 name(VSS)) + net(4 name(VDD)) # Outgoing pins and their connections to nets pin(1 name(A)) pin(2 name(Z)) - pin(3 name(VDD)) - pin(4 name(VSS)) + pin(4 name(VDD)) + pin(3 name(VSS)) # Devices and their connections device(1 NMOS @@ -286,8 +286,8 @@ reference( param(PD 0) terminal(S 2) terminal(G 1) - terminal(D 4) - terminal(B 4) + terminal(D 3) + terminal(B 3) ) device(2 PMOS name('1') @@ -299,8 +299,8 @@ reference( param(PD 0) terminal(S 2) terminal(G 1) - terminal(D 3) - terminal(B 3) + terminal(D 4) + terminal(B 4) ) ) @@ -343,32 +343,32 @@ reference( net(1 name(A)) net(2 name(C)) net(3 name(D)) - net(4 name(VDD)) - net(5 name(VSS)) - net(6 name(B)) - net(7 name(E)) + net(4 name(B)) + net(5 name(E)) + net(6 name(VDD)) + net(7 name(VSS)) # Outgoing pins and their connections to nets pin(1 name(A)) pin(2 name(C)) pin(3 name(D)) - pin(4 name(VDD)) - pin(5 name(VSS)) + pin(6 name(VDD)) + pin(7 name(VSS)) # Subcircuits and their connections circuit(1 DINV name('0') pin(0 1) pin(1 2) - pin(2 6) - pin(3 7) - pin(4 4) - pin(5 5) - ) - circuit(2 INVX1 name('1') - pin(0 7) - pin(1 3) pin(2 4) pin(3 5) + pin(4 6) + pin(5 7) + ) + circuit(2 INVX1 name('1') + pin(0 5) + pin(1 3) + pin(2 6) + pin(3 7) ) ) @@ -398,8 +398,8 @@ xref( xref( net(3 1 match) net(1 2 match) - net(2 3 match) - net(4 4 match) + net(2 4 match) + net(4 3 match) pin(2 0 match) pin(0 1 match) pin(1 2 match) @@ -411,11 +411,11 @@ xref( circuit(TOP TOP match xref( net(5 3 match) - net(1 7 match) - net(6 4 match) + net(1 5 match) + net(6 6 match) net(2 1 match) net(3 2 match) - net(4 5 match) + net(4 7 match) pin(() 2 match) pin(() 3 match) pin(0 0 match)