WIP: netlist browser.

This commit is contained in:
Matthias Koefferlein 2019-04-21 10:41:20 +02:00
parent 20b984cc50
commit ae9064021c
7 changed files with 974 additions and 4 deletions

View File

@ -309,6 +309,14 @@ public:
*/
void remove_net (Net *net);
/**
* @brief Gets the number of nets
*/
size_t net_count () const
{
return m_nets.size ();
}
/**
* @brief Begin iterator for the nets of the circuit (non-const version)
*/
@ -393,6 +401,14 @@ public:
*/
void remove_device (Device *device);
/**
* @brief Gets the number of devices
*/
size_t device_count () const
{
return m_nets.size ();
}
/**
* @brief Gets the device from a given ID (const version)
*
@ -477,6 +493,14 @@ public:
*/
void remove_subcircuit (SubCircuit *subcircuit);
/**
* @brief Gets the number of subcircuits
*/
size_t subcircuit_count () const
{
return m_subcircuits.size ();
}
/**
* @brief Gets the subcircuit from a given ID (const version)
*

View File

@ -138,6 +138,14 @@ public:
*/
void remove_circuit (Circuit *circuit);
/**
* @brief Gets the number of circuits
*/
size_t circuit_count () const
{
return m_circuits.size ();
}
/**
* @brief Flattens the given circuit
* All subcircuit references are replaced by the content of this circuit.

View File

@ -230,8 +230,7 @@
<widget class="QLabel" name="label_2">
<property name="text">
<string>Choose &quot;Open&quot; from the &quot;File ...&quot; menu
to load a netlist, a net database
or a LVS cross-reference</string>
to load a netlist or a netlist/LVS database</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>

View File

@ -1422,6 +1422,16 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Gets the report database with the given index\n"
"@return The \\ReportDatabase object or nil if the index is not valid"
) +
gsi::method ("add_rdb", &lay::LayoutView::add_rdb, gsi::arg ("db"),
"@brief Adds the given database to the view\n"
"\n"
"This method will add an existing database to the view. It will then appear in the marker database browser.\n"
"A similar method is \\create_rdb which will create a new database within the view.\n"
"\n"
"@return The index of the database within the view (see \\rdb)\n"
"\n"
"This method has been added in version 0.26."
) +
gsi::method_ext ("create_rdb", &create_rdb, gsi::arg ("name"),
"@brief Creates a new report database and returns the index of the new database\n"
"@param name The name of the new report database\n"
@ -1460,6 +1470,16 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been added in version 0.26."
) +
gsi::method ("add_l2ndb", &lay::LayoutView::add_l2ndb, gsi::arg ("db"),
"@brief Adds the given database to the view\n"
"\n"
"This method will add an existing database to the view. It will then appear in the netlist database browser.\n"
"A similar method is \\create_l2ndb which will create a new database within the view.\n"
"\n"
"@return The index of the database within the view (see \\l2ndb)\n"
"\n"
"This method has been added in version 0.26."
) +
gsi::method_ext ("create_l2ndb", &create_l2ndb, gsi::arg ("name"),
"@brief Creates a new netlist database and returns the index of the new database\n"
"@param name The name of the new netlist database\n"

View File

@ -7090,7 +7090,7 @@ static void make_unique_name (T *object, Iter from, Iter to)
do {
bool found = false;
bool found = n.empty ();
for (Iter i = from; i != to && !found; ++i) {
if ((*i)->name () == n) {
found = true;
@ -7114,6 +7114,9 @@ LayoutView::add_l2ndb (db::LayoutToNetlist *l2ndb)
make_unique_name (l2ndb, m_l2ndbs.begin (), m_l2ndbs.end ());
m_l2ndbs.push_back (l2ndb);
// Mark this object as owned by us (for GSI)
l2ndb->keep ();
l2ndb_list_changed_event ();
return (unsigned int)(m_l2ndbs.size () - 1);
@ -7164,6 +7167,9 @@ LayoutView::add_rdb (rdb::Database *rdb)
make_unique_name (rdb, m_l2ndbs.begin (), m_l2ndbs.end ());
m_rdbs.push_back (rdb);
// Mark this object as owned by us (for GSI)
rdb->keep ();
rdb_list_changed_event ();
return (unsigned int)(m_rdbs.size () - 1);

View File

@ -562,7 +562,7 @@ NetlistBrowserDialog::deactivated ()
void
NetlistBrowserDialog::menu_activated (const std::string &symbol)
{
if (symbol == "marker_browser::show") {
if (symbol == "netlist_browser::show") {
view ()->deactivate_all_browsers ();
activate ();
} else {

View File

@ -22,12 +22,925 @@
#include "layNetlistBrowserPage.h"
#include "dbLayoutToNetlist.h"
namespace lay
{
extern std::string cfg_l2ndb_show_all;
// ----------------------------------------------------------------------------------
// NetlistBrowserModel definition and implementation
/**
* @brief The NetlistBrowserModel
*
* The model hierarchy is the following
* - circuits
* - 0..#pins: pins
* - net (1x)
* - #pins..#pins+#nets: nets
* - 0..#devices: terminals
* - other terminals and nets
* - #devices..#devices+#pins: pins
* - #devices+#pins..: subcircuit pins
* - other pins and nets
* - #pins+#nets..#pins+#nets+#subcircuits: subcircuits
* - pins and nets
* - #pins+#nets+#subcircuits..: devices
* - terminals and nets
*/
class NetlistBrowserModel
: public QAbstractItemModel
{
public:
NetlistBrowserModel (db::LayoutToNetlist *l2ndb);
virtual int columnCount (const QModelIndex &parent) const;
virtual QVariant data (const QModelIndex &index, int role) const;
virtual Qt::ItemFlags flags (const QModelIndex &index) const;
virtual bool hasChildren (const QModelIndex &parent) const;
virtual QVariant headerData (int section, Qt::Orientation orientation, int role) const;
virtual QModelIndex index (int row, int column, const QModelIndex &parent) const;
virtual QModelIndex parent (const QModelIndex &index) const;
virtual int rowCount (const QModelIndex &parent) const;
private:
static inline void *make_id (size_t i1)
{
return reinterpret_cast<void *> (i1);
}
static inline void *make_id (size_t i1, size_t n1, size_t i2)
{
return reinterpret_cast<void *> (i1 + n1 * i2);
}
static inline void *make_id (size_t i1, size_t n1, size_t i2, size_t n2, size_t i3)
{
return reinterpret_cast<void *> (i1 + n1 * (i2 + n2 * i3));
}
static inline void *make_id (size_t i1, size_t n1, size_t i2, size_t n2, size_t i3, size_t n3, size_t i4)
{
return reinterpret_cast<void *> (i1 + n1 * (i2 + n2 * (i3 + n3 * i4)));
}
static inline void *make_id (size_t i1, size_t n1, size_t i2, size_t n2, size_t i3, size_t n3, size_t i4, size_t n4, size_t i5)
{
return reinterpret_cast<void *> (i1 + n1 * (i2 + n2 * (i3 + n3 * (i4 + n4 * i5))));
}
static inline void *make_id (size_t i1, size_t n1, size_t i2, size_t n2, size_t i3, size_t n3, size_t i4, size_t n4, size_t i5, size_t n5, size_t i6)
{
return reinterpret_cast<void *> (i1 + n1 * (i2 + n2 * (i3 + n3 * (i4 + n4 * (i5 + n5 * i6)))));
}
static inline size_t pop (void *&idp, size_t n)
{
size_t id = reinterpret_cast<size_t> (idp);
size_t i = id % n;
id /= n;
idp = reinterpret_cast<void *> (id);
return i;
}
static inline bool always (bool)
{
return true;
}
virtual void *make_id_circuit (size_t circuit_index) const
{
return make_id (circuit_index);
}
virtual void *make_id_circuit_pin (size_t circuit_index, size_t pin_index) const
{
return make_id (circuit_index, netlist ()->circuit_count (), 1, 8, pin_index);
}
void *make_id_circuit_pin_net (size_t circuit_index, size_t pin_index, size_t net_index) const
{
db::Circuit *circuit = circuit_from_id (make_id_circuit (circuit_index));
return make_id (circuit_index, netlist ()->circuit_count (), 1, 8, pin_index, circuit->pin_count (), net_index);
}
void *make_id_circuit_net (size_t circuit_index, size_t net_index) const
{
return make_id (circuit_index, netlist ()->circuit_count (), 2, 8, net_index);
}
void *make_id_circuit_net_device_terminal (size_t circuit_index, size_t net_index, size_t terminal_ref_index) const
{
db::Circuit *circuit = circuit_from_id (make_id_circuit (circuit_index));
return make_id (circuit_index, netlist ()->circuit_count (), 2, 8, net_index, circuit->net_count (), 1, 4, terminal_ref_index);
}
void *make_id_circuit_net_device_terminal_others (size_t circuit_index, size_t net_index, size_t terminal_ref_index, size_t other_index) const
{
db::Circuit *circuit = circuit_from_id (make_id_circuit (circuit_index));
db::Net *net = net_from_id (make_id_circuit_net (circuit_index, net_index));
return make_id (circuit_index, netlist ()->circuit_count (), 2, 8, net_index, circuit->net_count (), 1, 4, terminal_ref_index, net->terminal_count (), other_index + 1);
}
void *make_id_circuit_net_pin (size_t circuit_index, size_t net_index, size_t pin_index) const
{
db::Circuit *circuit = circuit_from_id (make_id_circuit (circuit_index));
return make_id (circuit_index, netlist ()->circuit_count (), 2, 8, net_index, circuit->net_count (), 2, 4, pin_index);
}
void *make_id_circuit_net_subcircuit_pin (size_t circuit_index, size_t net_index, size_t pin_ref_index) const
{
db::Circuit *circuit = circuit_from_id (make_id_circuit (circuit_index));
return make_id (circuit_index, netlist ()->circuit_count (), 2, 8, net_index, circuit->net_count (), 3, 4, pin_ref_index);
}
void *make_id_circuit_net_subcircuit_pin_others (size_t circuit_index, size_t net_index, size_t pin_ref_index, size_t other_index) const
{
db::Circuit *circuit = circuit_from_id (make_id_circuit (circuit_index));
db::Net *net = net_from_id (make_id_circuit_net (circuit_index, net_index));
return make_id (circuit_index, netlist ()->circuit_count (), 2, 8, net_index, circuit->net_count (), 3, 4, pin_ref_index, net->subcircuit_pin_count (), other_index + 1);
}
void *make_id_circuit_subcircuit (size_t circuit_index, size_t subcircuit_index) const
{
return make_id (circuit_index, netlist ()->circuit_count (), 3, 8, subcircuit_index);
}
void *make_id_circuit_subcircuit_pin (size_t circuit_index, size_t subcircuit_index, size_t pin_index) const
{
db::Circuit *circuit = circuit_from_id (make_id_circuit (circuit_index));
return make_id (circuit_index, netlist ()->circuit_count (), 3, 8, subcircuit_index, circuit->subcircuit_count (), pin_index + 1);
}
void *make_id_circuit_device (size_t circuit_index, size_t device_index) const
{
return make_id (circuit_index, netlist ()->circuit_count (), 4, 8, device_index);
}
void *make_id_circuit_device_terminal (size_t circuit_index, size_t device_index, size_t terminal_index) const
{
db::Circuit *circuit = circuit_from_id (make_id_circuit (circuit_index));
return make_id (circuit_index, netlist ()->circuit_count (), 4, 8, device_index, circuit->device_count (), terminal_index + 1);
}
bool is_id_circuit (void *id) const
{
pop (id, netlist ()->circuit_count ());
return id == 0;
}
bool is_id_circuit_pin (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 1 && always (pop (id, circuit->pin_count ())) && id == 0);
}
bool is_id_circuit_pin_net (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 1 && always (pop (id, circuit->pin_count ())) && id != 0);
}
bool is_id_circuit_net (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 2 && always (pop (id, circuit->net_count ())) && id == 0);
}
bool is_id_circuit_net_device_terminal (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
db::Net *net = net_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 2 && always (pop (id, circuit->net_count ())) && pop (id, 4) == 1 && always (pop (id, net->terminal_count ())) && id == 0);
}
bool is_id_circuit_net_device_terminal_others (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
db::Net *net = net_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 2 && always (pop (id, circuit->net_count ())) && pop (id, 4) == 1 && always (pop (id, net->terminal_count ())) && id != 0);
}
bool is_id_circuit_net_pin (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 2 && always (pop (id, circuit->net_count ())) && pop (id, 4) == 2);
}
bool is_id_circuit_net_subcircuit_pin (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
db::Net *net = net_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 2 && always (pop (id, circuit->net_count ())) && pop (id, 4) == 3 && always (pop (id, net->subcircuit_pin_count ())) && id == 0);
}
bool is_id_circuit_net_subcircuit_pin_others (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
db::Net *net = net_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 2 && always (pop (id, circuit->net_count ())) && pop (id, 4) == 3 && always (pop (id, net->subcircuit_pin_count ())) && id != 0);
}
bool is_id_circuit_subcircuit (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 3 && always (pop (id, circuit->subcircuit_count ())) && id == 0);
}
bool is_id_circuit_subcircuit_pin (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 3 && always (pop (id, circuit->subcircuit_count ())) && id != 0);
}
bool is_id_circuit_device (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 4 && always (pop (id, circuit->device_count ())) && id == 0);
}
bool is_id_circuit_device_terminal (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
return (pop (id, 8) == 4 && always (pop (id, circuit->device_count ())) && id != 0);
}
size_t circuit_index_from_id (void *id) const
{
return pop (id, netlist ()->circuit_count ());
}
size_t circuit_pin_index_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
pop (id, 8);
return pop (id, circuit->pin_count ());
}
size_t circuit_device_index_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
pop (id, 8);
return pop (id, circuit->device_count ());
}
size_t circuit_device_terminal_index_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
pop (id, 8);
pop (id, circuit->device_count ());
return reinterpret_cast<size_t> (id) - 1;
}
size_t circuit_subcircuit_index_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
pop (id, 8);
return pop (id, circuit->subcircuit_count ());
}
size_t circuit_subcircuit_pin_index_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
pop (id, 8);
pop (id, circuit->subcircuit_count ());
return reinterpret_cast<size_t> (id) - 1;
}
size_t circuit_net_index_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
pop (id, netlist ()->circuit_count ());
pop (id, 8);
return pop (id, circuit->net_count ());
}
size_t circuit_net_subcircuit_pin_index_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
db::Net *net = net_from_id (id);
pop (id, netlist ()->circuit_count ());
pop (id, 8);
pop (id, circuit->net_count ());
pop (id, 4);
return pop (id, net->subcircuit_pin_count ());
}
size_t circuit_net_subcircuit_pin_other_index_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
db::Net *net = net_from_id (id);
pop (id, netlist ()->circuit_count ());
pop (id, 8);
pop (id, circuit->net_count ());
pop (id, 4);
pop (id, net->subcircuit_pin_count ());
return reinterpret_cast<size_t> (id) - 1;
}
size_t circuit_net_device_terminal_index_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
db::Net *net = net_from_id (id);
pop (id, netlist ()->circuit_count ());
pop (id, 8);
pop (id, circuit->net_count ());
pop (id, 4);
return pop (id, net->terminal_count ());
}
size_t circuit_net_device_terminal_other_index_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
db::Net *net = net_from_id (id);
pop (id, netlist ()->circuit_count ());
pop (id, 8);
pop (id, circuit->net_count ());
pop (id, 4);
pop (id, net->terminal_count ());
return reinterpret_cast<size_t> (id) - 1;
}
db::Circuit *circuit_from_id (void *id) const
{
size_t index = circuit_index_from_id (id);
std::map<size_t, db::Circuit *>::iterator c = m_circuit_by_index.find (index);
if (c == m_circuit_by_index.end ()) {
c = m_circuit_by_index.insert (std::make_pair (index, (db::Circuit *) 0)).first;
for (db::Netlist::circuit_iterator i = netlist ()->begin_circuits (); i != netlist ()->end_circuits (); ++i) {
if (index-- == 0) {
c->second = i.operator-> ();
break;
}
}
}
return c->second;
}
db::Net *net_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
size_t index = circuit_net_index_from_id (id);
std::map<db::Circuit *, std::map<size_t, db::Net *> >::iterator cc = m_net_by_circuit_and_index.find (circuit);
if (cc != m_net_by_circuit_and_index.end ()) {
cc = m_net_by_circuit_and_index.insert (std::make_pair (circuit, std::map<size_t, db::Net *> ())).first;
}
std::map<size_t, db::Net *>::iterator c = cc->second.find (index);
if (c == cc->second.end ()) {
c = cc->second.insert (std::make_pair (index, (db::Net *) 0)).first;
for (db::Circuit::net_iterator i = circuit->begin_nets (); i != circuit->end_nets (); ++i) {
if (index-- == 0) {
c->second = i.operator-> ();
break;
}
}
}
return c->second;
}
const db::NetSubcircuitPinRef *net_pinref_from_id (void *id) const
{
db::Net *net = net_from_id (id);
size_t index = circuit_net_subcircuit_pin_index_from_id (id);
std::map<db::Net *, std::map<size_t, db::NetSubcircuitPinRef *> >::iterator cc = m_pinref_by_net_and_index.find (net);
if (cc != m_pinref_by_net_and_index.end ()) {
cc = m_pinref_by_net_and_index.insert (std::make_pair (net, std::map<size_t, db::NetSubcircuitPinRef *> ())).first;
}
std::map<size_t, db::NetSubcircuitPinRef *>::iterator c = cc->second.find (index);
if (c == cc->second.end ()) {
c = cc->second.insert (std::make_pair (index, (db::NetSubcircuitPinRef *) 0)).first;
for (db::Net::subcircuit_pin_iterator i = net->begin_subcircuit_pins (); i != net->end_subcircuit_pins (); ++i) {
if (index-- == 0) {
c->second = i.operator-> ();
break;
}
}
}
return c->second;
}
const db::NetTerminalRef *net_terminalref_from_id (void *id) const
{
db::Net *net = net_from_id (id);
size_t index = circuit_net_device_terminal_index_from_id (id);
std::map<db::Net *, std::map<size_t, db::NetTerminalRef *> >::iterator cc = m_terminalref_by_net_and_index.find (net);
if (cc != m_terminalref_by_net_and_index.end ()) {
cc = m_terminalref_by_net_and_index.insert (std::make_pair (net, std::map<size_t, db::NetTerminalRef *> ())).first;
}
std::map<size_t, db::NetTerminalRef *>::iterator c = cc->second.find (index);
if (c == cc->second.end ()) {
c = cc->second.insert (std::make_pair (index, (db::NetTerminalRef *) 0)).first;
for (db::Net::terminal_iterator i = net->begin_terminals (); i != net->end_terminals (); ++i) {
if (index-- == 0) {
c->second = i.operator-> ();
break;
}
}
}
return c->second;
}
db::Device *device_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
size_t index = circuit_device_index_from_id (id);
std::map<db::Circuit *, std::map<size_t, db::Device *> >::iterator cc = m_device_by_circuit_and_index.find (circuit);
if (cc != m_device_by_circuit_and_index.end ()) {
cc = m_device_by_circuit_and_index.insert (std::make_pair (circuit, std::map<size_t, db::Device *> ())).first;
}
std::map<size_t, db::Device *>::iterator c = cc->second.find (index);
if (c == cc->second.end ()) {
c = cc->second.insert (std::make_pair (index, (db::Device *) 0)).first;
for (db::Circuit::device_iterator i = circuit->begin_devices (); i != circuit->end_devices (); ++i) {
if (index-- == 0) {
c->second = i.operator-> ();
break;
}
}
}
return c->second;
}
db::Pin *pin_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
size_t index = circuit_pin_index_from_id (id);
std::map<db::Circuit *, std::map<size_t, db::Pin *> >::iterator cc = m_pin_by_circuit_and_index.find (circuit);
if (cc != m_pin_by_circuit_and_index.end ()) {
cc = m_pin_by_circuit_and_index.insert (std::make_pair (circuit, std::map<size_t, db::Pin *> ())).first;
}
std::map<size_t, db::Pin *>::iterator c = cc->second.find (index);
if (c == cc->second.end ()) {
c = cc->second.insert (std::make_pair (index, (db::Pin *) 0)).first;
for (db::Circuit::pin_iterator i = circuit->begin_pins (); i != circuit->end_pins (); ++i) {
if (index-- == 0) {
c->second = i.operator-> ();
break;
}
}
}
return c->second;
}
db::SubCircuit *subcircuit_from_id (void *id) const
{
db::Circuit *circuit = circuit_from_id (id);
size_t index = circuit_subcircuit_index_from_id (id);
std::map<db::Circuit *, std::map<size_t, db::SubCircuit *> >::iterator cc = m_subcircuit_by_circuit_and_index.find (circuit);
if (cc != m_subcircuit_by_circuit_and_index.end ()) {
cc = m_subcircuit_by_circuit_and_index.insert (std::make_pair (circuit, std::map<size_t, db::SubCircuit *> ())).first;
}
std::map<size_t, db::SubCircuit *>::iterator c = cc->second.find (index);
if (c == cc->second.end ()) {
c = cc->second.insert (std::make_pair (index, (db::SubCircuit *) 0)).first;
for (db::Circuit::subcircuit_iterator i = circuit->begin_subcircuits (); i != circuit->end_subcircuits (); ++i) {
if (index-- == 0) {
c->second = i.operator-> ();
break;
}
}
}
return c->second;
}
db::Netlist *netlist () const
{
return const_cast<db::Netlist *> (mp_l2ndb->netlist ());
}
db::LayoutToNetlist *mp_l2ndb;
mutable std::map<size_t, db::Circuit *> m_circuit_by_index;
mutable std::map<db::Circuit *, std::map<size_t, db::Net *> > m_net_by_circuit_and_index;
mutable std::map<db::Net *, std::map<size_t, db::NetSubcircuitPinRef *> > m_pinref_by_net_and_index;
mutable std::map<db::Net *, std::map<size_t, db::NetTerminalRef *> > m_terminalref_by_net_and_index;
mutable std::map<db::Circuit *, std::map<size_t, db::Device *> > m_device_by_circuit_and_index;
mutable std::map<db::Circuit *, std::map<size_t, db::Pin *> > m_pin_by_circuit_and_index;
mutable std::map<db::Circuit *, std::map<size_t, db::SubCircuit *> > m_subcircuit_by_circuit_and_index;
};
NetlistBrowserModel::NetlistBrowserModel (db::LayoutToNetlist *l2ndb)
: mp_l2ndb (l2ndb)
{
// .. nothing yet ..
}
int
NetlistBrowserModel::columnCount (const QModelIndex & /*parent*/) const
{
// Item type & icon, link or description
return 2;
}
QVariant
NetlistBrowserModel::data (const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole || ! index.isValid ()) {
return QVariant ();
}
void *id = index.internalPointer ();
/*
* - circuits
* - 0..#pins: pins
* - net (1x)
* - #pins..#pins+#nets: nets
* - 0..#devices: terminals
* - other terminals and nets
* - #devices..#devices+#pins: pins
* - #devices+#pins..: subcircuit pins
* - other pins and nets
* - #pins+#nets..#pins+#nets+#subcircuits: subcircuits
* - pins and nets
* - #pins+#nets+#subcircuits..: devices
* - terminals and nets
*/
if (is_id_circuit (id)) {
db::Circuit *circuit = circuit_from_id (id);
if (circuit) {
return tl::to_qstring (circuit->name ());
}
} else if (is_id_circuit_pin (id) || is_id_circuit_net_subcircuit_pin_others (id)) {
db::Pin *pin = pin_from_id (id);
if (pin) {
return tl::to_qstring (pin->expanded_name ());
}
} else if (is_id_circuit_device (id)) {
db::Device *device = device_from_id (id);
if (device) {
return tl::to_qstring (device->expanded_name ());
}
} else if (is_id_circuit_subcircuit (id)) {
db::SubCircuit *subcircuit = subcircuit_from_id (id);
if (subcircuit) {
return tl::to_qstring (subcircuit->expanded_name ());
}
} else if (is_id_circuit_net (id)) {
db::Net *net = net_from_id (id);
if (net) {
return tl::to_qstring (net->expanded_name ());
}
} else if (is_id_circuit_net_subcircuit_pin (id)) {
const db::NetSubcircuitPinRef *ref = net_pinref_from_id (id);
if (ref && ref->pin ()) {
return tl::to_qstring (ref->pin ()->expanded_name ());
}
} else if (is_id_circuit_net_device_terminal (id)) {
const db::NetTerminalRef *ref = net_terminalref_from_id (id);
if (ref && ref->terminal_def ()) {
return tl::to_qstring (ref->terminal_def ()->name ());
}
} else if (is_id_circuit_net_device_terminal_others (id)) {
const db::NetTerminalRef *ref = net_terminalref_from_id (id);
size_t other_index = circuit_net_device_terminal_other_index_from_id (id);
if (ref && ref->device_class () && ref->device_class ()->terminal_definitions ().size () > other_index) {
const db::DeviceTerminalDefinition &def = ref->device_class ()->terminal_definitions ()[other_index];
return tl::to_qstring (def.name ());
}
}
return QVariant ();
}
Qt::ItemFlags
NetlistBrowserModel::flags (const QModelIndex & /*index*/) const
{
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
bool
NetlistBrowserModel::hasChildren (const QModelIndex &parent) const
{
if (! parent.isValid ()) {
return mp_l2ndb->netlist () && mp_l2ndb->netlist ()->circuit_count () > 0;
} else {
void *id = parent.internalPointer ();
if (is_id_circuit (id)) {
db::Circuit *circuit = circuit_from_id (id);
return circuit->device_count () + circuit->pin_count () + circuit->net_count () + circuit->subcircuit_count () > 0;
} else if (is_id_circuit_pin (id)) {
return true;
} else if (is_id_circuit_device (id)) {
db::Device *device = device_from_id (id);
return device->device_class () && ! device->device_class ()->terminal_definitions ().empty ();
} else if (is_id_circuit_subcircuit (id)) {
db::SubCircuit *subcircuit = subcircuit_from_id (id);
return subcircuit->circuit_ref () && subcircuit->circuit_ref ()->pin_count () > 0;
} else if (is_id_circuit_net (id)) {
db::Net *net = net_from_id (id);
return net->pin_count () + net->subcircuit_pin_count () + net->terminal_count () > 0;
} else if (is_id_circuit_net_subcircuit_pin (id)) {
const db::NetSubcircuitPinRef *ref = net_pinref_from_id (id);
return ref->subcircuit ()->circuit_ref () && ref->subcircuit ()->circuit_ref ()->pin_count () > 0;
} else if (is_id_circuit_net_device_terminal (id)) {
const db::NetTerminalRef *ref = net_terminalref_from_id (id);
return ref->device_class () && ! ref->device_class ()->terminal_definitions ().empty ();
} else {
return false;
}
}
}
QVariant
NetlistBrowserModel::headerData (int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const
{
return QVariant ();
}
QModelIndex
NetlistBrowserModel::index (int row, int column, const QModelIndex &parent) const
{
if (! parent.isValid ()) {
return createIndex (row, column, make_id_circuit (row));
} else {
void *id = parent.internalPointer ();
/*
* - circuits
* - 0..#pins: pins
* - net (1x)
* - #pins..#pins+#nets: nets
* - 0..#devices: terminals
* - other terminals and nets
* - #devices..#devices+#pins: pins
* - #devices+#pins..: subcircuit pins
* - other pins and nets
* - #pins+#nets..#pins+#nets+#subcircuits: subcircuits
* - pins and nets
* - #pins+#nets+#subcircuits..: devices
* - terminals and nets
*/
if (is_id_circuit (id)) {
db::Circuit *circuit = circuit_from_id (id);
if (size_t (row) < circuit->pin_count ()) {
return createIndex (row, column, make_id_circuit_pin (circuit_index_from_id (id), row));
}
row -= int (circuit->pin_count ());
if (size_t (row) < circuit->net_count ()) {
return createIndex (row, column, make_id_circuit_net (circuit_index_from_id (id), row));
}
row -= int (circuit->net_count ());
if (size_t (row) < circuit->subcircuit_count ()) {
return createIndex (row, column, make_id_circuit_subcircuit (circuit_index_from_id (id), row));
}
row -= int (circuit->subcircuit_count ());
if (size_t (row) < circuit->device_count ()) {
return createIndex (row, column, make_id_circuit_device (circuit_index_from_id (id), row));
}
} else if (is_id_circuit_pin (id)) {
return createIndex (row, column, make_id_circuit_pin_net (circuit_index_from_id (id), circuit_pin_index_from_id (id), row));
} else if (is_id_circuit_device (id)) {
return createIndex (row, column, make_id_circuit_device_terminal (circuit_index_from_id (id), circuit_device_index_from_id (id), row));
} else if (is_id_circuit_subcircuit (id)) {
return createIndex (row, column, make_id_circuit_subcircuit_pin (circuit_index_from_id (id), circuit_subcircuit_index_from_id (id), row));
} else if (is_id_circuit_net (id)) {
db::Net *net = net_from_id (id);
if (size_t (row) < net->terminal_count ()) {
return createIndex (row, column, make_id_circuit_net_device_terminal (circuit_index_from_id (id), circuit_net_index_from_id (id), row));
}
row -= int (net->terminal_count ());
if (size_t (row) < net->pin_count ()) {
return createIndex (row, column, make_id_circuit_net_pin (circuit_index_from_id (id), circuit_net_index_from_id (id), row));
}
row -= int (net->pin_count ());
if (size_t (row) < net->subcircuit_pin_count ()) {
return createIndex (row, column, make_id_circuit_net_subcircuit_pin (circuit_index_from_id (id), circuit_net_index_from_id (id), row));
}
} else if (is_id_circuit_net_subcircuit_pin (id)) {
return createIndex (row, column, make_id_circuit_net_subcircuit_pin_others (circuit_index_from_id (id), circuit_net_index_from_id (id), circuit_net_subcircuit_pin_index_from_id (id), row));
} else if (is_id_circuit_net_device_terminal (id)) {
return createIndex (row, column, make_id_circuit_net_device_terminal_others (circuit_index_from_id (id), circuit_net_index_from_id (id), circuit_net_device_terminal_index_from_id (id), row));
}
}
return QModelIndex ();
}
QModelIndex
NetlistBrowserModel::parent (const QModelIndex &index) const
{
if (! index.isValid ()) {
return QModelIndex ();
} else {
void *id = index.internalPointer ();
int column = index.column ();
/*
* - circuits
* - 0..#pins: pins
* - net (1x)
* - #pins..#pins+#nets: nets
* - 0..#devices: terminals
* - other terminals and nets
* - #devices..#devices+#pins: pins
* - #devices+#pins..: subcircuit pins
* - other pins and nets
* - #pins+#nets..#pins+#nets+#subcircuits: subcircuits
* - pins and nets
* - #pins+#nets+#subcircuits..: devices
* - terminals and nets
*/
if (is_id_circuit (id)) {
return QModelIndex ();
} else if (is_id_circuit_pin (id) || is_id_circuit_net (id) || is_id_circuit_device (id) || is_id_circuit_subcircuit (id)) {
return createIndex (int (circuit_index_from_id (id)), column, make_id_circuit (circuit_index_from_id (id)));
} else if (is_id_circuit_pin_net (id)) {
return createIndex (int (circuit_pin_index_from_id (id)), column, make_id_circuit_pin (circuit_index_from_id (id), circuit_pin_index_from_id (id)));
} else if (is_id_circuit_net_device_terminal (id) || is_id_circuit_net_pin (id) || is_id_circuit_net_subcircuit_pin (id)) {
db::Circuit *circuit = circuit_from_id (id);
return createIndex (int (circuit->pin_count () + circuit_net_index_from_id (id)), column, make_id_circuit_net (circuit_index_from_id (id), circuit_net_index_from_id (id)));
} else if (is_id_circuit_subcircuit_pin (id)) {
db::Circuit *circuit = circuit_from_id (id);
return createIndex (int (circuit->pin_count () + circuit->net_count () + circuit_subcircuit_index_from_id (id)), column, make_id_circuit_subcircuit (circuit_index_from_id (id), circuit_subcircuit_index_from_id (id)));
} else if (is_id_circuit_device_terminal (id)) {
db::Circuit *circuit = circuit_from_id (id);
return createIndex (int (circuit->pin_count () + circuit->net_count () + circuit->subcircuit_count () + circuit_device_terminal_index_from_id (id)), column, make_id_circuit_device (circuit_index_from_id (id), circuit_device_index_from_id (id)));
} else if (is_id_circuit_net_device_terminal_others (id)) {
return createIndex (circuit_net_device_terminal_index_from_id (id), column, make_id_circuit_net_device_terminal (circuit_index_from_id (id), circuit_net_index_from_id (id), circuit_net_device_terminal_index_from_id (id)));
} else if (is_id_circuit_net_subcircuit_pin_others (id)) {
db::Net *net = net_from_id (id);
return createIndex (size_t (net->terminal_count () + net->pin_count () + circuit_net_subcircuit_pin_index_from_id (id)), column, make_id_circuit_net_subcircuit_pin (circuit_index_from_id (id), circuit_net_index_from_id (id), circuit_net_subcircuit_pin_index_from_id (id)));
}
}
return QModelIndex ();
}
int
NetlistBrowserModel::rowCount (const QModelIndex &parent) const
{
if (! parent.isValid ()) {
return int (mp_l2ndb->netlist ()->circuit_count ());
} else {
void *id = parent.internalPointer ();
/*
* - circuits
* - 0..#pins: pins
* - net (1x)
* - #pins..#pins+#nets: nets
* - 0..#devices: terminals
* - other terminals and nets
* - #devices..#devices+#pins: pins
* - #devices+#pins..: subcircuit pins
* - other pins and nets
* - #pins+#nets..#pins+#nets+#subcircuits: subcircuits
* - pins and nets
* - #pins+#nets+#subcircuits..: devices
* - terminals and nets
*/
if (is_id_circuit (id)) {
db::Circuit *circuit = circuit_from_id (id);
return int (circuit->pin_count () + circuit->net_count () + circuit->subcircuit_count () + circuit->device_count ());
} else if (is_id_circuit_pin (id)) {
return 1;
} else if (is_id_circuit_device (id) || is_id_circuit_net_device_terminal (id)) {
db::Device *device = device_from_id (id);
return int (device->device_class () ? device->device_class ()->terminal_definitions ().size () : 0);
} else if (is_id_circuit_subcircuit (id) || is_id_circuit_net_subcircuit_pin (id)) {
db::SubCircuit *subcircuit = subcircuit_from_id (id);
return int (subcircuit->circuit_ref () ? subcircuit->circuit_ref ()->pin_count () : 0);
} else if (is_id_circuit_net (id)) {
db::Net *net = net_from_id (id);
return int (net->terminal_count () + net->pin_count () + net->subcircuit_pin_count ());
}
}
return 0;
}
// ----------------------------------------------------------------------------------
// NetlistBrowserPage implementation