From 80fa7e47e23e06102844213eb632dcfd38d5a780 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 21 Feb 2023 00:49:23 +0100 Subject: [PATCH] WIP: tests pass --- src/db/db/dbNetlistSpiceReader.cc | 72 +++++++++++++++-------- src/db/unit_tests/dbNetlistReaderTests.cc | 50 +++++++++------- 2 files changed, 77 insertions(+), 45 deletions(-) diff --git a/src/db/db/dbNetlistSpiceReader.cc b/src/db/db/dbNetlistSpiceReader.cc index e59362086..7654ba9b0 100644 --- a/src/db/db/dbNetlistSpiceReader.cc +++ b/src/db/db/dbNetlistSpiceReader.cc @@ -294,6 +294,8 @@ double NetlistSpiceReaderDelegate::read_atomic_value (tl::Extractor &ex, const s throw tl::Exception (tl::sprintf (tl::to_string (tr ("Expected number of variable name here: '...%s'")), ex.get ())); } + return 0.0; + } } @@ -840,6 +842,7 @@ struct ParametersLessFunction if (fabs (ia->second - ib->second) > avg * db::epsilon) { return ia->second < ib->second; } + ++ia, ++ib; } return false; @@ -1003,6 +1006,7 @@ public: const std::string &file_path (int file_id) const; const SpiceCachedCircuit *cached_circuit (const std::string &name) const; + SpiceCachedCircuit *create_cached_circuit (const std::string &name); private: NetlistSpiceReader *mp_reader; @@ -1032,7 +1036,6 @@ private: void error (const std::string &msg); void warn (const std::string &msg); int file_id (const std::string &path); - SpiceCachedCircuit *create_cached_circuit (const std::string &name); }; SpiceCircuitDict::SpiceCircuitDict (NetlistSpiceReader *reader, Netlist *netlist, NetlistSpiceReaderDelegate *delegate) @@ -1323,6 +1326,8 @@ SpiceCircuitDict::ensure_circuit () // TODO: make top name configurable mp_circuit = new SpiceCachedCircuit (".TOP"); + m_cached_circuits.insert (std::make_pair (mp_circuit->name (), mp_circuit)); + mp_anonymous_top_level_circuit = mp_circuit; } @@ -1373,12 +1378,18 @@ public: SpiceNetlistBuilder (SpiceCircuitDict *dict, Netlist *netlist, NetlistSpiceReaderDelegate *delegate); + void set_strict (bool s) + { + m_strict = s; + } + void build (); private: - const SpiceCircuitDict *mp_dict; + SpiceCircuitDict *mp_dict; tl::weak_ptr mp_delegate; Netlist *mp_netlist; + bool m_strict; const SpiceCachedCircuit *mp_circuit; std::map > m_circuits; db::Circuit *mp_netlist_circuit; @@ -1402,7 +1413,7 @@ private: }; SpiceNetlistBuilder::SpiceNetlistBuilder (SpiceCircuitDict *dict, Netlist *netlist, NetlistSpiceReaderDelegate *delegate) - : mp_dict (dict), mp_delegate (delegate), mp_netlist (netlist) + : mp_dict (dict), mp_delegate (delegate), mp_netlist (netlist), m_strict (false) { mp_circuit = 0; mp_netlist_circuit = 0; @@ -1499,28 +1510,32 @@ make_circuit_name (const std::string &name, const std::map } res += p->first; res += "="; - if (p->second < 0.5e-12) { - res += tl::sprintf ("%.gF", p->second * 1e15); - } else if (p->second < 0.5e-9) { - res += tl::sprintf ("%.gP", p->second * 1e12); - } else if (p->second < 0.5e-6) { - res += tl::sprintf ("%.gN", p->second * 1e9); - } else if (p->second < 0.5e-3) { - res += tl::sprintf ("%.gU", p->second * 1e6); - } else if (p->second < 0.5) { - res += tl::sprintf ("%.gM", p->second * 1e3); - } else if (p->second < 0.5e3) { - res += tl::sprintf ("%.g", p->second); - } else if (p->second < 0.5e6) { - res += tl::sprintf ("%.gK", p->second * 1e-3); - } else if (p->second < 0.5e9) { - res += tl::sprintf ("%.gMEG", p->second * 1e-6); - } else if (p->second < 0.5e12) { - res += tl::sprintf ("%.gG", p->second * 1e-9); + double va = fabs (p->second); + if (va < 1e-15) { + res += tl::sprintf ("%g", p->second); + } else if (va < 0.1e-12) { + res += tl::sprintf ("%gF", p->second * 1e15); + } else if (va < 0.1e-9) { + res += tl::sprintf ("%gP", p->second * 1e12); + } else if (va < 0.1e-6) { + res += tl::sprintf ("%gN", p->second * 1e9); + } else if (va < 0.1e-3) { + res += tl::sprintf ("%gU", p->second * 1e6); + } else if (va< 0.1) { + res += tl::sprintf ("%gM", p->second * 1e3); + } else if (va < 0.1e3) { + res += tl::sprintf ("%g", p->second); + } else if (va < 0.1e6) { + res += tl::sprintf ("%gK", p->second * 1e-3); + } else if (va < 0.1e9) { + res += tl::sprintf ("%gMEG", p->second * 1e-6); + } else if (va < 0.1e12) { + res += tl::sprintf ("%gG", p->second * 1e-9); } else { - res += tl::sprintf ("%.g", p->second); + res += tl::sprintf ("%g", p->second); } } + res += ")"; return res; } @@ -1554,7 +1569,8 @@ SpiceNetlistBuilder::build_circuit (const SpiceCachedCircuit *cc, const paramete // produce the explicit pins for (auto i = mp_circuit->begin_pins (); i != mp_circuit->end_pins (); ++i) { - db::Net *net = make_net (*i); + std::string net_name = mp_delegate->translate_net_name (mp_netlist->normalize_name (*i)); + db::Net *net = make_net (net_name); // use the net name to name the pin (otherwise SPICE pins are always unnamed) size_t pin_id = i - mp_circuit->begin_pins (); if (! i->empty ()) { @@ -1674,7 +1690,15 @@ SpiceNetlistBuilder::process_element (tl::Extractor &ex, const std::string &pref const db::SpiceCachedCircuit *cc = mp_dict->cached_circuit (model); if (! cc) { - error (tl::sprintf (tl::to_string (tr ("Subcircuit '%s' not found in netlist")), model)); + if (m_strict) { + error (tl::sprintf (tl::to_string (tr ("Subcircuit '%s' not found in netlist")), model)); + } else { + db::SpiceCachedCircuit *cc_nc = mp_dict->create_cached_circuit (model); + cc = cc_nc; + std::vector pins; + pins.resize (nn.size ()); + cc_nc->set_pins (pins); + } } if (cc->pin_count () != nn.size ()) { diff --git a/src/db/unit_tests/dbNetlistReaderTests.cc b/src/db/unit_tests/dbNetlistReaderTests.cc index 4b1fbf70b..19197bf4d 100644 --- a/src/db/unit_tests/dbNetlistReaderTests.cc +++ b/src/db/unit_tests/dbNetlistReaderTests.cc @@ -185,15 +185,19 @@ TEST(5_CircuitParameters) EXPECT_EQ (nl.to_string (), "circuit SUBCKT ($1=$1,'A[5]<1>'='A[5]<1>','V42(%)'='V42(%)',Z=Z,GND=GND,GND$1=GND$1);\n" - " subcircuit HVPMOS D_$1 ($1='V42(%)',$2=$3,$3=Z,$4=$1);\n" - " subcircuit HVPMOS D_$2 ($1='V42(%)',$2='A[5]<1>',$3=$3,$4=$1);\n" - " subcircuit HVNMOS D_$3 ($1=GND,$2=$3,$3=GND,$4=GND$1);\n" - " subcircuit HVNMOS D_$4 ($1=GND,$2=$3,$3=Z,$4=GND$1);\n" - " subcircuit HVNMOS D_$5 ($1=GND,$2='A[5]<1>',$3=$3,$4=GND$1);\n" + " subcircuit 'HVPMOS(AD=0.18,AS=0.18,L=0.2,PD=2.16,PS=2.16,W=1)' D_$1 ($1='V42(%)',$2=$3,$3=Z,$4=$1);\n" + " subcircuit 'HVPMOS(AD=0.18,AS=0.18,L=0.2,PD=2.16,PS=2.16,W=1)' D_$2 ($1='V42(%)',$2='A[5]<1>',$3=$3,$4=$1);\n" + " subcircuit 'HVNMOS(AD=0,AS=0,L=1.13,PD=6,PS=6,W=2.12)' D_$3 ($1=GND,$2=$3,$3=GND,$4=GND$1);\n" + " subcircuit 'HVNMOS(AD=0.19,AS=0.19,L=0.4,PD=1.16,PS=1.16,W=0.4)' D_$4 ($1=GND,$2=$3,$3=Z,$4=GND$1);\n" + " subcircuit 'HVNMOS(AD=0.19,AS=0.19,L=0.4,PD=1.76,PS=1.76,W=0.4)' D_$5 ($1=GND,$2='A[5]<1>',$3=$3,$4=GND$1);\n" "end;\n" - "circuit HVPMOS ($1=(null),$2=(null),$3=(null),$4=(null));\n" + "circuit 'HVPMOS(AD=0.18,AS=0.18,L=0.2,PD=2.16,PS=2.16,W=1)' ($1=$0,$2=$0,$3=$0,$4=$0);\n" "end;\n" - "circuit HVNMOS ($1=(null),$2=(null),$3=(null),$4=(null));\n" + "circuit 'HVNMOS(AD=0,AS=0,L=1.13,PD=6,PS=6,W=2.12)' ($1=$0,$2=$0,$3=$0,$4=$0);\n" + "end;\n" + "circuit 'HVNMOS(AD=0.19,AS=0.19,L=0.4,PD=1.16,PS=1.16,W=0.4)' ($1=$0,$2=$0,$3=$0,$4=$0);\n" + "end;\n" + "circuit 'HVNMOS(AD=0.19,AS=0.19,L=0.4,PD=1.76,PS=1.76,W=0.4)' ($1=$0,$2=$0,$3=$0,$4=$0);\n" "end;\n" ); } @@ -262,6 +266,9 @@ TEST(6_ReaderWithDelegate) reader.read (is, nl); EXPECT_EQ (nl.to_string (), + "circuit .TOP ();\n" + " subcircuit SUBCKT SUBCKT ($1=IN,A=OUT,VDD=VDD,Z=Z,GND=VSS,GND$1=VSS);\n" + "end;\n" "circuit SUBCKT ($1=$1,A=A,VDD=VDD,Z=Z,GND=GND,GND$1=GND$1);\n" " device HVPMOS $1 (S=VDD,G=$3,D=Z,B=$1) (L=0.3,W=1.5,AS=0.27,AD=0.27,PS=3.24,PD=3.24);\n" " device HVPMOS $2 (S=VDD,G=A,D=$3,B=$1) (L=0.3,W=1.5,AS=0.27,AD=0.27,PS=3.24,PD=3.24);\n" @@ -270,9 +277,6 @@ TEST(6_ReaderWithDelegate) " device HVNMOS $5 (S=GND,G=A,D=$3,B=GND$1) (L=0.6,W=0.6,AS=0.285,AD=0.285,PS=2.64,PD=2.64);\n" " device RES $1 (A=A,B=Z) (R=100000,L=0,W=0,A=0,P=0);\n" "end;\n" - "circuit .TOP ();\n" - " subcircuit SUBCKT SUBCKT ($1=IN,A=OUT,VDD=VDD,Z=Z,GND=VSS,GND$1=VSS);\n" - "end;\n" ); } @@ -527,16 +531,16 @@ TEST(13_NoGlobalNetsIfNotUsed) " subcircuit C3 '3' (VDD=VDD,GND=GND);\n" " subcircuit C4 '4' (VDD=VDD,GND=GND);\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 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" @@ -578,15 +582,19 @@ TEST(15_ContinuationWithBlanks) EXPECT_EQ (nl.to_string (), "circuit SUBCKT ($1=$1,'A[5]<1>'='A[5]<1>','V42(%)'='V42(%)',Z=Z,GND=GND,GND$1=GND$1);\n" - " subcircuit HVPMOS D_$1 ($1='V42(%)',$2=$3,$3=Z,$4=$1);\n" - " subcircuit HVPMOS D_$2 ($1='V42(%)',$2='A[5]<1>',$3=$3,$4=$1);\n" - " subcircuit HVNMOS D_$3 ($1=GND,$2=$3,$3=GND,$4=GND$1);\n" - " subcircuit HVNMOS D_$4 ($1=GND,$2=$3,$3=Z,$4=GND$1);\n" - " subcircuit HVNMOS D_$5 ($1=GND,$2='A[5]<1>',$3=$3,$4=GND$1);\n" + " subcircuit 'HVPMOS(AD=0.18,AS=0.18,L=0.2,PD=2.16,PS=2.16,W=1)' D_$1 ($1='V42(%)',$2=$3,$3=Z,$4=$1);\n" + " subcircuit 'HVPMOS(AD=0.18,AS=0.18,L=0.2,PD=2.16,PS=2.16,W=1)' D_$2 ($1='V42(%)',$2='A[5]<1>',$3=$3,$4=$1);\n" + " subcircuit 'HVNMOS(AD=0,AS=0,L=1.13,PD=6,PS=6,W=2.12)' D_$3 ($1=GND,$2=$3,$3=GND,$4=GND$1);\n" + " subcircuit 'HVNMOS(AD=0.19,AS=0.19,L=0.4,PD=1.16,PS=1.16,W=0.4)' D_$4 ($1=GND,$2=$3,$3=Z,$4=GND$1);\n" + " subcircuit 'HVNMOS(AD=0.19,AS=0.19,L=0.4,PD=1.76,PS=1.76,W=0.4)' D_$5 ($1=GND,$2='A[5]<1>',$3=$3,$4=GND$1);\n" "end;\n" - "circuit HVPMOS ($1=(null),$2=(null),$3=(null),$4=(null));\n" + "circuit 'HVPMOS(AD=0.18,AS=0.18,L=0.2,PD=2.16,PS=2.16,W=1)' ($1=$0,$2=$0,$3=$0,$4=$0);\n" "end;\n" - "circuit HVNMOS ($1=(null),$2=(null),$3=(null),$4=(null));\n" + "circuit 'HVNMOS(AD=0,AS=0,L=1.13,PD=6,PS=6,W=2.12)' ($1=$0,$2=$0,$3=$0,$4=$0);\n" + "end;\n" + "circuit 'HVNMOS(AD=0.19,AS=0.19,L=0.4,PD=1.16,PS=1.16,W=0.4)' ($1=$0,$2=$0,$3=$0,$4=$0);\n" + "end;\n" + "circuit 'HVNMOS(AD=0.19,AS=0.19,L=0.4,PD=1.76,PS=1.76,W=0.4)' ($1=$0,$2=$0,$3=$0,$4=$0);\n" "end;\n" ); }