From 2c8d065eb3a49caae4d1c2fcc5486bd8cdd93678 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 18 Jul 2021 22:34:02 +0200 Subject: [PATCH] Some enhancments + test update 1. Be more careful with net names Net names are used now for sorting the graph nodes, but not for strict compare. This is useful to derive swappable pins for blackbox circuits. 2. Be more careful with pins from schematic netlist Pins from schematic netlist without a corresponding pin on the layer side are treated as mandatory unless connected to a trivial net. Pins connecting to non-trivial nets inside the subcircuit are always considered mandatory. This way schematic pins enforce corresponding layout pins. On the other hand, layout pins connecting to trivial nets inside the subcircuit are considered non-mandatory. --- src/db/db/dbNetlistCompare.cc | 84 +++--- src/db/unit_tests/dbLayoutToNetlistTests.cc | 18 +- src/db/unit_tests/dbNetlistCompareTests.cc | 268 +++++++++++++++----- 3 files changed, 260 insertions(+), 110 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 862d86cb0..d7ca56d48 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -917,12 +917,12 @@ public: /** * @brief Builds a node for a net */ - NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id); + NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id); /** * @brief Builds a virtual node for a subcircuit */ - NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id); + NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id); void expand_subcircuit_nodes (NetGraph *graph); @@ -970,8 +970,18 @@ public: void apply_net_index (const std::map &ni); - bool operator< (const NetGraphNode &node) const; - bool operator== (const NetGraphNode &node) const; + bool less (const NetGraphNode &node, bool with_name) const; + bool equal (const NetGraphNode &node, bool with_name) const; + + bool operator== (const NetGraphNode &node) const + { + return equal (node, false); + } + + bool operator< (const NetGraphNode &node) const + { + return less (node, false); + } void swap (NetGraphNode &other) { @@ -1009,13 +1019,13 @@ private: * @brief Compares edges as "less" * Edge comparison is based on the pins attached (name of the first pin). */ - static bool net_less (const db::Net *a, const db::Net *b); + static bool net_less (const db::Net *a, const db::Net *b, bool with_name); /** * @brief Compares edges as "equal" * See edge_less for the comparison details. */ - static bool edge_equal (const db::Net *a, const db::Net *b); + static bool net_equal (const db::Net *a, const db::Net *b, bool with_name); }; // -------------------------------------------------------------------------------------------------------------------- @@ -1038,7 +1048,7 @@ struct CompareNodePtr { bool operator() (const std::pair &a, const std::pair &b) const { - return *a.first < *b.first; + return a.first->less (*b.first, true); } }; @@ -1072,7 +1082,7 @@ public: /** * @brief Builds the net graph */ - void build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper); + void build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper, size_t *unique_pin_id); /** * @brief Gets the node index for the given net @@ -1223,7 +1233,7 @@ private: // -------------------------------------------------------------------------------------------------------------------- -NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id) +NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id) : mp_net (net), m_other_net_index (invalid_id) { if (! net) { @@ -1262,8 +1272,10 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego // isolated pins are ignored, others are considered for the matching if (net->pin_count () == 0 && net->terminal_count () == 0 && net->subcircuit_pin_count () == 1) { continue; + } else if (! unique_pin_id) { + continue; } else { - pin_id = unique_pin_id++; + pin_id = (*unique_pin_id)++; } } else { @@ -1340,7 +1352,7 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego } } -NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id) +NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id) : mp_net (0), m_other_net_index (invalid_id) { std::map n2entry; @@ -1373,8 +1385,10 @@ NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circui // isolated pins are ignored, others are considered for the matching if (net_at_pin->pin_count () == 0 && net_at_pin->terminal_count () == 0 && net_at_pin->subcircuit_pin_count () == 1) { continue; + } else if (! unique_pin_id) { + continue; } else { - pin_id = unique_pin_id++; + pin_id = (*unique_pin_id)++; } } else { @@ -1517,7 +1531,7 @@ NetGraphNode::apply_net_index (const std::map &ni) } bool -NetGraphNode::operator< (const NetGraphNode &node) const +NetGraphNode::less (const NetGraphNode &node, bool with_name) const { if (m_edges.size () != node.m_edges.size ()) { return m_edges.size () < node.m_edges.size (); @@ -1529,13 +1543,13 @@ NetGraphNode::operator< (const NetGraphNode &node) const } if (m_edges.empty ()) { // do a more detailed analysis on the nets involved - return net_less (net (), node.net ()); + return net_less (net (), node.net (), with_name); } return false; } bool -NetGraphNode::operator== (const NetGraphNode &node) const +NetGraphNode::equal (const NetGraphNode &node, bool with_name) const { if (m_edges.size () != node.m_edges.size ()) { return false; @@ -1547,13 +1561,13 @@ NetGraphNode::operator== (const NetGraphNode &node) const } if (m_edges.empty ()) { // do a more detailed analysis on the edges - return edge_equal (net (), node.net ()); + return net_equal (net (), node.net (), with_name); } return true; } bool -NetGraphNode::net_less (const db::Net *a, const db::Net *b) +NetGraphNode::net_less (const db::Net *a, const db::Net *b, bool with_name) { if ((a != 0) != (b != 0)) { return (a != 0) < (b != 0); @@ -1564,14 +1578,11 @@ NetGraphNode::net_less (const db::Net *a, const db::Net *b) if (a->pin_count () != b->pin_count ()) { return a->pin_count () < b->pin_count (); } - if (a->pin_count () == 0) { - return true; - } - return db::Netlist::name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), a->begin_pins ()->pin ()->name (), b->begin_pins ()->pin ()->name ()) < 0; + return with_name ? name_compare (a, b) < 0 : false; } bool -NetGraphNode::edge_equal (const db::Net *a, const db::Net *b) +NetGraphNode::net_equal (const db::Net *a, const db::Net *b, bool with_name) { if ((a != 0) != (b != 0)) { return false; @@ -1582,10 +1593,7 @@ NetGraphNode::edge_equal (const db::Net *a, const db::Net *b) if (a->pin_count () != b->pin_count ()) { return false; } - if (a->pin_count () == 0) { - return true; - } - return db::Netlist::name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), a->begin_pins ()->pin ()->name (), b->begin_pins ()->pin ()->name ()) == 0; + return with_name ? name_compare (a, b) == 0 : true; } // -------------------------------------------------------------------------------------------------------------------- @@ -1871,7 +1879,7 @@ private: // NetGraph implementation void -NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper) +NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper, size_t *unique_pin_id) { tl::SelfTimer timer (tl::verbosity () >= 31, tl::to_string (tr ("Building net graph for circuit: ")) + c->name ()); @@ -1880,8 +1888,6 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci m_nodes.clear (); m_net_index.clear (); - size_t unique_pin_id = Transition::first_unique_pin_id (); - // create a dummy node for a null net m_nodes.push_back (NetGraphNode (0, device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper, unique_pin_id)); @@ -3613,16 +3619,21 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::NetGraph g1, g2; + size_t unique_pin_id = Transition::first_unique_pin_id (); + // NOTE: for normalization we map all subcircuits of c1 to c2. // Also, pin swapping will only happen there. if (options ()->debug_netgraph) { tl::info << "Netlist graph:"; } - g1.build (c1, device_categorizer, circuit_categorizer, device_filter, &c12_circuit_and_pin_mapping, &circuit_pin_mapper); + g1.build (c1, device_categorizer, circuit_categorizer, device_filter, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, (size_t *)0); + if (options ()->debug_netgraph) { tl::info << "Other netlist graph:"; } - g2.build (c2, device_categorizer, circuit_categorizer, device_filter, &c22_circuit_and_pin_mapping, &circuit_pin_mapper); + // NOTE: the second netlist graph is the reference (schematic). We treat it a little more carefully by using pins from subcircuits which + // lead to passive nets but connect to non-trivial nets on the outside. This is done by specifying a unique_pin_id counter for the last argument. + g2.build (c2, device_categorizer, circuit_categorizer, device_filter, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, &unique_pin_id); // Match dummy nodes for null nets g1.identify (0, 0); @@ -4287,14 +4298,19 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG bool mapped = true, valid = true; std::vector > k = compute_subcircuit_key_for_this (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, mapped, valid); - if (! mapped || ! valid) { + if (! mapped) { if (mp_logger) { mp_logger->subcircuit_mismatch (sc.operator-> (), 0); } good = false; - } else { + } else if (valid) { // TODO: report devices which cannot be distinguished topologically? subcircuit_map.insert (std::make_pair (k, std::make_pair (sc.operator-> (), sc_cat))); + } else { + // emit a mismatch event but do not consider that an error - this may happen if the circuit has been dropped intentionally (e.g. via cells) + if (mp_logger) { + mp_logger->subcircuit_mismatch (sc.operator-> (), 0); + } } } @@ -4584,7 +4600,7 @@ NetlistComparer::join_symmetric_nets (db::Circuit *circuit) db::NetGraph graph; db::CircuitCategorizer circuit_categorizer; db::DeviceCategorizer device_categorizer; - graph.build (circuit, device_categorizer, circuit_categorizer, device_filter, &circuit_and_pin_mapping, &circuit_pin_mapper); + graph.build (circuit, device_categorizer, circuit_categorizer, device_filter, &circuit_and_pin_mapping, &circuit_pin_mapper, (size_t *) 0); // sort the nodes so we can easily identify the identical ones (in terms of topology) // nodes are identical if the attached devices and circuits are of the same kind and with the same parameters diff --git a/src/db/unit_tests/dbLayoutToNetlistTests.cc b/src/db/unit_tests/dbLayoutToNetlistTests.cc index 155a371fd..7acad9839 100644 --- a/src/db/unit_tests/dbLayoutToNetlistTests.cc +++ b/src/db/unit_tests/dbLayoutToNetlistTests.cc @@ -1140,17 +1140,17 @@ TEST(3_GlobalNetConnections) CHECKPOINT (); db::compare_netlist (_this, *l2n.netlist (), "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" + " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" + " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" + " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n" + " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n" + " subcircuit INV2PAIR $5 ($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" + "circuit INV2PAIR ($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);\n" + " subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6);\n" "end;\n" - "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\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" diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 081351a47..9d10f8b88 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -1984,6 +1984,7 @@ TEST(13_MismatchingSubcircuitsAdditionalHierarchy) "match_pins $1 $0\n" "match_pins $2 $2\n" "match_pins $3 $3\n" + "subcircuit_mismatch $2 (null)\n" "match_subcircuits $3 $1\n" "match_subcircuits $1 $2\n" "end_circuit TOP TOP MATCH" @@ -3931,25 +3932,6 @@ TEST(21_BusLikeAmbiguousConnections) 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" @@ -3968,6 +3950,25 @@ TEST(22_NodesRemoved) " 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 ($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"; + db::Netlist nl1, nl2; prep_nl (nl1, nls1); prep_nl (nl2, nls2); @@ -3980,6 +3981,79 @@ TEST(22_NodesRemoved) 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 $1 (null)\n" + "match_nets BULK (null)\n" + "match_pins IN IN\n" + "match_pins $2 $1\n" + "match_pins OUT OUT\n" + "match_pins VSS VSS\n" + "match_pins VDD VDD\n" + "match_pins $0 (null)\n" + "match_pins BULK (null)\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 $I6 $I5\n" + "match_nets $I5 $I4\n" + "match_nets $I4 $I6\n" + "match_nets $I3 $I3\n" + "match_nets $I7 $I7\n" + "match_nets $I8 $I8\n" + "match_nets BULK (null)\n" + "match_nets $I1 (null)\n" + "match_pins $1 $0\n" + "match_pins $2 $1\n" + "match_pins $3 $2\n" + "match_pins $4 $3\n" + "match_pins $5 $4\n" + "match_pins BULK (null)\n" + "match_pins $6 (null)\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 $I13 $I21\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); + + logger.clear (); + good = comp.compare (&nl2, &nl1); + + txt = logger.text (); + + // additional nodes are not ignored when they come from the reference side (second) EXPECT_EQ (txt, "begin_circuit INV2 INV2\n" "match_nets VDD VDD\n" @@ -4028,24 +4102,28 @@ TEST(22_NodesRemoved) "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" + "net_mismatch VDD (null)\n" + "net_mismatch VSS (null)\n" + "net_mismatch (null) VDD\n" + "net_mismatch (null) VSS\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" + "match_pins VDD (null)\n" + "match_pins VSS (null)\n" + "match_pins (null) VDD\n" + "match_pins (null) VSS\n" + "subcircuit_mismatch $1 $1\n" + "subcircuit_mismatch $2 $2\n" + "subcircuit_mismatch $3 $3\n" + "subcircuit_mismatch $4 $4\n" + "subcircuit_mismatch $5 $5\n" + "end_circuit RINGO RINGO NOMATCH" ); - EXPECT_EQ (good, true); + EXPECT_EQ (good, false); } TEST(23_NodesRemovedWithError) @@ -4150,25 +4228,6 @@ TEST(23_NodesRemovedWithError) 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" @@ -4189,6 +4248,25 @@ TEST(24_NodesRemovedButConnectedInOther) " 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 ($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"; + db::Netlist nl1, nl2; prep_nl (nl1, nls1); prep_nl (nl2, nls2); @@ -4208,15 +4286,15 @@ TEST(24_NodesRemovedButConnectedInOther) "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_nets $1 (null)\n" + "match_nets BULK (null)\n" "match_pins IN IN\n" - "match_pins $1 $2\n" + "match_pins $2 $1\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_pins $0 (null)\n" + "match_pins BULK (null)\n" "match_devices $1 $1\n" "match_devices $2 $2\n" "match_devices $3 $3\n" @@ -4224,21 +4302,21 @@ TEST(24_NodesRemovedButConnectedInOther) "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 $I6 $I5\n" + "match_nets $I5 $I4\n" + "match_nets $I4 $I6\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_nets BULK (null)\n" + "match_nets $I1 (null)\n" + "match_pins $1 $0\n" + "match_pins $2 $1\n" + "match_pins $3 $2\n" + "match_pins $4 $3\n" + "match_pins $5 $4\n" + "match_pins BULK (null)\n" + "match_pins $6 (null)\n" "match_subcircuits $1 $1\n" "match_subcircuits $2 $2\n" "end_circuit INV2PAIR INV2PAIR MATCH\n" @@ -4247,7 +4325,7 @@ TEST(24_NodesRemovedButConnectedInOther) "match_nets $I7 $I7\n" "match_nets $I6 $I6\n" "match_nets $I5 $I5\n" - "match_nets $I21 $I13\n" + "match_nets $I13 $I21\n" "match_nets FB FB\n" "match_nets VSS VSS\n" "match_nets VDD VDD\n" @@ -4267,6 +4345,62 @@ TEST(24_NodesRemovedButConnectedInOther) "end_circuit RINGO RINGO MATCH" ); EXPECT_EQ (good, true); + + + logger.clear (); + good = comp.compare (&nl2, &nl1); + + txt = logger.text (); + + // NOTE: additional nets are ignored in the first netlist but not from the second + 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 $I8 $I8\n" + "match_nets $I7 $I7\n" + "net_mismatch $I6 $I4\n" + "net_mismatch $I4 (null)\n" + "net_mismatch $I3 (null)\n" + "net_mismatch (null) BULK\n" + "net_mismatch (null) $I5\n" + "net_mismatch (null) $I3\n" + "net_mismatch (null) $I1\n" + "match_pins $0 $1\n" + "match_pins $1 $2\n" + "match_pins $4 $5\n" + "pin_mismatch $2 (null)\n" + "pin_mismatch $3 (null)\n" + "pin_mismatch (null) BULK\n" + "pin_mismatch (null) $3\n" + "pin_mismatch (null) $4\n" + "pin_mismatch (null) $6\n" + "subcircuit_mismatch $1 $1\n" + "subcircuit_mismatch $2 $2\n" + "end_circuit INV2PAIR INV2PAIR NOMATCH\n" + "circuit_skipped RINGO RINGO" + ); + EXPECT_EQ (good, false); } TEST(25_JoinSymmetricNets)