klayout/src/laybasic/laybasic/layIndexedNetlistModel.cc

473 lines
17 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2020 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
{
// NOTE: we don't use expanded_name () for performance
if (a->name ().empty () != b->name ().empty ()) {
// named ones first
return a->name ().empty () < b->name ().empty ();
}
if (a->name ().empty ()) {
return a->id () < b->id ();
} else {
return a->name () < b->name ();
}
}
};
template <class Obj>
struct sort_single_by_pin_name
{
inline bool operator() (const Obj *a, const Obj *b) const
{
return sort_single_by_expanded_name<db::Pin> () (a->pin (), b->pin ());
}
};
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 ..
};
}
struct Unsorted { };
template <class Iter, class SortBy>
struct sort_by
{
void operator() (const Iter &begin, const Iter &end, const SortBy &sorter)
{
std::sort (begin, end, sorter);
}
};
template <class Iter>
struct sort_by<Iter, Unsorted>
{
void operator() (const Iter &, const Iter &, const Unsorted &)
{
// don't sort
}
};
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), std::make_pair((const Attr *)0, (const Attr *)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-> ();
}
sort_by<typename std::vector<std::pair<const Attr *, const Attr *> >::iterator, SortBy> () (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::top_circuit_count () const
{
return mp_netlist->top_circuit_count ();
}
size_t
SingleIndexedNetlistModel::net_count (const circuit_pair &circuits) const
{
return circuits.first ? circuits.first->net_count () : 0;
}
size_t
SingleIndexedNetlistModel::net_terminal_count (const net_pair &nets) const
{
return nets.first ? nets.first->terminal_count () : 0;
}
size_t
SingleIndexedNetlistModel::net_subcircuit_pin_count (const net_pair &nets) const
{
return nets.first ? nets.first->subcircuit_pin_count () : 0;
}
size_t
SingleIndexedNetlistModel::net_pin_count (const net_pair &nets) const
{
return nets.first ? nets.first->pin_count () : 0;
}
size_t
SingleIndexedNetlistModel::device_count (const circuit_pair &circuits) const
{
return circuits.first ? circuits.first->device_count () : 0;
}
size_t
SingleIndexedNetlistModel::subcircuit_pin_count (const subcircuit_pair &subcircuits) const
{
return subcircuits.first ? subcircuits.first->circuit_ref ()->pin_count () : 0;
}
size_t
SingleIndexedNetlistModel::pin_count (const circuit_pair &circuits) const
{
return circuits.first ? circuits.first->pin_count () : 0;
}
size_t
SingleIndexedNetlistModel::subcircuit_count (const circuit_pair &circuits) const
{
return circuits.first ? circuits.first->subcircuit_count () : 0;
}
size_t
SingleIndexedNetlistModel::child_circuit_count (const circuit_pair &circuits) const
{
return circuits.first ? (circuits.first->end_children () - circuits.first->begin_children ()) : 0;
}
IndexedNetlistModel::circuit_pair
SingleIndexedNetlistModel::parent_of (const net_pair &nets) const
{
return std::make_pair (nets.first ? nets.first->circuit () : 0, (const db::Circuit *) 0);
}
IndexedNetlistModel::circuit_pair
SingleIndexedNetlistModel::parent_of (const device_pair &devices) const
{
return std::make_pair (devices.first ? devices.first->circuit () : 0, (const db::Circuit *) 0);
}
IndexedNetlistModel::circuit_pair
SingleIndexedNetlistModel::parent_of (const subcircuit_pair &subcircuits) const
{
return std::make_pair (subcircuits.first ? subcircuits.first->circuit () : 0, (const db::Circuit *) 0);
}
std::pair<IndexedNetlistModel::circuit_pair, IndexedNetlistModel::Status>
SingleIndexedNetlistModel::top_circuit_from_index (size_t index) const
{
db::Netlist::const_top_down_circuit_iterator none;
return std::make_pair (attr_by_object_and_index (std::make_pair ((const db::Circuit *) 0, (const db::Circuit *) 0), index, mp_netlist->begin_top_down (), mp_netlist->begin_top_down () + mp_netlist->top_circuit_count (), none, none, m_child_circuit_by_circuit_and_index, sort_by_name<db::Circuit> ()), db::NetlistCrossReference::None);
}
std::pair<IndexedNetlistModel::circuit_pair, IndexedNetlistModel::Status>
SingleIndexedNetlistModel::child_circuit_from_index (const circuit_pair &circuits, size_t index) const
{
db::Circuit::const_child_circuit_iterator none;
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_children (), circuits.first->end_children (), none, none, m_child_circuit_by_circuit_and_index, sort_by_name<db::Circuit> ()), db::NetlistCrossReference::None);
}
std::pair<IndexedNetlistModel::circuit_pair, IndexedNetlistModel::Status>
SingleIndexedNetlistModel::circuit_from_index (size_t index) const
{
db::Netlist::const_circuit_iterator none;
return std::make_pair (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> ()), db::NetlistCrossReference::None);
}
std::pair<IndexedNetlistModel::net_pair, IndexedNetlistModel::Status>
SingleIndexedNetlistModel::net_from_index (const circuit_pair &circuits, size_t index) const
{
db::Circuit::const_net_iterator none;
return std::make_pair (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> ()), db::NetlistCrossReference::None);
}
const db::Net *
SingleIndexedNetlistModel::second_net_for (const db::Net * /*first*/) const
{
return 0;
}
const db::Circuit *
SingleIndexedNetlistModel::second_circuit_for (const db::Circuit * /*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_subcircuit_pin_pair
SingleIndexedNetlistModel::subcircuit_pinref_from_index (const subcircuit_pair &subcircuits, size_t index) const
{
if (! subcircuits.first) {
return IndexedNetlistModel::net_subcircuit_pin_pair ((const db::NetSubcircuitPinRef *) 0, (const db::NetSubcircuitPinRef *) 0);
}
std::map<subcircuit_pair, std::vector<net_subcircuit_pin_pair> >::iterator i = m_subcircuit_pins_by_index.find (subcircuits);
if (i == m_subcircuit_pins_by_index.end ()) {
i = m_subcircuit_pins_by_index.insert (std::make_pair (subcircuits, std::vector<net_subcircuit_pin_pair> ())).first;
std::vector<net_subcircuit_pin_pair> &refs = i->second;
const db::Circuit *circuit = subcircuits.first->circuit_ref ();
for (db::Circuit::const_pin_iterator p = circuit->begin_pins (); p != circuit->end_pins (); ++p) {
const db::NetSubcircuitPinRef *ref = subcircuits.first->netref_for_pin (p->id ());
if (! ref) {
m_synthetic_pinrefs.push_back (db::NetSubcircuitPinRef (const_cast<db::SubCircuit *> (subcircuits.first), p->id ()));
ref = & m_synthetic_pinrefs.back ();
}
refs.push_back (net_subcircuit_pin_pair (ref, (const db::NetSubcircuitPinRef *) 0));
}
}
return index < i->second.size () ? i->second [index] : IndexedNetlistModel::net_subcircuit_pin_pair ((const db::NetSubcircuitPinRef *) 0, (const db::NetSubcircuitPinRef *) 0);
}
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> ());
}
std::pair<IndexedNetlistModel::device_pair, IndexedNetlistModel::Status>
SingleIndexedNetlistModel::device_from_index (const circuit_pair &circuits, size_t index) const
{
db::Circuit::const_device_iterator none;
return std::make_pair (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> ()), db::NetlistCrossReference::None);
}
std::pair<IndexedNetlistModel::pin_pair, IndexedNetlistModel::Status>
SingleIndexedNetlistModel::pin_from_index (const circuit_pair &circuits, size_t index) const
{
db::Circuit::const_pin_iterator none;
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_pins (), circuits.first->end_pins (), none, none, m_pin_by_circuit_and_index, Unsorted ()), db::NetlistCrossReference::None);
}
std::pair<IndexedNetlistModel::subcircuit_pair, IndexedNetlistModel::Status>
SingleIndexedNetlistModel::subcircuit_from_index (const circuit_pair &circuits, size_t index) const
{
db::Circuit::const_subcircuit_iterator none;
return std::make_pair (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> ()), db::NetlistCrossReference::None);
}
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> ());
}
}