WIP: netlist cross reference - tests and bugfixes

This commit is contained in:
Matthias Koefferlein 2019-05-16 22:43:28 +02:00
parent 924daa65b7
commit 95caca1dd5
3 changed files with 383 additions and 14 deletions

View File

@ -70,6 +70,24 @@ NetlistCrossReference::per_net_data_for (const std::pair<const db::Net *, const
return &i->second;
}
void
NetlistCrossReference::clear ()
{
mp_netlist_a.reset (0);
mp_netlist_b.reset (0);
m_circuits.clear ();
m_per_circuit_data.clear ();
m_per_net_data.clear ();
m_other_circuit.clear ();
m_other_net.clear ();
m_other_device.clear ();
m_other_pin.clear ();
m_other_subcircuit.clear ();
m_current_circuits.first = 0;
m_current_circuits.second = 0;
mp_per_circuit_data = 0;
}
void
NetlistCrossReference::begin_netlist (const db::Netlist *a, const db::Netlist *b)
{
@ -100,6 +118,68 @@ struct CircuitsCompareByName
}
};
struct SortNetTerminalsByTerminalId
{
bool operator() (const std::pair<const db::NetTerminalRef *, const db::NetTerminalRef *> &a, const std::pair<const db::NetTerminalRef *, const db::NetTerminalRef *> &b)
{
if ((a.first == 0) != (b.first == 0)) {
return (a.first == 0) > (b.first == 0);
}
if (a.first != 0 && a.first->terminal_id () != b.first->terminal_id ()) {
return a.first->terminal_id () < b.first->terminal_id ();
}
if ((a.second == 0) != (b.second == 0)) {
return (a.second == 0) > (b.second == 0);
}
if (a.second != 0 && a.second->terminal_id () != b.second->terminal_id ()) {
return a.second->terminal_id () < b.second->terminal_id ();
}
return false;
}
};
template <class Data>
struct sort_data_pairs_by_pin_name
{
bool operator() (const std::pair<const Data *, const Data *> &a, const std::pair<const Data *, const Data *> &b)
{
if ((a.first == 0) != (b.first == 0)) {
return (a.first == 0) > (b.first == 0);
}
if (a.first != 0 && a.first->pin ()->expanded_name () != b.first->pin ()->expanded_name ()) {
return a.first->pin ()->expanded_name () < b.first->pin ()->expanded_name ();
}
if ((a.second == 0) != (b.second == 0)) {
return (a.second == 0) > (b.second == 0);
}
if (a.second != 0 && a.second->pin ()->expanded_name () != b.second->pin ()->expanded_name ()) {
return a.second->pin ()->expanded_name () < b.second->pin ()->expanded_name ();
}
return false;
}
};
template <class PairData>
struct sort_pair_data_by_expanded_name
{
bool operator() (const PairData &a, const PairData &b) const
{
if ((a.pair.first == 0) != (b.pair.first == 0)) {
return (a.pair.first == 0) > (b.pair.first == 0);
}
if (a.pair.first != 0 && a.pair.first->expanded_name () != b.pair.first->expanded_name ()) {
return a.pair.first->expanded_name () < b.pair.first->expanded_name ();
}
if ((a.pair.second == 0) != (b.pair.second == 0)) {
return (a.pair.second == 0) > (b.pair.second == 0);
}
if (a.pair.second != 0 && a.pair.second->expanded_name () != b.pair.second->expanded_name ()) {
return a.pair.second->expanded_name () < b.pair.second->expanded_name ();
}
return false;
}
};
}
void
@ -192,7 +272,10 @@ NetlistCrossReference::end_circuit (const db::Circuit *, const db::Circuit *, bo
{
mp_per_circuit_data->status = matching ? Match : NoMatch;
// @@@ TODO: sort per-circuit data vectors by name?
std::sort (mp_per_circuit_data->devices.begin (), mp_per_circuit_data->devices.end (), sort_pair_data_by_expanded_name<DevicePairData> ());
std::sort (mp_per_circuit_data->pins.begin (), mp_per_circuit_data->pins.end (), sort_pair_data_by_expanded_name<PinPairData> ());
std::sort (mp_per_circuit_data->subcircuits.begin (), mp_per_circuit_data->subcircuits.end (), sort_pair_data_by_expanded_name<SubCircuitPairData> ());
std::sort (mp_per_circuit_data->nets.begin (), mp_per_circuit_data->nets.end (), sort_pair_data_by_expanded_name<NetPairData> ());
m_current_circuits = std::pair<const db::Circuit *, const db::Circuit *> (0, 0);
mp_per_circuit_data = 0;
@ -328,7 +411,7 @@ NetlistCrossReference::build_terminal_refs (const std::pair<const db::Net *, con
const db::NetTerminalRef *pb = 0;
std::map<const db::Device *, const db::Device *>::const_iterator idb = m_other_device.find (da);
if (idb != m_other_device.end ()) {
if (idb != m_other_device.end () && idb->second) {
const db::Device *db = idb->second;
@ -353,12 +436,13 @@ NetlistCrossReference::build_terminal_refs (const std::pair<const db::Net *, con
}
data.terminals.push_back (std::make_pair (a->second, pb));
}
for (std::map<std::pair<const db::Device *, size_t>, const db::NetTerminalRef *>::const_iterator b = d2t_b.begin (); b != d2t_b.end (); ++b) {
data.terminals.push_back (std::make_pair ((const db::NetTerminalRef *) 0, b->second));
}
std::sort (data.terminals.begin (), data.terminals.end (), SortNetTerminalsByTerminalId ());
}
void
@ -381,7 +465,7 @@ NetlistCrossReference::build_pin_refs (const std::pair<const db::Net *, const db
const db::NetPinRef *prb = 0;
std::map<const db::Pin *, const db::Pin *>::const_iterator ipb = m_other_pin.find (pa);
if (ipb != m_other_pin.end ()) {
if (ipb != m_other_pin.end () && ipb->second) {
const db::Pin *pb = ipb->second;
std::map<const Pin *, const db::NetPinRef *>::iterator b = p2r_b.find (pb);
@ -401,6 +485,8 @@ NetlistCrossReference::build_pin_refs (const std::pair<const db::Net *, const db
for (std::map<const Pin *, const db::NetPinRef *>::const_iterator b = p2r_b.begin (); b != p2r_b.end (); ++b) {
data.pins.push_back (std::make_pair ((const db::NetPinRef *) 0, b->second));
}
std::sort (data.pins.begin (), data.pins.end (), sort_data_pairs_by_pin_name<db::NetPinRef> ());
}
void
@ -408,11 +494,11 @@ NetlistCrossReference::build_subcircuit_pin_refs (const std::pair<const db::Net
{
std::map<std::pair<const db::SubCircuit *, size_t>, const db::NetSubcircuitPinRef *> s2t_a, s2t_b;
for (db::Net::const_subcircuit_pin_iterator i = nets.first->begin_subcircuit_pins (); i != nets.first->begin_subcircuit_pins (); ++i) {
for (db::Net::const_subcircuit_pin_iterator i = nets.first->begin_subcircuit_pins (); i != nets.first->end_subcircuit_pins (); ++i) {
s2t_a.insert (std::make_pair (std::make_pair (i->subcircuit (), i->pin_id ()), i.operator-> ()));
}
for (db::Net::const_subcircuit_pin_iterator i = nets.second->begin_subcircuit_pins (); i != nets.second->begin_subcircuit_pins (); ++i) {
for (db::Net::const_subcircuit_pin_iterator i = nets.second->begin_subcircuit_pins (); i != nets.second->end_subcircuit_pins (); ++i) {
s2t_b.insert (std::make_pair (std::make_pair (i->subcircuit (), i->pin_id ()), i.operator-> ()));
}
@ -423,7 +509,7 @@ NetlistCrossReference::build_subcircuit_pin_refs (const std::pair<const db::Net
const db::NetSubcircuitPinRef *pb = 0;
std::map<const db::SubCircuit *, const db::SubCircuit *>::const_iterator isb = m_other_subcircuit.find (sa);
if (isb != m_other_subcircuit.end ()) {
if (isb != m_other_subcircuit.end () && isb->second) {
const db::SubCircuit *sb = isb->second;
@ -452,6 +538,8 @@ NetlistCrossReference::build_subcircuit_pin_refs (const std::pair<const db::Net
for (std::map<std::pair<const db::SubCircuit *, size_t>, const db::NetSubcircuitPinRef *>::const_iterator b = s2t_b.begin (); b != s2t_b.end (); ++b) {
data.subcircuit_pins.push_back (std::make_pair ((const db::NetSubcircuitPinRef *) 0, b->second));
}
std::sort (data.subcircuit_pins.begin (), data.subcircuit_pins.end (), sort_data_pairs_by_pin_name<db::NetSubcircuitPinRef> ());
}
void

View File

@ -97,15 +97,31 @@ public:
{
PerCircuitData () : status (None) { }
typedef std::vector<NetPairData> net_pairs_type;
typedef net_pairs_type::const_iterator net_pairs_const_iterator;
typedef std::vector<DevicePairData> device_pairs_type;
typedef device_pairs_type::const_iterator device_pairs_const_iterator;
typedef std::vector<PinPairData> pin_pairs_type;
typedef pin_pairs_type::const_iterator pin_pairs_const_iterator;
typedef std::vector<SubCircuitPairData> subcircuit_pairs_type;
typedef subcircuit_pairs_type::const_iterator subcircuit_pairs_const_iterator;
Status status;
std::vector<NetPairData> nets;
std::vector<DevicePairData> devices;
std::vector<PinPairData> pins;
std::vector<SubCircuitPairData> subcircuits;
net_pairs_type nets;
device_pairs_type devices;
pin_pairs_type pins;
subcircuit_pairs_type subcircuits;
};
struct PerNetData
{
typedef std::vector<std::pair<const db::NetTerminalRef *, const db::NetTerminalRef *> > terminal_pairs_type;
typedef terminal_pairs_type::const_iterator terminal_pairs_const_iterator;
typedef std::vector<std::pair<const db::NetPinRef *, const db::NetPinRef *> > pin_pairs_type;
typedef pin_pairs_type::const_iterator pin_pairs_const_iterator;
typedef std::vector<std::pair<const db::NetSubcircuitPinRef *, const db::NetSubcircuitPinRef *> > subcircuit_pin_pairs_type;
typedef subcircuit_pin_pairs_type::const_iterator subcircuit_pin_pairs_const_iterator;
std::vector<std::pair<const db::NetTerminalRef *, const db::NetTerminalRef *> > terminals;
std::vector<std::pair<const db::NetPinRef *, const db::NetPinRef *> > pins;
std::vector<std::pair<const db::NetSubcircuitPinRef *, const db::NetSubcircuitPinRef *> > subcircuit_pins;
@ -130,6 +146,8 @@ public:
virtual void match_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b);
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b);
void clear ();
size_t circuit_count () const
{
return m_per_circuit_data.size ();

View File

@ -181,17 +181,57 @@ std::string xref_status2s (db::NetlistCrossReference::Status status)
}
template <class Obj>
std::string name_of (const Obj *obj)
static std::string name_of (const Obj *obj)
{
return obj ? obj->name () : std::string ("(null)");
}
template <class Obj>
std::string expanded_name_of (const Obj *obj)
static std::string expanded_name_of (const Obj *obj)
{
return obj ? obj->expanded_name () : std::string ("(null)");
}
template <class PairData>
static
std::string dp2s (const PairData &dp)
{
return expanded_name_of (dp.pair.first) + ":" + expanded_name_of (dp.pair.second) + " [" + xref_status2s (dp.status) + "]";
}
static std::string ne2s (const db::NetTerminalRef *ref)
{
if (ref) {
return expanded_name_of (ref->device ()) + "[" + name_of (ref->terminal_def ()) + "]";
} else {
return "(null)";
}
}
static std::string ne2s (const db::NetSubcircuitPinRef *ref)
{
if (ref) {
return expanded_name_of (ref->subcircuit ()) + "[" + expanded_name_of (ref->pin ()) + "]";
} else {
return "(null)";
}
}
static std::string ne2s (const db::NetPinRef *ref)
{
if (ref) {
return expanded_name_of (ref->pin ());
} else {
return "(null)";
}
}
template <class Data>
static std::string nep2s (const std::pair<const Data *, const Data *> &p)
{
return ne2s (p.first) + ":" + ne2s (p.second);
}
std::string xref2s (const db::NetlistCrossReference &xref)
{
std::string s;
@ -203,7 +243,28 @@ std::string xref2s (const db::NetlistCrossReference &xref)
s += name_of (c->first) + ":" + name_of (c->second) + " [" + xref_status2s (pcd->status) + "]:\n";
//@@@
for (db::NetlistCrossReference::PerCircuitData::pin_pairs_const_iterator i = pcd->pins.begin (); i != pcd->pins.end (); ++i) {
s += " pin " + dp2s (*i) + "\n";
}
for (db::NetlistCrossReference::PerCircuitData::net_pairs_const_iterator i = pcd->nets.begin (); i != pcd->nets.end (); ++i) {
s += " net " + dp2s (*i) + "\n";
const db::NetlistCrossReference::PerNetData *pnd = xref.per_net_data_for (i->pair);
for (db::NetlistCrossReference::PerNetData::terminal_pairs_const_iterator j = pnd->terminals.begin (); j != pnd->terminals.end (); ++j) {
s += " terminal " + nep2s (*j) + "\n";
}
for (db::NetlistCrossReference::PerNetData::pin_pairs_const_iterator j = pnd->pins.begin (); j != pnd->pins.end (); ++j) {
s += " pin " + nep2s (*j) + "\n";
}
for (db::NetlistCrossReference::PerNetData::subcircuit_pin_pairs_const_iterator j = pnd->subcircuit_pins.begin (); j != pnd->subcircuit_pins.end (); ++j) {
s += " subcircuit_pin " + nep2s (*j) + "\n";
}
}
for (db::NetlistCrossReference::PerCircuitData::device_pairs_const_iterator i = pcd->devices.begin (); i != pcd->devices.end (); ++i) {
s += " device " + dp2s (*i) + "\n";
}
for (db::NetlistCrossReference::PerCircuitData::subcircuit_pairs_const_iterator i = pcd->subcircuits.begin (); i != pcd->subcircuits.end (); ++i) {
s += " subcircuit " + dp2s (*i) + "\n";
}
}
@ -414,6 +475,22 @@ TEST(1_SimpleInverter)
EXPECT_EQ (xref2s (xref),
"INV:INV [Match]:\n"
" pin $0:$1 [Match]\n"
" pin $1:$3 [Match]\n"
" pin $2:$0 [Match]\n"
" pin $3:$2 [Match]\n"
" net IN:IN [Match]\n"
" terminal $1[G]:$2[G]\n"
" terminal $2[G]:$1[G]\n"
" net OUT:OUT [Match]\n"
" terminal $2[D]:$1[S]\n"
" terminal $1[D]:$2[D]\n"
" net VDD:VDD [Match]\n"
" terminal $1[S]:$2[S]\n"
" net VSS:VSS [Match]\n"
" terminal $2[S]:$1[D]\n"
" device $1:$2 [Match]\n"
" device $2:$1 [Match]\n"
);
EXPECT_EQ (good, true);
}
@ -511,6 +588,38 @@ TEST(1_SimpleInverterSkippedDevices)
);
EXPECT_EQ (good, false);
db::NetlistCrossReference xref;
db::NetlistComparer comp_xref (&xref);
good = comp_xref.compare (&nl1, &nl2);
EXPECT_EQ (xref2s (xref),
"INV:INV [NoMatch]:\n"
" pin $0:$1 [Match]\n"
" pin $1:$3 [Match]\n"
" pin $2:$0 [Match]\n"
" pin $3:$2 [Match]\n"
" net IN:IN [Mismatch]\n"
" terminal (null):$3[B]\n"
" terminal $1[G]:$4[G]\n"
" terminal $2[B]:$2[B]\n"
" terminal $3[G]:$1[G]\n"
" net OUT:OUT [Mismatch]\n"
" terminal (null):$3[A]\n"
" terminal $2[A]:$2[A]\n"
" terminal $3[D]:$1[S]\n"
" terminal $1[D]:$4[D]\n"
" net VDD:VDD [Match]\n"
" terminal $1[S]:$4[S]\n"
" net VSS:VSS [Match]\n"
" terminal $3[S]:$1[D]\n"
" device (null):$3 [Mismatch]\n"
" device $1:$4 [Match]\n"
" device $2:$2 [MatchWithWarning]\n"
" device $3:$1 [Match]\n"
);
EXPECT_EQ (good, false);
comp.exclude_caps (1e-11);
comp.exclude_resistors (900.0);
@ -532,6 +641,40 @@ TEST(1_SimpleInverterSkippedDevices)
"end_circuit INV INV MATCH"
);
EXPECT_EQ (good, true);
xref.clear ();
comp_xref.exclude_caps (1e-11);
comp_xref.exclude_resistors (900.0);
good = comp_xref.compare (&nl1, &nl2);
EXPECT_EQ (xref2s (xref),
"INV:INV [Match]:\n"
" pin $0:$1 [Match]\n"
" pin $1:$3 [Match]\n"
" pin $2:$0 [Match]\n"
" pin $3:$2 [Match]\n"
" net IN:IN [Match]\n"
" terminal (null):$2[B]\n"
" terminal (null):$3[B]\n"
" terminal $2[B]:(null)\n"
" terminal $1[G]:$4[G]\n"
" terminal $3[G]:$1[G]\n"
" net OUT:OUT [Match]\n"
" terminal (null):$2[A]\n"
" terminal (null):$3[A]\n"
" terminal $2[A]:(null)\n"
" terminal $3[D]:$1[S]\n"
" terminal $1[D]:$4[D]\n"
" net VDD:VDD [Match]\n"
" terminal $1[S]:$4[S]\n"
" net VSS:VSS [Match]\n"
" terminal $3[S]:$1[D]\n"
" device $1:$4 [Match]\n"
" device $3:$1 [Match]\n"
);
EXPECT_EQ (good, true);
}
TEST(2_SimpleInverterWithForcedNetAssignment)
@ -1498,6 +1641,56 @@ TEST(11_MismatchingSubcircuits)
);
EXPECT_EQ (good, false);
db::NetlistCrossReference xref;
db::NetlistComparer comp_xref (&xref);
good = comp_xref.compare (&nl1, &nl2);
EXPECT_EQ (xref2s (xref),
"INV:INV [NoMatch]:\n"
" pin $0:$1 [Match]\n"
" pin $1:$3 [Match]\n"
" pin $2:$0 [Match]\n"
" pin $3:$2 [Match]\n"
" net IN:IN [Mismatch]\n"
" terminal (null):$2[S]\n"
" terminal (null):$2[G]\n"
" terminal $1[G]:(null)\n"
" terminal $2[G]:$1[G]\n"
" net OUT:OUT [Mismatch]\n"
" terminal (null):$2[D]\n"
" terminal $1[D]:(null)\n"
" terminal $2[D]:$1[S]\n"
" net VDD:VDD [Mismatch]\n"
" terminal $1[S]:(null)\n"
" net VSS:VSS [Match]\n"
" terminal $2[S]:$1[D]\n"
" device (null):$2 [Mismatch]\n"
" device $1:(null) [Mismatch]\n"
" device $2:$1 [Match]\n"
"TOP:TOP [Match]:\n"
" pin $0:$2 [Match]\n"
" pin $1:$0 [Match]\n"
" pin $2:$1 [Match]\n"
" pin $3:$3 [Match]\n"
" net IN:IN [Match]\n"
" subcircuit_pin $1[$0]:$2[$1]\n"
" net INT:INT [Match]\n"
" subcircuit_pin $2[$0]:$1[$1]\n"
" subcircuit_pin $1[$1]:$2[$3]\n"
" net OUT:OUT [Match]\n"
" subcircuit_pin $2[$1]:$1[$3]\n"
" net VDD:VDD [Match]\n"
" subcircuit_pin $2[$2]:$1[$0]\n"
" subcircuit_pin $1[$2]:$2[$0]\n"
" net VSS:VSS [Match]\n"
" subcircuit_pin $2[$3]:$1[$2]\n"
" subcircuit_pin $1[$3]:$2[$2]\n"
" subcircuit $1:$2 [Match]\n"
" subcircuit $2:$1 [Match]\n"
);
EXPECT_EQ (good, false);
}
TEST(12_MismatchingSubcircuitsDuplicates)
@ -1779,6 +1972,76 @@ TEST(14_Subcircuit2NandMismatchNoSwap)
);
EXPECT_EQ (good, false);
db::NetlistCrossReference xref;
db::NetlistComparer comp_xref (&xref);
good = comp_xref.compare (&nl1, &nl2);
EXPECT_EQ (xref2s (xref),
"NAND:NAND [Match]:\n"
" pin $0:$0 [Match]\n"
" pin $1:$1 [Match]\n"
" pin $2:$2 [Match]\n"
" pin $3:$3 [Match]\n"
" pin $4:$4 [Match]\n"
" net A:A [Match]\n"
" terminal $3[G]:$3[G]\n"
" terminal $1[G]:$1[G]\n"
" net B:B [Match]\n"
" terminal $4[G]:$4[G]\n"
" terminal $2[G]:$2[G]\n"
" net INT:INT [Match]\n"
" terminal $4[S]:$4[S]\n"
" terminal $3[D]:$3[D]\n"
" net OUT:OUT [Match]\n"
" terminal $4[D]:$4[D]\n"
" terminal $1[D]:$1[D]\n"
" terminal $2[D]:$2[D]\n"
" net VDD:VDD [Match]\n"
" terminal $1[S]:$1[S]\n"
" terminal $2[S]:$2[S]\n"
" net VSS:VSS [Match]\n"
" terminal $3[S]:$3[S]\n"
" device $1:$1 [Match]\n"
" device $2:$2 [Match]\n"
" device $3:$3 [Match]\n"
" device $4:$4 [Match]\n"
"TOP:TOP [NoMatch]:\n"
" pin (null):$0 [Mismatch]\n"
" pin $0:(null) [Mismatch]\n"
" pin $1:$1 [Match]\n"
" pin $2:$2 [Match]\n"
" pin $3:$3 [Match]\n"
" pin $4:$4 [Match]\n"
" net IN1:INT [Mismatch]\n"
" pin $0:(null)\n"
" subcircuit_pin (null):$2[$2]\n"
" subcircuit_pin $1[$0]:(null)\n"
" subcircuit_pin $2[$0]:$1[$0]\n"
" net IN2:IN2 [Mismatch]\n"
" subcircuit_pin (null):$2[$0]\n"
" subcircuit_pin $1[$1]:(null)\n"
" net INT:IN1 [Mismatch]\n"
" pin (null):$0\n"
" subcircuit_pin (null):$2[$1]\n"
" subcircuit_pin $2[$1]:$1[$1]\n"
" subcircuit_pin $1[$2]:(null)\n"
" net OUT:OUT [Match]\n"
" subcircuit_pin $2[$2]:$1[$2]\n"
" net VDD:VDD [Mismatch]\n"
" subcircuit_pin (null):$2[$3]\n"
" subcircuit_pin $1[$3]:(null)\n"
" subcircuit_pin $2[$3]:$1[$3]\n"
" net VSS:VSS [Mismatch]\n"
" subcircuit_pin (null):$2[$4]\n"
" subcircuit_pin $1[$4]:(null)\n"
" subcircuit_pin $2[$4]:$1[$4]\n"
" subcircuit (null):$2 [Mismatch]\n"
" subcircuit $1:(null) [Mismatch]\n"
" subcircuit $2:$1 [Match]\n"
);
EXPECT_EQ (good, false);
}
TEST(14_Subcircuit2MatchWithSwap)