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"