From 93a072903cd98faba480ec34d8e56cfcc6209ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6fferlein?= Date: Sun, 26 Apr 2020 16:53:50 +0200 Subject: [PATCH 1/2] Fixed #539 (internal error on circuit flatten) (#542) Previously, circuits which connected two pins through a net could not be flattened. This capability now has been added. --- src/db/db/dbCircuit.cc | 20 ++++-- src/db/unit_tests/dbNetlistTests.cc | 96 +++++++++++++++++++++++++++-- 2 files changed, 107 insertions(+), 9 deletions(-) diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc index d0fea79ee..a2d5036bb 100644 --- a/src/db/db/dbCircuit.cc +++ b/src/db/db/dbCircuit.cc @@ -344,6 +344,10 @@ void Circuit::remove_net (Net *net) void Circuit::join_nets (Net *net, Net *with) { + if (net == with || ! with) { + return; + } + while (with->begin_terminals () != with->end_terminals ()) { db::Device *device = const_cast (with->begin_terminals ()->device ()); device->connect_terminal (with->begin_terminals ()->terminal_id (), net); @@ -426,15 +430,21 @@ void Circuit::flatten_subcircuit (SubCircuit *subcircuit) for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { - // TODO: cannot join pins through subcircuits currently - tl_assert (n->pin_count () <= 1); - db::Net *outside_net = 0; if (n->pin_count () > 0) { - size_t pin_id = n->begin_pins ()->pin_id (); - outside_net = subcircuit->net_for_pin (pin_id); + for (db::Net::const_pin_iterator p = n->begin_pins (); p != n->end_pins (); ++p) { + + size_t pin_id = p->pin_id (); + + if (outside_net) { + join_nets (outside_net, subcircuit->net_for_pin (pin_id)); + } else { + outside_net = subcircuit->net_for_pin (pin_id); + } + + } } else { diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index 9f66d06f0..e3732ded5 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -1337,9 +1337,97 @@ TEST(21_FlattenSubCircuit2) " device NMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" "end;\n" ); + + } -TEST(22_BlankCircuit) +TEST(22_FlattenSubCircuitPinsJoinNets) +{ + db::Netlist nl; + + db::DeviceClass *dc; + + dc = new db::DeviceClassMOS3Transistor (); + dc->set_name ("NMOS"); + nl.add_device_class (dc); + + dc = new db::DeviceClassMOS3Transistor (); + dc->set_name ("PMOS"); + nl.add_device_class (dc); + + nl.from_string ( + "circuit RINGO (IN=IN,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" + "circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);\n" + " subcircuit PTRANS SC1 ($1=$5,$2=$2,$3=IN);\n" + " subcircuit NTRANS SC2 ($1=$4,$2=$2,$3=IN);\n" + " subcircuit PTRANS SC3 ($1=$5,$2=OUT,$3=$2);\n" + " subcircuit NTRANS SC4 ($1=$4,$2=OUT,$3=$2);\n" + "end;\n" + "circuit PTRANS ($1=$1,$2=$2,$3=$1);\n" + " device PMOS $1 (S=$1,D=$2,G=$1) (L=0.25,W=0.95);\n" + "end;\n" + "circuit NTRANS ($1=$1,$2=$2,$3=$2);\n" + " device NMOS $1 (S=$1,D=$2,G=$2) (L=0.25,W=0.95);\n" + "end;\n" + ); + + db::Netlist nl2; + + nl2 = nl; + nl2.flatten_circuit (nl2.circuit_by_name ("PTRANS")); + + EXPECT_EQ (nl2.to_string (), + "circuit RINGO (IN=IN,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" + "circuit INV2 (IN=$5,$2=$5,OUT=OUT,$4=$4,$5=$5);\n" + " device PMOS $1 (S=$5,G=$5,D=$5) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device PMOS $2 (S=$5,G=$5,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " subcircuit NTRANS SC2 ($1=$4,$2=$5,$3=$5);\n" + " subcircuit NTRANS SC4 ($1=$4,$2=OUT,$3=$5);\n" + "end;\n" + "circuit NTRANS ($1=$1,$2=$2,$3=$2);\n" + " device NMOS $1 (S=$1,G=$2,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + "end;\n" + ); + + nl2.flatten_circuit (nl2.circuit_by_name ("NTRANS")); + + EXPECT_EQ (nl2.to_string (), + "circuit RINGO (IN=IN,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" + "circuit INV2 (IN=OUT,$2=OUT,OUT=OUT,$4=$4,$5=OUT);\n" + " device PMOS $1 (S=OUT,G=OUT,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device PMOS $2 (S=OUT,G=OUT,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device NMOS $3 (S=$4,G=OUT,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device NMOS $4 (S=$4,G=OUT,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + "end;\n" + ); + + nl2.flatten_circuit (nl2.circuit_by_name ("INV2")); + + EXPECT_EQ (nl2.to_string (), + "circuit RINGO (IN=IN,OSC=OSC,VSS=VSS,VDD=OSC);\n" + " device PMOS $1 (S=OSC,G=OSC,D=OSC) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device PMOS $2 (S=OSC,G=OSC,D=OSC) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device NMOS $3 (S=VSS,G=OSC,D=OSC) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device NMOS $4 (S=VSS,G=OSC,D=OSC) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device PMOS $5 (S=OSC,G=OSC,D=OSC) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device PMOS $6 (S=OSC,G=OSC,D=OSC) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device NMOS $7 (S=VSS,G=OSC,D=OSC) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device NMOS $8 (S=VSS,G=OSC,D=OSC) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + "end;\n" + ); + +} + +TEST(23_BlankCircuit) { db::Netlist nl; @@ -1439,7 +1527,7 @@ TEST(22_BlankCircuit) ); } -TEST(23_NetlistObject) +TEST(24_NetlistObject) { db::NetlistObject nlo; nlo.set_property (1, "hello"); @@ -1526,7 +1614,7 @@ TEST(23_NetlistObject) EXPECT_EQ (pin3.property (1).to_string (), "hello"); } -TEST(24_JoinNets) +TEST(25_JoinNets) { db::Netlist nl; db::Circuit *c; @@ -1575,7 +1663,7 @@ TEST(24_JoinNets) ); } -TEST(25_JoinNets) +TEST(26_JoinNets) { db::Netlist nl; db::Circuit *c; From 9b0362d03ddbab5a8169236a4998c4820382a14c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6fferlein?= Date: Sun, 26 Apr 2020 16:54:13 +0200 Subject: [PATCH 2/2] Fixed #544 (ignore duplicate global nets in SPICE reader) (#545) --- src/db/db/dbNetlistSpiceReader.cc | 5 ++++- src/db/db/dbNetlistSpiceReader.h | 1 + src/db/unit_tests/dbNetlistReaderTests.cc | 21 +++++++++++++++++++++ testdata/algo/nreader12.cir | 14 ++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 testdata/algo/nreader12.cir diff --git a/src/db/db/dbNetlistSpiceReader.cc b/src/db/db/dbNetlistSpiceReader.cc index af72199e5..269a85bb5 100644 --- a/src/db/db/dbNetlistSpiceReader.cc +++ b/src/db/db/dbNetlistSpiceReader.cc @@ -419,7 +419,10 @@ bool NetlistSpiceReader::read_card () while (! ex.at_end ()) { std::string n = read_name (ex); - m_global_nets.push_back (n); + if (m_global_net_names.find (n) == m_global_net_names.end ()) { + m_global_nets.push_back (n); + m_global_net_names.insert (n); + } } } else if (ex.test_without_case ("subckt")) { diff --git a/src/db/db/dbNetlistSpiceReader.h b/src/db/db/dbNetlistSpiceReader.h index fd1de5e26..088400258 100644 --- a/src/db/db/dbNetlistSpiceReader.h +++ b/src/db/db/dbNetlistSpiceReader.h @@ -131,6 +131,7 @@ private: std::string m_stored_line; std::map m_captured; std::vector m_global_nets; + std::set m_global_net_names; std::set m_circuits_read; void push_stream (const std::string &path); diff --git a/src/db/unit_tests/dbNetlistReaderTests.cc b/src/db/unit_tests/dbNetlistReaderTests.cc index 8c6f29de0..75ff3bf80 100644 --- a/src/db/unit_tests/dbNetlistReaderTests.cc +++ b/src/db/unit_tests/dbNetlistReaderTests.cc @@ -422,3 +422,24 @@ TEST(11_ErrorOnCircuitRedefinition) EXPECT_EQ (tl::replaced (msg, path, "?"), "Redefinition of circuit SUBCKT in ?, line 20"); } +TEST(12_IgnoreDuplicateGlobals) +{ + db::Netlist nl; + + std::string path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nreader12.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=GND) (R=1000,L=0,W=0,A=0,P=0);\n" + " subcircuit FILLER_CAP '0' (VDD=VDD,GND=GND);\n" + "end;\n" + "circuit FILLER_CAP (VDD=VDD,GND=GND);\n" + " device NMOS '0' (S=GND,G=VDD,D=GND,B=GND) (L=10,W=10,AS=0,AD=0,PS=0,PD=0);\n" + "end;\n" + ); +} + diff --git a/testdata/algo/nreader12.cir b/testdata/algo/nreader12.cir new file mode 100644 index 000000000..86a72691d --- /dev/null +++ b/testdata/algo/nreader12.cir @@ -0,0 +1,14 @@ + +.global vdd gnd + +X0 FILLER_CAP +R$1 vdd gnd 1k + +* should be ignored: +.global vdd +.global gnd + +.subckt FILLER_CAP +M0 gnd vdd gnd gnd NMOS W=10u L=10u +.ends FILLER_CAP +