WIP: new version of subcircuit match algorithm - needs refactoring.

This commit is contained in:
Matthias Koefferlein 2019-07-11 23:14:53 +02:00
parent 0d9273aaf6
commit 7bc4acd8f6
2 changed files with 466 additions and 368 deletions

View File

@ -706,196 +706,30 @@ public:
size_t m_id1, m_id2;
};
typedef std::pair<std::vector<Transition>, std::pair<size_t, const db::Net *> > edge_type;
struct EdgeToEdgeOnlyCompare
{
bool operator() (const std::pair<std::vector<Transition>, std::pair<size_t, const db::Net *> > &a, const std::vector<Transition> &b) const
bool operator() (const edge_type &a, const std::vector<Transition> &b) const
{
return a.first < b;
}
};
typedef std::vector<std::pair<std::vector<Transition>, std::pair<size_t, const db::Net *> > >::const_iterator edge_iterator;
typedef std::vector<edge_type>::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 ())
NetGraphNode ()
: mp_net (0)
{
if (! net) {
return;
}
std::map<const void *, size_t> n2entry;
for (db::Net::const_subcircuit_pin_iterator i = net->begin_subcircuit_pins (); i != net->end_subcircuit_pins (); ++i) {
const db::SubCircuit *sc = i->subcircuit ();
size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (sc);
if (! circuit_cat) {
// circuit is ignored
continue;
}
size_t pin_id = i->pin ()->id ();
const db::Circuit *cr = sc->circuit_ref ();
std::map<const db::Circuit *, CircuitMapper>::const_iterator icm = circuit_map->find (cr);
if (icm == circuit_map->end ()) {
// this can happen if the other circuit is not present - this is allowed for single-pin
// circuits.
continue;
}
const CircuitMapper *cm = & icm->second;
// A pin assignment may be missing because there is no net for a pin -> skip this
if (! cm->has_other_pin_for_this_pin (pin_id)) {
continue;
}
// NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit.
// For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper.
pin_id = cm->other_pin_from_this_pin (pin_id);
// realize pin swapping by normalization of pin ID
pin_id = pin_map->normalize_pin_id (cm->other (), pin_id);
// Subcircuits are routed to a null node and descend from a virtual node inside the subcircuit.
// The reasoning is that this way we don't need #pins*(#pins-1) edges but rather #pins.
Transition ed (sc, circuit_cat, pin_id, pin_id);
std::map<const void *, size_t>::const_iterator in = n2entry.find ((const void *) sc);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const void *) sc, m_edges.size ())).first;
m_edges.push_back (std::make_pair (std::vector<Transition> (), std::make_pair (size_t (0), (const db::Net *) 0)));
}
m_edges [in->second].first.push_back (ed);
}
for (db::Net::const_terminal_iterator i = net->begin_terminals (); i != net->end_terminals (); ++i) {
const db::Device *d = i->device ();
if (! device_filter.filter (d)) {
continue;
}
size_t device_cat = device_categorizer.cat_for_device (d);
if (! device_cat) {
// device is ignored
continue;
}
size_t terminal1_id = translate_terminal_id (i->terminal_id (), d);
const std::vector<db::DeviceTerminalDefinition> &td = d->device_class ()->terminal_definitions ();
for (std::vector<db::DeviceTerminalDefinition>::const_iterator it = td.begin (); it != td.end (); ++it) {
if (it->id () != i->terminal_id ()) {
size_t terminal2_id = translate_terminal_id (it->id (), d);
Transition ed2 (d, device_cat, terminal1_id, terminal2_id);
const db::Net *net2 = d->net_for_terminal (it->id ());
std::map<const void *, size_t>::const_iterator in = n2entry.find ((const void *) net2);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const void *) net2, m_edges.size ())).first;
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);
}
}
}
// .. nothing yet ..
}
NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map)
: mp_net (0), m_other_net_index (std::numeric_limits<size_t>::max ())
{
std::map<const db::Net *, size_t> n2entry;
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);
NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map);
size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (sc);
tl_assert (circuit_cat != 0);
void expand_subcircuit_nodes (NetGraph *graph);
const db::Circuit *cr = sc->circuit_ref ();
tl_assert (cr != 0);
std::map<const db::Circuit *, CircuitMapper>::const_iterator icm = circuit_map->find (cr);
tl_assert (icm != circuit_map->end ());
const CircuitMapper *cm = & icm->second;
for (db::Circuit::const_pin_iterator p = cr->begin_pins (); p != cr->end_pins (); ++p) {
size_t pin_id = p->id ();
const db::Net *net_at_pin = sc->net_for_pin (pin_id);
// A pin assignment may be missing because there is no net for a pin -> skip this
if (! cm->has_other_pin_for_this_pin (pin_id)) {
continue;
}
// NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit.
// For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper.
pin_id = cm->other_pin_from_this_pin (pin_id);
// realize pin swapping by normalization of pin ID
pin_id = pin_map->normalize_pin_id (cm->other (), pin_id);
// Make the other endpoint
Transition ed (sc, circuit_cat, pin_id, pin_id);
std::map<const db::Net *, size_t>::const_iterator in = n2entry.find (net_at_pin);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const db::Net *) net_at_pin, m_edges.size ())).first;
m_edges.push_back (std::make_pair (std::vector<Transition> (), std::make_pair (size_t (0), net_at_pin)));
}
m_edges [in->second].first.push_back (ed);
}
}
std::string to_string () const
{
std::string res = std::string ("[");
if (mp_net) {
res += mp_net->expanded_name ();
} else {
res += "(null)";
}
res += "]";
if (m_other_net_index != std::numeric_limits<size_t>::max ()) {
res += " (other: #" + tl::to_string (m_other_net_index) + ")";
}
res += "\n";
for (std::vector<std::pair<std::vector<Transition>, std::pair<size_t, const db::Net *> > >::const_iterator e = m_edges.begin (); e != m_edges.end (); ++e) {
res += " (\n";
for (std::vector<Transition>::const_iterator i = e->first.begin (); i != e->first.end (); ++i) {
res += std::string (" ") + i->to_string () + "\n";
}
res += " )->";
if (! e->second.second) {
res += "(null)";
} else {
res += e->second.second->expanded_name () + "[#" + tl::to_string (e->second.first) + "]";
}
res += "\n";
}
return res;
}
std::string to_string () const;
const db::Net *net () const
{
@ -927,55 +761,10 @@ public:
return m_edges.empty ();
}
void apply_net_index (const std::map<const db::Net *, size_t> &ni)
{
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;
}
void apply_net_index (const std::map<const db::Net *, size_t> &ni);
// "deep sorting" of the edge descriptor
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 ());
}
std::sort (m_edges.begin (), m_edges.end ());
}
bool operator< (const NetGraphNode &node) const
{
if (m_edges.size () != node.m_edges.size ()) {
return m_edges.size () < node.m_edges.size ();
}
for (size_t i = 0; i < m_edges.size (); ++i) {
if (m_edges [i].first != node.m_edges [i].first) {
return m_edges [i].first < node.m_edges [i].first;
}
}
if (m_edges.empty ()) {
// do a more detailed analysis on the edges
return edge_less (net (), node.net ());
}
return false;
}
bool operator== (const NetGraphNode &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;
}
}
if (m_edges.empty ()) {
// do a more detailed analysis on the edges
return edge_equal (net (), node.net ());
}
return true;
}
bool operator< (const NetGraphNode &node) const;
bool operator== (const NetGraphNode &node) const;
void swap (NetGraphNode &other)
{
@ -1007,59 +796,19 @@ public:
private:
const db::Net *mp_net;
size_t m_other_net_index;
std::vector<std::pair<std::vector<Transition>, std::pair<size_t, const db::Net *> > > m_edges;
std::vector<edge_type> m_edges;
/**
* @brief Compares edges as "less"
* Edge comparison is based on the pins attached (name of the first pin).
*/
static bool edge_less (const db::Net *a, const db::Net *b)
{
if ((a != 0) != (b != 0)) {
return (a != 0) < (b != 0);
}
if (a != 0) {
if (a->pin_count () != b->pin_count ()) {
return a->pin_count () < b->pin_count ();
}
if (a->pin_count () > 0) {
const std::string &pna = a->begin_pins ()->pin ()->name ();
const std::string &pnb = b->begin_pins ()->pin ()->name ();
if (! pna.empty () && ! pnb.empty ()) {
return pna < pnb;
}
}
return false;
} else {
return false;
}
}
static bool edge_less (const db::Net *a, const db::Net *b);
/**
* @brief Compares edges as "equal"
* See edge_less for the comparison details.
*/
static bool edge_equal (const db::Net *a, const db::Net *b)
{
if ((a != 0) != (b != 0)) {
return false;
}
if (a != 0) {
if (a->pin_count () != b->pin_count ()) {
return false;
}
if (a->pin_count () > 0) {
const std::string &pna = a->begin_pins ()->pin ()->name ();
const std::string &pnb = b->begin_pins ()->pin ()->name ();
if (! pna.empty () && ! pnb.empty ()) {
return pna == pnb;
}
}
return true;
} else {
return true;
}
}
static bool edge_equal (const db::Net *a, const db::Net *b);
};
// --------------------------------------------------------------------------------------------------------------------
@ -1253,11 +1002,352 @@ private:
std::map<const db::Net *, size_t> m_net_index;
const db::Circuit *mp_circuit;
size_t derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGraphNode::edge_iterator ee, size_t net_index, NetGraphNode *n, size_t other_net_index, NetGraphNode *nother, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data);
size_t derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGraphNode::edge_iterator ee, NetGraphNode::edge_iterator e_other, NetGraphNode::edge_iterator ee_other, size_t net_index, NetGraphNode *n, size_t other_net_index, NetGraphNode *nother, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data);
};
// --------------------------------------------------------------------------------------------------------------------
NetGraphNode::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 ())
{
if (! net) {
return;
}
std::map<const void *, size_t> n2entry;
for (db::Net::const_subcircuit_pin_iterator i = net->begin_subcircuit_pins (); i != net->end_subcircuit_pins (); ++i) {
const db::SubCircuit *sc = i->subcircuit ();
size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (sc);
if (! circuit_cat) {
// circuit is ignored
continue;
}
size_t pin_id = i->pin ()->id ();
const db::Circuit *cr = sc->circuit_ref ();
std::map<const db::Circuit *, CircuitMapper>::const_iterator icm = circuit_map->find (cr);
if (icm == circuit_map->end ()) {
// this can happen if the other circuit is not present - this is allowed for single-pin
// circuits.
continue;
}
const CircuitMapper *cm = & icm->second;
// A pin assignment may be missing because there is no net for a pin -> skip this
if (! cm->has_other_pin_for_this_pin (pin_id)) {
continue;
}
// NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit.
// For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper.
pin_id = cm->other_pin_from_this_pin (pin_id);
// realize pin swapping by normalization of pin ID
pin_id = pin_map->normalize_pin_id (cm->other (), pin_id);
// Subcircuits are routed to a null node and descend from a virtual node inside the subcircuit.
// The reasoning is that this way we don't need #pins*(#pins-1) edges but rather #pins.
Transition ed (sc, circuit_cat, pin_id, pin_id);
std::map<const void *, size_t>::const_iterator in = n2entry.find ((const void *) sc);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const void *) sc, m_edges.size ())).first;
m_edges.push_back (edge_type (std::vector<Transition> (), std::make_pair (size_t (0), (const db::Net *) 0)));
}
m_edges [in->second].first.push_back (ed);
}
for (db::Net::const_terminal_iterator i = net->begin_terminals (); i != net->end_terminals (); ++i) {
const db::Device *d = i->device ();
if (! device_filter.filter (d)) {
continue;
}
size_t device_cat = device_categorizer.cat_for_device (d);
if (! device_cat) {
// device is ignored
continue;
}
size_t terminal1_id = translate_terminal_id (i->terminal_id (), d);
const std::vector<db::DeviceTerminalDefinition> &td = d->device_class ()->terminal_definitions ();
for (std::vector<db::DeviceTerminalDefinition>::const_iterator it = td.begin (); it != td.end (); ++it) {
if (it->id () != i->terminal_id ()) {
size_t terminal2_id = translate_terminal_id (it->id (), d);
Transition ed2 (d, device_cat, terminal1_id, terminal2_id);
const db::Net *net2 = d->net_for_terminal (it->id ());
std::map<const void *, size_t>::const_iterator in = n2entry.find ((const void *) net2);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const void *) net2, m_edges.size ())).first;
m_edges.push_back (edge_type (std::vector<Transition> (), std::make_pair (size_t (0), net2)));
}
m_edges [in->second].first.push_back (ed2);
}
}
}
}
NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map)
: mp_net (0), m_other_net_index (std::numeric_limits<size_t>::max ())
{
std::map<const db::Net *, size_t> n2entry;
size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (sc);
tl_assert (circuit_cat != 0);
const db::Circuit *cr = sc->circuit_ref ();
tl_assert (cr != 0);
std::map<const db::Circuit *, CircuitMapper>::const_iterator icm = circuit_map->find (cr);
tl_assert (icm != circuit_map->end ());
const CircuitMapper *cm = & icm->second;
for (db::Circuit::const_pin_iterator p = cr->begin_pins (); p != cr->end_pins (); ++p) {
size_t pin_id = p->id ();
const db::Net *net_at_pin = sc->net_for_pin (pin_id);
// A pin assignment may be missing because there is no net for a pin -> skip this
if (! cm->has_other_pin_for_this_pin (pin_id)) {
continue;
}
// NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit.
// For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper.
pin_id = cm->other_pin_from_this_pin (pin_id);
// realize pin swapping by normalization of pin ID
pin_id = pin_map->normalize_pin_id (cm->other (), pin_id);
// Make the other endpoint
Transition ed (sc, circuit_cat, pin_id, pin_id);
std::map<const db::Net *, size_t>::const_iterator in = n2entry.find (net_at_pin);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const db::Net *) net_at_pin, m_edges.size ())).first;
m_edges.push_back (edge_type (std::vector<Transition> (), std::make_pair (size_t (0), net_at_pin)));
}
m_edges [in->second].first.push_back (ed);
}
}
void
NetGraphNode::expand_subcircuit_nodes (NetGraph *graph)
{
std::map<const db::Net *, size_t> n2entry;
std::list<edge_type> sc_edges;
for (size_t i = 0; i < m_edges.size (); ) {
if (m_edges [i].second.second == 0) {
// subcircuit pin
sc_edges.push_back (m_edges [i]);
m_edges.erase (m_edges.begin () + i);
} else {
n2entry.insert (std::make_pair (m_edges [i].second.second, i));
++i;
}
}
for (std::list<edge_type>::const_iterator e = sc_edges.begin (); e != sc_edges.end (); ++e) {
const db::SubCircuit *sc = 0;
for (std::vector<Transition>::const_iterator t = e->first.begin (); t != e->first.end (); ++t) {
tl_assert (t->is_for_subcircuit ());
if (! sc) {
sc = t->subcircuit_pair ().first;
} else {
tl_assert (sc == t->subcircuit_pair ().first);
}
}
const NetGraphNode &dn = graph->distro_node (sc);
for (NetGraphNode::edge_iterator de = dn.begin (); de != dn.end (); ++de) {
const db::Net *net_at_pin = de->second.second;
if (net_at_pin == net ()) {
continue;
}
std::map<const db::Net *, size_t>::const_iterator in = n2entry.find (net_at_pin);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const db::Net *) net_at_pin, m_edges.size ())).first;
m_edges.push_back (edge_type (std::vector<Transition> (), de->second));
}
m_edges [in->second].first.insert (m_edges [in->second].first.end (), de->first.begin (), de->first.end ());
}
}
// "deep sorting" of the edge descriptor
for (std::vector<edge_type>::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 ());
}
std::string
NetGraphNode::to_string () const
{
std::string res = std::string ("[");
if (mp_net) {
res += mp_net->expanded_name ();
} else {
res += "(null)";
}
res += "]";
if (m_other_net_index != std::numeric_limits<size_t>::max ()) {
res += " (other: #" + tl::to_string (m_other_net_index) + ")";
}
res += "\n";
for (std::vector<edge_type>::const_iterator e = m_edges.begin (); e != m_edges.end (); ++e) {
res += " (\n";
for (std::vector<Transition>::const_iterator i = e->first.begin (); i != e->first.end (); ++i) {
res += std::string (" ") + i->to_string () + "\n";
}
res += " )->";
if (! e->second.second) {
res += "(null)";
} else {
res += e->second.second->expanded_name () + "[#" + tl::to_string (e->second.first) + "]";
}
res += "\n";
}
return res;
}
void
NetGraphNode::apply_net_index (const std::map<const db::Net *, size_t> &ni)
{
for (std::vector<edge_type>::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<edge_type>::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
NetGraphNode::operator< (const NetGraphNode &node) const
{
if (m_edges.size () != node.m_edges.size ()) {
return m_edges.size () < node.m_edges.size ();
}
for (size_t i = 0; i < m_edges.size (); ++i) {
if (m_edges [i].first != node.m_edges [i].first) {
return m_edges [i].first < node.m_edges [i].first;
}
}
if (m_edges.empty ()) {
// do a more detailed analysis on the edges
return edge_less (net (), node.net ());
}
return false;
}
bool
NetGraphNode::operator== (const NetGraphNode &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;
}
}
if (m_edges.empty ()) {
// do a more detailed analysis on the edges
return edge_equal (net (), node.net ());
}
return true;
}
bool
NetGraphNode::edge_less (const db::Net *a, const db::Net *b)
{
if ((a != 0) != (b != 0)) {
return (a != 0) < (b != 0);
}
if (a != 0) {
if (a->pin_count () != b->pin_count ()) {
return a->pin_count () < b->pin_count ();
}
if (a->pin_count () > 0) {
const std::string &pna = a->begin_pins ()->pin ()->name ();
const std::string &pnb = b->begin_pins ()->pin ()->name ();
if (! pna.empty () && ! pnb.empty ()) {
return pna < pnb;
}
}
return false;
} else {
return false;
}
}
bool
NetGraphNode::edge_equal (const db::Net *a, const db::Net *b)
{
if ((a != 0) != (b != 0)) {
return false;
}
if (a != 0) {
if (a->pin_count () != b->pin_count ()) {
return false;
}
if (a->pin_count () > 0) {
const std::string &pna = a->begin_pins ()->pin ()->name ();
const std::string &pnb = b->begin_pins ()->pin ()->name ();
if (! pna.empty () && ! pnb.empty ()) {
return pna == pnb;
}
}
return true;
} else {
return true;
}
}
// --------------------------------------------------------------------------------------------------------------------
/**
* @brief Represents an interval of NetGraphNode objects in a node set
*/
@ -1391,7 +1481,7 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci
}
size_t
NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGraphNode::edge_iterator ee, size_t net_index, NetGraphNode *n, size_t other_net_index, NetGraphNode *nother, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data)
NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGraphNode::edge_iterator ee, NetGraphNode::edge_iterator e_other, NetGraphNode::edge_iterator ee_other, size_t net_index, NetGraphNode *n, size_t other_net_index, NetGraphNode *nother, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data)
{
size_t new_nodes = 0;
@ -1419,29 +1509,17 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
if (! nodes.empty ()) { // if non-ambiguous, non-assigned
NetGraphNode::edge_iterator e_other = nother->find_edge (e->first);
if (e_other != nother->end ()) {
NetGraphNode::edge_iterator ee_other = e_other;
++ee_other;
while (ee_other != nother->end () && ee_other->first == e_other->first) {
++ee_other;
}
for (NetGraphNode::edge_iterator i = e_other; i != ee_other; ++i) {
if (i->second.first != other_net_index) {
const NetGraphNode *nn = &data->other->node (i->second.first);
for (NetGraphNode::edge_iterator i = e_other; i != ee_other; ++i) {
if (i->second.first != other_net_index) {
const NetGraphNode *nn = &data->other->node (i->second.first);
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::info << indent(depth) << "there: " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via";
for (std::vector<NetGraphNode::Transition>::const_iterator t = i->first.begin (); t != i->first.end(); ++t) {
tl::info << indent(depth) << " " << t->to_string();
}
#endif
other_nodes.push_back (nn);
tl::info << indent(depth) << "there: " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via";
for (std::vector<NetGraphNode::Transition>::const_iterator t = i->first.begin (); t != i->first.end(); ++t) {
tl::info << indent(depth) << " " << t->to_string();
}
#endif
other_nodes.push_back (nn);
}
}
}
@ -1488,28 +1566,17 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
return new_nodes;
}
const db::SubCircuit *subcircuit_on_edges (NetGraphNode::edge_iterator e, NetGraphNode::edge_iterator ee, CompareData *data)
static bool has_subcircuits (db::NetGraphNode::edge_iterator e, db::NetGraphNode::edge_iterator ee)
{
const db::SubCircuit *subcircuit_on_node = 0;
bool subcircuit_on_node_ambiguous = false;
while (e != ee) {
for (std::vector<NetGraphNode::Transition>::const_iterator t = e->first.begin (); t != e->first.end (); ++t) {
if (t->is_for_subcircuit ()) {
const db::SubCircuit *sc = t->subcircuit_pair ().first;
if (data->subcircuit_categorizer->has_cat_for (sc)) {
// ignore known subcircuits
} else if (! subcircuit_on_node || subcircuit_on_node == sc) {
subcircuit_on_node = sc;
} else {
subcircuit_on_node_ambiguous = true;
}
return true;
}
}
++e;
}
return subcircuit_on_node_ambiguous ? 0 : subcircuit_on_node;
return false;
}
size_t
@ -1518,28 +1585,60 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
NetGraphNode *n = & node (net_index);
size_t other_net_index = n->other_net_index ();
NetGraphNode *nother = & data->other->node (other_net_index);
NetGraphNode *n_other = & data->other->node (other_net_index);
#if defined(PRINT_DEBUG_NETCOMPARE)
if (! tentative) {
tl::info << indent(depth) << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << nother->net ()->expanded_name ();
tl::info << indent(depth) << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
}
#endif
size_t new_nodes = 0;
NetGraphNode nn, nn_other;
// If there are subcircuits on the graph we temporarily create edges from our node to the other nodes of
// the subcircuit. This way we don't need to keep #pin*(#pin-1) edges
if (has_subcircuits (n->begin (), n->end ())) {
nn = *n;
nn.expand_subcircuit_nodes (this);
n = &nn;
nn_other = *n_other;
nn_other.expand_subcircuit_nodes (data->other);
n_other = &nn_other;
}
// non-ambiguous paths to non-assigned nodes create a node identity on the
// end of this path
for (NetGraphNode::edge_iterator e = n->begin (); e != n->end (); ) {
NetGraphNode::edge_iterator ee = e;
++ee;
while (ee != n->end () && ee->first == e->first) {
++ee;
}
new_nodes += derive_node_identities_for_edges (e, ee, net_index, n, other_net_index, nother, depth, n_branch, tentative, with_ambiguous, data);
NetGraphNode::edge_iterator e_other = n_other->find_edge (e->first);
if (e_other != n_other->end ()) {
NetGraphNode::edge_iterator ee_other = e_other;
++ee_other;
while (ee_other != n_other->end () && ee_other->first == e_other->first) {
++ee_other;
}
new_nodes += derive_node_identities_for_edges (e, ee, e_other, ee_other, net_index, n, other_net_index, n_other, depth, n_branch, tentative, with_ambiguous, data);
}
#if 0 // @@@
// Subcircuits are handled explicitly: the edges aren't real edges, but pin descriptors with
// a single endpoint and nil at the other end. The subcircuit provides a set of edges
// providing the other endpoints and nil at our side. This saves us creating #pin*(#pin-1) edges
@ -1580,6 +1679,7 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
}
}
#endif
e = ee;
@ -1587,7 +1687,7 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
#if defined(PRINT_DEBUG_NETCOMPARE)
if (! tentative && new_nodes > 0) {
tl::info << indent(depth) << "finished pair deduction: " << n->net ()->expanded_name () << " vs. " << nother->net ()->expanded_name () << " with " << new_nodes << " new pairs";
tl::info << indent(depth) << "finished pair deduction: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name () << " with " << new_nodes << " new pairs";
}
#endif
@ -1609,7 +1709,7 @@ NetGraph::derive_node_identities_from_node_set (const std::vector<const NetGraph
if (depth > data->max_depth) {
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::info << indent << "max. depth exhausted (" << depth + 1 << ">" << max_depth << ")";
tl::info << indent << "max. depth exhausted (" << depth + 1 << ">" << data->max_depth << ")";
#endif
return std::numeric_limits<size_t>::max ();
}
@ -1814,7 +1914,7 @@ NetGraph::derive_node_identities_from_node_set (const std::vector<const NetGraph
} else if (nr->num * n_branch > data->max_n_branch) {
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::info << indent << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << max_n_branch << ") - mismatch.";
tl::info << indent << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << data->max_n_branch << ") - mismatch.";
#endif
return std::numeric_limits<size_t>::max ();
@ -2376,7 +2476,7 @@ bool
NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinMapper &circuit_pin_mapper, const std::vector<std::pair<const Net *, const Net *> > &net_identity, bool &pin_mismatch, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping) const
{
db::DeviceFilter device_filter (m_cap_threshold, m_res_threshold);
db::SubCircuitCategorizer subcircuit_categorizer;
db::SubCircuitCategorizer subcircuit_categorizer; // @@@ no longer required
db::NetGraph g1, g2;

View File

@ -1550,10 +1550,10 @@ TEST(10_SimpleSubCircuits)
"end_circuit INV INV MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets OUT OUT\n"
"match_nets VDD VDD\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets INT INT\n"
"match_nets IN IN\n"
"match_nets VDD VDD\n"
"match_pins $0 $2\n"
"match_pins $1 $0\n"
"match_pins $2 $1\n"
@ -1617,10 +1617,10 @@ TEST(10_SimpleSubCircuitsMatchedNames)
"end_circuit INV INVB MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets OUT OUT\n"
"match_nets VDD VDD\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets INT INT\n"
"match_nets IN IN\n"
"match_nets VDD VDD\n"
"match_pins $0 $2\n"
"match_pins $1 $0\n"
"match_pins $2 $1\n"
@ -1681,12 +1681,10 @@ TEST(11_MismatchingSubcircuits)
"end_circuit INV INV NOMATCH\n"
"begin_circuit TOP TOP\n"
"match_nets OUT OUT\n"
// because VDD is a floating pin in #1 and floating pins are treated different from
// connected ones
"net_mismatch VDD VDD\n"
"match_nets VSS VSS\n"
"match_nets INT INT\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_pins $0 $2\n"
"match_pins $1 $0\n"
"match_pins $2 $1\n"
@ -1743,7 +1741,7 @@ TEST(11_MismatchingSubcircuits)
" net OUT:OUT [Match]\n"
" pin $1:$0\n"
" subcircuit_pin $2[$1]:$1[$3]\n"
" net VDD:VDD [Mismatch]\n"
" net VDD:VDD [Match]\n"
" pin $2:$1\n"
" subcircuit_pin $1[$2]:$2[$0]\n"
" subcircuit_pin $2[$2]:$1[$0]\n"
@ -1841,9 +1839,9 @@ TEST(12_MismatchingSubcircuitsDuplicates)
"end_circuit INV INV MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets IN IN\n"
"net_mismatch VDD VDD\n"
"net_mismatch VSS VSS\n"
"net_mismatch INT INT\n"
"net_mismatch VSS VSS\n"
"net_mismatch VDD VDD\n"
"net_mismatch OUT OUT\n"
"match_pins $0 $1\n"
"match_pins $1 $0\n"
@ -1909,10 +1907,10 @@ TEST(13_MismatchingSubcircuitsAdditionalHierarchy)
"end_circuit INV INV MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets OUT OUT\n"
"match_nets VDD VDD\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets INT INT\n"
"match_nets IN IN\n"
"match_nets VDD VDD\n"
"match_pins $0 $1\n"
"match_pins $1 $0\n"
"match_pins $2 $2\n"
@ -1980,12 +1978,12 @@ TEST(14_Subcircuit2Nand)
"match_devices $4 $4\n"
"end_circuit NAND NAND MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets IN2 IN2\n"
"match_nets INT INT\n"
"match_nets IN1 IN1\n"
"match_nets OUT OUT\n"
"match_nets VDD VDD\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets INT INT\n"
"match_nets IN2 IN2\n"
"match_nets IN1 IN1\n"
"match_pins $0 $0\n"
"match_pins $1 $1\n"
"match_pins $2 $2\n"
@ -2055,10 +2053,10 @@ TEST(14_Subcircuit2NandMismatchNoSwap)
"end_circuit NAND NAND MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets OUT OUT\n"
"net_mismatch IN1 INT\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"net_mismatch INT IN1\n"
"net_mismatch VDD VDD\n"
"net_mismatch VSS VSS\n"
"net_mismatch IN1 INT\n"
"net_mismatch IN2 IN2\n"
"pin_mismatch $0 (null)\n"
"match_pins $1 $1\n"
@ -2136,11 +2134,11 @@ TEST(14_Subcircuit2NandMismatchNoSwap)
" net OUT:OUT [Match]\n"
" pin $2:$2\n"
" subcircuit_pin $2[$2]:$1[$2]\n"
" net VDD:VDD [Mismatch]\n"
" net VDD:VDD [Match]\n"
" pin $3:$3\n"
" subcircuit_pin $1[$3]:$2[$3]\n"
" subcircuit_pin $2[$3]:$1[$3]\n"
" net VSS:VSS [Mismatch]\n"
" net VSS:VSS [Match]\n"
" pin $4:$4\n"
" subcircuit_pin $1[$4]:$2[$4]\n"
" subcircuit_pin $2[$4]:$1[$4]\n"
@ -2205,12 +2203,12 @@ TEST(14_Subcircuit2MatchWithSwap)
"match_devices $4 $4\n"
"end_circuit NAND NAND MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets IN2 IN2\n"
"match_nets INT INT\n"
"match_nets IN1 IN1\n"
"match_nets OUT OUT\n"
"match_nets VDD VDD\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets INT INT\n"
"match_nets IN2 IN2\n"
"match_nets IN1 IN1\n"
"match_pins $0 $0\n"
"match_pins $1 $1\n"
"match_pins $2 $2\n"
@ -2275,10 +2273,10 @@ TEST(15_EmptySubCircuitTest)
"end_circuit TRANS TRANS MATCH\n"
"begin_circuit INV2 INV2\n"
"match_nets $5 $5\n"
"match_nets OUT OUT\n"
"match_nets $2 $2\n"
"match_nets IN IN\n"
"match_nets $4 $4\n"
"match_nets OUT OUT\n"
"match_pins IN IN\n"
"match_pins $1 $1\n"
"match_pins OUT OUT\n"
@ -2350,10 +2348,10 @@ TEST(15_EmptySubCircuitWithoutPinNames)
"end_circuit TRANS TRANS MATCH\n"
"begin_circuit INV2 INV2\n"
"match_nets $5 $5\n"
"match_nets OUT OUT\n"
"match_nets $2 $2\n"
"match_nets IN IN\n"
"match_nets $4 $4\n"
"match_nets OUT OUT\n"
"match_pins IN IN\n"
"match_pins $1 $1\n"
"match_pins OUT OUT\n"
@ -2444,14 +2442,14 @@ TEST(16_UniqueSubCircuitMatching)
"end_circuit INV2 INV2 MATCH\n"
"begin_circuit INV2PAIR INV2PAIR\n"
"match_nets $I2 $I2\n"
"match_nets $I1 $I1\n"
"match_nets BULK BULK\n"
"match_nets $I6 $I6\n"
"match_nets $I5 $I5\n"
"match_nets $I4 $I4\n"
"match_nets $I3 $I3\n"
"match_nets $I7 $I7\n"
"match_nets $I4 $I4\n"
"match_nets $I5 $I5\n"
"match_nets $I1 $I1\n"
"match_nets $I8 $I8\n"
"match_nets $I6 $I6\n"
"match_nets BULK BULK\n"
"match_pins BULK BULK\n"
"match_pins $1 $1\n"
"match_pins $2 $2\n"
@ -2464,17 +2462,17 @@ TEST(16_UniqueSubCircuitMatching)
"end_circuit INV2PAIR INV2PAIR MATCH\n"
"begin_circuit RINGO RINGO\n"
"match_nets OSC OSC\n"
"match_nets BULK,VSS BULK,VSS\n"
"match_nets FB FB\n"
"match_nets $I22 $I22\n"
"match_nets VDD VDD\n"
"match_nets FB FB\n"
"match_nets $I13 $I13\n"
"match_nets $I23 $I23\n"
"match_nets $I5 $I5\n"
"match_nets $I24 $I24\n"
"match_nets $I6 $I6\n"
"match_nets $I7 $I7\n"
"match_nets BULK,VSS BULK,VSS\n"
"match_nets $I25 $I25\n"
"match_nets $I24 $I24\n"
"match_nets $I23 $I23\n"
"match_nets $I22 $I22\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $4 $2\n"
"match_subcircuits $3 $3\n"
@ -2552,28 +2550,28 @@ TEST(17_InherentlyAmbiguousDecoder)
"begin_circuit DECODER DECODER\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_ambiguous_nets A B\n"
"match_ambiguous_nets B A\n"
"match_nets NQ1 NQ2\n"
"match_nets NQ3 NQ3\n"
"match_nets NB NA\n"
"match_nets NQ0 NQ0\n"
"match_nets NA NB\n"
"match_nets NQ2 NQ1\n"
"match_pins $0 $0\n"
"match_pins $1 $1\n"
"match_ambiguous_nets NQ1 NQ1\n"
"match_ambiguous_nets NQ2 NQ2\n"
"match_nets NQ3 NQ3\n"
"match_ambiguous_nets NA NA\n"
"match_ambiguous_nets NB NB\n"
"match_nets B B\n"
"match_nets A A\n"
"match_pins $0 $1\n"
"match_pins $1 $0\n"
"match_pins $2 $2\n"
"match_pins $3 $4\n"
"match_pins $4 $3\n"
"match_pins $3 $3\n"
"match_pins $4 $4\n"
"match_pins $5 $5\n"
"match_pins $6 $6\n"
"match_pins $7 $7\n"
"match_subcircuits $2 $1\n"
"match_subcircuits $1 $2\n"
"match_subcircuits $5 $3\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $2 $2\n"
"match_subcircuits $4 $3\n"
"match_subcircuits $6 $4\n"
"match_subcircuits $3 $5\n"
"match_subcircuits $4 $6\n"
"match_subcircuits $5 $6\n"
"end_circuit DECODER DECODER MATCH"
);
@ -2602,11 +2600,11 @@ TEST(17_InherentlyAmbiguousDecoder)
"match_devices $4 $4\n"
"end_circuit NAND NAND MATCH\n"
"begin_circuit DECODER DECODER\n"
"match_nets NA NA\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets B B\n"
"match_nets NB NB\n"
"match_nets VSS VSS\n"
"match_nets NA NA\n"
"match_nets NQ0 NQ0\n"
"match_nets NQ2 NQ2\n"
"match_nets NQ1 NQ1\n"
@ -2709,9 +2707,9 @@ TEST(18_ClockTree)
"end_circuit INV INV MATCH\n"
"begin_circuit TXEE TXEE\n"
"match_nets IN IN\n"
"match_nets S S\n"
"match_nets VDD VDD\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets S S\n"
"match_ambiguous_nets SX SX\n"
"match_ambiguous_nets SX SX\n"
"match_ambiguous_nets SXX SXX\n"