From 14d9689498332ccdf3ba8915d8f7b04205b4d4b8 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 22 Jul 2019 23:02:31 +0200 Subject: [PATCH] Added .global to Spice reader. --- src/db/db/dbNetlistSpiceReader.cc | 49 +++++++++++++++++++++-- src/db/db/dbNetlistSpiceReader.h | 1 + src/db/unit_tests/dbNetlistReaderTests.cc | 39 ++++++++++++++++++ testdata/algo/nreader7.cir | 31 ++++++++++++++ 4 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 testdata/algo/nreader7.cir diff --git a/src/db/db/dbNetlistSpiceReader.cc b/src/db/db/dbNetlistSpiceReader.cc index 7f7c4235c..50218d7d2 100644 --- a/src/db/db/dbNetlistSpiceReader.cc +++ b/src/db/db/dbNetlistSpiceReader.cc @@ -195,6 +195,7 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist) mp_netlist = &netlist; mp_circuit = 0; mp_nets_by_name.reset (0); + m_global_nets.clear (); try { @@ -343,6 +344,11 @@ bool NetlistSpiceReader::read_card () // ignore model statements + } else if (ex.test_without_case ("global")) { + + std::string n = read_name (ex); + m_global_nets.push_back (n); + } else if (ex.test_without_case ("subckt")) { std::string nc = read_name (ex); @@ -497,6 +503,10 @@ void NetlistSpiceReader::ensure_circuit () mp_circuit->set_name (".TOP"); 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); + } + } } @@ -737,16 +747,25 @@ void NetlistSpiceReader::read_subcircuit (const std::string &sc_name, const std: db::Circuit *cc = mp_netlist->circuit_by_name (nc_name); if (! cc) { + cc = new db::Circuit (); mp_netlist->add_circuit (cc); cc->set_name (nc_name); + + // we'll make the names later ... 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 ()) { + + if (cc->pin_count () != nets.size () + m_global_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 ()))); } + } db::SubCircuit *sc = new db::SubCircuit (cc, sc_name); @@ -755,6 +774,11 @@ 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*/) @@ -789,16 +813,23 @@ void NetlistSpiceReader::read_circuit (tl::Extractor &ex, const std::string &nc) db::Circuit *cc = mp_netlist->circuit_by_name (nc); if (! cc) { + cc = new db::Circuit (); mp_netlist->add_circuit (cc); cc->set_name (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 ()) { + + if (cc->pin_count () != nn.size () + m_global_nets.size ()) { error (tl::sprintf (tl::to_string (tr ("Pin count mismatch between implicit (through call) and explicit circuit definition: %d expected, got %d")), int (cc->pin_count ()), int (nn.size ()))); } + } std::auto_ptr > n2n (mp_nets_by_name.release ()); @@ -806,13 +837,23 @@ void NetlistSpiceReader::read_circuit (tl::Extractor &ex, const std::string &nc) std::swap (cc, mp_circuit); + // produce the explicit pins for (std::vector::const_iterator i = nn.begin (); i != nn.end (); ++i) { db::Net *net = make_net (*i); // use the net name to name the pin (otherwise SPICE pins are always unnamed) + size_t pin_id = i - nn.begin (); if (! i->empty ()) { - mp_circuit->rename_pin (i - nn.begin (), net->name ()); + mp_circuit->rename_pin (pin_id, net->name ()); } - mp_circuit->connect_pin (i - nn.begin (), net); + 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 ()) { diff --git a/src/db/db/dbNetlistSpiceReader.h b/src/db/db/dbNetlistSpiceReader.h index 056b2b2d4..95eca62e2 100644 --- a/src/db/db/dbNetlistSpiceReader.h +++ b/src/db/db/dbNetlistSpiceReader.h @@ -128,6 +128,7 @@ private: std::auto_ptr > mp_nets_by_name; std::string m_stored_line; std::map m_captured; + std::vector m_global_nets; void push_stream (const std::string &path); void pop_stream (); diff --git a/src/db/unit_tests/dbNetlistReaderTests.cc b/src/db/unit_tests/dbNetlistReaderTests.cc index 8683d27d6..c39e477a6 100644 --- a/src/db/unit_tests/dbNetlistReaderTests.cc +++ b/src/db/unit_tests/dbNetlistReaderTests.cc @@ -255,3 +255,42 @@ TEST(6_ReaderWithDelegate) "end;\n" ); } + +TEST(7_GlobalNets) +{ + db::Netlist nl; + + std::string path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nreader7.cir"); + + MyNetlistReaderDelegate delegate; + db::NetlistSpiceReader reader (&delegate); + tl::InputStream is (path); + reader.read (is, nl); + + EXPECT_EQ (nl.to_string (), + "circuit RINGO (FB=FB,OUT=OUT,ENABLE=ENABLE,VDD=VDD,VSS=VSS);\n" + " subcircuit ND2X1 $1 (OUT='1',B=FB,A=ENABLE,VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $2 (OUT='2',IN='1',VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $3 (OUT='3',IN='2',VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $4 (OUT='4',IN='3',VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $5 (OUT='5',IN='4',VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $6 (OUT='6',IN='5',VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $7 (OUT='7',IN='6',VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $8 (OUT='8',IN='7',VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $9 (OUT='9',IN='8',VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $10 (OUT='10',IN='9',VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $11 (OUT=FB,IN='10',VDD=VDD,VSS=VSS);\n" + " subcircuit INVX1 $12 (OUT=OUT,IN=FB,VDD=VDD,VSS=VSS);\n" + "end;\n" + "circuit ND2X1 (OUT=OUT,B=B,A=A,VDD=VDD,VSS=VSS);\n" + " device MLVPMOS $1 (S=OUT,G=A,D=VDD,B=VDD) (L=0.25,W=1.5,AS=0.6375,AD=0.3375,PS=3.85,PD=1.95);\n" + " device MLVPMOS $2 (S=VDD,G=B,D=OUT,B=VDD) (L=0.25,W=1.5,AS=0.3375,AD=0.6375,PS=1.95,PD=3.85);\n" + " device MLVNMOS $3 (S=VSS,G=A,D=INT,B=VSS) (L=0.25,W=0.95,AS=0.40375,AD=0.21375,PS=2.75,PD=1.4);\n" + " device MLVNMOS $4 (S=INT,G=B,D=OUT,B=VSS) (L=0.25,W=0.95,AS=0.21375,AD=0.40375,PS=1.4,PD=2.75);\n" + "end;\n" + "circuit INVX1 (OUT=OUT,IN=IN,VDD=VDD,VSS=VSS);\n" + " device MLVPMOS $1 (S=VDD,G=IN,D=OUT,B=VDD) (L=0.25,W=1.5,AS=0.6375,AD=0.6375,PS=3.85,PD=3.85);\n" + " device MLVNMOS $2 (S=VSS,G=IN,D=OUT,B=VSS) (L=0.25,W=0.95,AS=0.40375,AD=0.40375,PS=2.75,PD=2.75);\n" + "end;\n" + ); +} diff --git a/testdata/algo/nreader7.cir b/testdata/algo/nreader7.cir new file mode 100644 index 000000000..210af361c --- /dev/null +++ b/testdata/algo/nreader7.cir @@ -0,0 +1,31 @@ +* RINGO netlist with global nets + +.GLOBAL VDD +.GLOBAL VSS + +.SUBCKT RINGO FB OUT ENABLE +X$1 1 FB ENABLE ND2X1 +X$2 2 1 INVX1 +X$3 3 2 INVX1 +X$4 4 3 INVX1 +X$5 5 4 INVX1 +X$6 6 5 INVX1 +X$7 7 6 INVX1 +X$8 8 7 INVX1 +X$9 9 8 INVX1 +X$10 10 9 INVX1 +X$11 FB 10 INVX1 +X$12 OUT FB INVX1 +.ENDS RINGO + +.SUBCKT ND2X1 OUT B A +M$1 OUT A VDD VDD MLVPMOS L=0.25U W=1.5U AS=0.6375P AD=0.3375P PS=3.85U PD=1.95U +M$2 VDD B OUT VDD MLVPMOS L=0.25U W=1.5U AS=0.3375P AD=0.6375P PS=1.95U PD=3.85U +M$3 VSS A INT VSS MLVNMOS L=0.25U W=0.95U AS=0.40375P AD=0.21375P PS=2.75U PD=1.4U +M$4 INT B OUT VSS MLVNMOS L=0.25U W=0.95U AS=0.21375P AD=0.40375P PS=1.4U PD=2.75U +.ENDS ND2X1 + +.SUBCKT INVX1 OUT IN +M$1 VDD IN OUT VDD MLVPMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U +M$2 VSS IN OUT VSS MLVNMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U +.ENDS INVX1