diff --git a/src/laybasic/laybasic/layIndexedNetlistModel.cc b/src/laybasic/laybasic/layIndexedNetlistModel.cc new file mode 100644 index 000000000..e52a330f8 --- /dev/null +++ b/src/laybasic/laybasic/layIndexedNetlistModel.cc @@ -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 + struct sort_single_by_name + { + inline bool operator() (const Obj *a, const Obj *b) const + { + return a->name () < b->name (); + } + }; + + template + struct sort_single_by_expanded_name + { + inline bool operator() (const Obj *a, const Obj *b) const + { + return a->expanded_name () < b->expanded_name (); + } + }; + + template + 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 + struct sort_single_by_terminal_id + { + inline bool operator() (const Obj *a, const Obj *b) const + { + return a->terminal_id () < b->terminal_id (); + } + }; + + template + 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 + struct sort_pair + { + bool operator() (const std::pair &a, const std::pair &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 + struct sort_by_name + : public sort_pair > > + { + // .. nothing yet .. + }; + + template + struct sort_by_expanded_name + : public sort_pair > > + { + // .. nothing yet .. + }; + + template + struct sort_by_pin_name + : public sort_pair > > + { + // .. nothing yet .. + }; + + template + struct sort_by_terminal_id + : public sort_pair > > + { + // .. nothing yet .. + }; + +} + +template +static void fill_map (std::vector > &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 (0, 0)); + + typename std::vector >::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 +static std::pair attr_by_object_and_index (const std::pair &obj, size_t index, const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, std::map, std::vector > > &cache, const SortBy &sorter) +{ + typename std::map, std::vector > >::iterator cc = cache.find (obj); + if (cc == cache.end ()) { + cc = cache.insert (std::make_pair (obj, std::vector > ())).first; + fill_map (cc->second, begin1, end1, begin2, end2, sorter); + } + + tl_assert (index < cc->second.size ()); + return cc->second [index]; +} + +template +static size_t index_from_attr (const std::pair &attrs, const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, std::map, size_t> &cache, const SortBy &sorter) +{ + typename std::map, size_t>::iterator cc = cache.find (attrs); + if (cc != cache.end ()) { + return cc->second; + } + + std::vector > 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 ()); +} + +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 ()); +} + +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 ()); +} + +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 ()); +} + +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 ()); +} + +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 ()); +} + +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 ()); +} + +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 ()); +} + +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 ()); +} + +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 ()); +} + +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 ()); +} + +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 ()); +} + +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 ()); +} + +} diff --git a/src/laybasic/laybasic/layIndexedNetlistModel.h b/src/laybasic/laybasic/layIndexedNetlistModel.h new file mode 100644 index 000000000..aa812e271 --- /dev/null +++ b/src/laybasic/laybasic/layIndexedNetlistModel.h @@ -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 +#include + +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 circuit_pair; + typedef std::pair net_pair; + typedef std::pair net_subcircuit_pin_pair; + typedef std::pair net_terminal_pair; + typedef std::pair net_pin_pair; + typedef std::pair device_pair; + typedef std::pair pin_pair; + typedef std::pair 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 netlist_pair; + + const db::Netlist *mp_netlist; + + mutable std::map > m_circuit_by_index; + mutable std::map > m_net_by_circuit_and_index; + mutable std::map > m_subcircuit_pinref_by_net_and_index; + mutable std::map > m_terminalref_by_net_and_index; + mutable std::map > m_pinref_by_net_and_index; + mutable std::map > m_device_by_circuit_and_index; + mutable std::map > m_pin_by_circuit_and_index; + mutable std::map > m_subcircuit_by_circuit_and_index; + mutable std::map m_circuit_index_by_object; + mutable std::map m_net_index_by_object; + mutable std::map m_pin_index_by_object; + mutable std::map m_subcircuit_index_by_object; + mutable std::map m_device_index_by_object; +}; + +} + +#endif diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 03a4ac9cc..2d543e9a1 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -22,6 +22,7 @@ #include "layNetlistBrowserModel.h" +#include "layIndexedNetlistModel.h" #include "dbNetlistDeviceClasses.h" #include @@ -154,418 +155,6 @@ NetColorizer::color_of_net (const db::Net *net) const } } -// ---------------------------------------------------------------------------------- -// IndexedNetlistModel - -namespace { - - template - struct sort_single_by_name - { - inline bool operator() (const Obj *a, const Obj *b) const - { - return a->name () < b->name (); - } - }; - - template - struct sort_single_by_expanded_name - { - inline bool operator() (const Obj *a, const Obj *b) const - { - return a->expanded_name () < b->expanded_name (); - } - }; - - template - 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 - struct sort_single_by_terminal_id - { - inline bool operator() (const Obj *a, const Obj *b) const - { - return a->terminal_id () < b->terminal_id (); - } - }; - - template - 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 - struct sort_pair - { - bool operator() (const std::pair &a, const std::pair &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 - struct sort_by_name - : public sort_pair > > - { - // .. nothing yet .. - }; - - template - struct sort_by_expanded_name - : public sort_pair > > - { - // .. nothing yet .. - }; - - template - struct sort_by_pin_name - : public sort_pair > > - { - // .. nothing yet .. - }; - - template - struct sort_by_terminal_id - : public sort_pair > > - { - // .. nothing yet .. - }; - -} - -template -static void fill_map (std::vector > &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 (0, 0)); - - typename std::vector >::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 -static std::pair attr_by_object_and_index (const std::pair &obj, size_t index, const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, std::map, std::vector > > &cache, const SortBy &sorter) -{ - typename std::map, std::vector > >::iterator cc = cache.find (obj); - if (cc == cache.end ()) { - cc = cache.insert (std::make_pair (obj, std::vector > ())).first; - fill_map (cc->second, begin1, end1, begin2, end2, sorter); - } - - tl_assert (index < cc->second.size ()); - return cc->second [index]; -} - -template -static size_t index_from_attr (const std::pair &attrs, const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, std::map, size_t> &cache, const SortBy &sorter) -{ - typename std::map, size_t>::iterator cc = cache.find (attrs); - if (cc != cache.end ()) { - return cc->second; - } - - std::vector > 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 circuit_pair; - typedef std::pair net_pair; - typedef std::pair net_subcircuit_pin_pair; - typedef std::pair net_terminal_pair; - typedef std::pair net_pin_pair; - typedef std::pair device_pair; - typedef std::pair pin_pair; - typedef std::pair 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 ()); - } - - 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 ()); - } - - 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 ()); - } - - 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 ()); - } - - 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 ()); - } - - 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 ()); - } - - 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 ()); - } - - 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 ()); - } - - 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 ()); - } - - 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 ()); - } - - 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 ()); - } - - 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 ()); - } - - 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 ()); - } - -private: - typedef std::pair netlist_pair; - - const db::Netlist *mp_netlist; - - mutable std::map > m_circuit_by_index; - mutable std::map > m_net_by_circuit_and_index; - mutable std::map > m_subcircuit_pinref_by_net_and_index; - mutable std::map > m_terminalref_by_net_and_index; - mutable std::map > m_pinref_by_net_and_index; - mutable std::map > m_device_by_circuit_and_index; - mutable std::map > m_pin_by_circuit_and_index; - mutable std::map > m_subcircuit_by_circuit_and_index; - mutable std::map m_circuit_index_by_object; - mutable std::map m_net_index_by_object; - mutable std::map m_pin_index_by_object; - mutable std::map m_subcircuit_index_by_object; - mutable std::map m_device_index_by_object; -}; - // ---------------------------------------------------------------------------------- // NetlistBrowserModel implementation diff --git a/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc b/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc new file mode 100644 index 000000000..8feda7e4c --- /dev/null +++ b/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc @@ -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 struct DataGetter; + +template <> +struct DataGetter +{ + typedef typename std::vector >::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 +{ + typedef typename std::vector >::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 +{ + typedef typename std::vector >::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 +static IndexedNetlistModel::circuit_pair get_parent_of (const Pair &pair, const db::NetlistCrossReference *cross_ref, std::map &cache) +{ + typename std::map::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 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 +static size_t get_index_of (const Pair &pair, Iter begin, Iter end, std::map &cache) +{ + typename std::map::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); +} + +} diff --git a/src/laybasic/laybasic/layNetlistCrossReferenceModel.h b/src/laybasic/laybasic/layNetlistCrossReferenceModel.h new file mode 100644 index 000000000..3db0bbdfe --- /dev/null +++ b/src/laybasic/laybasic/layNetlistCrossReferenceModel.h @@ -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 > nets; + std::vector > devices; + std::vector > pins; + std::vector > subcircuits; + }; + + struct PerNetData + { + std::vector > terminals; + std::vector > pins; + std::vector > 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, 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 &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 >::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_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 &nets) const + { + std::map, 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 mp_netlist_a, mp_netlist_b; + std::vector > m_circuits; + std::map, PerCircuitData> m_per_circuit_data; + mutable std::map, PerNetData> m_per_net_data; + std::map m_other_circuit; + std::map m_other_net; + std::map m_other_device; + std::map m_other_pin; + std::map m_other_subcircuit; + std::pair m_current_circuits; + std::map, status> m_circuit_status; + std::map, status> m_net_status; + std::map, status> m_device_status; + std::map, status> m_pin_status; + std::map, 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 &nets, PerNetData &data) const; + void build_subcircuit_pin_refs (const std::pair &nets, PerNetData &data) const; + void build_pin_refs (const std::pair &nets, PerNetData &data) const; + void build_terminal_refs (const std::pair &nets, PerNetData &data) const; +}; + +void +NetlistCrossReference::begin_netlist (const db::Netlist *a, const db::Netlist *b) +{ + mp_netlist_a.reset (const_cast (a)); + mp_netlist_b.reset (const_cast (b)); + m_current_circuits = std::pair (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 (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 (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 (a, b)] = Skipped; +} + +void +NetlistCrossReference::circuit_mismatch (const db::Circuit *a, const db::Circuit *b) +{ + establish_pair (a, b); + m_circuit_status [std::pair (a, b)] = Mismatch; +} + +void +NetlistCrossReference::match_nets (const db::Net *a, const db::Net *b) +{ + establish_pair (a, b); + m_net_status [std::pair (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 (a, b)] = MatchWithWarning; +} + +void +NetlistCrossReference::net_mismatch (const db::Net *a, const db::Net *b) +{ + establish_pair (a, b); + m_net_status [std::pair (a, b)] = Mismatch; +} + +void +NetlistCrossReference::match_devices (const db::Device *a, const db::Device *b) +{ + establish_pair (a, b); + m_device_status [std::pair (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 (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 (a, b)] = MatchWithWarning; +} + +void +NetlistCrossReference::device_mismatch (const db::Device *a, const db::Device *b) +{ + establish_pair (a, b); + m_device_status [std::pair (a, b)] = Mismatch; +} + +void +NetlistCrossReference::match_pins (const db::Pin *a, const db::Pin *b) +{ + establish_pair (a, b); + m_pin_status [std::pair (a, b)] = Match; +} + +void +NetlistCrossReference::pin_mismatch (const db::Pin *a, const db::Pin *b) +{ + establish_pair (a, b); + m_pin_status [std::pair (a, b)] = Mismatch; +} + +void +NetlistCrossReference::match_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b) +{ + establish_pair (a, b); + m_subcircuit_status [std::pair (a, b)] = Match; +} + +void +NetlistCrossReference::subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b) +{ + establish_pair (a, b); + m_subcircuit_status [std::pair (a, b)] = Mismatch; +} + +static void init_data_from_single (const db::Net *net, NetlistCrossReference::PerNetData &data, bool first) +{ + data.pins.reserve (net->pin_count ()); + for (db::Net::const_pin_iterator i = net->begin_pins (); i != net->end_pins (); ++i) { + if (! first) { + data.pins.push_back (std::make_pair ((const db::NetPinRef *) 0, i.operator-> ())); + } else { + data.pins.push_back (std::make_pair (i.operator-> (), (const db::NetPinRef *) 0)); + } + } + + data.subcircuit_pins.reserve (net->subcircuit_pin_count ()); + for (db::Net::const_subcircuit_pin_iterator i = net->begin_subcircuit_pins (); i != net->end_subcircuit_pins (); ++i) { + if (! first) { + data.subcircuit_pins.push_back (std::make_pair ((const db::NetSubcircuitPinRef *) 0, i.operator-> ())); + } else { + data.subcircuit_pins.push_back (std::make_pair (i.operator-> (), (const db::NetSubcircuitPinRef *) 0)); + } + } + + data.terminals.reserve (net->terminal_count ()); + for (db::Net::const_terminal_iterator i = net->begin_terminals (); i != net->end_terminals (); ++i) { + if (! first) { + data.terminals.push_back (std::make_pair ((const db::NetTerminalRef *) 0, i.operator-> ())); + } else { + data.terminals.push_back (std::make_pair (i.operator-> (), (const db::NetTerminalRef *) 0)); + } + } +} + +void +NetlistCrossReference::build_terminal_refs (const std::pair &nets, PerNetData &data) const +{ + std::map, 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, 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_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 &termdefs_b = db->device_class ()->terminal_definitions (); + + for (std::vector::const_iterator t = termdefs_b.begin (); t != termdefs_b.end (); ++t) { + if (atid == db->device_class ()->normalize_terminal_id (t->id ())) { + std::map, 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, 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 &nets, PerNetData &data) const +{ + std::map 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_iterator a = p2r_a.begin (); a != p2r_a.end (); ++a) { + + const db::Pin *pa = a->first; + + const db::NetPinRef *prb = 0; + + std::map::const_iterator ipb = m_other_pin.find (pa); + if (ipb != m_other_pin.end ()) { + + const db::Pin *pb = ipb->second; + std::map::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_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 &nets, PerNetData &data) const +{ + std::map, 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, 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_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_iterator ipb = m_other_pin.find (pa); + if (ipb != m_other_pin.end ()) { + + std::map, 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, 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 &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, size_t> index_of_nets; + std::map, size_t> index_of_devices; + std::map, size_t> index_of_pins; + std::map, size_t> index_of_subcircuits; + }; + + tl::weak_ptr mp_cross_ref; + mutable std::map m_parents_of_nets; + mutable std::map m_parents_of_devices; + mutable std::map m_parents_of_pins; + mutable std::map m_parents_of_subcircuits; + mutable std::map, PerCircuitCacheData> m_per_circuit_data; + mutable std::map, size_t> m_index_of_circuits; +}; + +} + +#endif diff --git a/src/laybasic/laybasic/laybasic.pro b/src/laybasic/laybasic/laybasic.pro index d7921d210..610b9f87a 100644 --- a/src/laybasic/laybasic/laybasic.pro +++ b/src/laybasic/laybasic/laybasic.pro @@ -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