mirror of https://github.com/KLayout/klayout.git
WIP: netlist compare algo
1.) Can identify transistor netlists without subcircuits 2.) Ambiguities stay unresolved Next steps: assign ambiguous nets one by one and continue in case of ambiguitites.
This commit is contained in:
parent
c568838bbe
commit
e424a88c90
|
|
@ -6,6 +6,8 @@
|
||||||
#include "dbNetlistDeviceClasses.h"
|
#include "dbNetlistDeviceClasses.h"
|
||||||
#include "dbHash.h"
|
#include "dbHash.h"
|
||||||
#include "tlUnitTest.h"
|
#include "tlUnitTest.h"
|
||||||
|
#include "tlProgress.h"
|
||||||
|
#include "tlTimer.h"
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
@ -14,9 +16,11 @@ struct DeviceCompare
|
||||||
{
|
{
|
||||||
bool operator() (const db::Device *d1, const db::Device *d2) const
|
bool operator() (const db::Device *d1, const db::Device *d2) const
|
||||||
{
|
{
|
||||||
if (d1->device_class () != d2->device_class ()) {
|
// @@@ TODO: device class identity should not be defined via name
|
||||||
|
if (d1->device_class () != d2->device_class () && d1->device_class ()->name () != d2->device_class ()->name ()) {
|
||||||
return d1->device_class ()->name () < d1->device_class ()->name ();
|
return d1->device_class ()->name () < d1->device_class ()->name ();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<db::DeviceParameterDefinition> &dp = d1->device_class ()->parameter_definitions ();
|
const std::vector<db::DeviceParameterDefinition> &dp = d1->device_class ()->parameter_definitions ();
|
||||||
for (std::vector<db::DeviceParameterDefinition>::const_iterator i = dp.begin (); i != dp.end (); ++i) {
|
for (std::vector<db::DeviceParameterDefinition>::const_iterator i = dp.begin (); i != dp.end (); ++i) {
|
||||||
double v1 = d1->parameter_value (i->id ());
|
double v1 = d1->parameter_value (i->id ());
|
||||||
|
|
@ -211,6 +215,15 @@ namespace std
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static std::string net2string (const db::Net *net)
|
||||||
|
{
|
||||||
|
if (! net) {
|
||||||
|
return "(null)";
|
||||||
|
} else {
|
||||||
|
return net->expanded_name ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class NetDeviceGraph
|
class NetDeviceGraph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -223,6 +236,8 @@ public:
|
||||||
|
|
||||||
void build (const db::Circuit *c)
|
void build (const db::Circuit *c)
|
||||||
{
|
{
|
||||||
|
tl::SelfTimer timer (tl::verbosity () >= 31, tl::to_string (tr ("Building net graph for circuit: ")) + c->name ());
|
||||||
|
|
||||||
m_device_map.clear ();
|
m_device_map.clear ();
|
||||||
m_device_prototypes.clear ();
|
m_device_prototypes.clear ();
|
||||||
m_nodes.clear ();
|
m_nodes.clear ();
|
||||||
|
|
@ -247,8 +262,6 @@ public:
|
||||||
for (std::vector<NetDeviceGraphNode>::iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) {
|
for (std::vector<NetDeviceGraphNode>::iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) {
|
||||||
i->apply_net_index (m_net_index);
|
i->apply_net_index (m_net_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index_for_net (const db::Net *net) const
|
size_t index_for_net (const db::Net *net) const
|
||||||
|
|
@ -298,7 +311,7 @@ public:
|
||||||
NetDeviceGraphNode::edge_iterator ee = e;
|
NetDeviceGraphNode::edge_iterator ee = e;
|
||||||
++ee;
|
++ee;
|
||||||
|
|
||||||
while (ee != n->end () && *ee == *e) {
|
while (ee != n->end () && ee->first == e->first) {
|
||||||
++ee;
|
++ee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,12 +327,12 @@ public:
|
||||||
if (count == 1) { // if non-ambiguous, non-assigned
|
if (count == 1) { // if non-ambiguous, non-assigned
|
||||||
|
|
||||||
NetDeviceGraphNode::edge_iterator e_other = std::lower_bound (nother->begin (), nother->end (), *ec);
|
NetDeviceGraphNode::edge_iterator e_other = std::lower_bound (nother->begin (), nother->end (), *ec);
|
||||||
if (e_other != nother->end () && *e_other == *ec) {
|
if (e_other != nother->end () && e_other->first == ec->first) {
|
||||||
|
|
||||||
NetDeviceGraphNode::edge_iterator ee_other = e_other;
|
NetDeviceGraphNode::edge_iterator ee_other = e_other;
|
||||||
++ee_other;
|
++ee_other;
|
||||||
|
|
||||||
while (ee_other != n->end () && *ee_other == *e_other) {
|
while (ee_other != n->end () && ee_other->first == e_other->first) {
|
||||||
++ee_other;
|
++ee_other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,8 +346,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count_other == 1) {
|
if (count_other == 1) {
|
||||||
identify (ec->second.second, ec_other->second.second);
|
confirm_identity (*this, begin () + ec->second.second, other, other.begin () + ec_other->second.second);
|
||||||
other.identify (ec_other->second.second, ec->second.second);
|
|
||||||
++added;
|
++added;
|
||||||
more.push_back (ec->second.second);
|
more.push_back (ec->second.second);
|
||||||
}
|
}
|
||||||
|
|
@ -354,6 +366,15 @@ public:
|
||||||
return added;
|
return added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void confirm_identity (db::NetDeviceGraph &g1, db::NetDeviceGraph::node_iterator s1, db::NetDeviceGraph &g2, db::NetDeviceGraph::node_iterator s2)
|
||||||
|
{
|
||||||
|
if (tl::verbosity () >= 30) {
|
||||||
|
tl::log << tl::to_string (tr ("Net identity confirmed: ")) << net2string (s1->net ()) << " - " << net2string (s2->net ());
|
||||||
|
}
|
||||||
|
g1.identify (s1 - g1.begin (), s2 - g2.begin ());
|
||||||
|
g2.identify (s2 - g2.begin (), s1 - g1.begin ());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<NetDeviceGraphNode> m_nodes;
|
std::vector<NetDeviceGraphNode> m_nodes;
|
||||||
std::map<const db::Device *, size_t, DeviceCompare> m_device_map;
|
std::map<const db::Device *, size_t, DeviceCompare> m_device_map;
|
||||||
|
|
@ -361,7 +382,6 @@ private:
|
||||||
std::map<const db::Net *, size_t> m_net_index;
|
std::map<const db::Net *, size_t> m_net_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2)
|
static bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2)
|
||||||
{
|
{
|
||||||
db::NetDeviceGraph g1, g2;
|
db::NetDeviceGraph g1, g2;
|
||||||
|
|
@ -380,7 +400,7 @@ static bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2)
|
||||||
|
|
||||||
bool any_without = false;
|
bool any_without = false;
|
||||||
for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end () && ! any_without; ++i1) {
|
for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end () && ! any_without; ++i1) {
|
||||||
any_without = i1->has_other ();
|
any_without = ! i1->has_other ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! any_without) {
|
if (! any_without) {
|
||||||
|
|
@ -415,8 +435,7 @@ static bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2)
|
||||||
|
|
||||||
if (seeds == 1) {
|
if (seeds == 1) {
|
||||||
// found a candidate - a single node with the same edges
|
// found a candidate - a single node with the same edges
|
||||||
g1.identify (s1 - g1.begin (), s2 - g2.begin ());
|
db::NetDeviceGraph::confirm_identity (g1, s1, g2, s2);
|
||||||
g2.identify (s2 - g2.begin (), s1 - g1.begin ());
|
|
||||||
++new_identities;
|
++new_identities;
|
||||||
} else if (seeds > 1) {
|
} else if (seeds > 1) {
|
||||||
ambiguous = true;
|
ambiguous = true;
|
||||||
|
|
@ -438,8 +457,7 @@ static bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2)
|
||||||
|
|
||||||
if (seeds == 1) {
|
if (seeds == 1) {
|
||||||
// found a candidate - a single node with the same edges
|
// found a candidate - a single node with the same edges
|
||||||
g1.identify (s1 - g1.begin (), s2 - g2.begin ());
|
db::NetDeviceGraph::confirm_identity (g1, s1, g2, s2);
|
||||||
g2.identify (s2 - g2.begin (), s1 - g1.begin ());
|
|
||||||
++new_identities;
|
++new_identities;
|
||||||
} else if (seeds > 1) {
|
} else if (seeds > 1) {
|
||||||
ambiguous = true;
|
ambiguous = true;
|
||||||
|
|
@ -448,15 +466,25 @@ static bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_identities == 0) {
|
if (new_identities == 0) {
|
||||||
|
// @@@
|
||||||
if (ambiguous) {
|
if (ambiguous) {
|
||||||
// @@@
|
|
||||||
tl::error << tr ("No seed found - no non-ambiguous nets identified");
|
tl::error << tr ("No seed found - no non-ambiguous nets identified");
|
||||||
// @@@
|
|
||||||
} else {
|
} else {
|
||||||
// @@@
|
|
||||||
tl::error << tr ("No seed found - no equivalent nets identified");
|
tl::error << tr ("No seed found - no equivalent nets identified");
|
||||||
// @@@
|
|
||||||
}
|
}
|
||||||
|
tl::error << tr ("Unassigned in netlist A:");
|
||||||
|
for (db::NetDeviceGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) {
|
||||||
|
if (! i->has_other ()) {
|
||||||
|
tl::error << " " << net2string (i->net ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tl::error << tr ("Unassigned in netlist B:");
|
||||||
|
for (db::NetDeviceGraph::node_iterator i = g2.begin (); i != g2.end (); ++i) {
|
||||||
|
if (! i->has_other ()) {
|
||||||
|
tl::error << " " << net2string (i->net ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @@@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue