From aa28aa807a5999bdf38fc94269efcc12821b7fba Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 23 Nov 2019 22:04:25 +0100 Subject: [PATCH] Unit tests fixed and a bugfix in the netlist compare One unit test was failing because the netlist compare did not properly consider dropped pins: * A severe bug ("g1" should be "g2") * Incomplete detection of dropped pins upwards in the hierarchy The general pin and net mapping scheme has been enhanced so that net mapping to "0" is valid (this will happen in case of dropped pins) and this condition is used to detect pins without match requirement. --- src/db/db/dbNetlistCompare.cc | 113 +++++-- src/db/db/dbNetlistCompare.h | 2 +- src/db/unit_tests/dbNetlistCompareTests.cc | 361 ++++++++++++++++++++- src/db/unit_tests/dbNetlistTests.cc | 2 +- 4 files changed, 444 insertions(+), 34 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index a95f6fba2..55f6091de 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -2951,14 +2951,34 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, // Report missing net assignment for (db::NetGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) { - if (! i->has_other () && mp_logger) { - mp_logger->net_mismatch (i->net (), 0); + if (! i->has_other ()) { + if (mp_logger) { + if (good) { + mp_logger->match_nets (i->net (), 0); + } else { + mp_logger->net_mismatch (i->net (), 0); + } + } + if (good) { + // in the "good" case, match the nets against 0 + g1.identify (g1.node_index_for_net (i->net ()), 0); + } } } for (db::NetGraph::node_iterator i = g2.begin (); i != g2.end (); ++i) { - if (! i->has_other () && mp_logger) { - mp_logger->net_mismatch (0, i->net ()); + if (! i->has_other ()) { + if (mp_logger) { + if (good) { + mp_logger->match_nets (0, i->net ()); + } else { + mp_logger->net_mismatch (0, i->net ()); + } + } + if (good) { + // in the "good" case, match the nets against 0 + g2.identify (g2.node_index_for_net (i->net ()), 0); + } } } @@ -2969,22 +2989,33 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, return good; } -void -NetlistComparer::handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1, const db::Circuit *c2, const db::Pin *pin2, bool &good, bool &pin_mismatch) const +bool +NetlistComparer::handle_pin_mismatch (const db::NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const db::NetGraph &g2, const db::Circuit *c2, const db::Pin *pin2) const { const db::Circuit *c = pin1 ? c1 : c2; const db::Pin *pin = pin1 ? pin1 : pin2; + const db::NetGraph *graph = pin1 ? &g1 : &g2; + const db::Net *net = c->net_for_pin (pin->id ()); - // If the pin isn't connected internally inside the circuit we can ignore it - if (c->net_for_pin (pin->id ()) && c->net_for_pin (pin->id ())->is_passive ()) { - if (mp_logger) { - mp_logger->match_pins (pin1, pin2); + // Nets which are paired with "null" trigger this condition: + if (net) { + const db::NetGraphNode &n = graph->node (graph->node_index_for_net (net)); + if (n.has_other ()) { + if (mp_logger) { + mp_logger->match_pins (pin1, pin2); + } + return true; } - return; } // Determine whether the pin in question is used - only in this case we will report an error. // Otherwise, the report will be "match" against 0. + // "used" follows a heuristic criterion derived from the subcircuits which make use of this circuit: + // if one of these connects the pin to a net with either connections upwards, other subcircuits or + // devices, the pin is regarded "used". + // TODO: it would be better probably to have a global concept of "used pins" which considers all + // devices and propagates their presence as "used" property upwards, then downwards to the subcircuit + // pins. bool is_not_connected = true; for (db::Circuit::const_refs_iterator r = c->begin_refs (); r != c->end_refs () && is_not_connected; ++r) { @@ -2999,12 +3030,12 @@ NetlistComparer::handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1 if (mp_logger) { mp_logger->match_pins (pin1, pin2); } + return true; } else { if (mp_logger) { mp_logger->pin_mismatch (pin1, pin2); } - good = false; - pin_mismatch = true; + return false; } } @@ -3042,18 +3073,21 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g } } - std::vector abstract_pins; - std::multimap net2pin; + std::vector abstract_pins2; + std::multimap net2pin2; for (db::Circuit::const_pin_iterator p = c2->begin_pins (); p != c2->end_pins (); ++p) { const db::Net *net = c2->net_for_pin (p->id ()); if (net) { - net2pin.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ())); + net2pin2.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ())); } else if (abstract_pin_name_mapping.find (p.operator-> ()) == abstract_pin_name_mapping.end ()) { - abstract_pins.push_back (p.operator-> ()); + abstract_pins2.push_back (p.operator-> ()); } } - std::vector::iterator next_abstract = abstract_pins.begin (); + // collect missing assignment for circuit 1 + std::multimap net2pin1; + + std::vector::iterator next_abstract = abstract_pins2.begin (); CircuitMapper &c12_pin_mapping = c12_circuit_and_pin_mapping [c1]; c12_pin_mapping.set_other (c2); @@ -3078,7 +3112,7 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g c12_pin_mapping.map_pin (p->id (), fp->second->id ()); c22_pin_mapping.map_pin (fp->second->id (), p->id ()); - } else if (next_abstract != abstract_pins.end ()) { + } else if (next_abstract != abstract_pins2.end ()) { // assign an abstract pin - this is a dummy assignment which is mitigated // by declaring the pins equivalent in derive_pin_equivalence @@ -3093,7 +3127,10 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g } else { // otherwise this is an error for subcircuits or worth a report for top-level circuits - handle_pin_mismatch (c1, p.operator-> (), c2, 0, good, pin_mismatch); + if (! handle_pin_mismatch (g1, c1, p.operator-> (), g2, c2, 0)) { + good = false; + pin_mismatch = true; + } } @@ -3104,14 +3141,15 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g const db::NetGraphNode &n = *(g1.begin () + g1.node_index_for_net (net)); if (! n.has_other ()) { - handle_pin_mismatch (c1, p.operator-> (), c2, 0, good, pin_mismatch); + // remember and handle later when we know which pins are not mapped + net2pin1.insert (std::make_pair (g1.node_index_for_net (net), p.operator-> ())); continue; } - std::multimap::iterator np = net2pin.find (n.other_net_index ()); + std::multimap::iterator np = net2pin2.find (n.other_net_index ()); for (db::Net::const_pin_iterator pi = net->begin_pins (); pi != net->end_pins (); ++pi) { - if (np != net2pin.end () && np->first == n.other_net_index ()) { + if (np != net2pin2.end () && np->first == n.other_net_index ()) { if (mp_logger) { mp_logger->match_pins (pi->pin (), np->second); @@ -3122,11 +3160,12 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g std::multimap::iterator np_delete = np; ++np; - net2pin.erase (np_delete); + net2pin2.erase (np_delete); } else { - handle_pin_mismatch (c1, pi->pin (), c2, 0, good, pin_mismatch); + // remember and handle later when we know which pins are not mapped + net2pin1.insert (std::make_pair (g1.node_index_for_net (net), p.operator-> ())); } @@ -3134,16 +3173,28 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g } - for (std::multimap::iterator np = net2pin.begin (); np != net2pin.end (); ++np) { - handle_pin_mismatch (c1, 0, c2, np->second, good, pin_mismatch); + for (std::multimap::iterator np = net2pin1.begin (); np != net2pin1.end (); ++np) { + if (! handle_pin_mismatch (g1, c1, np->second, g2, c2, 0)) { + good = false; + pin_mismatch = true; + } + } + + for (std::multimap::iterator np = net2pin2.begin (); np != net2pin2.end (); ++np) { + if (! handle_pin_mismatch (g1, c1, 0, g2, c2, np->second)) { + good = false; + pin_mismatch = true; + } } // abstract pins must match. - while (next_abstract != abstract_pins.end ()) { - handle_pin_mismatch (c1, 0, c2, *next_abstract, good, pin_mismatch); + while (next_abstract != abstract_pins2.end ()) { + if (! handle_pin_mismatch (g1, c1, 0, g2, c2, *next_abstract)) { + good = false; + pin_mismatch = true; + } ++next_abstract; } - } void @@ -3384,7 +3435,7 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG bool mapped = true; for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { - if (! g1.begin () [i->second].has_other ()) { + if (! g2.begin () [i->second].has_other ()) { mapped = false; } else { i->second = g2.begin () [i->second].other_net_index (); diff --git a/src/db/db/dbNetlistCompare.h b/src/db/db/dbNetlistCompare.h index bcb6b9f56..f1a7b2ff6 100644 --- a/src/db/db/dbNetlistCompare.h +++ b/src/db/db/dbNetlistCompare.h @@ -314,7 +314,7 @@ protected: void do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, bool &pin_mismatch, bool &good) const; void do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, DeviceCategorizer &device_categorizer, bool &good) const; void do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const db::CircuitPinMapper &circuit_pin_mapper, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, bool &good) const; - void handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1, const db::Circuit *c2, const db::Pin *p2, bool &good, bool &pin_mismatch) const; + bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const; mutable NetlistCompareLogger *mp_logger; std::map, std::vector > > m_same_nets; diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 820b61b1f..2a4ae00d5 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -2055,11 +2055,11 @@ TEST(14_Subcircuit2NandMismatchNoSwap) "net_mismatch INT IN1\n" "net_mismatch IN1 INT\n" "net_mismatch IN2 IN2\n" - "match_pins $0 (null)\n" "match_pins $1 $1\n" "match_pins $2 $2\n" "match_pins $3 $3\n" "match_pins $4 $4\n" + "match_pins $0 (null)\n" "match_pins (null) $0\n" "match_subcircuits $2 $1\n" "subcircuit_mismatch $1 $2\n" @@ -3366,3 +3366,362 @@ TEST(21_BusLikeAmbiguousConnections) EXPECT_EQ (good, true); } +TEST(22_NodesRemoved) +{ + const char *nls1 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n" + " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n" + " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n" + " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n" + " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" + "end;\n" + "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" + " subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" + " subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" + "end;\n" + "circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + const char *nls2 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" + " subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" + " subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n" + " subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n" + " subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n" + "end;\n" + "circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n" + " subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);\n" + " subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);\n" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + db::Netlist nl1, nl2; + prep_nl (nl1, nls1); + prep_nl (nl2, nls2); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + + bool good = comp.compare (&nl1, &nl2); + + std::string txt = logger.text (); + + EXPECT_EQ (txt, + "begin_circuit INV2 INV2\n" + "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets $3 $3\n" + "match_nets IN IN\n" + "match_nets VSS VSS\n" + "match_nets (null) $1\n" + "match_nets (null) BULK\n" + "match_pins IN IN\n" + "match_pins $1 $2\n" + "match_pins OUT OUT\n" + "match_pins VSS VSS\n" + "match_pins VDD VDD\n" + "match_pins (null) $0\n" + "match_pins (null) BULK\n" + "match_devices $1 $1\n" + "match_devices $2 $2\n" + "match_devices $3 $3\n" + "match_devices $4 $4\n" + "end_circuit INV2 INV2 MATCH\n" + "begin_circuit INV2PAIR INV2PAIR\n" + "match_nets $I2 $I2\n" + "match_nets $I5 $I6\n" + "match_nets $I4 $I5\n" + "match_nets $I6 $I4\n" + "match_nets $I3 $I3\n" + "match_nets $I7 $I7\n" + "match_nets $I8 $I8\n" + "match_nets (null) BULK\n" + "match_nets (null) $I1\n" + "match_pins $0 $1\n" + "match_pins $1 $2\n" + "match_pins $2 $3\n" + "match_pins $3 $4\n" + "match_pins $4 $5\n" + "match_pins (null) BULK\n" + "match_pins (null) $6\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "end_circuit INV2PAIR INV2PAIR MATCH\n" + "begin_circuit RINGO RINGO\n" + "match_nets OSC OSC\n" + "match_nets $I7 $I7\n" + "match_nets $I6 $I6\n" + "match_nets $I5 $I5\n" + "match_nets $I21 $I13\n" + "match_nets FB FB\n" + "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets $I22 $I22\n" + "match_nets $I23 $I23\n" + "match_nets $I24 $I24\n" + "match_nets $I25 $I25\n" + "match_pins FB FB\n" + "match_pins OSC OSC\n" + "match_pins VDD VDD\n" + "match_pins VSS VSS\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "match_subcircuits $3 $3\n" + "match_subcircuits $4 $4\n" + "match_subcircuits $5 $5\n" + "end_circuit RINGO RINGO MATCH" + ); + EXPECT_EQ (good, true); +} + +TEST(23_NodesRemovedWithError) +{ + const char *nls1 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n" + " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n" + " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n" + " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n" + " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" + "end;\n" + "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" + // NOTE: $1 pin should not be connected to different nets, although it's not functional + " subcircuit INV2 $1 ($1=$3,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" + " subcircuit INV2 $2 ($1=$6,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + const char *nls2 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" + " subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" + " subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n" + " subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n" + " subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n" + "end;\n" + "circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n" + " subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);\n" + " subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);\n" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + db::Netlist nl1, nl2; + prep_nl (nl1, nls1); + prep_nl (nl2, nls2); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + + bool good = comp.compare (&nl1, &nl2); + + std::string txt = logger.text (); + + EXPECT_EQ (txt, + "begin_circuit INV2 INV2\n" + "match_nets $1 $1\n" + "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets $3 $3\n" + "match_nets IN IN\n" + "match_nets VSS VSS\n" + "match_nets (null) BULK\n" + "match_pins $0 $0\n" + "match_pins IN IN\n" + "match_pins $2 $2\n" + "match_pins OUT OUT\n" + "match_pins VSS VSS\n" + "match_pins VDD VDD\n" + "match_pins (null) BULK\n" + "match_devices $1 $1\n" + "match_devices $2 $2\n" + "match_devices $3 $3\n" + "match_devices $4 $4\n" + "end_circuit INV2 INV2 MATCH\n" + "begin_circuit INV2PAIR INV2PAIR\n" + "match_nets $I2 $I2\n" + "match_nets $I5 $I6\n" + "match_nets $I4 $I5\n" + "match_nets $I6 $I4\n" + "match_nets $I3 $I3\n" + "match_nets $I7 $I7\n" + "net_mismatch $3 $I1\n" + "match_nets $I8 $I8\n" + "net_mismatch $6 BULK\n" + "match_pins $0 $1\n" + "match_pins $1 $2\n" + "match_pins $2 $3\n" + "match_pins $3 $4\n" + "match_pins $4 $5\n" + "match_pins (null) BULK\n" + "match_pins (null) $6\n" + "match_subcircuits $1 $1\n" + "subcircuit_mismatch $2 $2\n" + "end_circuit INV2PAIR INV2PAIR NOMATCH\n" + "begin_circuit RINGO RINGO\n" + "match_nets OSC OSC\n" + "match_nets $I7 $I7\n" + "match_nets $I6 $I6\n" + "match_nets $I5 $I5\n" + "match_nets $I21 $I13\n" + "match_nets FB FB\n" + "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets $I22 $I22\n" + "match_nets $I23 $I23\n" + "match_nets $I24 $I24\n" + "match_nets $I25 $I25\n" + "match_pins FB FB\n" + "match_pins OSC OSC\n" + "match_pins VDD VDD\n" + "match_pins VSS VSS\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "match_subcircuits $3 $3\n" + "match_subcircuits $4 $4\n" + "match_subcircuits $5 $5\n" + "end_circuit RINGO RINGO MATCH" + ); + EXPECT_EQ (good, false); +} + +TEST(24_NodesRemovedButConnectedInOther) +{ + const char *nls1 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n" + " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n" + " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n" + " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n" + " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" + "end;\n" + "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" + " subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" + " subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" + "end;\n" + "circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + const char *nls2 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" + " subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" + " subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n" + " subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n" + " subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n" + "end;\n" + // rewired here: BULK->VSS (pin $4), $1->$I3/$I4 (both rewired pins are deleted in the first netlist) + // This proves that we can basically do everything with the dropped pins. + "circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n" + " subcircuit INV2 $1 ($1=$I3,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=$I5);\n" + " subcircuit INV2 $2 ($1=$I4,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=$I5);\n" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + db::Netlist nl1, nl2; + prep_nl (nl1, nls1); + prep_nl (nl2, nls2); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + + bool good = comp.compare (&nl1, &nl2); + + std::string txt = logger.text (); + + EXPECT_EQ (txt, + "begin_circuit INV2 INV2\n" + "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets $3 $3\n" + "match_nets IN IN\n" + "match_nets VSS VSS\n" + "match_nets (null) $1\n" + "match_nets (null) BULK\n" + "match_pins IN IN\n" + "match_pins $1 $2\n" + "match_pins OUT OUT\n" + "match_pins VSS VSS\n" + "match_pins VDD VDD\n" + "match_pins (null) $0\n" + "match_pins (null) BULK\n" + "match_devices $1 $1\n" + "match_devices $2 $2\n" + "match_devices $3 $3\n" + "match_devices $4 $4\n" + "end_circuit INV2 INV2 MATCH\n" + "begin_circuit INV2PAIR INV2PAIR\n" + "match_nets $I2 $I2\n" + "match_nets $I5 $I6\n" + "match_nets $I4 $I5\n" + "match_nets $I6 $I4\n" + "match_nets $I3 $I3\n" + "match_nets $I7 $I7\n" + "match_nets $I8 $I8\n" + "match_nets (null) BULK\n" + "match_nets (null) $I1\n" + "match_pins $0 $1\n" + "match_pins $1 $2\n" + "match_pins $2 $3\n" + "match_pins $3 $4\n" + "match_pins $4 $5\n" + "match_pins (null) BULK\n" + "match_pins (null) $6\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "end_circuit INV2PAIR INV2PAIR MATCH\n" + "begin_circuit RINGO RINGO\n" + "match_nets OSC OSC\n" + "match_nets $I7 $I7\n" + "match_nets $I6 $I6\n" + "match_nets $I5 $I5\n" + "match_nets $I21 $I13\n" + "match_nets FB FB\n" + "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets $I22 $I22\n" + "match_nets $I23 $I23\n" + "match_nets $I24 $I24\n" + "match_nets $I25 $I25\n" + "match_pins FB FB\n" + "match_pins OSC OSC\n" + "match_pins VDD VDD\n" + "match_pins VSS VSS\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "match_subcircuits $3 $3\n" + "match_subcircuits $4 $4\n" + "match_subcircuits $5 $5\n" + "end_circuit RINGO RINGO MATCH" + ); + EXPECT_EQ (good, true); +} diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index 06e1eea1b..c6bc770cf 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -1404,7 +1404,7 @@ TEST(22_BlankCircuit) nl2.purge (); EXPECT_EQ (nl2.to_string (), - "circuit RINGO (IN=IN,OSC=OSC,VSS=VSS,VDD=VDD);\n" + "circuit RINGO (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"