mirror of https://github.com/KLayout/klayout.git
WIP: tests for netlist cross ref.
This commit is contained in:
parent
a46d991c6f
commit
924daa65b7
|
|
@ -176,7 +176,8 @@ SOURCES = \
|
||||||
dbNetlistCompare.cc \
|
dbNetlistCompare.cc \
|
||||||
dbNetlistReader.cc \
|
dbNetlistReader.cc \
|
||||||
dbNetlistSpiceReader.cc \
|
dbNetlistSpiceReader.cc \
|
||||||
gsiDeclDbNetlistCompare.cc
|
gsiDeclDbNetlistCompare.cc \
|
||||||
|
dbNetlistCrossReference.cc
|
||||||
|
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
dbArray.h \
|
dbArray.h \
|
||||||
|
|
@ -317,7 +318,8 @@ HEADERS = \
|
||||||
gsiDeclDbHelpers.h \
|
gsiDeclDbHelpers.h \
|
||||||
dbNetlistCompare.h \
|
dbNetlistCompare.h \
|
||||||
dbNetlistReader.h \
|
dbNetlistReader.h \
|
||||||
dbNetlistSpiceReader.h
|
dbNetlistSpiceReader.h \
|
||||||
|
dbNetlistCrossReference.h
|
||||||
|
|
||||||
!equals(HAVE_QT, "0") {
|
!equals(HAVE_QT, "0") {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1772,7 +1772,7 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mp_logger) {
|
if (mp_logger) {
|
||||||
mp_logger->begin_netlist (a, b);
|
mp_logger->end_netlist (a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
return good;
|
return good;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,471 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "dbNetlistCrossReference.h"
|
||||||
|
|
||||||
|
namespace db
|
||||||
|
{
|
||||||
|
|
||||||
|
NetlistCrossReference::NetlistCrossReference ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
NetlistCrossReference::~NetlistCrossReference ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetlistCrossReference::PerCircuitData *
|
||||||
|
NetlistCrossReference::per_circuit_data_for (const std::pair<const db::Circuit *, const db::Circuit *> &circuits) const
|
||||||
|
{
|
||||||
|
per_circuit_data_iterator i = m_per_circuit_data.find (circuits);
|
||||||
|
if (i == m_per_circuit_data.end ()) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return & i->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const db::Net *
|
||||||
|
NetlistCrossReference::other_net_for (const db::Net *net) const
|
||||||
|
{
|
||||||
|
std::map<const db::Net *, const db::Net *>::const_iterator i = m_other_net.find (net);
|
||||||
|
if (i != m_other_net.end ()) {
|
||||||
|
return i->second;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetlistCrossReference::PerNetData *
|
||||||
|
NetlistCrossReference::per_net_data_for (const std::pair<const db::Net *, const db::Net *> &nets) const
|
||||||
|
{
|
||||||
|
std::map<std::pair<const db::Net *, const db::Net *>, PerNetData>::iterator i = m_per_net_data.find (nets);
|
||||||
|
if (i == m_per_net_data.end ()) {
|
||||||
|
i = m_per_net_data.insert (std::make_pair (nets, PerNetData ())).first;
|
||||||
|
build_per_net_info (nets, i->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::begin_netlist (const db::Netlist *a, const db::Netlist *b)
|
||||||
|
{
|
||||||
|
mp_netlist_a.reset (const_cast <db::Netlist *> (a));
|
||||||
|
mp_netlist_b.reset (const_cast <db::Netlist *> (b));
|
||||||
|
m_current_circuits = std::pair<const db::Circuit *, const db::Circuit *> (0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct CircuitsCompareByName
|
||||||
|
{
|
||||||
|
bool operator() (const std::pair<const db::Circuit *, const db::Circuit *> &a, const std::pair<const db::Circuit *, const db::Circuit *> &b)
|
||||||
|
{
|
||||||
|
if ((a.first == 0) != (b.first == 0)) {
|
||||||
|
return (a.first == 0) > (b.first == 0);
|
||||||
|
}
|
||||||
|
if (a.first != 0 && a.first->name () != b.first->name ()) {
|
||||||
|
return a.first->name () < b.first->name ();
|
||||||
|
}
|
||||||
|
if ((a.second == 0) != (b.second == 0)) {
|
||||||
|
return (a.second == 0) > (b.second == 0);
|
||||||
|
}
|
||||||
|
if (a.second != 0 && a.second->name () != b.second->name ()) {
|
||||||
|
return a.second->name () < b.second->name ();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::end_netlist (const db::Netlist *, const db::Netlist *)
|
||||||
|
{
|
||||||
|
m_circuits.reserve (m_per_circuit_data.size ());
|
||||||
|
for (per_circuit_data_iterator i = begin_per_circuit_data (); i != end_per_circuit_data (); ++i) {
|
||||||
|
m_circuits.push_back (i->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort (m_circuits.begin (), m_circuits.end (), CircuitsCompareByName ());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::device_class_mismatch (const db::DeviceClass *, const db::DeviceClass *)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::establish_pair (const db::Circuit *a, const db::Circuit *b)
|
||||||
|
{
|
||||||
|
mp_per_circuit_data = & m_per_circuit_data [std::make_pair (a, b)];
|
||||||
|
|
||||||
|
if (a) {
|
||||||
|
m_other_circuit [a] = b;
|
||||||
|
}
|
||||||
|
if (b) {
|
||||||
|
m_other_circuit [b] = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::establish_pair (const db::Net *a, const db::Net *b, Status status)
|
||||||
|
{
|
||||||
|
mp_per_circuit_data->nets.push_back (NetPairData (a, b, status));
|
||||||
|
if (a) {
|
||||||
|
m_other_net [a] = b;
|
||||||
|
}
|
||||||
|
if (b) {
|
||||||
|
m_other_net [b] = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::establish_pair (const db::Device *a, const db::Device *b, Status status)
|
||||||
|
{
|
||||||
|
mp_per_circuit_data->devices.push_back (DevicePairData (a, b, status));
|
||||||
|
if (a) {
|
||||||
|
m_other_device [a] = b;
|
||||||
|
}
|
||||||
|
if (b) {
|
||||||
|
m_other_device [b] = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::establish_pair (const db::Pin *a, const db::Pin *b, Status status)
|
||||||
|
{
|
||||||
|
mp_per_circuit_data->pins.push_back (PinPairData (a, b, status));
|
||||||
|
if (a) {
|
||||||
|
m_other_pin [a] = b;
|
||||||
|
}
|
||||||
|
if (b) {
|
||||||
|
m_other_pin [b] = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::establish_pair (const db::SubCircuit *a, const db::SubCircuit *b, Status status)
|
||||||
|
{
|
||||||
|
mp_per_circuit_data->subcircuits.push_back (SubCircuitPairData (a, b, status));
|
||||||
|
if (a) {
|
||||||
|
m_other_subcircuit [a] = b;
|
||||||
|
}
|
||||||
|
if (b) {
|
||||||
|
m_other_subcircuit [b] = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::begin_circuit (const db::Circuit *a, const db::Circuit *b)
|
||||||
|
{
|
||||||
|
m_current_circuits = std::pair<const db::Circuit *, const db::Circuit *> (a, b);
|
||||||
|
establish_pair (a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::end_circuit (const db::Circuit *, const db::Circuit *, bool matching)
|
||||||
|
{
|
||||||
|
mp_per_circuit_data->status = matching ? Match : NoMatch;
|
||||||
|
|
||||||
|
// @@@ TODO: sort per-circuit data vectors by name?
|
||||||
|
|
||||||
|
m_current_circuits = std::pair<const db::Circuit *, const db::Circuit *> (0, 0);
|
||||||
|
mp_per_circuit_data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::circuit_skipped (const db::Circuit *a, const db::Circuit *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b);
|
||||||
|
mp_per_circuit_data->status = Skipped;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::circuit_mismatch (const db::Circuit *a, const db::Circuit *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b);
|
||||||
|
mp_per_circuit_data->status = Mismatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::match_nets (const db::Net *a, const db::Net *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, Match);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::match_ambiguous_nets (const db::Net *a, const db::Net *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, MatchWithWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::net_mismatch (const db::Net *a, const db::Net *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, Mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::match_devices (const db::Device *a, const db::Device *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, Match);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::match_devices_with_different_parameters (const db::Device *a, const db::Device *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, MatchWithWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::match_devices_with_different_device_classes (const db::Device *a, const db::Device *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, MatchWithWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::device_mismatch (const db::Device *a, const db::Device *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, Mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::match_pins (const db::Pin *a, const db::Pin *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, Match);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::pin_mismatch (const db::Pin *a, const db::Pin *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, Mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::match_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, Match);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b)
|
||||||
|
{
|
||||||
|
establish_pair (a, b, Mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_data_from_single (const db::Net *net, NetlistCrossReference::PerNetData &data, bool first)
|
||||||
|
{
|
||||||
|
data.pins.reserve (net->pin_count ());
|
||||||
|
for (db::Net::const_pin_iterator i = net->begin_pins (); i != net->end_pins (); ++i) {
|
||||||
|
if (! first) {
|
||||||
|
data.pins.push_back (std::make_pair ((const db::NetPinRef *) 0, i.operator-> ()));
|
||||||
|
} else {
|
||||||
|
data.pins.push_back (std::make_pair (i.operator-> (), (const db::NetPinRef *) 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.subcircuit_pins.reserve (net->subcircuit_pin_count ());
|
||||||
|
for (db::Net::const_subcircuit_pin_iterator i = net->begin_subcircuit_pins (); i != net->end_subcircuit_pins (); ++i) {
|
||||||
|
if (! first) {
|
||||||
|
data.subcircuit_pins.push_back (std::make_pair ((const db::NetSubcircuitPinRef *) 0, i.operator-> ()));
|
||||||
|
} else {
|
||||||
|
data.subcircuit_pins.push_back (std::make_pair (i.operator-> (), (const db::NetSubcircuitPinRef *) 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.terminals.reserve (net->terminal_count ());
|
||||||
|
for (db::Net::const_terminal_iterator i = net->begin_terminals (); i != net->end_terminals (); ++i) {
|
||||||
|
if (! first) {
|
||||||
|
data.terminals.push_back (std::make_pair ((const db::NetTerminalRef *) 0, i.operator-> ()));
|
||||||
|
} else {
|
||||||
|
data.terminals.push_back (std::make_pair (i.operator-> (), (const db::NetTerminalRef *) 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::build_terminal_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const
|
||||||
|
{
|
||||||
|
std::map<std::pair<const db::Device *, size_t>, const db::NetTerminalRef *> d2t_a, d2t_b;
|
||||||
|
|
||||||
|
for (db::Net::const_terminal_iterator i = nets.first->begin_terminals (); i != nets.first->end_terminals (); ++i) {
|
||||||
|
d2t_a.insert (std::make_pair (std::make_pair (i->device (), i->terminal_id ()), i.operator-> ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (db::Net::const_terminal_iterator i = nets.second->begin_terminals (); i != nets.second->end_terminals (); ++i) {
|
||||||
|
d2t_b.insert (std::make_pair (std::make_pair (i->device (), i->terminal_id ()), i.operator-> ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::map<std::pair<const db::Device *, size_t>, const db::NetTerminalRef *>::const_iterator a = d2t_a.begin (); a != d2t_a.end (); ++a) {
|
||||||
|
|
||||||
|
const db::Device *da = a->first.first;
|
||||||
|
|
||||||
|
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 ()) {
|
||||||
|
|
||||||
|
const db::Device *db = idb->second;
|
||||||
|
|
||||||
|
// we have a device pair - now we need to match the terminals: we do so on the basis
|
||||||
|
// of normalized terminal ID's
|
||||||
|
|
||||||
|
size_t atid = da->device_class ()->normalize_terminal_id (a->first.second);
|
||||||
|
const std::vector<db::DeviceTerminalDefinition> &termdefs_b = db->device_class ()->terminal_definitions ();
|
||||||
|
|
||||||
|
for (std::vector<db::DeviceTerminalDefinition>::const_iterator t = termdefs_b.begin (); t != termdefs_b.end (); ++t) {
|
||||||
|
if (atid == db->device_class ()->normalize_terminal_id (t->id ())) {
|
||||||
|
std::map<std::pair<const db::Device *, size_t>, const db::NetTerminalRef *>::iterator b = d2t_b.find (std::make_pair (db, t->id ()));
|
||||||
|
if (b != d2t_b.end ()) {
|
||||||
|
pb = b->second;
|
||||||
|
// remove the entry so we won't find it again
|
||||||
|
d2t_b.erase (b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::build_pin_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const
|
||||||
|
{
|
||||||
|
std::map<const db::Pin *, const db::NetPinRef *> p2r_a, p2r_b;
|
||||||
|
|
||||||
|
for (db::Net::const_pin_iterator i = nets.first->begin_pins (); i != nets.first->end_pins (); ++i) {
|
||||||
|
p2r_a.insert (std::make_pair (i->pin (), i.operator-> ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (db::Net::const_pin_iterator i = nets.second->begin_pins (); i != nets.second->end_pins (); ++i) {
|
||||||
|
p2r_b.insert (std::make_pair (i->pin (), i.operator-> ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::map<const Pin *, const db::NetPinRef *>::const_iterator a = p2r_a.begin (); a != p2r_a.end (); ++a) {
|
||||||
|
|
||||||
|
const db::Pin *pa = a->first;
|
||||||
|
|
||||||
|
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 ()) {
|
||||||
|
|
||||||
|
const db::Pin *pb = ipb->second;
|
||||||
|
std::map<const Pin *, const db::NetPinRef *>::iterator b = p2r_b.find (pb);
|
||||||
|
if (b != p2r_b.end ()) {
|
||||||
|
prb = b->second;
|
||||||
|
// remove the entry so we won't find it again
|
||||||
|
p2r_b.erase (b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data.pins.push_back (std::make_pair (a->second, prb));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::build_subcircuit_pin_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
|
s2t_b.insert (std::make_pair (std::make_pair (i->subcircuit (), i->pin_id ()), i.operator-> ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::map<std::pair<const db::SubCircuit *, size_t>, const db::NetSubcircuitPinRef *>::const_iterator a = s2t_a.begin (); a != s2t_a.end (); ++a) {
|
||||||
|
|
||||||
|
const db::SubCircuit *sa = a->first.first;
|
||||||
|
|
||||||
|
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 ()) {
|
||||||
|
|
||||||
|
const db::SubCircuit *sb = isb->second;
|
||||||
|
|
||||||
|
// we have a subcircuit pair - now we need to match the pins: we do so on the basis
|
||||||
|
// pin matching
|
||||||
|
|
||||||
|
const db::Pin *pa = sa->circuit_ref ()->pin_by_id (a->first.second);
|
||||||
|
std::map<const db::Pin *, const db::Pin *>::const_iterator ipb = m_other_pin.find (pa);
|
||||||
|
if (ipb != m_other_pin.end ()) {
|
||||||
|
|
||||||
|
std::map<std::pair<const db::SubCircuit *, size_t>, const db::NetSubcircuitPinRef *>::iterator b = s2t_b.find (std::make_pair (sb, ipb->second->id ()));
|
||||||
|
if (b != s2t_b.end ()) {
|
||||||
|
pb = b->second;
|
||||||
|
// remove the entry so we won't find it again
|
||||||
|
s2t_b.erase (b);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data.subcircuit_pins.push_back (std::make_pair (a->second, pb));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetlistCrossReference::build_per_net_info (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const
|
||||||
|
{
|
||||||
|
if (! nets.second) {
|
||||||
|
init_data_from_single (nets.first, data, true);
|
||||||
|
} else if (! nets.first) {
|
||||||
|
init_data_from_single (nets.second, data, false);
|
||||||
|
} else if (nets.first) {
|
||||||
|
build_terminal_refs (nets, data);
|
||||||
|
build_pin_refs (nets, data);
|
||||||
|
build_subcircuit_pin_refs (nets, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,194 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HDR_dbNetlistCrossReference
|
||||||
|
#define HDR_dbNetlistCrossReference
|
||||||
|
|
||||||
|
#include "dbCommon.h"
|
||||||
|
#include "dbNetlistCompare.h"
|
||||||
|
#include "tlObject.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace db
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The NetlistCrossReference class
|
||||||
|
*
|
||||||
|
* This class stores the results of a netlist compare in a form which is compatible
|
||||||
|
* with the netlist cross-reference model. The intention of this class is twofold:
|
||||||
|
* persisting the results of a netlist compare and display in the netlist browser.
|
||||||
|
*/
|
||||||
|
class DB_PUBLIC NetlistCrossReference
|
||||||
|
: public db::NetlistCompareLogger, public tl::Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NetlistCrossReference ();
|
||||||
|
~NetlistCrossReference ();
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
None = 0,
|
||||||
|
Match, // objects are paired and match
|
||||||
|
NoMatch, // objects are paired, but don't match
|
||||||
|
Skipped, // objects are skipped
|
||||||
|
MatchWithWarning, // objects are paired and match, but with warning (i.e. ambiguous nets)
|
||||||
|
Mismatch // objects are not paired
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NetPairData
|
||||||
|
{
|
||||||
|
NetPairData (const db::Net *a, const db::Net *b, Status s) : pair (a, b), status (s) { }
|
||||||
|
NetPairData () : pair (0, 0), status (None) { }
|
||||||
|
|
||||||
|
std::pair<const db::Net *, const db::Net *> pair;
|
||||||
|
Status status;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DevicePairData
|
||||||
|
{
|
||||||
|
DevicePairData (const db::Device *a, const db::Device *b, Status s) : pair (a, b), status (s) { }
|
||||||
|
DevicePairData () : pair (0, 0), status (None) { }
|
||||||
|
|
||||||
|
std::pair<const db::Device *, const db::Device *> pair;
|
||||||
|
Status status;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PinPairData
|
||||||
|
{
|
||||||
|
PinPairData (const db::Pin *a, const db::Pin *b, Status s) : pair (a, b), status (s) { }
|
||||||
|
PinPairData () : pair (0, 0), status (None) { }
|
||||||
|
|
||||||
|
std::pair<const db::Pin *, const db::Pin *> pair;
|
||||||
|
Status status;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubCircuitPairData
|
||||||
|
{
|
||||||
|
SubCircuitPairData (const db::SubCircuit *a, const db::SubCircuit *b, Status s) : pair (a, b), status (s) { }
|
||||||
|
SubCircuitPairData () : pair (0, 0), status (None) { }
|
||||||
|
|
||||||
|
std::pair<const db::SubCircuit *, const db::SubCircuit *> pair;
|
||||||
|
Status status;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PerCircuitData
|
||||||
|
{
|
||||||
|
PerCircuitData () : status (None) { }
|
||||||
|
|
||||||
|
Status status;
|
||||||
|
std::vector<NetPairData> nets;
|
||||||
|
std::vector<DevicePairData> devices;
|
||||||
|
std::vector<PinPairData> pins;
|
||||||
|
std::vector<SubCircuitPairData> subcircuits;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PerNetData
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void begin_netlist (const db::Netlist *a, const db::Netlist *b);
|
||||||
|
virtual void end_netlist (const db::Netlist *a, const db::Netlist *b);
|
||||||
|
virtual void device_class_mismatch (const db::DeviceClass *a, const db::DeviceClass *b);
|
||||||
|
virtual void begin_circuit (const db::Circuit *a, const db::Circuit *b);
|
||||||
|
virtual void end_circuit (const db::Circuit *a, const db::Circuit *b, bool matching);
|
||||||
|
virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b);
|
||||||
|
virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b);
|
||||||
|
virtual void match_nets (const db::Net *a, const db::Net *b);
|
||||||
|
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b);
|
||||||
|
virtual void net_mismatch (const db::Net *a, const db::Net *b);
|
||||||
|
virtual void match_devices (const db::Device *a, const db::Device *b);
|
||||||
|
virtual void match_devices_with_different_parameters (const db::Device *a, const db::Device *b);
|
||||||
|
virtual void match_devices_with_different_device_classes (const db::Device *a, const db::Device *b);
|
||||||
|
virtual void device_mismatch (const db::Device *a, const db::Device *b);
|
||||||
|
virtual void match_pins (const db::Pin *a, const db::Pin *b);
|
||||||
|
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b);
|
||||||
|
virtual void match_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b);
|
||||||
|
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b);
|
||||||
|
|
||||||
|
size_t circuit_count () const
|
||||||
|
{
|
||||||
|
return m_per_circuit_data.size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef std::map<std::pair<const db::Circuit *, const db::Circuit *>, PerCircuitData>::const_iterator per_circuit_data_iterator;
|
||||||
|
|
||||||
|
per_circuit_data_iterator begin_per_circuit_data () const
|
||||||
|
{
|
||||||
|
return m_per_circuit_data.begin ();
|
||||||
|
}
|
||||||
|
|
||||||
|
per_circuit_data_iterator end_per_circuit_data () const
|
||||||
|
{
|
||||||
|
return m_per_circuit_data.end ();
|
||||||
|
}
|
||||||
|
|
||||||
|
const PerCircuitData *per_circuit_data_for (const std::pair<const db::Circuit *, const db::Circuit *> &circuits) const;
|
||||||
|
|
||||||
|
typedef std::vector<std::pair<const db::Circuit *, const db::Circuit *> >::const_iterator circuits_iterator;
|
||||||
|
|
||||||
|
circuits_iterator begin_circuits () const
|
||||||
|
{
|
||||||
|
return m_circuits.begin ();
|
||||||
|
}
|
||||||
|
|
||||||
|
circuits_iterator end_circuits () const
|
||||||
|
{
|
||||||
|
return m_circuits.end ();
|
||||||
|
}
|
||||||
|
|
||||||
|
const db::Net *other_net_for (const db::Net *net) const;
|
||||||
|
const PerNetData *per_net_data_for (const std::pair<const db::Net *, const db::Net *> &nets) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tl::weak_ptr<db::Netlist> mp_netlist_a, mp_netlist_b;
|
||||||
|
std::vector<std::pair<const db::Circuit *, const db::Circuit *> > m_circuits;
|
||||||
|
std::map<std::pair<const db::Circuit *, const db::Circuit *>, PerCircuitData> m_per_circuit_data;
|
||||||
|
mutable std::map<std::pair<const db::Net *, const db::Net *>, PerNetData> m_per_net_data;
|
||||||
|
std::map<const db::Circuit *, const db::Circuit *> m_other_circuit;
|
||||||
|
std::map<const db::Net *, const db::Net *> m_other_net;
|
||||||
|
std::map<const db::Device *, const db::Device *> m_other_device;
|
||||||
|
std::map<const db::Pin *, const db::Pin *> m_other_pin;
|
||||||
|
std::map<const db::SubCircuit *, const db::SubCircuit *> m_other_subcircuit;
|
||||||
|
std::pair<const db::Circuit *, const db::Circuit *> m_current_circuits;
|
||||||
|
PerCircuitData *mp_per_circuit_data;
|
||||||
|
|
||||||
|
void establish_pair (const db::Circuit *a, const db::Circuit *b);
|
||||||
|
void establish_pair (const db::Net *a, const db::Net *b, Status status);
|
||||||
|
void establish_pair (const db::Device *a, const db::Device *b, Status status);
|
||||||
|
void establish_pair (const db::Pin *a, const db::Pin *b, Status status);
|
||||||
|
void establish_pair (const db::SubCircuit *a, const db::SubCircuit *b, Status status);
|
||||||
|
|
||||||
|
void build_per_net_info (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const;
|
||||||
|
void build_subcircuit_pin_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const;
|
||||||
|
void build_pin_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const;
|
||||||
|
void build_terminal_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include "tlUnitTest.h"
|
#include "tlUnitTest.h"
|
||||||
#include "dbNetlistDeviceClasses.h"
|
#include "dbNetlistDeviceClasses.h"
|
||||||
#include "dbNetlistCompare.h"
|
#include "dbNetlistCompare.h"
|
||||||
|
#include "dbNetlistCrossReference.h"
|
||||||
|
|
||||||
class NetlistCompareTestLogger
|
class NetlistCompareTestLogger
|
||||||
: public db::NetlistCompareLogger
|
: public db::NetlistCompareLogger
|
||||||
|
|
@ -162,6 +163,53 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string xref_status2s (db::NetlistCrossReference::Status status)
|
||||||
|
{
|
||||||
|
if (status == db::NetlistCrossReference::Match) {
|
||||||
|
return "Match";
|
||||||
|
} else if (status == db::NetlistCrossReference::Mismatch) {
|
||||||
|
return "Mismatch";
|
||||||
|
} else if (status == db::NetlistCrossReference::NoMatch) {
|
||||||
|
return "NoMatch";
|
||||||
|
} else if (status == db::NetlistCrossReference::MatchWithWarning) {
|
||||||
|
return "MatchWithWarning";
|
||||||
|
} else if (status == db::NetlistCrossReference::Skipped) {
|
||||||
|
return "Skipped";
|
||||||
|
} else {
|
||||||
|
return "None";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Obj>
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return obj ? obj->expanded_name () : std::string ("(null)");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string xref2s (const db::NetlistCrossReference &xref)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
for (db::NetlistCrossReference::circuits_iterator c = xref.begin_circuits (); c != xref.end_circuits (); ++c) {
|
||||||
|
|
||||||
|
const db::NetlistCrossReference::PerCircuitData *pcd = xref.per_circuit_data_for (*c);
|
||||||
|
tl_assert (pcd != 0);
|
||||||
|
|
||||||
|
s += name_of (c->first) + ":" + name_of (c->second) + " [" + xref_status2s (pcd->status) + "]:\n";
|
||||||
|
|
||||||
|
//@@@
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
static void prep_nl (db::Netlist &nl, const char *str)
|
static void prep_nl (db::Netlist &nl, const char *str)
|
||||||
{
|
{
|
||||||
db::DeviceClass *dc;
|
db::DeviceClass *dc;
|
||||||
|
|
@ -358,6 +406,16 @@ TEST(1_SimpleInverter)
|
||||||
"end_circuit INV INV MATCH"
|
"end_circuit INV INV MATCH"
|
||||||
);
|
);
|
||||||
EXPECT_EQ (good, true);
|
EXPECT_EQ (good, true);
|
||||||
|
|
||||||
|
db::NetlistCrossReference xref;
|
||||||
|
db::NetlistComparer comp_xref (&xref);
|
||||||
|
|
||||||
|
good = comp_xref.compare (&nl1, &nl2);
|
||||||
|
|
||||||
|
EXPECT_EQ (xref2s (xref),
|
||||||
|
"INV:INV [Match]:\n"
|
||||||
|
);
|
||||||
|
EXPECT_EQ (good, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(1_SimpleInverterMatchedDeviceClasses)
|
TEST(1_SimpleInverterMatchedDeviceClasses)
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
namespace lay
|
namespace lay
|
||||||
{
|
{
|
||||||
|
|
||||||
NetlistCrossReferenceModel::NetlistCrossReferenceModel (db::NetlistCrossReference *cross_ref)
|
NetlistCrossReferenceModel::NetlistCrossReferenceModel (const db::NetlistCrossReference *cross_ref)
|
||||||
: mp_cross_ref (cross_ref)
|
: mp_cross_ref (const_cast<db::NetlistCrossReference *> (cross_ref))
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +79,7 @@ template <class Obj> struct DataGetter;
|
||||||
template <>
|
template <>
|
||||||
struct DataGetter<const db::Net *>
|
struct DataGetter<const db::Net *>
|
||||||
{
|
{
|
||||||
typedef typename std::vector<std::pair<const db::Net *, const db::Net *> >::const_iterator iterator_type;
|
typedef typename std::vector<db::NetlistCrossReference::NetPairData>::const_iterator iterator_type;
|
||||||
iterator_type begin (const db::NetlistCrossReference::PerCircuitData &data) const { return data.nets.begin (); }
|
iterator_type begin (const db::NetlistCrossReference::PerCircuitData &data) const { return data.nets.begin (); }
|
||||||
iterator_type end (const db::NetlistCrossReference::PerCircuitData &data) const { return data.nets.end (); }
|
iterator_type end (const db::NetlistCrossReference::PerCircuitData &data) const { return data.nets.end (); }
|
||||||
};
|
};
|
||||||
|
|
@ -87,7 +87,7 @@ struct DataGetter<const db::Net *>
|
||||||
template <>
|
template <>
|
||||||
struct DataGetter<const db::Device *>
|
struct DataGetter<const db::Device *>
|
||||||
{
|
{
|
||||||
typedef typename std::vector<std::pair<const db::Device *, const db::Device *> >::const_iterator iterator_type;
|
typedef typename std::vector<db::NetlistCrossReference::DevicePairData>::const_iterator iterator_type;
|
||||||
iterator_type begin (const db::NetlistCrossReference::PerCircuitData &data) const { return data.devices.begin (); }
|
iterator_type begin (const db::NetlistCrossReference::PerCircuitData &data) const { return data.devices.begin (); }
|
||||||
iterator_type end (const db::NetlistCrossReference::PerCircuitData &data) const { return data.devices.end (); }
|
iterator_type end (const db::NetlistCrossReference::PerCircuitData &data) const { return data.devices.end (); }
|
||||||
};
|
};
|
||||||
|
|
@ -95,7 +95,7 @@ struct DataGetter<const db::Device *>
|
||||||
template <>
|
template <>
|
||||||
struct DataGetter<const db::SubCircuit *>
|
struct DataGetter<const db::SubCircuit *>
|
||||||
{
|
{
|
||||||
typedef typename std::vector<std::pair<const db::SubCircuit *, const db::SubCircuit *> >::const_iterator iterator_type;
|
typedef typename std::vector<db::NetlistCrossReference::SubCircuitPairData>::const_iterator iterator_type;
|
||||||
iterator_type begin (const db::NetlistCrossReference::PerCircuitData &data) const { return data.subcircuits.begin (); }
|
iterator_type begin (const db::NetlistCrossReference::PerCircuitData &data) const { return data.subcircuits.begin (); }
|
||||||
iterator_type end (const db::NetlistCrossReference::PerCircuitData &data) const { return data.subcircuits.end (); }
|
iterator_type end (const db::NetlistCrossReference::PerCircuitData &data) const { return data.subcircuits.end (); }
|
||||||
};
|
};
|
||||||
|
|
@ -114,7 +114,7 @@ static IndexedNetlistModel::circuit_pair get_parent_of (const Pair &pair, const
|
||||||
iterator_type b = getter_type ().begin (c->second);
|
iterator_type b = getter_type ().begin (c->second);
|
||||||
iterator_type e = getter_type ().end (c->second);
|
iterator_type e = getter_type ().end (c->second);
|
||||||
for (iterator_type j = b; j != e; ++j) {
|
for (iterator_type j = b; j != e; ++j) {
|
||||||
cache.insert (std::make_pair (*j, c->first));
|
cache.insert (std::make_pair (j->pair, c->first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,7 +149,7 @@ IndexedNetlistModel::net_pair NetlistCrossReferenceModel::net_from_index (const
|
||||||
{
|
{
|
||||||
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||||
tl_assert (data != 0);
|
tl_assert (data != 0);
|
||||||
return data->nets [index];
|
return data->nets [index].pair;
|
||||||
}
|
}
|
||||||
|
|
||||||
const db::Net *NetlistCrossReferenceModel::second_net_for (const db::Net *first) const
|
const db::Net *NetlistCrossReferenceModel::second_net_for (const db::Net *first) const
|
||||||
|
|
@ -182,21 +182,21 @@ IndexedNetlistModel::device_pair NetlistCrossReferenceModel::device_from_index (
|
||||||
{
|
{
|
||||||
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||||
tl_assert (data != 0);
|
tl_assert (data != 0);
|
||||||
return data->devices [index];
|
return data->devices [index].pair;
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexedNetlistModel::pin_pair NetlistCrossReferenceModel::pin_from_index (const circuit_pair &circuits, size_t index) const
|
IndexedNetlistModel::pin_pair NetlistCrossReferenceModel::pin_from_index (const circuit_pair &circuits, size_t index) const
|
||||||
{
|
{
|
||||||
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||||
tl_assert (data != 0);
|
tl_assert (data != 0);
|
||||||
return data->pins [index];
|
return data->pins [index].pair;
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexedNetlistModel::subcircuit_pair NetlistCrossReferenceModel::subcircuit_from_index (const circuit_pair &circuits, size_t index) const
|
IndexedNetlistModel::subcircuit_pair NetlistCrossReferenceModel::subcircuit_from_index (const circuit_pair &circuits, size_t index) const
|
||||||
{
|
{
|
||||||
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||||
tl_assert (data != 0);
|
tl_assert (data != 0);
|
||||||
return data->subcircuits [index];
|
return data->subcircuits [index].pair;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Pair, class Iter>
|
template <class Pair, class Iter>
|
||||||
|
|
@ -207,7 +207,7 @@ static size_t get_index_of (const Pair &pair, Iter begin, Iter end, std::map<Pai
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (Iter j = begin; j != end; ++j, ++index) {
|
for (Iter j = begin; j != end; ++j, ++index) {
|
||||||
cache.insert (std::make_pair (*j, index));
|
cache.insert (std::make_pair (j->pair, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
i = cache.find (pair);
|
i = cache.find (pair);
|
||||||
|
|
@ -220,7 +220,19 @@ static size_t get_index_of (const Pair &pair, Iter begin, Iter end, std::map<Pai
|
||||||
|
|
||||||
size_t NetlistCrossReferenceModel::circuit_index (const circuit_pair &circuits) const
|
size_t NetlistCrossReferenceModel::circuit_index (const circuit_pair &circuits) const
|
||||||
{
|
{
|
||||||
return get_index_of (circuits, mp_cross_ref->begin_circuits (), mp_cross_ref->end_circuits (), m_index_of_circuits);
|
typename std::map<circuit_pair, size_t>::iterator i = m_index_of_circuits.find (circuits);
|
||||||
|
if (i != m_index_of_circuits.end ()) {
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
for (db::NetlistCrossReference::circuits_iterator j = mp_cross_ref->begin_circuits (); j != mp_cross_ref->end_circuits (); ++j, ++index) {
|
||||||
|
m_index_of_circuits.insert (std::make_pair (*j, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
i = m_index_of_circuits.find (circuits);
|
||||||
|
tl_assert (i != m_index_of_circuits.end ());
|
||||||
|
}
|
||||||
|
|
||||||
|
return i->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t NetlistCrossReferenceModel::net_index (const net_pair &nets) const
|
size_t NetlistCrossReferenceModel::net_index (const net_pair &nets) const
|
||||||
|
|
|
||||||
|
|
@ -27,542 +27,7 @@
|
||||||
#include "laybasicCommon.h"
|
#include "laybasicCommon.h"
|
||||||
#include "layIndexedNetlistModel.h"
|
#include "layIndexedNetlistModel.h"
|
||||||
|
|
||||||
#include "tlObject.h"
|
#include "dbNetlistCrossReference.h"
|
||||||
#include "dbNetlistCompare.h" // @@@
|
|
||||||
|
|
||||||
// @@@
|
|
||||||
namespace db
|
|
||||||
{
|
|
||||||
|
|
||||||
class NetlistCrossReference
|
|
||||||
: public db::NetlistCompareLogger, public tl::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NetlistCrossReference ();
|
|
||||||
|
|
||||||
enum status {
|
|
||||||
None = 0,
|
|
||||||
Match, // objects are paired and match
|
|
||||||
NoMatch, // objects are paired, but don't match
|
|
||||||
Skipped, // objects are skipped
|
|
||||||
MatchWithWarning, // objects are paired and match, but with warning (i.e. ambiguous nets)
|
|
||||||
Mismatch // objects are not paired
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PerCircuitData
|
|
||||||
{
|
|
||||||
std::vector<std::pair<const db::Net *, const db::Net *> > nets;
|
|
||||||
std::vector<std::pair<const db::Device *, const db::Device *> > devices;
|
|
||||||
std::vector<std::pair<const db::Pin *, const db::Pin *> > pins;
|
|
||||||
std::vector<std::pair<const db::SubCircuit *, const db::SubCircuit *> > subcircuits;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PerNetData
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual void begin_netlist (const db::Netlist *a, const db::Netlist *b);
|
|
||||||
virtual void end_netlist (const db::Netlist *a, const db::Netlist *b);
|
|
||||||
virtual void device_class_mismatch (const db::DeviceClass *a, const db::DeviceClass *b);
|
|
||||||
virtual void begin_circuit (const db::Circuit *a, const db::Circuit *b);
|
|
||||||
virtual void end_circuit (const db::Circuit *a, const db::Circuit *b, bool matching);
|
|
||||||
virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b);
|
|
||||||
virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b);
|
|
||||||
virtual void match_nets (const db::Net *a, const db::Net *b);
|
|
||||||
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b);
|
|
||||||
virtual void net_mismatch (const db::Net *a, const db::Net *b);
|
|
||||||
virtual void match_devices (const db::Device *a, const db::Device *b);
|
|
||||||
virtual void match_devices_with_different_parameters (const db::Device *a, const db::Device *b);
|
|
||||||
virtual void match_devices_with_different_device_classes (const db::Device *a, const db::Device *b);
|
|
||||||
virtual void device_mismatch (const db::Device *a, const db::Device *b);
|
|
||||||
virtual void match_pins (const db::Pin *a, const db::Pin *b);
|
|
||||||
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b);
|
|
||||||
virtual void match_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b);
|
|
||||||
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b);
|
|
||||||
|
|
||||||
size_t circuit_count () const
|
|
||||||
{
|
|
||||||
return m_per_circuit_data.size ();
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef std::map<std::pair<const db::Circuit *, const db::Circuit *>, PerCircuitData>::const_iterator per_circuit_data_iterator;
|
|
||||||
|
|
||||||
per_circuit_data_iterator begin_per_circuit_data () const
|
|
||||||
{
|
|
||||||
return m_per_circuit_data.begin ();
|
|
||||||
}
|
|
||||||
|
|
||||||
per_circuit_data_iterator end_per_circuit_data () const
|
|
||||||
{
|
|
||||||
return m_per_circuit_data.end ();
|
|
||||||
}
|
|
||||||
|
|
||||||
const PerCircuitData *per_circuit_data_for (const std::pair<const db::Circuit *, const db::Circuit *> &circuits) const
|
|
||||||
{
|
|
||||||
per_circuit_data_iterator i = m_per_circuit_data.find (circuits);
|
|
||||||
if (i == m_per_circuit_data.end ()) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return & i->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef std::vector<std::pair<const db::Circuit *, const db::Circuit *> >::const_iterator circuits_iterator;
|
|
||||||
|
|
||||||
circuits_iterator begin_circuits () const
|
|
||||||
{
|
|
||||||
return m_circuits.begin ();
|
|
||||||
}
|
|
||||||
|
|
||||||
circuits_iterator end_circuits () const
|
|
||||||
{
|
|
||||||
return m_circuits.end ();
|
|
||||||
}
|
|
||||||
|
|
||||||
const db::Net *other_net_for (const db::Net *net) const
|
|
||||||
{
|
|
||||||
std::map<const db::Net *, const db::Net *>::const_iterator i = m_other_net.find (net);
|
|
||||||
if (i != m_other_net.end ()) {
|
|
||||||
return i->second;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const PerNetData *per_net_data_for (const std::pair<const db::Net *, const db::Net *> &nets) const
|
|
||||||
{
|
|
||||||
std::map<std::pair<const db::Net *, const db::Net *>, PerNetData>::iterator i = m_per_net_data.find (nets);
|
|
||||||
if (i == m_per_net_data.end ()) {
|
|
||||||
i = m_per_net_data.insert (std::make_pair (nets, PerNetData ())).first;
|
|
||||||
build_per_net_info (nets, i->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return &i->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
tl::weak_ptr<db::Netlist> mp_netlist_a, mp_netlist_b;
|
|
||||||
std::vector<std::pair<const db::Circuit *, const db::Circuit *> > m_circuits;
|
|
||||||
std::map<std::pair<const db::Circuit *, const db::Circuit *>, PerCircuitData> m_per_circuit_data;
|
|
||||||
mutable std::map<std::pair<const db::Net *, const db::Net *>, PerNetData> m_per_net_data;
|
|
||||||
std::map<const db::Circuit *, const db::Circuit *> m_other_circuit;
|
|
||||||
std::map<const db::Net *, const db::Net *> m_other_net;
|
|
||||||
std::map<const db::Device *, const db::Device *> m_other_device;
|
|
||||||
std::map<const db::Pin *, const db::Pin *> m_other_pin;
|
|
||||||
std::map<const db::SubCircuit *, const db::SubCircuit *> m_other_subcircuit;
|
|
||||||
std::pair<const db::Circuit *, const db::Circuit *> m_current_circuits;
|
|
||||||
std::map<std::pair<const db::Circuit *, const db::Circuit *>, status> m_circuit_status;
|
|
||||||
std::map<std::pair<const db::Net *, const db::Net *>, status> m_net_status;
|
|
||||||
std::map<std::pair<const db::Device *, const db::Device *>, status> m_device_status;
|
|
||||||
std::map<std::pair<const db::Pin *, const db::Pin *>, status> m_pin_status;
|
|
||||||
std::map<std::pair<const db::SubCircuit *, const db::SubCircuit *>, status> m_subcircuit_status;
|
|
||||||
PerCircuitData *mp_per_circuit_data;
|
|
||||||
|
|
||||||
void establish_pair (const db::Circuit *a, const db::Circuit *b);
|
|
||||||
void establish_pair (const db::Net *a, const db::Net *b);
|
|
||||||
void establish_pair (const db::Device *a, const db::Device *b);
|
|
||||||
void establish_pair (const db::Pin *a, const db::Pin *b);
|
|
||||||
void establish_pair (const db::SubCircuit *a, const db::SubCircuit *b);
|
|
||||||
|
|
||||||
void build_per_net_info (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const;
|
|
||||||
void build_subcircuit_pin_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const;
|
|
||||||
void build_pin_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const;
|
|
||||||
void build_terminal_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::begin_netlist (const db::Netlist *a, const db::Netlist *b)
|
|
||||||
{
|
|
||||||
mp_netlist_a.reset (const_cast <db::Netlist *> (a));
|
|
||||||
mp_netlist_b.reset (const_cast <db::Netlist *> (b));
|
|
||||||
m_current_circuits = std::pair<const db::Circuit *, const db::Circuit *> (0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::end_netlist (const db::Netlist *, const db::Netlist *)
|
|
||||||
{
|
|
||||||
m_circuits.reserve (m_per_circuit_data.size ());
|
|
||||||
for (per_circuit_data_iterator i = begin_per_circuit_data (); i != end_per_circuit_data (); ++i) {
|
|
||||||
m_circuits.push_back (i->first);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// @@@ TODO: sort m_circuits by name?
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::device_class_mismatch (const db::DeviceClass *, const db::DeviceClass *)
|
|
||||||
{
|
|
||||||
// .. nothing yet ..
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::establish_pair (const db::Circuit *a, const db::Circuit *b)
|
|
||||||
{
|
|
||||||
mp_per_circuit_data = & m_per_circuit_data [std::make_pair (a, b)];
|
|
||||||
|
|
||||||
if (a) {
|
|
||||||
m_other_circuit [a] = b;
|
|
||||||
}
|
|
||||||
if (b) {
|
|
||||||
m_other_circuit [b] = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::establish_pair (const db::Net *a, const db::Net *b)
|
|
||||||
{
|
|
||||||
mp_per_circuit_data->nets.push_back (std::make_pair (a, b));
|
|
||||||
if (a) {
|
|
||||||
m_other_net [a] = b;
|
|
||||||
}
|
|
||||||
if (b) {
|
|
||||||
m_other_net [b] = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::establish_pair (const db::Device *a, const db::Device *b)
|
|
||||||
{
|
|
||||||
mp_per_circuit_data->devices.push_back (std::make_pair (a, b));
|
|
||||||
if (a) {
|
|
||||||
m_other_device [a] = b;
|
|
||||||
}
|
|
||||||
if (b) {
|
|
||||||
m_other_device [b] = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::establish_pair (const db::Pin *a, const db::Pin *b)
|
|
||||||
{
|
|
||||||
mp_per_circuit_data->pins.push_back (std::make_pair (a, b));
|
|
||||||
if (a) {
|
|
||||||
m_other_pin [a] = b;
|
|
||||||
}
|
|
||||||
if (b) {
|
|
||||||
m_other_pin [b] = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::establish_pair (const db::SubCircuit *a, const db::SubCircuit *b)
|
|
||||||
{
|
|
||||||
mp_per_circuit_data->subcircuits.push_back (std::make_pair (a, b));
|
|
||||||
if (a) {
|
|
||||||
m_other_subcircuit [a] = b;
|
|
||||||
}
|
|
||||||
if (b) {
|
|
||||||
m_other_subcircuit [b] = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::begin_circuit (const db::Circuit *a, const db::Circuit *b)
|
|
||||||
{
|
|
||||||
m_current_circuits = std::pair<const db::Circuit *, const db::Circuit *> (a, b);
|
|
||||||
establish_pair (a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::end_circuit (const db::Circuit *, const db::Circuit *, bool matching)
|
|
||||||
{
|
|
||||||
if (matching) {
|
|
||||||
m_circuit_status [m_current_circuits] = Match;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @@@ TODO: sort per-circuit data vectors by name?
|
|
||||||
|
|
||||||
m_current_circuits = std::pair<const db::Circuit *, const db::Circuit *> (0, 0);
|
|
||||||
mp_per_circuit_data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::circuit_skipped (const db::Circuit *a, const db::Circuit *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_circuit_status [std::pair<const db::Circuit *, const db::Circuit *> (a, b)] = Skipped;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::circuit_mismatch (const db::Circuit *a, const db::Circuit *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_circuit_status [std::pair<const db::Circuit *, const db::Circuit *> (a, b)] = Mismatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::match_nets (const db::Net *a, const db::Net *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_net_status [std::pair<const db::Net *, const db::Net *> (a, b)] = Match;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::match_ambiguous_nets (const db::Net *a, const db::Net *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_net_status [std::pair<const db::Net *, const db::Net *> (a, b)] = MatchWithWarning;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::net_mismatch (const db::Net *a, const db::Net *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_net_status [std::pair<const db::Net *, const db::Net *> (a, b)] = Mismatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::match_devices (const db::Device *a, const db::Device *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_device_status [std::pair<const db::Device *, const db::Device *> (a, b)] = Match;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::match_devices_with_different_parameters (const db::Device *a, const db::Device *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_device_status [std::pair<const db::Device *, const db::Device *> (a, b)] = MatchWithWarning;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::match_devices_with_different_device_classes (const db::Device *a, const db::Device *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_device_status [std::pair<const db::Device *, const db::Device *> (a, b)] = MatchWithWarning;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::device_mismatch (const db::Device *a, const db::Device *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_device_status [std::pair<const db::Device *, const db::Device *> (a, b)] = Mismatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::match_pins (const db::Pin *a, const db::Pin *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_pin_status [std::pair<const db::Pin *, const db::Pin *> (a, b)] = Match;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::pin_mismatch (const db::Pin *a, const db::Pin *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_pin_status [std::pair<const db::Pin *, const db::Pin *> (a, b)] = Mismatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::match_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_subcircuit_status [std::pair<const db::SubCircuit *, const db::SubCircuit *> (a, b)] = Match;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b)
|
|
||||||
{
|
|
||||||
establish_pair (a, b);
|
|
||||||
m_subcircuit_status [std::pair<const db::SubCircuit *, const db::SubCircuit *> (a, b)] = Mismatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void init_data_from_single (const db::Net *net, NetlistCrossReference::PerNetData &data, bool first)
|
|
||||||
{
|
|
||||||
data.pins.reserve (net->pin_count ());
|
|
||||||
for (db::Net::const_pin_iterator i = net->begin_pins (); i != net->end_pins (); ++i) {
|
|
||||||
if (! first) {
|
|
||||||
data.pins.push_back (std::make_pair ((const db::NetPinRef *) 0, i.operator-> ()));
|
|
||||||
} else {
|
|
||||||
data.pins.push_back (std::make_pair (i.operator-> (), (const db::NetPinRef *) 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.subcircuit_pins.reserve (net->subcircuit_pin_count ());
|
|
||||||
for (db::Net::const_subcircuit_pin_iterator i = net->begin_subcircuit_pins (); i != net->end_subcircuit_pins (); ++i) {
|
|
||||||
if (! first) {
|
|
||||||
data.subcircuit_pins.push_back (std::make_pair ((const db::NetSubcircuitPinRef *) 0, i.operator-> ()));
|
|
||||||
} else {
|
|
||||||
data.subcircuit_pins.push_back (std::make_pair (i.operator-> (), (const db::NetSubcircuitPinRef *) 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.terminals.reserve (net->terminal_count ());
|
|
||||||
for (db::Net::const_terminal_iterator i = net->begin_terminals (); i != net->end_terminals (); ++i) {
|
|
||||||
if (! first) {
|
|
||||||
data.terminals.push_back (std::make_pair ((const db::NetTerminalRef *) 0, i.operator-> ()));
|
|
||||||
} else {
|
|
||||||
data.terminals.push_back (std::make_pair (i.operator-> (), (const db::NetTerminalRef *) 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::build_terminal_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const
|
|
||||||
{
|
|
||||||
std::map<std::pair<const db::Device *, size_t>, const db::NetTerminalRef *> d2t_a, d2t_b;
|
|
||||||
|
|
||||||
for (db::Net::const_terminal_iterator i = nets.first->begin_terminals (); i != nets.first->end_terminals (); ++i) {
|
|
||||||
d2t_a.insert (std::make_pair (std::make_pair (i->device (), i->terminal_id ()), i.operator-> ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (db::Net::const_terminal_iterator i = nets.second->begin_terminals (); i != nets.second->end_terminals (); ++i) {
|
|
||||||
d2t_b.insert (std::make_pair (std::make_pair (i->device (), i->terminal_id ()), i.operator-> ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::map<std::pair<const db::Device *, size_t>, const db::NetTerminalRef *>::const_iterator a = d2t_a.begin (); a != d2t_a.end (); ++a) {
|
|
||||||
|
|
||||||
const db::Device *da = a->first.first;
|
|
||||||
|
|
||||||
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 ()) {
|
|
||||||
|
|
||||||
const db::Device *db = idb->second;
|
|
||||||
|
|
||||||
// we have a device pair - now we need to match the terminals: we do so on the basis
|
|
||||||
// of normalized terminal ID's
|
|
||||||
|
|
||||||
size_t atid = da->device_class ()->normalize_terminal_id (a->first.second);
|
|
||||||
const std::vector<db::DeviceTerminalDefinition> &termdefs_b = db->device_class ()->terminal_definitions ();
|
|
||||||
|
|
||||||
for (std::vector<db::DeviceTerminalDefinition>::const_iterator t = termdefs_b.begin (); t != termdefs_b.end (); ++t) {
|
|
||||||
if (atid == db->device_class ()->normalize_terminal_id (t->id ())) {
|
|
||||||
std::map<std::pair<const db::Device *, size_t>, const db::NetTerminalRef *>::iterator b = d2t_b.find (std::make_pair (db, t->id ()));
|
|
||||||
if (b != d2t_b.end ()) {
|
|
||||||
pb = b->second;
|
|
||||||
// remove the entry so we won't find it again
|
|
||||||
d2t_b.erase (b);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::build_pin_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const
|
|
||||||
{
|
|
||||||
std::map<const db::Pin *, const db::NetPinRef *> p2r_a, p2r_b;
|
|
||||||
|
|
||||||
for (db::Net::const_pin_iterator i = nets.first->begin_pins (); i != nets.first->end_pins (); ++i) {
|
|
||||||
p2r_a.insert (std::make_pair (i->pin (), i.operator-> ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (db::Net::const_pin_iterator i = nets.second->begin_pins (); i != nets.second->end_pins (); ++i) {
|
|
||||||
p2r_b.insert (std::make_pair (i->pin (), i.operator-> ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::map<const Pin *, const db::NetPinRef *>::const_iterator a = p2r_a.begin (); a != p2r_a.end (); ++a) {
|
|
||||||
|
|
||||||
const db::Pin *pa = a->first;
|
|
||||||
|
|
||||||
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 ()) {
|
|
||||||
|
|
||||||
const db::Pin *pb = ipb->second;
|
|
||||||
std::map<const Pin *, const db::NetPinRef *>::iterator b = p2r_b.find (pb);
|
|
||||||
if (b != p2r_b.end ()) {
|
|
||||||
prb = b->second;
|
|
||||||
// remove the entry so we won't find it again
|
|
||||||
p2r_b.erase (b);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
data.pins.push_back (std::make_pair (a->second, prb));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::build_subcircuit_pin_refs (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const
|
|
||||||
{
|
|
||||||
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) {
|
|
||||||
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) {
|
|
||||||
s2t_b.insert (std::make_pair (std::make_pair (i->subcircuit (), i->pin_id ()), i.operator-> ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::map<std::pair<const db::SubCircuit *, size_t>, const db::NetSubcircuitPinRef *>::const_iterator a = s2t_a.begin (); a != s2t_a.end (); ++a) {
|
|
||||||
|
|
||||||
const db::SubCircuit *sa = a->first.first;
|
|
||||||
|
|
||||||
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 ()) {
|
|
||||||
|
|
||||||
const db::SubCircuit *sb = isb->second;
|
|
||||||
|
|
||||||
// we have a subcircuit pair - now we need to match the pins: we do so on the basis
|
|
||||||
// pin matching
|
|
||||||
|
|
||||||
const db::Pin *pa = sa->circuit_ref ()->pin_by_id (a->first.second);
|
|
||||||
std::map<const db::Pin *, const db::Pin *>::const_iterator ipb = m_other_pin.find (pa);
|
|
||||||
if (ipb != m_other_pin.end ()) {
|
|
||||||
|
|
||||||
std::map<std::pair<const db::SubCircuit *, size_t>, const db::NetSubcircuitPinRef *>::iterator b = s2t_b.find (std::make_pair (sb, ipb->second->id ()));
|
|
||||||
if (b != s2t_b.end ()) {
|
|
||||||
pb = b->second;
|
|
||||||
// remove the entry so we won't find it again
|
|
||||||
s2t_b.erase (b);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
data.subcircuit_pins.push_back (std::make_pair (a->second, pb));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
NetlistCrossReference::build_per_net_info (const std::pair<const db::Net *, const db::Net *> &nets, PerNetData &data) const
|
|
||||||
{
|
|
||||||
if (! nets.second) {
|
|
||||||
init_data_from_single (nets.first, data, true);
|
|
||||||
} else if (! nets.first) {
|
|
||||||
init_data_from_single (nets.second, data, false);
|
|
||||||
} else if (nets.first) {
|
|
||||||
build_terminal_refs (nets, data);
|
|
||||||
build_pin_refs (nets, data);
|
|
||||||
build_subcircuit_pin_refs (nets, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// @@@
|
|
||||||
|
|
||||||
namespace lay
|
namespace lay
|
||||||
{
|
{
|
||||||
|
|
@ -574,7 +39,7 @@ class LAYBASIC_PUBLIC NetlistCrossReferenceModel
|
||||||
: public lay::IndexedNetlistModel
|
: public lay::IndexedNetlistModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NetlistCrossReferenceModel (db::NetlistCrossReference *cross_ref);
|
NetlistCrossReferenceModel (const db::NetlistCrossReference *cross_ref);
|
||||||
|
|
||||||
virtual bool is_single () const { return false; }
|
virtual bool is_single () const { return false; }
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue