diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 01ef3142b..834120c52 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -38,6 +38,12 @@ public: */ virtual void end_circuit (const db::Circuit * /*a*/, const db::Circuit * /*b*/, bool /*matching*/) { } + /** + * @brief Circuits are skipped + * Circuits are skipped if their subcircuits could not be matched. + */ + virtual void circuit_skipped (const db::Circuit * /*a*/, const db::Circuit * /*b*/) { } + /** * @brief There is a circuit mismatch * "a" is null if there is no match for b and vice versa. @@ -77,6 +83,12 @@ public: */ virtual void match_devices_with_different_device_classes (const db::Device * /*a*/, const db::Device * /*b*/) { } + /** + * @brief Device a or b doesn't match + * "a" is null if there is no match for b and vice versa. + */ + virtual void device_mismatch (const db::Device * /*a*/, const db::Device * /*b*/) { } + /** * @brief Pins a and b of the current circuit are matched */ @@ -106,7 +118,7 @@ struct DeviceCompare { // @@@ TODO: device class identity should not be defined via name if (d1->device_class () != d2->device_class () && d1->device_class ()->name () != d2->device_class ()->name ()) { - return d1->device_class ()->name () < d1->device_class ()->name (); + return d1->device_class ()->name () < d2->device_class ()->name (); } const std::vector &dp = d1->device_class ()->parameter_definitions (); @@ -267,6 +279,19 @@ public: return false; } + bool operator== (const NetDeviceGraphNode &node) const + { + if (m_edges.size () != node.m_edges.size ()) { + return false; + } + for (size_t i = 0; i < m_edges.size (); ++i) { + if (m_edges [i].first != node.m_edges [i].first) { + return false; + } + } + return true; + } + void swap (NetDeviceGraphNode &other) { std::swap (m_other_net_index, other.m_other_net_index); @@ -343,13 +368,18 @@ public: } } - size_t index_for_net (const db::Net *net) const + size_t node_index_for_net (const db::Net *net) const { std::map::const_iterator j = m_net_index.find (net); tl_assert (j != m_net_index.end ()); return j->second; } + const db::Net *net_by_node_index (size_t net_index) const + { + return m_nodes [net_index].net (); + } + void identify (size_t net_index, size_t other_net_index) { m_nodes [net_index].set_other_net (other_net_index); @@ -445,10 +475,14 @@ public: return added; } - static void confirm_identity (db::NetDeviceGraph &g1, db::NetDeviceGraph::node_iterator s1, db::NetDeviceGraph &g2, db::NetDeviceGraph::node_iterator s2, db::NetlistCompareLogger *logger) + static void confirm_identity (db::NetDeviceGraph &g1, db::NetDeviceGraph::node_iterator s1, db::NetDeviceGraph &g2, db::NetDeviceGraph::node_iterator s2, db::NetlistCompareLogger *logger, bool ambiguous = false) { if (logger) { - logger->match_nets (s1->net (), s2->net ()); + if (ambiguous) { + logger->match_ambiguous_nets (s1->net (), s2->net ()); + } else { + logger->match_nets (s1->net (), s2->net ()); + } } g1.identify (s1 - g1.begin (), s2 - g2.begin ()); g2.identify (s2 - g2.begin (), s1 - g1.begin ()); @@ -468,6 +502,11 @@ public: : mp_logger (logger) { } + void same_nets (const db::Circuit *a, const db::Net *na, const db::Circuit *b, const db::Net *nb) + { + m_same_nets [std::make_pair (a, b)].push_back (std::make_pair (na, nb)); + } + bool compare (const db::Netlist *a, const db::Netlist *b) const { bool good = true; @@ -495,22 +534,54 @@ public: } } + std::set verified_circuits_a, verified_circuits_b; + for (db::Netlist::const_bottom_up_circuit_iterator c = a->begin_bottom_up (); c != a->end_bottom_up (); ++c) { std::map >::const_iterator i = name2circuits.find ((*c)->name ()); tl_assert (i != name2circuits.end ()); if (i->second.first && i->second.second) { - if (mp_logger) { - mp_logger->begin_circuit (i->second.first, i->second.second); + + const db::Circuit *ca = i->second.first; + const db::Circuit *cb = i->second.second; + + std::vector > empty; + const std::vector > *net_identity = ∅ + std::map, std::vector > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb)); + if (sn != m_same_nets.end ()) { + net_identity = &sn->second; } - bool g = compare_circuits (i->second.first, i->second.second); - if (! g) { - good = false; - } - if (mp_logger) { - mp_logger->end_circuit (i->second.first, i->second.second, g); + + if (all_subcircuits_verified (ca, verified_circuits_a) && all_subcircuits_verified (cb, verified_circuits_b)) { + + if (mp_logger) { + mp_logger->begin_circuit (ca, cb); + } + + bool pin_mismatch = false; + bool g = compare_circuits (ca, cb, *net_identity, pin_mismatch); + if (! g) { + good = false; + } + + if (! pin_mismatch) { + verified_circuits_a.insert (ca); + verified_circuits_b.insert (cb); + } + + if (mp_logger) { + mp_logger->end_circuit (ca, cb, g); + } + + } else { + + if (mp_logger) { + mp_logger->circuit_skipped (ca, cb); + } + } + } } @@ -523,20 +594,59 @@ public: } protected: - bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2) const; + bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, const std::vector > &net_identity, bool &pin_mismatch) const; + bool all_subcircuits_verified (const db::Circuit *c, const std::set &verified_circuits) const; NetlistCompareLogger *mp_logger; + std::map, std::vector > > m_same_nets; }; bool -NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2) const +NetlistComparer::all_subcircuits_verified (const db::Circuit *c, const std::set &verified_circuits) const +{ + for (db::Circuit::const_subcircuit_iterator sc = c->begin_subcircuits (); sc != c->end_subcircuits (); ++sc) { + if (verified_circuits.find (sc->circuit_ref ()) == verified_circuits.end ()) { + return false; + } + } + return true; +} + +static std::vector > +compute_device_key (const db::Device &device, const db::NetDeviceGraph &g) +{ + std::vector > k; + + const std::vector &td = device.device_class ()->terminal_definitions (); + for (std::vector::const_iterator t = td.begin (); t != td.end (); ++t) { + size_t terminal_id = translate_terminal_id (t->id (), &device); + const db::Net *net = device.net_for_terminal (t->id ()); + size_t net_id = g.node_index_for_net (net); + k.push_back (std::make_pair (terminal_id, net_id)); + } + + std::sort (k.begin (), k.end ()); + + return k; +} + +bool +NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, const std::vector > &net_identity, bool &pin_mismatch) const { db::NetDeviceGraph g1, g2; g1.build (c1); g2.build (c2); - while (true) { + for (std::vector >::const_iterator p = net_identity.begin (); p != net_identity.end (); ++p) { + size_t ni1 = g1.node_index_for_net (p->first); + size_t ni2 = g2.node_index_for_net (p->second); + g1.identify (ni1, ni2); + g2.identify (ni2, ni1); + } + + bool good = true; + while (good) { size_t new_identities = 0; for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) { @@ -551,18 +661,13 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2) } if (! any_without) { - return true; + break; } - bool ambiguous = false; - if (new_identities == 0) { // derive new identities through topology - db::NetDeviceGraph::node_iterator s1 = g1.end (), s2 = g2.end (); - size_t seeds = 0; - db::NetDeviceGraph::node_iterator i1 = g1.begin (), i2 = g2.begin (); for ( ; i1 != g1.end () && i2 != g2.end (); ) { @@ -571,71 +676,153 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2) } else if (i2->has_other ()) { ++i2; } else if (*i1 < *i2) { - seeds = 0; ++i1; } else if (*i2 < *i1) { - seeds = 0; ++i2; } else { - if (seeds == 0 || *s1 < *i1) { - - if (seeds == 1) { - // found a candidate - a single node with the same edges - db::NetDeviceGraph::confirm_identity (g1, s1, g2, s2, mp_logger); - ++new_identities; - } else if (seeds > 1) { - ambiguous = true; - } - - s1 = i1; s2 = i2; - seeds = 1; - - } else { - ++seeds; - } + db::NetDeviceGraph::node_iterator ii1 = i1, ii2 = i2; ++i1; ++i2; + bool ambiguous = (i1 != g1.end () && *i1 == *ii1) || (i2 != g2.end () && *i2 == *ii2); + + // found a candidate - a single node with the same edges + db::NetDeviceGraph::confirm_identity (g1, ii1, g2, ii2, mp_logger, ambiguous); + ++new_identities; + } } - if (seeds == 1) { - // found a candidate - a single node with the same edges - db::NetDeviceGraph::confirm_identity (g1, s1, g2, s2, mp_logger); - ++new_identities; - } else if (seeds > 1) { - ambiguous = true; - } - } if (new_identities == 0) { - // @@@ - if (ambiguous) { - tl::error << tr ("No seed found - no non-ambiguous nets identified"); - } else { - tl::error << tr ("No seed found - no equivalent nets identified"); - } - tl::error << tr ("Unassigned in netlist A:"); - for (db::NetDeviceGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) { - if (! i->has_other ()) { - tl::error << " " << i->net ()->expanded_name (); - } - } - tl::error << tr ("Unassigned in netlist B:"); - for (db::NetDeviceGraph::node_iterator i = g2.begin (); i != g2.end (); ++i) { - if (! i->has_other ()) { - tl::error << " " << i->net ()->expanded_name (); - } - } - // @@@ - return false; + good = false; } } + + // Report missing net assignment + + for (db::NetDeviceGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) { + if (! i->has_other ()) { + mp_logger->net_mismatch (i->net (), 0); + } + } + tl::error << tr ("Unassigned in netlist B:"); + for (db::NetDeviceGraph::node_iterator i = g2.begin (); i != g2.end (); ++i) { + if (! i->has_other ()) { + mp_logger->net_mismatch (0, i->net ()); + } + } + + + // Report pin assignment + + std::multimap net2pin; + 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 ()); + tl_assert (net != 0); + net2pin.insert (std::make_pair (net, p.operator-> ())); + } + + for (db::NetDeviceGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) { + + const db::Net *net = i->net (); + tl_assert (net != 0); + + if (net->pin_count () == 0) { + continue; + } + + if (! i->has_other ()) { + for (db::Net::const_pin_iterator pi = net->begin_pins (); pi != net->end_pins (); ++pi) { + mp_logger->pin_mismatch (pi->pin (), 0); + pin_mismatch = true; + } + continue; + } + + const db::Net *other_net = g2.net_by_node_index (i->other_net_index ()); + + std::multimap::iterator np = net2pin.find (other_net); + for (db::Net::const_pin_iterator pi = net->begin_pins (); pi != net->end_pins (); ++pi) { + + if (np != net2pin.end () && np->first == other_net) { + + mp_logger->match_pins (pi->pin (), np->second); + + std::multimap::iterator np_delete = np; + ++np; + net2pin.erase (np_delete); + + } else { + mp_logger->pin_mismatch (pi->pin (), 0); + pin_mismatch = true; + } + + } + + } + + for (std::multimap::iterator np = net2pin.begin (); np != net2pin.end (); ++np) { + mp_logger->pin_mismatch (0, np->second); + pin_mismatch = true; + } + + // Report device assignment + + std::map >, const db::Device *> device_map; + + for (db::Circuit::const_device_iterator d = c1->begin_devices (); d != c1->end_devices (); ++d) { + + std::vector > k = compute_device_key (*d, g1); + + bool mapped = true; + for (std::vector >::iterator i = k.begin (); i != k.end () && mapped; ++i) { + if (! g1.begin () [i->second].has_other ()) { + mapped = false; + } + } + + if (! mapped) { + mp_logger->device_mismatch (d.operator-> (), 0); + } else { + // TODO: report devices which cannot be distiguished topologically? + device_map[k] = d.operator-> (); + } + + } + + for (db::Circuit::const_device_iterator d = c2->begin_devices (); d != c2->end_devices (); ++d) { + + std::vector > k = compute_device_key (*d, g2); + + bool mapped = true; + for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { + if (! g1.begin () [i->second].has_other ()) { + mapped = false; + } else { + i->second = g2.begin () [i->second].other_net_index (); + } + } + + std::sort (k.begin (), k.end ()); + + std::map >, const db::Device *>::const_iterator dm = device_map.find (k); + + if (! mapped || dm == device_map.end ()) { + mp_logger->device_mismatch (0, d.operator-> ()); + } else { + // @@@ compare parameters, device class + mp_logger->match_devices (dm->second, d.operator-> ()); + } + + } + + return good; } } @@ -656,6 +843,11 @@ public: m_texts.push_back ("end_circuit " + circuit2str (a) + " " + circuit2str (b) + " " + (matching ? "MATCH" : "NOMATCH")); } + virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b) + { + m_texts.push_back ("circuit_skipped " + circuit2str (a) + " " + circuit2str (b)); + } + virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b) { m_texts.push_back ("circuit_mismatch " + circuit2str (a) + " " + circuit2str (b)); @@ -681,6 +873,11 @@ public: m_texts.push_back ("match_devices " + device2str (a) + " " + device2str (b)); } + virtual void device_mismatch (const db::Device *a, const db::Device *b) + { + m_texts.push_back ("device_mismatch " + device2str (a) + " " + device2str (b)); + } + virtual void match_devices_with_different_parameters (const db::Device *a, const db::Device *b) { m_texts.push_back ("match_devices_with_different_parameters " + device2str (a) + " " + device2str (b)); @@ -745,8 +942,253 @@ private: } }; +static void prep_nl (db::Netlist &nl, const char *str) +{ + db::DeviceClass *dc; -TEST(1) + dc = new db::DeviceClassMOS3Transistor (); + dc->set_name ("PMOS"); + nl.add_device_class (dc); + + dc = new db::DeviceClassMOS3Transistor (); + dc->set_name ("NMOS"); + nl.add_device_class (dc); + + nl.from_string (str); +} + +TEST(1_SimpleInverter) +{ + const char *nls1 = + "circuit INV ($1=IN,$2=OUT,$3=VDD,$4=VSS);\n" + " device PMOS $1 (S=VDD,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $2 (S=VSS,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n"; + + const char *nls2 = + "circuit INV ($1=VDD,$2=IN,$3=VSS,$4=OUT);\n" + " device NMOS $1 (S=OUT,G=IN,D=VSS) (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=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\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); + + EXPECT_EQ (logger.text (), + "begin_circuit INV INV\n" + "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets IN IN\n" + "match_pins $3 $2\n" + "match_pins $2 $0\n" + "match_pins $1 $3\n" + "match_pins $0 $1\n" + "match_devices $2 $1\n" + "match_devices $1 $2\n" + "end_circuit INV INV MATCH" + ); + EXPECT_EQ (good, true); +} + +TEST(2_SimpleInverterWithForcedNetAssignment) +{ + const char *nls1 = + "circuit INV ($1=IN,$2=OUT,$3=VDD,$4=VSS);\n" + " device PMOS $1 (S=VDD,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $2 (S=VSS,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n"; + + const char *nls2 = + "circuit INV ($1=VDD,$2=IN,$3=VSS,$4=OUT);\n" + " device NMOS $1 (S=OUT,G=IN,D=VSS) (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=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n"; + + db::Netlist nl1, nl2; + prep_nl (nl1, nls1); + prep_nl (nl2, nls2); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + const db::Circuit *ca = nl1.circuit_by_name ("INV"); + const db::Circuit *cb = nl2.circuit_by_name ("INV"); + comp.same_nets (ca, ca->net_by_name ("VDD"), cb, cb->net_by_name ("VDD")); + comp.same_nets (ca, ca->net_by_name ("VSS"), cb, cb->net_by_name ("VSS")); + + bool good = comp.compare (&nl1, &nl2); + + EXPECT_EQ (logger.text (), + "begin_circuit INV INV\n" + "match_nets OUT OUT\n" + "match_nets IN IN\n" + "match_pins $3 $2\n" + "match_pins $2 $0\n" + "match_pins $1 $3\n" + "match_pins $0 $1\n" + "match_devices $2 $1\n" + "match_devices $1 $2\n" + "end_circuit INV INV MATCH" + ); + EXPECT_EQ (good, true); +} + +TEST(3_Buffer) +{ + const char *nls1 = + "circuit BUF ($1=IN,$2=OUT,$3=VDD,$4=VSS);\n" + " device PMOS $1 (S=VDD,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $2 (S=VSS,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $3 (S=VDD,G=INT,D=OUT) (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=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n"; + + const char *nls2 = + "circuit BUF ($1=VDD,$2=IN,$3=VSS,$4=OUT);\n" + " device PMOS $1 (S=VDD,G=IN,D=$10) (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=$10,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $3 (S=$10,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=OUT,G=$10,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\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); + + EXPECT_EQ (logger.text (), + "begin_circuit BUF BUF\n" + "match_nets VSS VSS\n" + "match_nets OUT OUT\n" + "match_nets IN IN\n" + "match_nets VDD VDD\n" + "match_nets INT $10\n" + "match_pins $3 $2\n" + "match_pins $1 $3\n" + "match_pins $0 $1\n" + "match_pins $2 $0\n" + "match_devices $1 $1\n" + "match_devices $3 $2\n" + "match_devices $2 $3\n" + "match_devices $4 $4\n" + "end_circuit BUF BUF MATCH" + ); + EXPECT_EQ (good, true); +} + +TEST(4_BufferTwoPaths) +{ + const char *nls1 = + "circuit BUF ($1=IN,$2=OUT,$3=VDD,$4=VSS);\n" + " device PMOS $1 (S=VDD,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $2 (S=VSS,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $3 (S=VDD,G=INT,D=OUT) (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=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $5 (S=VDD,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $6 (S=VSS,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $7 (S=VDD,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $8 (S=VSS,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n"; + + const char *nls2 = + "circuit BUF ($1=VDD,$2=IN,$3=VSS,$4=OUT);\n" + " device PMOS $1 (S=VDD,G=IN,D=$10) (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=$10,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $3 (S=VDD,G=IN,D=$11) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $4 (S=VDD,G=$11,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $5 (S=$10,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 $6 (S=OUT,G=$10,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $7 (S=$11,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 $8 (S=OUT,G=$11,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\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); + + EXPECT_EQ (logger.text (), + "begin_circuit BUF BUF\n" + "match_nets VSS VSS\n" + "match_nets OUT OUT\n" + "match_ambiguous_nets INT $10\n" + "match_nets INT2 $11\n" + "match_nets IN IN\n" + "match_nets VDD VDD\n" + "match_pins $3 $2\n" + "match_pins $1 $3\n" + "match_pins $0 $1\n" + "match_pins $2 $0\n" + "match_devices $1 $1\n" + "match_devices $3 $2\n" + "match_devices $5 $3\n" + "match_devices $7 $4\n" + "match_devices $2 $5\n" + "match_devices $4 $6\n" + "match_devices $6 $7\n" + "match_devices $8 $8\n" + "end_circuit BUF BUF MATCH" + ); + EXPECT_EQ (good, true); +} + +TEST(100_SimpleInverterWithWrongTransistorParameter) +{ +return; // @@@ doesn't work yet. + const char *nls1 = + "circuit INV ($1=IN,$2=OUT,$3=VDD,$4=VSS);\n" + " device PMOS $1 (S=VDD,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $2 (S=VSS,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n"; + + const char *nls2 = + "circuit INV ($1=VDD,$2=IN,$3=VSS,$4=OUT);\n" + " device NMOS $1 (S=OUT,G=IN,D=VSS) (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=IN,D=OUT) (L=0.30,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n"; + + db::Netlist nl1, nl2; + prep_nl (nl1, nls1); + prep_nl (nl2, nls2); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + const db::Circuit *ca = nl1.circuit_by_name ("INV"); + const db::Circuit *cb = nl2.circuit_by_name ("INV"); + comp.same_nets (ca, ca->net_by_name ("VDD"), cb, cb->net_by_name ("VDD")); + comp.same_nets (ca, ca->net_by_name ("VSS"), cb, cb->net_by_name ("VSS")); + + bool good = comp.compare (&nl1, &nl2); + + EXPECT_EQ (logger.text (), + "begin_circuit INV INV\n" + "match_nets OUT OUT\n" + "match_nets IN IN\n" + "match_pins $3 $2\n" + "match_pins $2 $0\n" + "match_pins $1 $3\n" + "match_pins $0 $1\n" + "end_circuit INV INV MATCH" + ); + EXPECT_EQ (good, true); +} + +#if 0 +TEST(2) { const char *nls2 = "circuit RINGO ();\n" @@ -866,3 +1308,4 @@ TEST(1) ); EXPECT_EQ (good, true); } +#endif