Netlist compare: Net mismatches reported if nets don't match but we still will proceed

This commit is contained in:
Matthias Koefferlein 2019-04-18 00:01:21 +02:00
parent 213a6f306b
commit 8121f70e65
5 changed files with 230 additions and 90 deletions

View File

@ -38,6 +38,13 @@ namespace db
// --------------------------------------------------------------------------------------------------------------------
// DeviceCompare definition and implementation
/**
* @brief The device compare function with "less" (operator()) and "equal" predicates
*
* Device comparison is based on the equivalence of device classes (by category) and
* in a second step, by equivalence of the devices. The device class will implement
* the device equivalence function.
*/
struct DeviceCompare
{
bool operator() (const std::pair<const db::Device *, size_t> &d1, const std::pair<const db::Device *, size_t> &d2) const
@ -60,6 +67,12 @@ struct DeviceCompare
// --------------------------------------------------------------------------------------------------------------------
// SubCircuitCompare definition and implementation
/**
* @brief The compare function for subcircuits
*
* As Subcircuits are not parametrized, the comparison of subcircuits is only based on
* the circuit equivalence (via category).
*/
struct SubCircuitCompare
{
bool operator() (const std::pair<const db::SubCircuit *, size_t> &sc1, const std::pair<const db::SubCircuit *, size_t> &sc2) const
@ -76,6 +89,14 @@ struct SubCircuitCompare
// --------------------------------------------------------------------------------------------------------------------
// CircuitPinMapper definition and implementation
/**
* @brief The Circuit pin mapper handles swappable pin definitions per circuit
*
* Swappable pins are implemented by mapping a pin ID to an equivalent or
* effective ID which is shared by all swappable pins.
*
* This class manages swappable pins on a per-circuit basis.
*/
class CircuitPinMapper
{
public:
@ -130,6 +151,15 @@ private:
// --------------------------------------------------------------------------------------------------------------------
// CircuitMapper definition and implementation
/**
* @brief A circuit mapper
*
* The circuit mapper handles the circuit equivalence between the circuits of
* netlist A and B and also the pin mapping between the circuits from these netlists.
*
* The "other" attribute will hold the circuit for the other netlist.
* The other methods handle pin mapping from "other" into "this" pin space.
*/
class CircuitMapper
{
public:
@ -187,6 +217,13 @@ private:
// --------------------------------------------------------------------------------------------------------------------
// DeviceFilter definition and implementation
/**
* @brief A device filter class
*
* This class implements a device filter which is used to skip devices when
* generating the net graph. This is useful for stripping small caps or big
* resistors.
*/
class DeviceFilter
{
public:
@ -221,6 +258,12 @@ private:
// --------------------------------------------------------------------------------------------------------------------
// DeviceCategorizer definition and implementation
/**
* @brief A device categorizer
*
* The objective of this class is to supply a category ID for a given device class.
* The category ID also identities equivalent device classes from netlist A and B.
*/
class DeviceCategorizer
{
public:
@ -280,6 +323,12 @@ public:
// --------------------------------------------------------------------------------------------------------------------
// CircuitCategorizer definition and implementation
/**
* @brief A circuit categorizer
*
* The objective of this class is to supply a category ID for a given device circuit.
* The category ID also identities equivalent circuit from netlist A and B.
*/
class CircuitCategorizer
{
public:
@ -332,19 +381,39 @@ public:
};
// --------------------------------------------------------------------------------------------------------------------
// NetDeviceGraphNode definition and implementation
// NetGraphNode definition and implementation
static size_t translate_terminal_id (size_t tid, const db::Device *device)
{
return device->device_class () ? device->device_class ()->normalize_terminal_id (tid) : tid;
}
/**
* @brief A node within the net graph
*
* This class represents a node and the edges leading from this node to
* other nodes.
*
* A graph edge is a collection of transitions, connecting terminals of
* devices or pins of subcircuits plus the index of node at the other end
* of the edge.
*
* Transitions are sorted within the edge.
*/
class NetGraphNode
{
public:
struct EdgeDesc {
/**
* @brief Represents one transition within an edge_iterator
*
* Each transition connects two pins of subcircuits or terminals
* of devices.
* An edge is basically a collection of transitions.
*/
struct Transition
{
EdgeDesc (const db::Device *device, size_t device_category, size_t terminal1_id, size_t terminal2_id)
Transition (const db::Device *device, size_t device_category, size_t terminal1_id, size_t terminal2_id)
{
device_pair ().first = device;
device_pair ().second = device_category;
@ -352,7 +421,7 @@ public:
m_id2 = terminal2_id;
}
EdgeDesc (const db::SubCircuit *subcircuit, size_t subcircuit_category, size_t pin1_id, size_t pin2_id)
Transition (const db::SubCircuit *subcircuit, size_t subcircuit_category, size_t pin1_id, size_t pin2_id)
{
subcircuit_pair ().first = subcircuit;
subcircuit_pair ().second = subcircuit_category;
@ -360,7 +429,7 @@ public:
m_id2 = pin2_id;
}
bool operator< (const EdgeDesc &other) const
bool operator< (const Transition &other) const
{
if (is_for_subcircuit () != other.is_for_subcircuit ()) {
return is_for_subcircuit () < other.is_for_subcircuit ();
@ -400,7 +469,7 @@ public:
return m_id2 < other.m_id2;
}
bool operator== (const EdgeDesc &other) const
bool operator== (const Transition &other) const
{
if (is_for_subcircuit () != other.is_for_subcircuit ()) {
return false;
@ -469,13 +538,13 @@ public:
struct EdgeToEdgeOnlyCompare
{
bool operator() (const std::pair<std::vector<EdgeDesc>, std::pair<size_t, const db::Net *> > &a, const std::vector<EdgeDesc> &b) const
bool operator() (const std::pair<std::vector<Transition>, std::pair<size_t, const db::Net *> > &a, const std::vector<Transition> &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;
typedef std::vector<std::pair<std::vector<Transition>, std::pair<size_t, const db::Net *> > >::const_iterator edge_iterator;
NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map)
: mp_net (net), m_other_net_index (std::numeric_limits<size_t>::max ())
@ -560,14 +629,14 @@ public:
// NOTE: if a pin mapping is given, EdgeDesc::pin1_id and EdgeDesc::pin2_id are given
// as pin ID's of the other circuit.
EdgeDesc ed (sc, circuit_categorizer.cat_for_subcircuit (sc), pin_id, pin_map->normalize_pin_id (cr, pin2_id));
Transition ed (sc, circuit_categorizer.cat_for_subcircuit (sc), pin_id, pin_map->normalize_pin_id (cr, pin2_id));
const db::Net *net2 = sc->net_for_pin (this_pin2_id);
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 (size_t (0), net2)));
m_edges.push_back (std::make_pair (std::vector<Transition> (), std::make_pair (size_t (0), net2)));
}
m_edges [in->second].first.push_back (ed);
@ -592,14 +661,14 @@ public:
if (it->id () != i->terminal_id ()) {
size_t terminal2_id = translate_terminal_id (it->id (), d);
EdgeDesc ed2 (d, device_cat, terminal1_id, terminal2_id);
Transition ed2 (d, device_cat, terminal1_id, terminal2_id);
const db::Net *net2 = d->net_for_terminal (it->id ());
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 (size_t (0), net2)));
m_edges.push_back (std::make_pair (std::vector<Transition> (), std::make_pair (size_t (0), net2)));
}
m_edges [in->second].first.push_back (ed2);
@ -643,14 +712,14 @@ public:
void apply_net_index (const std::map<const db::Net *, size_t> &ni)
{
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) {
for (std::vector<std::pair<std::vector<Transition>, 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.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) {
for (std::vector<std::pair<std::vector<Transition>, 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 ());
}
@ -708,7 +777,7 @@ public:
return m_edges.end ();
}
edge_iterator find_edge (const std::vector<EdgeDesc> &edge) const
edge_iterator find_edge (const std::vector<Transition> &edge) const
{
edge_iterator res = std::lower_bound (begin (), end (), edge, NetGraphNode::EdgeToEdgeOnlyCompare ());
if (res == end () || res->first != edge) {
@ -721,7 +790,7 @@ public:
private:
const db::Net *mp_net;
size_t m_other_net_index;
std::vector<std::pair<std::vector<EdgeDesc>, std::pair<size_t, const db::Net *> > > m_edges;
std::vector<std::pair<std::vector<Transition>, std::pair<size_t, const db::Net *> > > m_edges;
/**
* @brief Compares edges as "less"
@ -777,7 +846,7 @@ private:
};
// --------------------------------------------------------------------------------------------------------------------
// NetDeviceGraph definition and implementation
// NetGraph definition and implementation
}
@ -802,18 +871,27 @@ struct CompareNodePtr
class TentativeNodeMapping;
class NetDeviceGraph
/**
* @brief The net graph for the compare algorithm
*/
class NetGraph
{
public:
typedef std::vector<NetGraphNode>::const_iterator node_iterator;
NetDeviceGraph ()
NetGraph ()
{
// .. nothing yet ..
}
/**
* @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<const db::Circuit *, CircuitMapper> *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper);
/**
* @brief Gets the node index for the given net
*/
size_t node_index_for_net (const db::Net *net) const
{
std::map<const db::Net *, size_t>::const_iterator j = m_net_index.find (net);
@ -821,31 +899,65 @@ public:
return j->second;
}
/**
* @brief Gets the node for a given node index
*/
const db::NetGraphNode &node (size_t net_index) const
{
return m_nodes [net_index];
}
/**
* @brief Gets the node for a given node index (non-const version)
*/
db::NetGraphNode &node (size_t net_index)
{
return m_nodes [net_index];
}
/**
* @brief Gets the net for a given node index
*/
const db::Net *net_by_node_index (size_t net_index) const
{
return m_nodes [net_index].net ();
}
/**
* @brief Establishes an equivalence between two nodes of netlist A (this) and B (other)
*/
void identify (size_t net_index, size_t other_net_index)
{
m_nodes [net_index].set_other_net (other_net_index);
}
/**
* @brief Removes the equivalence from the node with the given index
*/
void unidentify (size_t net_index)
{
m_nodes [net_index].unset_other_net ();
}
/**
* @brief Iterator over the nodes in this graph (begin)
*/
node_iterator begin () const
{
return m_nodes.begin ();
}
/**
* @brief Iterator over the nodes in this graph (end)
*/
node_iterator end () const
{
return m_nodes.end ();
}
/**
* @brief The circuit this graph is associated with
*/
const db::Circuit *circuit () const
{
return mp_circuit;
@ -870,14 +982,22 @@ public:
* backtracking depth (number of graph jumps) and decision tree
* branching complexity N (="n_branch", means: N*N decisions to be made).
*
* The limits "depth_max" and "n_branch_max" are attributes of the graph.
* If "tentative" is non-null, assignments will be recorded in the TentativeMapping
* audit object and can be undone afterwards when backtracking recursion happens.
*
* If tentative is true, assignments will not be retained and just the
* status is reported.
* If "with_ambiguous" is true, ambiguous matches are considered. This will happen
* in a second pass to give exact and unique matches priority over ambiguous matches.
*/
size_t derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous);
size_t derive_node_identities (size_t net_index, NetGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous);
size_t derive_node_identities_from_node_set (const std::vector<const NetGraphNode *> &nodes, const std::vector<const NetGraphNode *> &other_nodes, NetDeviceGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous);
/**
* @brief The backtracking driver
*
* This method will analyze the given nodes and call "derive_node_identities" for all nodes
* with a proposed identity. With "with_ambiguous", amiguities are resolved by trying
* different combinations in tentative mode and deciding for one combination if possible.
*/
size_t derive_node_identities_from_node_set (const std::vector<const NetGraphNode *> &nodes, const std::vector<const NetGraphNode *> &other_nodes, NetGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous);
private:
std::vector<NetGraphNode> m_nodes;
@ -887,6 +1007,9 @@ private:
// --------------------------------------------------------------------------------------------------------------------
/**
* @brief Represents an interval of NetGraphNode objects in a node set
*/
struct NodeRange
{
NodeRange (size_t _num, std::vector<const NetGraphNode *>::const_iterator _n1, std::vector<const NetGraphNode *>::const_iterator _nn1, std::vector<const NetGraphNode *>::const_iterator _n2, std::vector<const NetGraphNode *>::const_iterator _nn2)
@ -906,10 +1029,13 @@ struct NodeRange
// --------------------------------------------------------------------------------------------------------------------
/**
* @brief An audit object which allows reverting tentative node assignments
*/
class TentativeNodeMapping
{
public:
TentativeNodeMapping (NetDeviceGraph *g1, NetDeviceGraph *g2)
TentativeNodeMapping (NetGraph *g1, NetGraph *g2)
: mp_g1 (g1), mp_g2 (g2)
{ }
@ -921,7 +1047,7 @@ public:
}
}
static void map_pair (TentativeNodeMapping *nm, NetDeviceGraph *g1, size_t n1, NetDeviceGraph *g2, size_t n2)
static void map_pair (TentativeNodeMapping *nm, NetGraph *g1, size_t n1, NetGraph *g2, size_t n2)
{
g1->identify (n1, n2);
g2->identify (n2, n1);
@ -932,7 +1058,7 @@ public:
private:
std::vector<std::pair<size_t, size_t> > m_to_undo;
NetDeviceGraph *mp_g1, *mp_g2;
NetGraph *mp_g1, *mp_g2;
void keep (size_t n1, size_t n2)
{
@ -941,9 +1067,10 @@ private:
};
// --------------------------------------------------------------------------------------------------------------------
// NetGraph implementation
void
NetDeviceGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *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<const db::Circuit *, CircuitMapper> *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper)
{
tl::SelfTimer timer (tl::verbosity () >= 31, tl::to_string (tr ("Building net graph for circuit: ")) + c->name ());
@ -979,10 +1106,10 @@ NetDeviceGraph::build (const db::Circuit *c, DeviceCategorizer &device_categoriz
}
size_t
NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous)
NetGraph::derive_node_identities (size_t net_index, NetGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous)
{
NetGraphNode *n = & m_nodes[net_index];
NetGraphNode *nother = & other.m_nodes[n->other_net_index ()];
NetGraphNode *n = & node (net_index);
NetGraphNode *nother = & other.node (n->other_net_index ());
#if defined(PRINT_DEBUG_NETCOMPARE)
std::string indent;
@ -1018,7 +1145,7 @@ NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other,
other_nodes.reserve (ee - e);
for (NetGraphNode::edge_iterator i = e; i != ee; ++i) {
const NetGraphNode *n = &m_nodes[i->second.first];
const NetGraphNode *n = &node (i->second.first);
nodes.push_back (n);
}
@ -1037,7 +1164,7 @@ NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other,
size_t count_other = 0;
for (NetGraphNode::edge_iterator i = e_other; i != ee_other && count_other < 2; ++i) {
const NetGraphNode *n = &other.m_nodes[i->second.first];
const NetGraphNode *n = &other.node (i->second.first);
other_nodes.push_back (n);
}
@ -1099,7 +1226,7 @@ NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other,
}
size_t
NetDeviceGraph::derive_node_identities_from_node_set (const std::vector<const NetGraphNode *> &nodes, const std::vector<const NetGraphNode *> &other_nodes, NetDeviceGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous)
NetGraph::derive_node_identities_from_node_set (const std::vector<const NetGraphNode *> &nodes, const std::vector<const NetGraphNode *> &other_nodes, NetGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous)
{
#if defined(PRINT_DEBUG_NETCOMPARE)
std::string indent;
@ -1133,8 +1260,11 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector<const Ne
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::info << indent << "deduced match (singular): " << nodes.front ()->net ()->expanded_name () << " vs. " << other_nodes.front ()->net ()->expanded_name ();
#endif
if (! tentative) {
if (logger) {
if (logger && ! tentative) {
if (! (node (ni) == other.node (other_ni))) {
// this is a mismatch but we continue, because that is the only candidate
logger->net_mismatch (nodes.front ()->net (), other_nodes.front ()->net ());
} else {
logger->match_nets (nodes.front ()->net (), other_nodes.front ()->net ());
}
}
@ -1279,8 +1409,11 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector<const Ne
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::info << indent << "deduced match (singular): " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
#endif
if (! tentative) {
if (logger) {
if (logger && ! tentative) {
if (! (node (ni) == other.node (other_ni))) {
// this is a mismatch, but we continue with this
logger->net_mismatch ((*nr->n1)->net (), (*nr->n2)->net ());
} else {
logger->match_nets ((*nr->n1)->net (), (*nr->n2)->net ());
}
}
@ -1694,7 +1827,7 @@ NetlistComparer::all_subcircuits_verified (const db::Circuit *c, const std::set<
}
static std::vector<std::pair<size_t, size_t> >
compute_device_key (const db::Device &device, const db::NetDeviceGraph &g)
compute_device_key (const db::Device &device, const db::NetGraph &g)
{
std::vector<std::pair<size_t, size_t> > k;
@ -1712,7 +1845,7 @@ compute_device_key (const db::Device &device, const db::NetDeviceGraph &g)
}
static std::vector<std::pair<size_t, size_t> >
compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetDeviceGraph &g, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map)
compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetGraph &g, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map)
{
std::vector<std::pair<size_t, size_t> > k;
@ -1755,7 +1888,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
{
db::DeviceFilter device_filter (m_cap_threshold, m_res_threshold);
db::NetDeviceGraph g1, g2;
db::NetGraph g1, g2;
// NOTE: for normalization we map all subcircuits of c1 to c2.
// Also, pin swapping will only happen there.
@ -1800,7 +1933,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
size_t new_identities = 0;
for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) {
for (db::NetGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) {
if (i1->has_other () && i1->net ()) {
size_t ni = g1.derive_node_identities (i1 - g1.begin (), g2, 0, m_max_depth, 1, m_max_n_branch, mp_logger, &circuit_pin_mapper, 0 /*not tentative*/, pass > 0 /*with ambiguities*/);
if (ni > 0 && ni != std::numeric_limits<size_t>::max ()) {
@ -1821,14 +1954,14 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
std::vector<const NetGraphNode *> nodes, other_nodes;
nodes.reserve (g1.end () - g1.begin ());
for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) {
for (db::NetGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) {
if (! i1->has_other () && i1->net ()) {
nodes.push_back (i1.operator-> ());
}
}
other_nodes.reserve (g2.end () - g2.begin ());
for (db::NetDeviceGraph::node_iterator i2 = g2.begin (); i2 != g2.end (); ++i2) {
for (db::NetGraph::node_iterator i2 = g2.begin (); i2 != g2.end (); ++i2) {
if (! i2->has_other () && i2->net ()) {
other_nodes.push_back (i2.operator-> ());
}
@ -1864,13 +1997,13 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
// Report missing net assignment
for (db::NetDeviceGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) {
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);
}
}
for (db::NetDeviceGraph::node_iterator i = g2.begin (); i != g2.end (); ++i) {
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 ());
}

View File

@ -99,6 +99,9 @@ public:
/**
* @brief Net a or b doesn't match
* "a" is null if there is no match for b and vice versa.
* In some cases, a mismatch is reported with two nets given. This means,
* nets are known not to match. Still the compare algorithm will proceed as
* if these nets were equivalent to derive further matches.
*/
virtual void net_mismatch (const db::Net * /*a*/, const db::Net * /*b*/) { }

View File

@ -374,6 +374,10 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger ("db", "Gene
"@brief This function is called when a net can't be paired.\n"
"This method will be called, if a net cannot be identified as identical with another net. The corresponding argument "
"will identify the net and source netlist. The other argument will be nil.\n"
"\n"
"In some cases, a mismatch is reported with two nets given. This means,\n"
"nets are known not to match. Still the compare algorithm will proceed as\n"
"if these nets were equivalent to derive further matches.\n"
) +
gsi::callback ("match_devices", &GenericNetlistCompareLogger::match_devices, &GenericNetlistCompareLogger::cb_match_devices, gsi::arg ("a"), gsi::arg ("b"),
"@brief This function is called when two devices are identified.\n"

View File

@ -438,9 +438,9 @@ TEST(1_SimpleInverterSkippedDevices)
EXPECT_EQ (logger.text (),
"begin_circuit INV INV\n"
"match_nets VDD VDD\n"
"match_nets OUT OUT\n"
"net_mismatch OUT OUT\n"
"match_nets VSS VSS\n"
"match_nets IN IN\n"
"net_mismatch IN IN\n"
"match_pins $0 $1\n"
"match_pins $1 $3\n"
"match_pins $2 $0\n"
@ -670,8 +670,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
"begin_circuit BUF BUF\n"
"match_nets OUT OUT\n"
"match_nets INT $10\n"
"match_nets IN IN\n"
"match_nets INT2 $11\n"
"net_mismatch IN IN\n"
"net_mismatch INT2 $11\n"
"match_pins $0 $1\n"
"match_pins $1 $3\n"
"match_pins $2 $0\n"
@ -722,8 +722,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
"begin_circuit BUF BUF\n"
"match_nets OUT OUT\n"
"match_nets INT $10\n"
"match_nets IN IN\n"
"match_nets INT2 $11\n"
"net_mismatch IN IN\n"
"net_mismatch INT2 $11\n"
"match_pins $0 $1\n"
"match_pins $1 $3\n"
"match_pins $2 $0\n"
@ -748,8 +748,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
"begin_circuit BUF BUF\n"
"match_nets OUT OUT\n"
"match_nets INT $10\n"
"match_nets IN IN\n"
"match_nets INT2 $11\n"
"net_mismatch IN IN\n"
"net_mismatch INT2 $11\n"
"match_pins $0 $1\n"
"match_pins $1 $3\n"
"match_pins $2 $0\n"
@ -828,8 +828,8 @@ TEST(5_BufferTwoPathsDifferentParameters)
"begin_circuit BUF BUF\n"
"match_nets OUT OUT\n"
"match_nets INT $10\n"
"match_nets IN IN\n"
"match_nets INT2 $11\n"
"net_mismatch IN IN\n"
"net_mismatch INT2 $11\n"
"match_pins $0 $1\n"
"match_pins $1 $3\n"
"match_pins $2 $0\n"
@ -892,8 +892,8 @@ TEST(5_BufferTwoPathsDifferentDeviceClasses)
"begin_circuit BUF BUF\n"
"match_nets INT $10\n"
"match_nets IN IN\n"
"match_nets OUT OUT\n"
"match_nets INT2 $11\n"
"net_mismatch OUT OUT\n"
"net_mismatch INT2 $11\n"
"match_pins $0 $1\n"
"match_pins $1 $3\n"
"match_pins $2 $0\n"
@ -955,10 +955,10 @@ TEST(6_BufferTwoPathsAdditionalResistor)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
"match_nets INT $10\n"
"net_mismatch INT $10\n"
"match_nets IN IN\n"
"match_nets OUT OUT\n"
"match_nets INT2 $11\n"
"net_mismatch INT2 $11\n"
"match_pins $0 $1\n"
"match_pins $1 $3\n"
"match_pins $2 $0\n"
@ -1017,11 +1017,11 @@ TEST(6_BufferTwoPathsAdditionalDevices)
EXPECT_EQ (logger.text (),
"begin_circuit BUF BUF\n"
"match_nets INT $11\n"
"match_nets VDD VDD\n"
"net_mismatch VDD VDD\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets INT2 $10\n"
"net_mismatch VSS VSS\n"
"net_mismatch OUT OUT\n"
"net_mismatch INT2 $10\n"
"match_pins $0 $1\n"
"match_pins $1 $3\n"
"match_pins $2 $0\n"
@ -1110,8 +1110,8 @@ TEST(7_ResistorsParameterMismatch)
EXPECT_EQ (logger.text (),
"begin_circuit TRIANGLE TRIANGLE\n"
"match_nets P2 P2\n"
"match_nets P1 P1\n"
"match_nets P3 P3\n"
"net_mismatch P1 P1\n"
"net_mismatch P3 P3\n"
"match_pins $0 $0\n"
"match_pins $1 $1\n"
"match_pins $2 $2\n"
@ -1152,8 +1152,8 @@ TEST(7_ResistorsPlusOneDevice)
EXPECT_EQ (logger.text (),
"begin_circuit TRIANGLE TRIANGLE\n"
"match_nets P3 P3\n"
"match_nets P2 P2\n"
"match_nets P1 P1\n"
"net_mismatch P2 P2\n"
"net_mismatch P1 P1\n"
"match_pins $0 $0\n"
"match_pins $1 $1\n"
"match_pins $2 $2\n"
@ -1235,8 +1235,8 @@ TEST(8_DiodesDontMatchOnSwappedPins)
EXPECT_EQ (logger.text (),
"begin_circuit TRIANGLE TRIANGLE\n"
"match_nets P1 P3\n"
"match_nets P2 P1\n"
"match_nets P3 P2\n"
"net_mismatch P2 P1\n"
"net_mismatch P3 P2\n"
"match_pins $0 $2\n"
"match_pins $1 $0\n"
"match_pins $2 $1\n"
@ -1413,9 +1413,9 @@ TEST(11_MismatchingSubcircuits)
EXPECT_EQ (logger.text (),
"begin_circuit INV INV\n"
"match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets IN IN\n"
"match_nets VDD VDD\n"
"net_mismatch OUT OUT\n"
"net_mismatch IN IN\n"
"net_mismatch VDD VDD\n"
"match_pins $0 $1\n"
"match_pins $1 $3\n"
"match_pins $2 $0\n"
@ -1489,10 +1489,10 @@ TEST(12_MismatchingSubcircuitsDuplicates)
"end_circuit INV INV MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets IN IN\n"
"match_nets VDD VDD\n"
"match_nets VSS VSS\n"
"match_nets INT INT\n"
"match_nets OUT OUT\n"
"net_mismatch VDD VDD\n"
"net_mismatch VSS VSS\n"
"net_mismatch INT INT\n"
"net_mismatch OUT OUT\n"
"match_pins $0 $1\n"
"match_pins $1 $0\n"
"match_pins $2 $2\n"
@ -1703,11 +1703,11 @@ TEST(14_Subcircuit2NandMismatchNoSwap)
"end_circuit NAND NAND MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets OUT OUT\n"
"match_nets IN1 INT\n"
"match_nets INT IN1\n"
"match_nets VDD VDD\n"
"match_nets VSS VSS\n"
"match_nets IN2 IN2\n"
"net_mismatch IN1 INT\n"
"net_mismatch INT IN1\n"
"net_mismatch VDD VDD\n"
"net_mismatch VSS VSS\n"
"net_mismatch IN2 IN2\n"
"pin_mismatch $0 (null)\n"
"match_pins $1 $1\n"
"match_pins $2 $2\n"

View File

@ -461,8 +461,8 @@ END
begin_circuit BUF BUF
match_nets OUT OUT
match_nets INT $10
match_nets IN IN
match_nets INT2 $11
net_mismatch IN IN
net_mismatch INT2 $11
match_pins $0 $1
match_pins $1 $3
match_pins $2 $0
@ -616,8 +616,8 @@ END
begin_circuit BUF BUF
match_nets INT $10
match_nets IN IN
match_nets OUT OUT
match_nets INT2 $11
net_mismatch OUT OUT
net_mismatch INT2 $11
match_pins $0 $1
match_pins $1 $3
match_pins $2 $0
@ -684,10 +684,10 @@ END
assert_equal(logger.text, <<"END")
begin_circuit BUF BUF
match_nets INT $10
net_mismatch INT $10
match_nets IN IN
match_nets OUT OUT
match_nets INT2 $11
net_mismatch INT2 $11
match_pins $0 $1
match_pins $1 $3
match_pins $2 $0
@ -945,9 +945,9 @@ END
assert_equal(logger.text(), <<"END")
begin_circuit INV INV
match_nets VDD VDD
match_nets OUT OUT
net_mismatch OUT OUT
match_nets VSS VSS
match_nets IN IN
net_mismatch IN IN
match_pins $0 $1
match_pins $1 $3
match_pins $2 $0