WIP: netlist compare

This commit is contained in:
Matthias Koefferlein 2019-03-24 21:14:08 +01:00
parent bb2d3765b8
commit 55052038ea
1 changed files with 172 additions and 43 deletions

View File

@ -182,7 +182,15 @@ public:
}
};
typedef std::vector<std::pair<std::vector<EdgeDesc>, std::pair<const db::Net *, size_t> > >::const_iterator edge_iterator;
struct EdgeToEdgeOnlyCompare
{
bool operator() (const std::pair<std::vector<EdgeDesc>, std::pair<size_t, const db::Net *> > &a, const std::vector<EdgeDesc> &b) const
{
return a.first < b;
}
};
typedef std::vector<std::pair<std::vector<EdgeDesc>, std::pair<size_t, const db::Net *> > >::const_iterator edge_iterator;
NetDeviceGraphNode (const db::Net *net, std::map<const db::Device *, size_t, DeviceCompare> &devmap, std::vector<const db::Device *> &device_prototypes)
: mp_net (net), m_other_net_index (std::numeric_limits<size_t>::max ())
@ -218,7 +226,7 @@ public:
std::map<const db::Net *, size_t>::const_iterator in = n2entry.find (net2);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair (net2, m_edges.size ())).first;
m_edges.push_back (std::make_pair (std::vector<EdgeDesc> (), std::make_pair (net2, size_t (0))));
m_edges.push_back (std::make_pair (std::vector<EdgeDesc> (), std::make_pair (size_t (0), net2)));
}
m_edges [in->second].first.push_back (ed2);
@ -228,13 +236,6 @@ public:
}
}
// "deep sorting" of the edge descriptor
for (std::vector<std::pair<std::vector<EdgeDesc>, std::pair<const db::Net *, size_t> > >::iterator i = m_edges.begin (); i != m_edges.end (); ++i) {
std::sort (i->first.begin (), i->first.end ());
}
std::sort (m_edges.begin (), m_edges.end ());
}
const db::Net *net () const
@ -259,11 +260,18 @@ public:
void apply_net_index (const std::map<const db::Net *, size_t> &ni)
{
for (std::vector<std::pair<std::vector<EdgeDesc>, std::pair<const db::Net *, size_t> > >::iterator i = m_edges.begin (); i != m_edges.end (); ++i) {
std::map<const db::Net *, size_t>::const_iterator j = ni.find (i->second.first);
for (std::vector<std::pair<std::vector<EdgeDesc>, std::pair<size_t, const db::Net *> > >::iterator i = m_edges.begin (); i != m_edges.end (); ++i) {
std::map<const db::Net *, size_t>::const_iterator j = ni.find (i->second.second);
tl_assert (j != ni.end ());
i->second.second = j->second;
i->second.first = j->second;
}
// "deep sorting" of the edge descriptor
for (std::vector<std::pair<std::vector<EdgeDesc>, std::pair<size_t, const db::Net *> > >::iterator i = m_edges.begin (); i != m_edges.end (); ++i) {
std::sort (i->first.begin (), i->first.end ());
}
std::sort (m_edges.begin (), m_edges.end ());
}
bool operator< (const NetDeviceGraphNode &node) const
@ -309,10 +317,20 @@ public:
return m_edges.end ();
}
edge_iterator find_edge (const std::vector<EdgeDesc> &edge) const
{
edge_iterator res = std::lower_bound (begin (), end (), edge, NetDeviceGraphNode::EdgeToEdgeOnlyCompare ());
if (res->first != edge) {
return end ();
} else {
return res;
}
}
private:
const db::Net *mp_net;
size_t m_other_net_index;
std::vector<std::pair<std::vector<EdgeDesc>, std::pair<const db::Net *, size_t> > > m_edges;
std::vector<std::pair<std::vector<EdgeDesc>, std::pair<size_t, const db::Net *> > > m_edges;
};
}
@ -427,7 +445,7 @@ public:
size_t count = 0;
NetDeviceGraphNode::edge_iterator ec;
for (NetDeviceGraphNode::edge_iterator i = e; i != ee; ++i) {
if (! m_nodes[i->second.second].has_other ()) {
if (! m_nodes[i->second.first].has_other ()) {
ec = i;
++count;
}
@ -435,29 +453,39 @@ public:
if (count == 1) { // if non-ambiguous, non-assigned
NetDeviceGraphNode::edge_iterator e_other = std::lower_bound (nother->begin (), nother->end (), *ec);
if (e_other != nother->end () && e_other->first == ec->first) {
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::log << "considering " << n->net ()->expanded_name () << " to " << ec->second.second->expanded_name ();
#endif
NetDeviceGraphNode::edge_iterator e_other = nother->find_edge (ec->first);
if (e_other != nother->end ()) {
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::log << "candidate accepted";
#endif
NetDeviceGraphNode::edge_iterator ee_other = e_other;
++ee_other;
while (ee_other != n->end () && ee_other->first == e_other->first) {
while (ee_other != nother->end () && ee_other->first == e_other->first) {
++ee_other;
}
size_t count_other = 0;
NetDeviceGraphNode::edge_iterator ec_other;
for (NetDeviceGraphNode::edge_iterator i = e_other; i != ee_other; ++i) {
if (! m_nodes[i->second.second].has_other ()) {
if (! m_nodes[i->second.first].has_other ()) {
ec_other = i;
++count_other;
}
}
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::log << "identity count = " << count_other;
#endif
if (count_other == 1) {
confirm_identity (*this, begin () + ec->second.second, other, other.begin () + ec_other->second.second, logger);
confirm_identity (*this, begin () + ec->second.first, other, other.begin () + ec_other->second.first, logger);
++added;
more.push_back (ec->second.second);
more.push_back (ec->second.first);
}
}
@ -648,10 +676,23 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
bool good = true;
while (good) {
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::log << "new iteration ...";
#endif
size_t new_identities = 0;
for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) {
if (i1->has_other ()) {
new_identities += g1.derive_node_identities (i1 - g1.begin (), g2, mp_logger);
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::log << "deriving new identities from " << i1->net ()->expanded_name ();
#endif
size_t ni = g1.derive_node_identities (i1 - g1.begin (), g2, mp_logger);
new_identities += ni;
if (ni > 0) {
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::log << ni << " new identities.";
#endif
}
}
}
@ -666,6 +707,9 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
if (new_identities == 0) {
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::log << "checking topological identity ...";
#endif
// derive new identities through topology
db::NetDeviceGraph::node_iterator i1 = g1.begin (), i2 = g2.begin ();
@ -711,7 +755,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
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 ());
@ -814,10 +858,23 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
std::map<std::vector<std::pair<size_t, size_t> >, 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-> ());
db::DeviceCompare dc;
if (dc (dm->second, d.operator-> ()) || dc (d.operator-> (), dm->second)) {
if (dm->second->device_class ()->name () != d->device_class ()->name ()) {
mp_logger->match_devices_with_different_device_classes (dm->second, d.operator-> ());
} else {
mp_logger->match_devices_with_different_parameters (dm->second, d.operator-> ());
}
} else {
mp_logger->match_devices (dm->second, d.operator-> ());
}
}
}
@ -833,79 +890,87 @@ class NetlistCompareTestLogger
public:
NetlistCompareTestLogger () { }
void out (const std::string &text)
{
m_texts.push_back (text);
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::log << m_texts.back ();
#endif
}
virtual void begin_circuit (const db::Circuit *a, const db::Circuit *b)
{
m_texts.push_back ("begin_circuit " + circuit2str (a) + " " + circuit2str (b));
out ("begin_circuit " + circuit2str (a) + " " + circuit2str (b));
}
virtual void end_circuit (const db::Circuit *a, const db::Circuit *b, bool matching)
{
m_texts.push_back ("end_circuit " + circuit2str (a) + " " + circuit2str (b) + " " + (matching ? "MATCH" : "NOMATCH"));
out ("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));
out ("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));
out ("circuit_mismatch " + circuit2str (a) + " " + circuit2str (b));
}
virtual void match_nets (const db::Net *a, const db::Net *b)
{
m_texts.push_back ("match_nets " + net2str (a) + " " + net2str (b));
out ("match_nets " + net2str (a) + " " + net2str (b));
}
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b)
{
m_texts.push_back ("match_ambiguous_nets " + net2str (a) + " " + net2str (b));
out ("match_ambiguous_nets " + net2str (a) + " " + net2str (b));
}
virtual void net_mismatch (const db::Net *a, const db::Net *b)
{
m_texts.push_back ("net_mismatch " + net2str (a) + " " + net2str (b));
out ("net_mismatch " + net2str (a) + " " + net2str (b));
}
virtual void match_devices (const db::Device *a, const db::Device *b)
{
m_texts.push_back ("match_devices " + device2str (a) + " " + device2str (b));
out ("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));
out ("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));
out ("match_devices_with_different_parameters " + device2str (a) + " " + device2str (b));
}
virtual void match_devices_with_different_device_classes (const db::Device *a, const db::Device *b)
{
m_texts.push_back ("match_devices_with_different_device_classes " + device2str (a) + " " + device2str (b));
out ("match_devices_with_different_device_classes " + device2str (a) + " " + device2str (b));
}
virtual void match_pins (const db::Pin *a, const db::Pin *b)
{
m_texts.push_back ("match_pins " + pin2str (a) + " " + pin2str (b));
out ("match_pins " + pin2str (a) + " " + pin2str (b));
}
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b)
{
m_texts.push_back ("pin_mismatch " + pin2str (a) + " " + pin2str (b));
out ("pin_mismatch " + pin2str (a) + " " + pin2str (b));
}
virtual void match_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b)
{
m_texts.push_back ("match_subcircuits " + subcircuit2str (a) + " " + subcircuit2str (b));
out ("match_subcircuits " + subcircuit2str (a) + " " + subcircuit2str (b));
}
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b)
{
m_texts.push_back ("subcircuit_mismatch " + subcircuit2str (a) + " " + subcircuit2str (b));
out ("subcircuit_mismatch " + subcircuit2str (a) + " " + subcircuit2str (b));
}
std::string text () const
@ -1070,13 +1135,13 @@ TEST(3_Buffer)
"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 IN IN\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_pins $0 $1\n"
"match_devices $1 $1\n"
"match_devices $3 $2\n"
"match_devices $2 $3\n"
@ -1127,12 +1192,12 @@ TEST(4_BufferTwoPaths)
"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_nets IN IN\n"
"match_pins $3 $2\n"
"match_pins $1 $3\n"
"match_pins $0 $1\n"
"match_pins $2 $0\n"
"match_pins $0 $1\n"
"match_devices $1 $1\n"
"match_devices $3 $2\n"
"match_devices $5 $3\n"
@ -1146,6 +1211,70 @@ TEST(4_BufferTwoPaths)
EXPECT_EQ (good, true);
}
TEST(5_BufferTwoPathsDifferentParameters)
{
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.35,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" // NOTE: 0.35 instead of 0.25
" 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);
// Forcing the power nets into equality makes the parameter error harder to detect
const db::Circuit *ca = nl1.circuit_by_name ("BUF");
const db::Circuit *cb = nl2.circuit_by_name ("BUF");
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 BUF BUF\n"
"match_nets OUT OUT\n"
"match_nets IN IN\n"
"match_ambiguous_nets INT $10\n"
"match_nets INT2 $11\n"
"match_pins $3 $2\n"
"match_pins $1 $3\n"
"match_pins $2 $0\n"
"match_pins $0 $1\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_with_different_parameters $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.