mirror of https://github.com/KLayout/klayout.git
WIP: netlist cross-reference
This commit is contained in:
parent
67e68e9e4f
commit
a46d991c6f
|
|
@ -0,0 +1,376 @@
|
|||
|
||||
/*
|
||||
|
||||
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 "layIndexedNetlistModel.h"
|
||||
#include "dbNetlist.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// SingleIndexedNetlistModel implementation
|
||||
|
||||
namespace {
|
||||
|
||||
template <class Obj>
|
||||
struct sort_single_by_name
|
||||
{
|
||||
inline bool operator() (const Obj *a, const Obj *b) const
|
||||
{
|
||||
return a->name () < b->name ();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_single_by_expanded_name
|
||||
{
|
||||
inline bool operator() (const Obj *a, const Obj *b) const
|
||||
{
|
||||
return a->expanded_name () < b->expanded_name ();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_single_by_pin_name
|
||||
{
|
||||
inline bool operator() (const Obj *a, const Obj *b) const
|
||||
{
|
||||
return a->pin ()->expanded_name () < b->pin ()->expanded_name ();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_single_by_terminal_id
|
||||
{
|
||||
inline bool operator() (const Obj *a, const Obj *b) const
|
||||
{
|
||||
return a->terminal_id () < b->terminal_id ();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj, class SortBy>
|
||||
struct sort_with_null
|
||||
{
|
||||
inline bool operator() (const Obj *a, const Obj *b) const
|
||||
{
|
||||
SortBy order;
|
||||
if ((a != 0) != (b != 0)) {
|
||||
return (a != 0) < (b != 0);
|
||||
}
|
||||
if (a) {
|
||||
if (order (a, b)) {
|
||||
return true;
|
||||
} else if (order (b, a)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj, class SortBy>
|
||||
struct sort_pair
|
||||
{
|
||||
bool operator() (const std::pair<const Obj *, const Obj *> &a, const std::pair<const Obj *, const Obj *> &b) const
|
||||
{
|
||||
SortBy order;
|
||||
if (order (a.first, b.first)) {
|
||||
return true;
|
||||
} else if (order (b.first, a.first)) {
|
||||
return false;
|
||||
}
|
||||
return order (a.second, b.second);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_by_name
|
||||
: public sort_pair<Obj, sort_with_null<Obj, sort_single_by_name<Obj> > >
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_by_expanded_name
|
||||
: public sort_pair<Obj, sort_with_null<Obj, sort_single_by_expanded_name<Obj> > >
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_by_pin_name
|
||||
: public sort_pair<Obj, sort_with_null<Obj, sort_single_by_pin_name<Obj> > >
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_by_terminal_id
|
||||
: public sort_pair<Obj, sort_with_null<Obj, sort_single_by_terminal_id<Obj> > >
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class Attr, class Iter, class SortBy>
|
||||
static void fill_map (std::vector<std::pair<const Attr *, const Attr *> > &map, const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, const SortBy &sorter)
|
||||
{
|
||||
size_t n1 = 0, n2 = 0;
|
||||
for (Iter i = begin1; i != end1; ++i) {
|
||||
++n1;
|
||||
}
|
||||
for (Iter i = begin2; i != end2; ++i) {
|
||||
++n2;
|
||||
}
|
||||
map.resize (std::max (n1, n2), typename std::pair<const Attr *, const Attr *> (0, 0));
|
||||
|
||||
typename std::vector<std::pair<const Attr *, const Attr *> >::iterator j;
|
||||
j = map.begin ();
|
||||
for (Iter i = begin1; i != end1; ++i, ++j) {
|
||||
j->first = i.operator-> ();
|
||||
}
|
||||
j = map.begin ();
|
||||
for (Iter i = begin2; i != end2; ++i, ++j) {
|
||||
j->second = i.operator-> ();
|
||||
}
|
||||
|
||||
std::sort (map.begin (), map.end (), sorter);
|
||||
}
|
||||
|
||||
template <class Obj, class Attr, class Iter, class SortBy>
|
||||
static std::pair<const Attr *, const Attr *> attr_by_object_and_index (const std::pair<const Obj *, const Obj *> &obj, size_t index, const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, std::map<std::pair<const Obj *, const Obj *>, std::vector<std::pair<const Attr *, const Attr *> > > &cache, const SortBy &sorter)
|
||||
{
|
||||
typename std::map<std::pair<const Obj *, const Obj *>, std::vector<std::pair<const Attr *, const Attr *> > >::iterator cc = cache.find (obj);
|
||||
if (cc == cache.end ()) {
|
||||
cc = cache.insert (std::make_pair (obj, std::vector<std::pair<const Attr *, const Attr *> > ())).first;
|
||||
fill_map (cc->second, begin1, end1, begin2, end2, sorter);
|
||||
}
|
||||
|
||||
tl_assert (index < cc->second.size ());
|
||||
return cc->second [index];
|
||||
}
|
||||
|
||||
template <class Attr, class Iter, class SortBy>
|
||||
static size_t index_from_attr (const std::pair<const Attr *, const Attr *> &attrs, const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, std::map<std::pair<const Attr *, const Attr *>, size_t> &cache, const SortBy &sorter)
|
||||
{
|
||||
typename std::map<std::pair<const Attr *, const Attr *>, size_t>::iterator cc = cache.find (attrs);
|
||||
if (cc != cache.end ()) {
|
||||
return cc->second;
|
||||
}
|
||||
|
||||
std::vector<std::pair<const Attr *, const Attr *> > map;
|
||||
fill_map (map, begin1, end1, begin2, end2, sorter);
|
||||
|
||||
for (size_t i = 0; i < map.size (); ++i) {
|
||||
cache.insert (std::make_pair (map [i], i));
|
||||
}
|
||||
|
||||
cc = cache.find (attrs);
|
||||
tl_assert (cc != cache.end ());
|
||||
return cc->second;
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::circuit_count () const
|
||||
{
|
||||
return mp_netlist->circuit_count ();
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::net_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return circuits.first->net_count ();
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::net_terminal_count (const net_pair &nets) const
|
||||
{
|
||||
return nets.first->terminal_count ();
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::net_subcircuit_pin_count (const net_pair &nets) const
|
||||
{
|
||||
return nets.first->subcircuit_pin_count ();
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::net_pin_count (const net_pair &nets) const
|
||||
{
|
||||
return nets.first->pin_count ();
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::device_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return circuits.first->device_count ();
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::pin_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return circuits.first->pin_count ();
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::subcircuit_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return circuits.first->subcircuit_count ();
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair
|
||||
SingleIndexedNetlistModel::parent_of (const net_pair &nets) const
|
||||
{
|
||||
return std::make_pair (nets.first->circuit (), (const db::Circuit *) 0);
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair
|
||||
SingleIndexedNetlistModel::parent_of (const device_pair &devices) const
|
||||
{
|
||||
return std::make_pair (devices.first->circuit (), (const db::Circuit *) 0);
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair
|
||||
SingleIndexedNetlistModel::parent_of (const subcircuit_pair &subcircuits) const
|
||||
{
|
||||
return std::make_pair (subcircuits.first->circuit (), (const db::Circuit *) 0);
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair
|
||||
SingleIndexedNetlistModel::circuit_from_index (size_t index) const
|
||||
{
|
||||
db::Netlist::const_circuit_iterator none;
|
||||
return attr_by_object_and_index (std::make_pair (mp_netlist, (const db::Netlist *) 0), index, mp_netlist->begin_circuits (), mp_netlist->end_circuits (), none, none, m_circuit_by_index, sort_by_name<db::Circuit> ());
|
||||
}
|
||||
|
||||
IndexedNetlistModel::net_pair
|
||||
SingleIndexedNetlistModel::net_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_net_iterator none;
|
||||
return attr_by_object_and_index (circuits, index, circuits.first->begin_nets (), circuits.first->end_nets (), none, none, m_net_by_circuit_and_index, sort_by_expanded_name<db::Net> ());
|
||||
}
|
||||
|
||||
const db::Net *
|
||||
SingleIndexedNetlistModel::second_net_for (const db::Net * /*first*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
IndexedNetlistModel::net_subcircuit_pin_pair
|
||||
SingleIndexedNetlistModel::net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
db::Net::const_subcircuit_pin_iterator none;
|
||||
return attr_by_object_and_index (nets, index, nets.first->begin_subcircuit_pins (), nets.first->end_subcircuit_pins (), none, none, m_subcircuit_pinref_by_net_and_index, sort_by_pin_name<db::NetSubcircuitPinRef> ());
|
||||
}
|
||||
|
||||
IndexedNetlistModel::net_terminal_pair
|
||||
SingleIndexedNetlistModel::net_terminalref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
db::Net::const_terminal_iterator none;
|
||||
return attr_by_object_and_index (nets, index, nets.first->begin_terminals (), nets.first->end_terminals (), none, none, m_terminalref_by_net_and_index, sort_by_terminal_id<db::NetTerminalRef> ());
|
||||
}
|
||||
|
||||
IndexedNetlistModel::net_pin_pair
|
||||
SingleIndexedNetlistModel::net_pinref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
db::Net::const_pin_iterator none;
|
||||
return attr_by_object_and_index (nets, index, nets.first->begin_pins (), nets.first->end_pins (), none, none, m_pinref_by_net_and_index, sort_by_pin_name<db::NetPinRef> ());
|
||||
}
|
||||
|
||||
IndexedNetlistModel::device_pair
|
||||
SingleIndexedNetlistModel::device_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_device_iterator none;
|
||||
return attr_by_object_and_index (circuits, index, circuits.first->begin_devices (), circuits.first->end_devices (), none, none, m_device_by_circuit_and_index, sort_by_expanded_name<db::Device> ());
|
||||
}
|
||||
|
||||
IndexedNetlistModel::pin_pair
|
||||
SingleIndexedNetlistModel::pin_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_pin_iterator none;
|
||||
return attr_by_object_and_index (circuits, index, circuits.first->begin_pins (), circuits.first->end_pins (), none, none, m_pin_by_circuit_and_index, sort_by_expanded_name<db::Pin> ());
|
||||
}
|
||||
|
||||
IndexedNetlistModel::subcircuit_pair
|
||||
SingleIndexedNetlistModel::subcircuit_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_subcircuit_iterator none;
|
||||
return attr_by_object_and_index (circuits, index, circuits.first->begin_subcircuits (), circuits.first->end_subcircuits (), none, none, m_subcircuit_by_circuit_and_index, sort_by_expanded_name<db::SubCircuit> ());
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::circuit_index (const circuit_pair &circuits) const
|
||||
{
|
||||
db::Netlist::const_circuit_iterator none;
|
||||
return index_from_attr (circuits, mp_netlist->begin_circuits (), mp_netlist->end_circuits (), none, none, m_circuit_index_by_object, sort_by_name<db::Circuit> ());
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::net_index (const net_pair &nets) const
|
||||
{
|
||||
db::Circuit::const_net_iterator none;
|
||||
|
||||
circuit_pair circuits = parent_of (nets);
|
||||
return index_from_attr (nets,
|
||||
circuits.first ? circuits.first->begin_nets () : none, circuits.first ? circuits.first->end_nets () : none,
|
||||
circuits.second ? circuits.second->begin_nets () : none, circuits.second ? circuits.second->end_nets () : none,
|
||||
m_net_index_by_object, sort_by_expanded_name<db::Net> ());
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::device_index (const device_pair &devices) const
|
||||
{
|
||||
db::Circuit::const_device_iterator none;
|
||||
|
||||
circuit_pair circuits = parent_of (devices);
|
||||
return index_from_attr (devices,
|
||||
circuits.first ? circuits.first->begin_devices () : none, circuits.first ? circuits.first->end_devices () : none,
|
||||
circuits.second ? circuits.second->begin_devices () : none, circuits.second ? circuits.second->end_devices () : none,
|
||||
m_device_index_by_object, sort_by_expanded_name<db::Device> ());
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::pin_index (const pin_pair &pins, const circuit_pair &circuits) const
|
||||
{
|
||||
db::Circuit::const_pin_iterator none;
|
||||
|
||||
return index_from_attr (pins,
|
||||
circuits.first ? circuits.first->begin_pins () : none, circuits.first ? circuits.first->end_pins () : none,
|
||||
circuits.second ? circuits.second->begin_pins () : none, circuits.second ? circuits.second->end_pins () : none,
|
||||
m_pin_index_by_object, sort_by_expanded_name<db::Pin> ());
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::subcircuit_index (const subcircuit_pair &subcircuits) const
|
||||
{
|
||||
db::Circuit::const_subcircuit_iterator none;
|
||||
|
||||
circuit_pair circuits = parent_of (subcircuits);
|
||||
return index_from_attr (subcircuits,
|
||||
circuits.first ? circuits.first->begin_subcircuits () : none, circuits.first ? circuits.first->end_subcircuits () : none,
|
||||
circuits.second ? circuits.second->begin_subcircuits () : none, circuits.second ? circuits.second->end_subcircuits () : none,
|
||||
m_subcircuit_index_by_object, sort_by_expanded_name<db::SubCircuit> ());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
|
||||
/*
|
||||
|
||||
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_layIndexedNetlistModel
|
||||
#define HDR_layIndexedNetlistModel
|
||||
|
||||
#include "laybasicCommon.h"
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
namespace db
|
||||
{
|
||||
class Net;
|
||||
class Circuit;
|
||||
class Netlist;
|
||||
class NetSubcircuitPinRef;
|
||||
class NetTerminalRef;
|
||||
class NetPinRef;
|
||||
class Device;
|
||||
class Pin;
|
||||
class SubCircuit;
|
||||
class Netlist;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief An interface to supply the netlist browser model with indexed items
|
||||
*/
|
||||
class LAYBASIC_PUBLIC IndexedNetlistModel
|
||||
{
|
||||
public:
|
||||
IndexedNetlistModel () { }
|
||||
virtual ~IndexedNetlistModel () { }
|
||||
|
||||
virtual bool is_single () const = 0;
|
||||
|
||||
typedef std::pair<const db::Circuit *, const db::Circuit *> circuit_pair;
|
||||
typedef std::pair<const db::Net *, const db::Net *> net_pair;
|
||||
typedef std::pair<const db::NetSubcircuitPinRef *, const db::NetSubcircuitPinRef *> net_subcircuit_pin_pair;
|
||||
typedef std::pair<const db::NetTerminalRef *, const db::NetTerminalRef *> net_terminal_pair;
|
||||
typedef std::pair<const db::NetPinRef *, const db::NetPinRef *> net_pin_pair;
|
||||
typedef std::pair<const db::Device *, const db::Device *> device_pair;
|
||||
typedef std::pair<const db::Pin *, const db::Pin *> pin_pair;
|
||||
typedef std::pair<const db::SubCircuit *, const db::SubCircuit *> subcircuit_pair;
|
||||
|
||||
virtual size_t circuit_count () const = 0;
|
||||
virtual size_t net_count (const circuit_pair &circuits) const = 0;
|
||||
virtual size_t net_terminal_count (const net_pair &nets) const = 0;
|
||||
virtual size_t net_subcircuit_pin_count (const net_pair &nets) const = 0;
|
||||
virtual size_t net_pin_count (const net_pair &nets) const = 0;
|
||||
virtual size_t device_count (const circuit_pair &circuits) const = 0;
|
||||
virtual size_t pin_count (const circuit_pair &circuits) const = 0;
|
||||
virtual size_t subcircuit_count (const circuit_pair &circuits) const = 0;
|
||||
|
||||
virtual circuit_pair parent_of (const net_pair &net_pair) const = 0;
|
||||
virtual circuit_pair parent_of (const device_pair &device_pair) const = 0;
|
||||
virtual circuit_pair parent_of (const subcircuit_pair &subcircuit_pair) const = 0;
|
||||
|
||||
virtual circuit_pair circuit_from_index (size_t index) const = 0;
|
||||
virtual net_pair net_from_index (const circuit_pair &circuits, size_t index) const = 0;
|
||||
virtual const db::Net *second_net_for (const db::Net *first) const = 0;
|
||||
virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const = 0;
|
||||
virtual net_terminal_pair net_terminalref_from_index (const net_pair &nets, size_t index) const = 0;
|
||||
virtual net_pin_pair net_pinref_from_index (const net_pair &nets, size_t index) const = 0;
|
||||
virtual device_pair device_from_index (const circuit_pair &circuits, size_t index) const = 0;
|
||||
virtual pin_pair pin_from_index (const circuit_pair &circuits, size_t index) const = 0;
|
||||
virtual subcircuit_pair subcircuit_from_index (const circuit_pair &circuits, size_t index) const = 0;
|
||||
|
||||
virtual size_t circuit_index (const circuit_pair &circuits) const = 0;
|
||||
virtual size_t net_index (const net_pair &nets) const = 0;
|
||||
virtual size_t device_index (const device_pair &devices) const = 0;
|
||||
virtual size_t pin_index (const pin_pair &pins, const circuit_pair &circuits) const = 0;
|
||||
virtual size_t subcircuit_index (const subcircuit_pair &subcircuits) const = 0;
|
||||
|
||||
private:
|
||||
IndexedNetlistModel &operator= (const IndexedNetlistModel &);
|
||||
IndexedNetlistModel (const IndexedNetlistModel &);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An incarnation of the indexed netlist model for a single netlist
|
||||
*/
|
||||
class LAYBASIC_PUBLIC SingleIndexedNetlistModel
|
||||
: public IndexedNetlistModel
|
||||
{
|
||||
public:
|
||||
SingleIndexedNetlistModel (const db::Netlist *netlist)
|
||||
: mp_netlist (netlist)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual ~SingleIndexedNetlistModel () { }
|
||||
|
||||
virtual bool is_single () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual size_t circuit_count () const;
|
||||
virtual size_t net_count (const circuit_pair &circuits) const;
|
||||
virtual size_t net_terminal_count (const net_pair &nets) const;
|
||||
virtual size_t net_subcircuit_pin_count (const net_pair &nets) const;
|
||||
virtual size_t net_pin_count (const net_pair &nets) const;
|
||||
virtual size_t device_count (const circuit_pair &circuits) const;
|
||||
virtual size_t pin_count (const circuit_pair &circuits) const;
|
||||
virtual size_t subcircuit_count (const circuit_pair &circuits) const;
|
||||
|
||||
virtual circuit_pair parent_of (const net_pair &nets) const;
|
||||
virtual circuit_pair parent_of (const device_pair &devices) const;
|
||||
virtual circuit_pair parent_of (const subcircuit_pair &subcircuits) const;
|
||||
virtual circuit_pair circuit_from_index (size_t index) const;
|
||||
|
||||
virtual net_pair net_from_index (const circuit_pair &circuits, size_t index) const;
|
||||
virtual const db::Net *second_net_for (const db::Net * /*first*/) const;
|
||||
virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const;
|
||||
virtual net_terminal_pair net_terminalref_from_index (const net_pair &nets, size_t index) const;
|
||||
virtual net_pin_pair net_pinref_from_index (const net_pair &nets, size_t index) const;
|
||||
virtual device_pair device_from_index (const circuit_pair &circuits, size_t index) const;
|
||||
virtual pin_pair pin_from_index (const circuit_pair &circuits, size_t index) const;
|
||||
virtual subcircuit_pair subcircuit_from_index (const circuit_pair &circuits, size_t index) const;
|
||||
|
||||
virtual size_t circuit_index (const circuit_pair &circuits) const;
|
||||
virtual size_t net_index (const net_pair &nets) const;
|
||||
virtual size_t device_index (const device_pair &devices) const;
|
||||
virtual size_t pin_index (const pin_pair &pins, const circuit_pair &circuits) const;
|
||||
virtual size_t subcircuit_index (const subcircuit_pair &subcircuits) const;
|
||||
|
||||
private:
|
||||
typedef std::pair<const db::Netlist *, const db::Netlist *> netlist_pair;
|
||||
|
||||
const db::Netlist *mp_netlist;
|
||||
|
||||
mutable std::map<netlist_pair, std::vector<circuit_pair> > m_circuit_by_index;
|
||||
mutable std::map<circuit_pair, std::vector<net_pair> > m_net_by_circuit_and_index;
|
||||
mutable std::map<net_pair, std::vector<net_subcircuit_pin_pair> > m_subcircuit_pinref_by_net_and_index;
|
||||
mutable std::map<net_pair, std::vector<net_terminal_pair> > m_terminalref_by_net_and_index;
|
||||
mutable std::map<net_pair, std::vector<net_pin_pair> > m_pinref_by_net_and_index;
|
||||
mutable std::map<circuit_pair, std::vector<device_pair> > m_device_by_circuit_and_index;
|
||||
mutable std::map<circuit_pair, std::vector<pin_pair> > m_pin_by_circuit_and_index;
|
||||
mutable std::map<circuit_pair, std::vector<subcircuit_pair> > m_subcircuit_by_circuit_and_index;
|
||||
mutable std::map<circuit_pair, size_t> m_circuit_index_by_object;
|
||||
mutable std::map<net_pair, size_t> m_net_index_by_object;
|
||||
mutable std::map<pin_pair, size_t> m_pin_index_by_object;
|
||||
mutable std::map<subcircuit_pair, size_t> m_subcircuit_index_by_object;
|
||||
mutable std::map<device_pair, size_t> m_device_index_by_object;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
|
||||
#include "layNetlistBrowserModel.h"
|
||||
#include "layIndexedNetlistModel.h"
|
||||
#include "dbNetlistDeviceClasses.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
|
@ -154,418 +155,6 @@ NetColorizer::color_of_net (const db::Net *net) const
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// IndexedNetlistModel
|
||||
|
||||
namespace {
|
||||
|
||||
template <class Obj>
|
||||
struct sort_single_by_name
|
||||
{
|
||||
inline bool operator() (const Obj *a, const Obj *b) const
|
||||
{
|
||||
return a->name () < b->name ();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_single_by_expanded_name
|
||||
{
|
||||
inline bool operator() (const Obj *a, const Obj *b) const
|
||||
{
|
||||
return a->expanded_name () < b->expanded_name ();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_single_by_pin_name
|
||||
{
|
||||
inline bool operator() (const Obj *a, const Obj *b) const
|
||||
{
|
||||
return a->pin ()->expanded_name () < b->pin ()->expanded_name ();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_single_by_terminal_id
|
||||
{
|
||||
inline bool operator() (const Obj *a, const Obj *b) const
|
||||
{
|
||||
return a->terminal_id () < b->terminal_id ();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj, class SortBy>
|
||||
struct sort_with_null
|
||||
{
|
||||
inline bool operator() (const Obj *a, const Obj *b) const
|
||||
{
|
||||
SortBy order;
|
||||
if ((a != 0) != (b != 0)) {
|
||||
return (a != 0) < (b != 0);
|
||||
}
|
||||
if (a) {
|
||||
if (order (a, b)) {
|
||||
return true;
|
||||
} else if (order (b, a)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj, class SortBy>
|
||||
struct sort_pair
|
||||
{
|
||||
bool operator() (const std::pair<const Obj *, const Obj *> &a, const std::pair<const Obj *, const Obj *> &b) const
|
||||
{
|
||||
SortBy order;
|
||||
if (order (a.first, b.first)) {
|
||||
return true;
|
||||
} else if (order (b.first, a.first)) {
|
||||
return false;
|
||||
}
|
||||
return order (a.second, b.second);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_by_name
|
||||
: public sort_pair<Obj, sort_with_null<Obj, sort_single_by_name<Obj> > >
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_by_expanded_name
|
||||
: public sort_pair<Obj, sort_with_null<Obj, sort_single_by_expanded_name<Obj> > >
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_by_pin_name
|
||||
: public sort_pair<Obj, sort_with_null<Obj, sort_single_by_pin_name<Obj> > >
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
template <class Obj>
|
||||
struct sort_by_terminal_id
|
||||
: public sort_pair<Obj, sort_with_null<Obj, sort_single_by_terminal_id<Obj> > >
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class Attr, class Iter, class SortBy>
|
||||
static void fill_map (std::vector<std::pair<const Attr *, const Attr *> > &map, const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, const SortBy &sorter)
|
||||
{
|
||||
size_t n1 = 0, n2 = 0;
|
||||
for (Iter i = begin1; i != end1; ++i) {
|
||||
++n1;
|
||||
}
|
||||
for (Iter i = begin2; i != end2; ++i) {
|
||||
++n2;
|
||||
}
|
||||
map.resize (std::max (n1, n2), typename std::pair<const Attr *, const Attr *> (0, 0));
|
||||
|
||||
typename std::vector<std::pair<const Attr *, const Attr *> >::iterator j;
|
||||
j = map.begin ();
|
||||
for (Iter i = begin1; i != end1; ++i, ++j) {
|
||||
j->first = i.operator-> ();
|
||||
}
|
||||
j = map.begin ();
|
||||
for (Iter i = begin2; i != end2; ++i, ++j) {
|
||||
j->second = i.operator-> ();
|
||||
}
|
||||
|
||||
std::sort (map.begin (), map.end (), sorter);
|
||||
}
|
||||
|
||||
template <class Obj, class Attr, class Iter, class SortBy>
|
||||
static std::pair<const Attr *, const Attr *> attr_by_object_and_index (const std::pair<const Obj *, const Obj *> &obj, size_t index, const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, std::map<std::pair<const Obj *, const Obj *>, std::vector<std::pair<const Attr *, const Attr *> > > &cache, const SortBy &sorter)
|
||||
{
|
||||
typename std::map<std::pair<const Obj *, const Obj *>, std::vector<std::pair<const Attr *, const Attr *> > >::iterator cc = cache.find (obj);
|
||||
if (cc == cache.end ()) {
|
||||
cc = cache.insert (std::make_pair (obj, std::vector<std::pair<const Attr *, const Attr *> > ())).first;
|
||||
fill_map (cc->second, begin1, end1, begin2, end2, sorter);
|
||||
}
|
||||
|
||||
tl_assert (index < cc->second.size ());
|
||||
return cc->second [index];
|
||||
}
|
||||
|
||||
template <class Attr, class Iter, class SortBy>
|
||||
static size_t index_from_attr (const std::pair<const Attr *, const Attr *> &attrs, const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, std::map<std::pair<const Attr *, const Attr *>, size_t> &cache, const SortBy &sorter)
|
||||
{
|
||||
typename std::map<std::pair<const Attr *, const Attr *>, size_t>::iterator cc = cache.find (attrs);
|
||||
if (cc != cache.end ()) {
|
||||
return cc->second;
|
||||
}
|
||||
|
||||
std::vector<std::pair<const Attr *, const Attr *> > map;
|
||||
fill_map (map, begin1, end1, begin2, end2, sorter);
|
||||
|
||||
for (size_t i = 0; i < map.size (); ++i) {
|
||||
cache.insert (std::make_pair (map [i], i));
|
||||
}
|
||||
|
||||
cc = cache.find (attrs);
|
||||
tl_assert (cc != cache.end ());
|
||||
return cc->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief An interface to supply the netlist browser model with indexed items
|
||||
*/
|
||||
class IndexedNetlistModel
|
||||
{
|
||||
public:
|
||||
IndexedNetlistModel () { }
|
||||
virtual ~IndexedNetlistModel () { }
|
||||
|
||||
virtual bool is_single () const = 0;
|
||||
|
||||
typedef std::pair<const db::Circuit *, const db::Circuit *> circuit_pair;
|
||||
typedef std::pair<const db::Net *, const db::Net *> net_pair;
|
||||
typedef std::pair<const db::NetSubcircuitPinRef *, const db::NetSubcircuitPinRef *> net_subcircuit_pin_pair;
|
||||
typedef std::pair<const db::NetTerminalRef *, const db::NetTerminalRef *> net_terminal_pair;
|
||||
typedef std::pair<const db::NetPinRef *, const db::NetPinRef *> net_pin_pair;
|
||||
typedef std::pair<const db::Device *, const db::Device *> device_pair;
|
||||
typedef std::pair<const db::Pin *, const db::Pin *> pin_pair;
|
||||
typedef std::pair<const db::SubCircuit *, const db::SubCircuit *> subcircuit_pair;
|
||||
|
||||
virtual size_t circuit_count () const = 0;
|
||||
virtual size_t net_count (const circuit_pair &circuits) const = 0;
|
||||
virtual size_t net_terminal_count (const net_pair &nets) const = 0;
|
||||
virtual size_t net_subcircuit_pin_count (const net_pair &nets) const = 0;
|
||||
virtual size_t net_pin_count (const net_pair &nets) const = 0;
|
||||
virtual size_t device_count (const circuit_pair &circuits) const = 0;
|
||||
virtual size_t pin_count (const circuit_pair &circuits) const = 0;
|
||||
virtual size_t subcircuit_count (const circuit_pair &circuits) const = 0;
|
||||
|
||||
virtual circuit_pair parent_of (const net_pair &net_pair) const = 0;
|
||||
virtual circuit_pair parent_of (const device_pair &device_pair) const = 0;
|
||||
virtual circuit_pair parent_of (const subcircuit_pair &subcircuit_pair) const = 0;
|
||||
|
||||
virtual circuit_pair circuit_from_index (size_t index) const = 0;
|
||||
virtual net_pair net_from_index (const circuit_pair &circuits, size_t index) const = 0;
|
||||
virtual const db::Net *second_net_for (const db::Net *first) const = 0;
|
||||
virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const = 0;
|
||||
virtual net_terminal_pair net_terminalref_from_index (const net_pair &nets, size_t index) const = 0;
|
||||
virtual net_pin_pair net_pinref_from_index (const net_pair &nets, size_t index) const = 0;
|
||||
virtual device_pair device_from_index (const circuit_pair &circuits, size_t index) const = 0;
|
||||
virtual pin_pair pin_from_index (const circuit_pair &circuits, size_t index) const = 0;
|
||||
virtual subcircuit_pair subcircuit_from_index (const circuit_pair &circuits, size_t index) const = 0;
|
||||
|
||||
virtual size_t circuit_index (const circuit_pair &circuits) const = 0;
|
||||
virtual size_t net_index (const net_pair &nets) const = 0;
|
||||
virtual size_t device_index (const device_pair &devices) const = 0;
|
||||
virtual size_t pin_index (const pin_pair &pins, const circuit_pair &circuits) const = 0;
|
||||
virtual size_t subcircuit_index (const subcircuit_pair &subcircuits) const = 0;
|
||||
|
||||
private:
|
||||
IndexedNetlistModel &operator= (const IndexedNetlistModel &);
|
||||
IndexedNetlistModel (const IndexedNetlistModel &);
|
||||
};
|
||||
|
||||
class SingleIndexedNetlistModel
|
||||
: public IndexedNetlistModel
|
||||
{
|
||||
public:
|
||||
SingleIndexedNetlistModel (const db::Netlist *netlist)
|
||||
: mp_netlist (netlist)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual ~SingleIndexedNetlistModel () { }
|
||||
|
||||
virtual bool is_single () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual size_t circuit_count () const
|
||||
{
|
||||
return mp_netlist->circuit_count ();
|
||||
}
|
||||
|
||||
virtual size_t net_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return circuits.first->net_count ();
|
||||
}
|
||||
|
||||
virtual size_t net_terminal_count (const net_pair &nets) const
|
||||
{
|
||||
return nets.first->terminal_count ();
|
||||
}
|
||||
|
||||
virtual size_t net_subcircuit_pin_count (const net_pair &nets) const
|
||||
{
|
||||
return nets.first->subcircuit_pin_count ();
|
||||
}
|
||||
|
||||
virtual size_t net_pin_count (const net_pair &nets) const
|
||||
{
|
||||
return nets.first->pin_count ();
|
||||
}
|
||||
|
||||
virtual size_t device_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return circuits.first->device_count ();
|
||||
}
|
||||
|
||||
virtual size_t pin_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return circuits.first->pin_count ();
|
||||
}
|
||||
|
||||
virtual size_t subcircuit_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return circuits.first->subcircuit_count ();
|
||||
}
|
||||
|
||||
virtual circuit_pair parent_of (const net_pair &nets) const
|
||||
{
|
||||
return std::make_pair (nets.first->circuit (), (const db::Circuit *) 0);
|
||||
}
|
||||
|
||||
virtual circuit_pair parent_of (const device_pair &devices) const
|
||||
{
|
||||
return std::make_pair (devices.first->circuit (), (const db::Circuit *) 0);
|
||||
}
|
||||
|
||||
virtual circuit_pair parent_of (const subcircuit_pair &subcircuits) const
|
||||
{
|
||||
return std::make_pair (subcircuits.first->circuit (), (const db::Circuit *) 0);
|
||||
}
|
||||
|
||||
virtual circuit_pair circuit_from_index (size_t index) const
|
||||
{
|
||||
db::Netlist::const_circuit_iterator none;
|
||||
return attr_by_object_and_index (std::make_pair (mp_netlist, (const db::Netlist *) 0), index, mp_netlist->begin_circuits (), mp_netlist->end_circuits (), none, none, m_circuit_by_index, sort_by_name<db::Circuit> ());
|
||||
}
|
||||
|
||||
virtual net_pair net_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_net_iterator none;
|
||||
return attr_by_object_and_index (circuits, index, circuits.first->begin_nets (), circuits.first->end_nets (), none, none, m_net_by_circuit_and_index, sort_by_expanded_name<db::Net> ());
|
||||
}
|
||||
|
||||
virtual const db::Net *second_net_for (const db::Net * /*first*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
db::Net::const_subcircuit_pin_iterator none;
|
||||
return attr_by_object_and_index (nets, index, nets.first->begin_subcircuit_pins (), nets.first->end_subcircuit_pins (), none, none, m_subcircuit_pinref_by_net_and_index, sort_by_pin_name<db::NetSubcircuitPinRef> ());
|
||||
}
|
||||
|
||||
virtual net_terminal_pair net_terminalref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
db::Net::const_terminal_iterator none;
|
||||
return attr_by_object_and_index (nets, index, nets.first->begin_terminals (), nets.first->end_terminals (), none, none, m_terminalref_by_net_and_index, sort_by_terminal_id<db::NetTerminalRef> ());
|
||||
}
|
||||
|
||||
virtual net_pin_pair net_pinref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
db::Net::const_pin_iterator none;
|
||||
return attr_by_object_and_index (nets, index, nets.first->begin_pins (), nets.first->end_pins (), none, none, m_pinref_by_net_and_index, sort_by_pin_name<db::NetPinRef> ());
|
||||
}
|
||||
|
||||
virtual device_pair device_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_device_iterator none;
|
||||
return attr_by_object_and_index (circuits, index, circuits.first->begin_devices (), circuits.first->end_devices (), none, none, m_device_by_circuit_and_index, sort_by_expanded_name<db::Device> ());
|
||||
}
|
||||
|
||||
virtual pin_pair pin_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_pin_iterator none;
|
||||
return attr_by_object_and_index (circuits, index, circuits.first->begin_pins (), circuits.first->end_pins (), none, none, m_pin_by_circuit_and_index, sort_by_expanded_name<db::Pin> ());
|
||||
}
|
||||
|
||||
virtual subcircuit_pair subcircuit_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_subcircuit_iterator none;
|
||||
return attr_by_object_and_index (circuits, index, circuits.first->begin_subcircuits (), circuits.first->end_subcircuits (), none, none, m_subcircuit_by_circuit_and_index, sort_by_expanded_name<db::SubCircuit> ());
|
||||
}
|
||||
|
||||
virtual size_t circuit_index (const circuit_pair &circuits) const
|
||||
{
|
||||
db::Netlist::const_circuit_iterator none;
|
||||
return index_from_attr (circuits, mp_netlist->begin_circuits (), mp_netlist->end_circuits (), none, none, m_circuit_index_by_object, sort_by_name<db::Circuit> ());
|
||||
}
|
||||
|
||||
virtual size_t net_index (const net_pair &nets) const
|
||||
{
|
||||
db::Circuit::const_net_iterator none;
|
||||
|
||||
circuit_pair circuits = parent_of (nets);
|
||||
return index_from_attr (nets,
|
||||
circuits.first ? circuits.first->begin_nets () : none, circuits.first ? circuits.first->end_nets () : none,
|
||||
circuits.second ? circuits.second->begin_nets () : none, circuits.second ? circuits.second->end_nets () : none,
|
||||
m_net_index_by_object, sort_by_expanded_name<db::Net> ());
|
||||
}
|
||||
|
||||
virtual size_t device_index (const device_pair &devices) const
|
||||
{
|
||||
db::Circuit::const_device_iterator none;
|
||||
|
||||
circuit_pair circuits = parent_of (devices);
|
||||
return index_from_attr (devices,
|
||||
circuits.first ? circuits.first->begin_devices () : none, circuits.first ? circuits.first->end_devices () : none,
|
||||
circuits.second ? circuits.second->begin_devices () : none, circuits.second ? circuits.second->end_devices () : none,
|
||||
m_device_index_by_object, sort_by_expanded_name<db::Device> ());
|
||||
}
|
||||
|
||||
virtual size_t pin_index (const pin_pair &pins, const circuit_pair &circuits) const
|
||||
{
|
||||
db::Circuit::const_pin_iterator none;
|
||||
|
||||
return index_from_attr (pins,
|
||||
circuits.first ? circuits.first->begin_pins () : none, circuits.first ? circuits.first->end_pins () : none,
|
||||
circuits.second ? circuits.second->begin_pins () : none, circuits.second ? circuits.second->end_pins () : none,
|
||||
m_pin_index_by_object, sort_by_expanded_name<db::Pin> ());
|
||||
}
|
||||
|
||||
virtual size_t subcircuit_index (const subcircuit_pair &subcircuits) const
|
||||
{
|
||||
db::Circuit::const_subcircuit_iterator none;
|
||||
|
||||
circuit_pair circuits = parent_of (subcircuits);
|
||||
return index_from_attr (subcircuits,
|
||||
circuits.first ? circuits.first->begin_subcircuits () : none, circuits.first ? circuits.first->end_subcircuits () : none,
|
||||
circuits.second ? circuits.second->begin_subcircuits () : none, circuits.second ? circuits.second->end_subcircuits () : none,
|
||||
m_subcircuit_index_by_object, sort_by_expanded_name<db::SubCircuit> ());
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::pair<const db::Netlist *, const db::Netlist *> netlist_pair;
|
||||
|
||||
const db::Netlist *mp_netlist;
|
||||
|
||||
mutable std::map<netlist_pair, std::vector<circuit_pair> > m_circuit_by_index;
|
||||
mutable std::map<circuit_pair, std::vector<net_pair> > m_net_by_circuit_and_index;
|
||||
mutable std::map<net_pair, std::vector<net_subcircuit_pin_pair> > m_subcircuit_pinref_by_net_and_index;
|
||||
mutable std::map<net_pair, std::vector<net_terminal_pair> > m_terminalref_by_net_and_index;
|
||||
mutable std::map<net_pair, std::vector<net_pin_pair> > m_pinref_by_net_and_index;
|
||||
mutable std::map<circuit_pair, std::vector<device_pair> > m_device_by_circuit_and_index;
|
||||
mutable std::map<circuit_pair, std::vector<pin_pair> > m_pin_by_circuit_and_index;
|
||||
mutable std::map<circuit_pair, std::vector<subcircuit_pair> > m_subcircuit_by_circuit_and_index;
|
||||
mutable std::map<circuit_pair, size_t> m_circuit_index_by_object;
|
||||
mutable std::map<net_pair, size_t> m_net_index_by_object;
|
||||
mutable std::map<pin_pair, size_t> m_pin_index_by_object;
|
||||
mutable std::map<subcircuit_pair, size_t> m_subcircuit_index_by_object;
|
||||
mutable std::map<device_pair, size_t> m_device_index_by_object;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// NetlistBrowserModel implementation
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,261 @@
|
|||
|
||||
/*
|
||||
|
||||
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 "layNetlistCrossReferenceModel.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
NetlistCrossReferenceModel::NetlistCrossReferenceModel (db::NetlistCrossReference *cross_ref)
|
||||
: mp_cross_ref (cross_ref)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::circuit_count () const
|
||||
{
|
||||
return mp_cross_ref->circuit_count ();
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::net_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return std::max (circuits.first ? circuits.first->net_count () : 0, circuits.second ? circuits.second->net_count () : 0);
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::net_terminal_count (const net_pair &nets) const
|
||||
{
|
||||
return std::max (nets.first ? nets.first->terminal_count () : 0, nets.second ? nets.second->terminal_count () : 0);
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::net_subcircuit_pin_count (const net_pair &nets) const
|
||||
{
|
||||
return std::max (nets.first ? nets.first->subcircuit_pin_count () : 0, nets.second ? nets.second->subcircuit_pin_count () : 0);
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::net_pin_count (const net_pair &nets) const
|
||||
{
|
||||
return std::max (nets.first ? nets.first->pin_count () : 0, nets.second ? nets.second->pin_count () : 0);
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::device_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return std::max (circuits.first ? circuits.first->device_count () : 0, circuits.second ? circuits.second->device_count () : 0);
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::pin_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return std::max (circuits.first ? circuits.first->pin_count () : 0, circuits.second ? circuits.second->pin_count () : 0);
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::subcircuit_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return std::max (circuits.first ? circuits.first->subcircuit_count () : 0, circuits.second ? circuits.second->subcircuit_count () : 0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <class Obj> struct DataGetter;
|
||||
|
||||
template <>
|
||||
struct DataGetter<const db::Net *>
|
||||
{
|
||||
typedef typename std::vector<std::pair<const db::Net *, const db::Net *> >::const_iterator iterator_type;
|
||||
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 (); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DataGetter<const db::Device *>
|
||||
{
|
||||
typedef typename std::vector<std::pair<const db::Device *, const db::Device *> >::const_iterator iterator_type;
|
||||
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 (); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DataGetter<const db::SubCircuit *>
|
||||
{
|
||||
typedef typename std::vector<std::pair<const db::SubCircuit *, const db::SubCircuit *> >::const_iterator iterator_type;
|
||||
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 (); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class Pair>
|
||||
static IndexedNetlistModel::circuit_pair get_parent_of (const Pair &pair, const db::NetlistCrossReference *cross_ref, std::map<Pair, IndexedNetlistModel::circuit_pair> &cache)
|
||||
{
|
||||
typename std::map<Pair, IndexedNetlistModel::circuit_pair>::iterator i = cache.find (pair);
|
||||
if (i == cache.end ()) {
|
||||
|
||||
for (db::NetlistCrossReference::per_circuit_data_iterator c = cross_ref->begin_per_circuit_data (); c != cross_ref->end_per_circuit_data (); ++c) {
|
||||
typedef DataGetter<typename Pair::first_type> getter_type;
|
||||
typedef typename getter_type::iterator_type iterator_type;
|
||||
iterator_type b = getter_type ().begin (c->second);
|
||||
iterator_type e = getter_type ().end (c->second);
|
||||
for (iterator_type j = b; j != e; ++j) {
|
||||
cache.insert (std::make_pair (*j, c->first));
|
||||
}
|
||||
}
|
||||
|
||||
i = cache.find (pair);
|
||||
tl_assert (i != cache.end ());
|
||||
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair NetlistCrossReferenceModel::parent_of (const IndexedNetlistModel::net_pair &net_pair) const
|
||||
{
|
||||
return get_parent_of (net_pair, mp_cross_ref.get (), m_parents_of_nets);
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair NetlistCrossReferenceModel::parent_of (const IndexedNetlistModel::device_pair &device_pair) const
|
||||
{
|
||||
return get_parent_of (device_pair, mp_cross_ref.get (), m_parents_of_devices);
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair NetlistCrossReferenceModel::parent_of (const IndexedNetlistModel::subcircuit_pair &subcircuit_pair) const
|
||||
{
|
||||
return get_parent_of (subcircuit_pair, mp_cross_ref.get (), m_parents_of_subcircuits);
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair NetlistCrossReferenceModel::circuit_from_index (size_t index) const
|
||||
{
|
||||
return mp_cross_ref->begin_circuits () [index];
|
||||
}
|
||||
|
||||
IndexedNetlistModel::net_pair NetlistCrossReferenceModel::net_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||
tl_assert (data != 0);
|
||||
return data->nets [index];
|
||||
}
|
||||
|
||||
const db::Net *NetlistCrossReferenceModel::second_net_for (const db::Net *first) const
|
||||
{
|
||||
return mp_cross_ref->other_net_for (first);
|
||||
}
|
||||
|
||||
IndexedNetlistModel::net_subcircuit_pin_pair NetlistCrossReferenceModel::net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
const db::NetlistCrossReference::PerNetData *data = mp_cross_ref->per_net_data_for (nets);
|
||||
tl_assert (data != 0);
|
||||
return data->subcircuit_pins [index];
|
||||
}
|
||||
|
||||
IndexedNetlistModel::net_terminal_pair NetlistCrossReferenceModel::net_terminalref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
const db::NetlistCrossReference::PerNetData *data = mp_cross_ref->per_net_data_for (nets);
|
||||
tl_assert (data != 0);
|
||||
return data->terminals [index];
|
||||
}
|
||||
|
||||
IndexedNetlistModel::net_pin_pair NetlistCrossReferenceModel::net_pinref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
const db::NetlistCrossReference::PerNetData *data = mp_cross_ref->per_net_data_for (nets);
|
||||
tl_assert (data != 0);
|
||||
return data->pins [index];
|
||||
}
|
||||
|
||||
IndexedNetlistModel::device_pair NetlistCrossReferenceModel::device_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||
tl_assert (data != 0);
|
||||
return data->devices [index];
|
||||
}
|
||||
|
||||
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);
|
||||
tl_assert (data != 0);
|
||||
return data->pins [index];
|
||||
}
|
||||
|
||||
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);
|
||||
tl_assert (data != 0);
|
||||
return data->subcircuits [index];
|
||||
}
|
||||
|
||||
template <class Pair, class Iter>
|
||||
static size_t get_index_of (const Pair &pair, Iter begin, Iter end, std::map<Pair, size_t> &cache)
|
||||
{
|
||||
typename std::map<Pair, size_t>::iterator i = cache.find (pair);
|
||||
if (i != cache.end ()) {
|
||||
|
||||
size_t index = 0;
|
||||
for (Iter j = begin; j != end; ++j, ++index) {
|
||||
cache.insert (std::make_pair (*j, index));
|
||||
}
|
||||
|
||||
i = cache.find (pair);
|
||||
tl_assert (i != cache.end ());
|
||||
}
|
||||
|
||||
return i->second;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::net_index (const net_pair &nets) const
|
||||
{
|
||||
circuit_pair circuits = parent_of (nets);
|
||||
PerCircuitCacheData *data = & m_per_circuit_data [circuits];
|
||||
const db::NetlistCrossReference::PerCircuitData *org_data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||
tl_assert (org_data != 0);
|
||||
return get_index_of (nets, org_data->nets.begin (), org_data->nets.end (), data->index_of_nets);
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::device_index (const device_pair &devices) const
|
||||
{
|
||||
circuit_pair circuits = parent_of (devices);
|
||||
PerCircuitCacheData *data = & m_per_circuit_data [circuits];
|
||||
const db::NetlistCrossReference::PerCircuitData *org_data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||
tl_assert (org_data != 0);
|
||||
return get_index_of (devices, org_data->devices.begin (), org_data->devices.end (), data->index_of_devices);
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::pin_index (const pin_pair &pins, const circuit_pair &circuits) const
|
||||
{
|
||||
PerCircuitCacheData *data = & m_per_circuit_data [circuits];
|
||||
const db::NetlistCrossReference::PerCircuitData *org_data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||
tl_assert (org_data != 0);
|
||||
return get_index_of (pins, org_data->pins.begin (), org_data->pins.end (), data->index_of_pins);
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::subcircuit_index (const subcircuit_pair &subcircuits) const
|
||||
{
|
||||
circuit_pair circuits = parent_of (subcircuits);
|
||||
PerCircuitCacheData *data = & m_per_circuit_data [circuits];
|
||||
const db::NetlistCrossReference::PerCircuitData *org_data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||
tl_assert (org_data != 0);
|
||||
return get_index_of (subcircuits, org_data->subcircuits.begin (), org_data->subcircuits.end (), data->index_of_subcircuits);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,630 @@
|
|||
|
||||
/*
|
||||
|
||||
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_layNetlistCrossReference
|
||||
#define HDR_layNetlistCrossReference
|
||||
|
||||
#include "laybasicCommon.h"
|
||||
#include "layIndexedNetlistModel.h"
|
||||
|
||||
#include "tlObject.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
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief An indexed netlist model for the netlist cross-reference
|
||||
*/
|
||||
class LAYBASIC_PUBLIC NetlistCrossReferenceModel
|
||||
: public lay::IndexedNetlistModel
|
||||
{
|
||||
public:
|
||||
NetlistCrossReferenceModel (db::NetlistCrossReference *cross_ref);
|
||||
|
||||
virtual bool is_single () const { return false; }
|
||||
|
||||
virtual size_t circuit_count () const;
|
||||
virtual size_t net_count (const circuit_pair &circuits) const;
|
||||
virtual size_t net_terminal_count (const net_pair &nets) const;
|
||||
virtual size_t net_subcircuit_pin_count (const net_pair &nets) const;
|
||||
virtual size_t net_pin_count (const net_pair &nets) const;
|
||||
virtual size_t device_count (const circuit_pair &circuits) const;
|
||||
virtual size_t pin_count (const circuit_pair &circuits) const;
|
||||
virtual size_t subcircuit_count (const circuit_pair &circuits) const;
|
||||
|
||||
virtual circuit_pair parent_of (const net_pair &net_pair) const;
|
||||
virtual circuit_pair parent_of (const device_pair &device_pair) const;
|
||||
virtual circuit_pair parent_of (const subcircuit_pair &subcircuit_pair) const;
|
||||
|
||||
virtual circuit_pair circuit_from_index (size_t index) const;
|
||||
virtual net_pair net_from_index (const circuit_pair &circuits, size_t index) const;
|
||||
virtual const db::Net *second_net_for (const db::Net *first) const;
|
||||
virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const;
|
||||
virtual net_terminal_pair net_terminalref_from_index (const net_pair &nets, size_t index) const;
|
||||
virtual net_pin_pair net_pinref_from_index (const net_pair &nets, size_t index) const;
|
||||
virtual device_pair device_from_index (const circuit_pair &circuits, size_t index) const;
|
||||
virtual pin_pair pin_from_index (const circuit_pair &circuits, size_t index) const;
|
||||
virtual subcircuit_pair subcircuit_from_index (const circuit_pair &circuits, size_t index) const;
|
||||
|
||||
virtual size_t circuit_index (const circuit_pair &circuits) const;
|
||||
virtual size_t net_index (const net_pair &nets) const;
|
||||
virtual size_t device_index (const device_pair &devices) const;
|
||||
virtual size_t pin_index (const pin_pair &pins, const circuit_pair &circuits) const;
|
||||
virtual size_t subcircuit_index (const subcircuit_pair &subcircuits) const;
|
||||
|
||||
public:
|
||||
struct PerCircuitCacheData
|
||||
{
|
||||
std::map<std::pair<const db::Net *, const db::Net *>, size_t> index_of_nets;
|
||||
std::map<std::pair<const db::Device *, const db::Device *>, size_t> index_of_devices;
|
||||
std::map<std::pair<const db::Pin *, const db::Pin *>, size_t> index_of_pins;
|
||||
std::map<std::pair<const db::SubCircuit *, const db::SubCircuit *>, size_t> index_of_subcircuits;
|
||||
};
|
||||
|
||||
tl::weak_ptr<db::NetlistCrossReference> mp_cross_ref;
|
||||
mutable std::map<net_pair, circuit_pair> m_parents_of_nets;
|
||||
mutable std::map<device_pair, circuit_pair> m_parents_of_devices;
|
||||
mutable std::map<pin_pair, circuit_pair> m_parents_of_pins;
|
||||
mutable std::map<subcircuit_pair, circuit_pair> m_parents_of_subcircuits;
|
||||
mutable std::map<std::pair<const db::Circuit *, const db::Circuit *>, PerCircuitCacheData> m_per_circuit_data;
|
||||
mutable std::map<std::pair<const db::Circuit *, const db::Circuit *>, size_t> m_index_of_circuits;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -172,7 +172,9 @@ SOURCES = \
|
|||
layItemDelegates.cc \
|
||||
layNetInfoDialog.cc \
|
||||
layNetExportDialog.cc \
|
||||
layNetlistBrowserModel.cc
|
||||
layNetlistBrowserModel.cc \
|
||||
layIndexedNetlistModel.cc \
|
||||
layNetlistCrossReferenceModel.cc
|
||||
|
||||
HEADERS = \
|
||||
gtf.h \
|
||||
|
|
@ -265,7 +267,9 @@ HEADERS = \
|
|||
layItemDelegates.h \
|
||||
layNetInfoDialog.h \
|
||||
layNetExportDialog.h \
|
||||
layNetlistBrowserModel.h
|
||||
layNetlistBrowserModel.h \
|
||||
layIndexedNetlistModel.h \
|
||||
layNetlistCrossReferenceModel.h
|
||||
|
||||
INCLUDEPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC
|
||||
DEPENDPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC
|
||||
|
|
|
|||
Loading…
Reference in New Issue