diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 541e5aeb2..dccfddbb2 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -426,20 +426,6 @@ IndexedNetlistModel::pin_pair pins_from_netrefs (const IndexedNetlistModel::net_ return std::make_pair (pin1, pin2); } -static -IndexedNetlistModel::net_pair nets_from_subcircuit_pins (const IndexedNetlistModel::subcircuit_pair &subcircuits, const IndexedNetlistModel::pin_pair &pins) -{ - const db::Net *net1 = 0, *net2 = 0; - if (pins.first && subcircuits.first) { - net1 = subcircuits.first->net_for_pin (pins.first->id ()); - } - if (pins.second && subcircuits.second) { - net2 = subcircuits.second->net_for_pin (pins.second->id ()); - } - - return std::make_pair (net1, net2); -} - static IndexedNetlistModel::net_pair nets_from_circuit_pins (const IndexedNetlistModel::circuit_pair &circuits, const IndexedNetlistModel::pin_pair &pins) { @@ -545,15 +531,6 @@ static size_t rows_for (const db::Device *device) } } -static size_t rows_for (const db::SubCircuit *subcircuit) -{ - if (! subcircuit || ! subcircuit->circuit_ref ()) { - return 0; - } else { - return subcircuit->circuit_ref ()->pin_count (); - } -} - static size_t rows_for (const db::NetTerminalRef *ref) { if (! ref || ! ref->device_class ()) { @@ -851,7 +828,7 @@ class CircuitItemData : public NetlistModelItemData { public: - CircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::circuit_pair &cp); + CircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::circuit_pair &cp, const IndexedNetlistModel::subcircuit_pair &sp = IndexedNetlistModel::subcircuit_pair (0, 0)); virtual void do_ensure_children (NetlistBrowserModel *model); virtual QIcon icon (NetlistBrowserModel *model); @@ -860,17 +837,23 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - virtual std::pair circuits () + virtual std::pair circuits_of_this () { return m_cp; } + virtual std::pair subcircuits_of_this () + { + return m_sp; + } + CircuitNetItemData *circuit_net_item (NetlistBrowserModel *model, const IndexedNetlistModel::net_pair &np); CircuitDeviceItemData *circuit_device_item (NetlistBrowserModel *model, const IndexedNetlistModel::device_pair &dp); CircuitSubCircuitItemData *circuit_subcircuit_item (NetlistBrowserModel *model, const IndexedNetlistModel::subcircuit_pair &sp); private: IndexedNetlistModel::circuit_pair m_cp; + IndexedNetlistModel::subcircuit_pair m_sp; }; // ---------------------------------------------------------------------------------- @@ -918,13 +901,14 @@ public: return m_pp; } - virtual std::pair pins () + virtual std::pair pins_of_this () { return pp (); } private: IndexedNetlistModel::pin_pair m_pp; + bool m_pin_seen; }; // ---------------------------------------------------------------------------------- @@ -1017,13 +1001,14 @@ public: return m_tp; } - virtual std::pair devices () + virtual std::pair devices_of_this () { return dp (); } private: IndexedNetlistModel::net_terminal_pair m_tp; + bool m_device_seen; }; // ---------------------------------------------------------------------------------- @@ -1047,11 +1032,6 @@ public: return p->dp (); } - virtual std::pair nets_of_this () - { - return m_np; - } - private: std::pair m_tp; IndexedNetlistModel::net_pair m_np; @@ -1089,12 +1069,12 @@ public: return pins_from_pinrefs (m_sp); } - virtual std::pair subcircuits () + virtual std::pair subcircuits_of_this () { return subcircuits_from_pinrefs (m_sp); } - virtual std::pair pins () + virtual std::pair pins_of_this () { return m_pp; } @@ -1102,6 +1082,7 @@ public: private: IndexedNetlistModel::net_subcircuit_pin_pair m_sp; IndexedNetlistModel::pin_pair m_pp; + bool m_subcircuit_seen; }; // ---------------------------------------------------------------------------------- @@ -1124,9 +1105,9 @@ public: return m_pp; } - virtual std::pair pins () + virtual std::pair pins_of_this () { - return std::pair (pins_from_netrefs (m_pp)); + return pins_from_pinrefs (m_pp); } private: @@ -1149,7 +1130,7 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - virtual std::pair pins () + virtual std::pair pins_of_this () { return pins_from_pinrefs (m_pp); } @@ -1178,13 +1159,14 @@ public: return m_sp; } - virtual std::pair subcircuits () + CircuitItemData *circuit_item () { - return m_sp; + return mp_circuit_node; } private: IndexedNetlistModel::subcircuit_pair m_sp; + CircuitItemData *mp_circuit_node; }; // ---------------------------------------------------------------------------------- @@ -1207,7 +1189,7 @@ public: return subcircuits_from_pinrefs (m_pp); } - virtual std::pair pins () + virtual std::pair pins_of_this () { return pins_from_netrefs (m_pp); } @@ -1236,7 +1218,7 @@ public: return m_dp; } - virtual std::pair devices () + virtual std::pair devices_of_this () { return m_dp; } @@ -1323,28 +1305,120 @@ NetlistModelItemData::child (size_t n) return (n < m_children_per_index.size () ? m_children_per_index [n] : 0); } +std::pair +NetlistModelItemData::circuits_of_this () +{ + return std::pair (0, 0); +} + std::pair NetlistModelItemData::circuits () { - return mp_parent ? mp_parent->circuits () : std::pair (0, 0); + std::pair r = circuits_of_this (); + if (! mp_parent || r.first || r.second) { + return r; + } else { + return mp_parent->circuits (); + } +} + +bool +NetlistModelItemData::derived_from_circuits (const std::pair &sp) +{ + if (circuits_of_this () == sp) { + return true; + } else if (mp_parent) { + return mp_parent->derived_from_circuits (sp); + } else { + return false; + } +} + +std::pair +NetlistModelItemData::devices_of_this () +{ + return std::pair (0, 0); } std::pair NetlistModelItemData::devices () { - return mp_parent ? mp_parent->devices () : std::pair (0, 0); + std::pair r = devices_of_this (); + if (! mp_parent || r.first || r.second) { + return r; + } else { + return mp_parent->devices (); + } +} + +bool +NetlistModelItemData::derived_from_devices (const std::pair &sp) +{ + if (devices_of_this () == sp) { + return true; + } else if (mp_parent) { + return mp_parent->derived_from_devices (sp); + } else { + return false; + } +} + +std::pair +NetlistModelItemData::pins_of_this () +{ + return std::pair (0, 0); } std::pair NetlistModelItemData::pins () { - return mp_parent ? mp_parent->pins () : std::pair (0, 0); + std::pair r = pins_of_this (); + if (! mp_parent || r.first || r.second) { + return r; + } else { + return mp_parent->pins (); + } +} + +bool +NetlistModelItemData::derived_from_pins (const std::pair &sp) +{ + if (pins_of_this () == sp) { + return true; + } else if (mp_parent) { + return mp_parent->derived_from_pins (sp); + } else { + return false; + } +} + +std::pair +NetlistModelItemData::subcircuits_of_this () +{ + return std::pair (0, 0); } std::pair NetlistModelItemData::subcircuits () { - return mp_parent ? mp_parent->subcircuits () : std::pair (0, 0); + std::pair r = subcircuits_of_this (); + if (! mp_parent || r.first || r.second) { + return r; + } else { + return mp_parent->subcircuits (); + } +} + +bool +NetlistModelItemData::derived_from_subcircuits (const std::pair &sp) +{ + if (subcircuits_of_this () == sp) { + return true; + } else if (mp_parent) { + return mp_parent->derived_from_subcircuits (sp); + } else { + return false; + } } std::pair @@ -1425,6 +1499,10 @@ RootItemData::status (NetlistBrowserModel * /*model*/) CircuitItemData * RootItemData::circuit_item (NetlistBrowserModel *model, const IndexedNetlistModel::circuit_pair &cp) { + if (! cp.first && ! cp.second) { + return 0; + } + size_t index = model->indexer ()->circuit_index (cp); ensure_children (model); return dynamic_cast (child (index)); @@ -1432,8 +1510,8 @@ RootItemData::circuit_item (NetlistBrowserModel *model, const IndexedNetlistMode // ---------------------------------------------------------------------------------- -CircuitItemData::CircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::circuit_pair &cp) - : NetlistModelItemData (parent), m_cp (cp) +CircuitItemData::CircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::circuit_pair &cp, const IndexedNetlistModel::subcircuit_pair &sp) + : NetlistModelItemData (parent), m_cp (cp), m_sp (sp) { } void @@ -1497,6 +1575,8 @@ CircuitItemData::status (NetlistBrowserModel *model) CircuitNetItemData * CircuitItemData::circuit_net_item (NetlistBrowserModel *model, const IndexedNetlistModel::net_pair &np) { + ensure_children (model); + for (size_t i = 0; i < child_count (); ++i) { CircuitNetItemData *d = static_cast (child (i))->circuit_net_item (model, np); if (d) { @@ -1509,6 +1589,8 @@ CircuitItemData::circuit_net_item (NetlistBrowserModel *model, const IndexedNetl CircuitDeviceItemData * CircuitItemData::circuit_device_item (NetlistBrowserModel *model, const IndexedNetlistModel::device_pair &dp) { + ensure_children (model); + for (size_t i = 0; i < child_count (); ++i) { CircuitDeviceItemData *d = static_cast (child (i))->circuit_device_item (model, dp); if (d) { @@ -1521,6 +1603,8 @@ CircuitItemData::circuit_device_item (NetlistBrowserModel *model, const IndexedN CircuitSubCircuitItemData * CircuitItemData::circuit_subcircuit_item (NetlistBrowserModel *model, const IndexedNetlistModel::subcircuit_pair &sp) { + ensure_children (model); + for (size_t i = 0; i < child_count (); ++i) { CircuitSubCircuitItemData *d = static_cast (child (i))->circuit_subcircuit_item (model, sp); if (d) { @@ -1626,6 +1710,12 @@ CircuitItemNodeData::status (NetlistBrowserModel * /*model*/) CircuitNetItemData * CircuitItemNodeData::circuit_net_item (NetlistBrowserModel *model, const IndexedNetlistModel::net_pair &np) { + if (! np.first && ! np.second) { + return 0; + } + + ensure_children (model); + if (m_type == Nets) { ensure_children (model); size_t index = model->indexer ()->net_index (np); @@ -1638,6 +1728,12 @@ CircuitItemNodeData::circuit_net_item (NetlistBrowserModel *model, const Indexed CircuitDeviceItemData * CircuitItemNodeData::circuit_device_item (NetlistBrowserModel *model, const IndexedNetlistModel::device_pair &dp) { + if (! dp.first && ! dp.second) { + return 0; + } + + ensure_children (model); + if (m_type == Devices) { ensure_children (model); size_t index = model->indexer ()->device_index (dp); @@ -1650,6 +1746,12 @@ CircuitItemNodeData::circuit_device_item (NetlistBrowserModel *model, const Inde CircuitSubCircuitItemData * CircuitItemNodeData::circuit_subcircuit_item (NetlistBrowserModel *model, const IndexedNetlistModel::subcircuit_pair &sp) { + if (! sp.first && ! sp.second) { + return 0; + } + + ensure_children (model); + if (m_type == SubCircuits) { ensure_children (model); size_t index = model->indexer ()->subcircuit_index (sp); @@ -1662,13 +1764,16 @@ CircuitItemNodeData::circuit_subcircuit_item (NetlistBrowserModel *model, const // ---------------------------------------------------------------------------------- CircuitPinItemData::CircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp) - : NetlistModelItemData (parent), m_pp (pp) -{ } + : NetlistModelItemData (parent), m_pp (pp), m_pin_seen (parent && parent->derived_from_pins (pp)) +{ +} void CircuitPinItemData::do_ensure_children (NetlistBrowserModel * /*model*/) { - push_back (new CircuitPinNetItemData (this, nets_from_circuit_pins (circuits (), pp ()))); + if (! m_pin_seen) { + push_back (new CircuitNetItemData (this, nets_from_circuit_pins (circuits (), pp ()))); + } } QIcon @@ -1684,7 +1789,11 @@ CircuitPinItemData::text (int column, NetlistBrowserModel *model) // + single mode: xname | | // + dual mode: xname(a)/xname(b) | xname(a) | xname(b) if (column == model->object_column ()) { - return escaped (str_from_expanded_names (pp (), model->indexer ()->is_single ())); + std::string suffix; + if (m_pin_seen) { + suffix = tl::to_string (tr (" (already seen)")); + } + return escaped (str_from_expanded_names (pp (), model->indexer ()->is_single ()) + suffix); } else if (!model->indexer ()->is_single () && (column == model->first_column () || column == model->second_column ())) { return escaped (str_from_expanded_name (column == model->first_column () ? pp ().first : pp ().second)); } @@ -1714,6 +1823,7 @@ CircuitPinItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- +// @@@ remove? CircuitPinNetItemData::CircuitPinNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np) : NetlistModelItemData (parent), m_np (np) { } @@ -1832,12 +1942,16 @@ CircuitNetItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- CircuitNetDeviceTerminalItemData::CircuitNetDeviceTerminalItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_terminal_pair &tp) - : NetlistModelItemData (parent), m_tp (tp) + : NetlistModelItemData (parent), m_tp (tp), m_device_seen (parent && parent->derived_from_devices (dp ())) { } void CircuitNetDeviceTerminalItemData::do_ensure_children (NetlistBrowserModel *model) { + if (m_device_seen) { + return; + } + size_t n = std::max (rows_for (m_tp.first), rows_for (m_tp.second)); for (size_t i = 0; i < n; ++i) { std::pair device_classes = device_classes_from_devices (dp ()); @@ -1862,10 +1976,15 @@ CircuitNetDeviceTerminalItemData::text (int column, NetlistBrowserModel *model) std::pair termdefs = terminal_defs_from_terminal_refs (m_tp); + std::string suffix; + if (m_device_seen) { + suffix = tl::to_string (tr (" (already seen)")); + } + if (model->indexer ()->is_single ()) { - return escaped (str_from_name (termdefs.first) + field_sep + device_string (dp ().first)); + return escaped (str_from_name (termdefs.first) + field_sep + device_string (dp ().first) + suffix); } else { - return escaped (str_from_names (termdefs, model->indexer ()->is_single ()) + field_sep + devices_string (dp (), model->indexer ()->is_single (), true /*with parameters*/)); + return escaped (str_from_names (termdefs, model->indexer ()->is_single ()) + field_sep + devices_string (dp (), model->indexer ()->is_single (), true /*with parameters*/) + suffix); } } else if (column == model->first_column () || column == model->second_column ()) { @@ -1963,20 +2082,27 @@ CircuitNetDeviceTerminalOthersItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- CircuitNetSubCircuitPinItemData::CircuitNetSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &sp) - : NetlistModelItemData (parent), m_sp (sp) + : NetlistModelItemData (parent), m_sp (sp), m_subcircuit_seen (parent && parent->derived_from_subcircuits (subcircuits ())) { } void CircuitNetSubCircuitPinItemData::do_ensure_children (NetlistBrowserModel *model) { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - - size_t n = model->indexer ()->subcircuit_pin_count (subcircuits); - for (size_t i = 0; i < n; ++i) { - IndexedNetlistModel::net_subcircuit_pin_pair pp = model->indexer ()->subcircuit_pinref_from_index (subcircuits, i); - bool is_seen = derived_from_nets (nets_from_pinrefs (pp)); - push_back (new CircuitNetSubCircuitPinOthersItemData (this, pp, is_seen)); + if (m_subcircuit_seen) { + return; } + + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + IndexedNetlistModel::circuit_pair circuits = circuit_refs_from_subcircuits (subcircuits); + IndexedNetlistModel::pin_pair pins = pins_from_pinrefs (m_sp); + IndexedNetlistModel::net_pair nets = nets_from_circuit_pins (circuits, pins); + + // Because of pin ambiguities the net identity might need to be fixed + if (nets.first) { + nets.second = model->indexer ()->second_net_for (nets.first); + } + + push_back (new CircuitNetItemData (this, nets)); } QIcon @@ -1993,7 +2119,14 @@ CircuitNetSubCircuitPinItemData::text (int column, NetlistBrowserModel *model) IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); if (column == model->object_column ()) { - return model->make_link_to (pp (), circuit_refs) + tl::to_qstring (field_sep) + model->make_link_to (circuit_refs); + + QString suffix; + if (m_subcircuit_seen) { + suffix = tr (" (already seen)"); + } + + return model->make_link_to (pp (), circuit_refs) + tl::to_qstring (field_sep) + model->make_link_to (circuit_refs) + suffix; + } else if (column == model->first_column () || column == model->second_column ()) { return model->make_link_to (subcircuits, column); } @@ -2147,7 +2280,7 @@ CircuitNetPinItemData::status (NetlistBrowserModel * /*model*/) // ---------------------------------------------------------------------------------- CircuitSubCircuitItemData::CircuitSubCircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp) - : NetlistModelItemData (parent), m_sp (sp) + : NetlistModelItemData (parent), m_sp (sp), mp_circuit_node (0) { } void @@ -2158,12 +2291,16 @@ CircuitSubCircuitItemData::do_ensure_children (NetlistBrowserModel *model) IndexedNetlistModel::net_subcircuit_pin_pair pp = model->indexer ()->subcircuit_pinref_from_index (sp (), i); push_back (new CircuitSubCircuitPinItemData (this, pp)); } + + // plus one item for the circuit reference + mp_circuit_node = new CircuitItemData (this, circuit_refs_from_subcircuits (m_sp), m_sp); + push_back (mp_circuit_node); } QIcon CircuitSubCircuitItemData::icon (NetlistBrowserModel * /*model*/) { - return icon_for_circuit (); + return icon_for_subcircuit (); } QString @@ -2493,8 +2630,71 @@ NetlistBrowserModel::data (const QModelIndex &index, int role) const return QVariant (); } +NetlistObjectPath +NetlistBrowserModel::netpath_from_index (const QModelIndex &index) const +{ + NetlistObjectPath np; + np.net = net_from_index (index, false); + np.device = device_from_index (index, false); + + QModelIndex i = index; + while (i.isValid ()) { + + IndexedNetlistModel::subcircuit_pair sp = subcircuit_from_index (i, false); + if (sp.first || sp.second) { + np.path.push_front (sp); + } else { + IndexedNetlistModel::circuit_pair cp = circuit_from_index (i, false); + if (cp.first || cp.second) { + np.root = cp; + } + } + + i = parent (i); + + } + + return np; +} + QModelIndex -NetlistBrowserModel::index_from_url (const QString &a) +NetlistBrowserModel::index_from_netpath (const NetlistObjectPath &path) +{ + QModelIndex index = index_from_circuit (path.root); + + CircuitItemData *node = dynamic_cast ((NetlistModelItemData *) (index.internalPointer ())); + + for (std::list >::const_iterator p = path.path.begin (); p != path.path.end () && node; ++p) { + CircuitSubCircuitItemData *sc_node = node->circuit_subcircuit_item (this, *p); + if (sc_node) { + sc_node->ensure_children (this); + node = sc_node->circuit_item (); + } else { + node = 0; + } + } + + CircuitNetItemData *net_node = 0; + CircuitDeviceItemData *device_node = 0; + + if (node) { + net_node = node->circuit_net_item (const_cast (this), path.net); + device_node = node->circuit_device_item (const_cast (this), path.device); + } + + if (net_node) { + return createIndex (int (net_node->index ()), 0, (void *) net_node); + } else if (device_node) { + return createIndex (int (device_node->index ()), 0, (void *) device_node); + } else if (node) { + return createIndex (int (node->index ()), 0, (void *) node); + } else { + return QModelIndex (); + } +} + +QModelIndex +NetlistBrowserModel::index_from_url (const QString &a) const { QUrl url (a); @@ -2633,12 +2833,12 @@ NetlistBrowserModel::make_link_to (const std::pair &subcircuits, int column) const { - QModelIndex idx; - if ((! subcircuits.first || column == m_second_column) && (! subcircuits.second || column == m_first_column)) { return QString (); } else { + QModelIndex idx = index_from_subcircuit (subcircuits); + if (mp_indexer->is_single () || column == m_first_column) { return build_url (idx, str_from_expanded_name (subcircuits.first)); } else if (column == m_second_column) { @@ -2862,6 +3062,21 @@ NetlistBrowserModel::index_from_circuit (const std::pair &subcircuits) const +{ + IndexedNetlistModel::circuit_pair circuits (subcircuits.first ? subcircuits.first->circuit () : 0, subcircuits.second ? subcircuits.second->circuit () : 0); + CircuitItemData *ci = root ()->circuit_item (const_cast (this), circuits); + if (ci) { + CircuitSubCircuitItemData *si = ci->circuit_subcircuit_item (const_cast (this), subcircuits); + if (si) { + return createIndex (int (si->index ()), 0, (void *) si); + } + } + + return QModelIndex (); +} + QModelIndex NetlistBrowserModel::index_from_circuit (const db::Circuit *net) const { @@ -2869,46 +3084,46 @@ NetlistBrowserModel::index_from_circuit (const db::Circuit *net) const } std::pair -NetlistBrowserModel::circuit_from_index (const QModelIndex &index) const +NetlistBrowserModel::circuit_from_index (const QModelIndex &index, bool include_parents) const { NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); if (! d) { return std::pair (0, 0); } else { - return d->circuits (); + return include_parents ? d->circuits () : d->circuits_of_this (); } } std::pair -NetlistBrowserModel::net_from_index (const QModelIndex &index) const +NetlistBrowserModel::net_from_index (const QModelIndex &index, bool include_parents) const { NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); if (! d) { return std::pair (0, 0); } else { - return d->nets (); + return include_parents ? d->nets () : d->nets_of_this (); } } std::pair -NetlistBrowserModel::device_from_index (const QModelIndex &index) const +NetlistBrowserModel::device_from_index (const QModelIndex &index, bool include_parents) const { NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); if (! d) { return std::pair (0, 0); } else { - return d->devices (); + return include_parents ? d->devices () : d->devices_of_this (); } } std::pair -NetlistBrowserModel::subcircuit_from_index (const QModelIndex &index) const +NetlistBrowserModel::subcircuit_from_index (const QModelIndex &index, bool include_parents) const { NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); if (! d) { return std::pair (0, 0); } else { - return d->subcircuits (); + return include_parents ? d->subcircuits () : d->subcircuits_of_this (); } } diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.h b/src/laybasic/laybasic/layNetlistBrowserModel.h index aa8e591d0..16496e471 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.h +++ b/src/laybasic/laybasic/layNetlistBrowserModel.h @@ -146,12 +146,23 @@ public: NetlistModelItemData *child (size_t n); - virtual std::pair circuits (); - virtual std::pair devices (); - virtual std::pair pins (); - virtual std::pair subcircuits (); - virtual std::pair nets_of_this (); + virtual std::pair circuits_of_this (); + std::pair circuits (); + bool derived_from_circuits (const std::pair &sp); + virtual std::pair devices_of_this (); + std::pair devices (); + bool derived_from_devices (const std::pair &sp); + + virtual std::pair pins_of_this (); + std::pair pins (); + bool derived_from_pins (const std::pair &sp); + + virtual std::pair subcircuits_of_this (); + std::pair subcircuits (); + bool derived_from_subcircuits (const std::pair &sp); + + virtual std::pair nets_of_this (); std::pair nets (); bool derived_from_nets (const std::pair &np); @@ -167,6 +178,29 @@ private: virtual void do_ensure_children (NetlistBrowserModel *model) = 0; }; +/** + * @brief An object describing the instantiation path of a net + */ +struct LAYBASIC_PUBLIC NetlistObjectPath +{ + NetlistObjectPath () { } + + bool operator== (const NetlistObjectPath &other) const + { + return root == other.root && path == other.path && net == other.net && device == other.device; + } + + bool operator!= (const NetlistObjectPath &other) const + { + return ! operator== (other); + } + + std::pair root; + std::list > path; + std::pair net; + std::pair device; +}; + /** * @brief The NetlistBrowserModel * @@ -229,16 +263,17 @@ public: return mp_indexer.get (); } - std::pair net_from_index (const QModelIndex &index) const; + std::pair net_from_index (const QModelIndex &index, bool include_parents = true) const; QModelIndex index_from_net (const std::pair &net) const; QModelIndex index_from_net (const db::Net *net) const; - std::pair circuit_from_index (const QModelIndex &index) const; + std::pair circuit_from_index (const QModelIndex &index, bool include_parents = true) const; QModelIndex index_from_circuit (const std::pair &circuit) const; QModelIndex index_from_circuit (const db::Circuit *circuit) const; + QModelIndex index_from_subcircuit (const std::pair &subcircuits) const; - std::pair subcircuit_from_index (const QModelIndex &index) const; + std::pair subcircuit_from_index (const QModelIndex &index, bool include_parents = true) const; - std::pair device_from_index (const QModelIndex &index) const; + std::pair device_from_index (const QModelIndex &index, bool include_parents = true) const; void set_item_visibility (QTreeView *view, bool show_all, bool with_warnings); @@ -253,7 +288,9 @@ public: QIcon icon_for_nets (const std::pair &net) const; QIcon icon_for_connection (const std::pair &net) const; - QModelIndex index_from_url (const QString &url); + QModelIndex index_from_url (const QString &url) const; + NetlistObjectPath netpath_from_index (const QModelIndex &index) const; + QModelIndex index_from_netpath (const NetlistObjectPath &path); private slots: void colors_changed (); diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index 1146e3827..d0cb92b98 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -69,7 +69,7 @@ inline const db::Circuit *deref_circuit (const db::Circuit *obj) } template -static db::ICplxTrans +static db::DCplxTrans trans_for (const Obj *objs, const db::Layout &ly, const db::Cell &cell, db::ContextCache &cc, const db::DCplxTrans &initial = db::DCplxTrans ()) { db::DCplxTrans t = initial; @@ -89,7 +89,6 @@ trans_for (const Obj *objs, const db::Layout &ly, const db::Cell &cell, db::Cont } db::CplxTrans dbu_trans (ly.dbu ()); - db::ICplxTrans it = dbu_trans.inverted () * t * dbu_trans; // The circuit may not be instantiated and still not be the top cell. // This happens if the subcell does not have connections. In this case @@ -98,11 +97,11 @@ trans_for (const Obj *objs, const db::Layout &ly, const db::Cell &cell, db::Cont if (circuit && ly.is_valid_cell_index (circuit->cell_index ())) { std::pair tc = cc.find_layout_context (circuit->cell_index (), cell.cell_index ()); if (tc.first) { - it = tc.second * it; + t = dbu_trans * tc.second * dbu_trans.inverted () * t; } } - return it; + return t; } NetlistBrowserPage::NetlistBrowserPage (QWidget * /*parent*/) @@ -456,18 +455,11 @@ NetlistBrowserPage::selected_devices () void NetlistBrowserPage::selection_changed () { - std::vector nets = selected_nets (); - if (mp_info_dialog) { - mp_info_dialog->set_nets (mp_database.get (), nets); - } + NetlistBrowserModel *model = dynamic_cast (directory_tree->model ()); + tl_assert (model != 0); - std::vector devices = selected_devices (); - - std::vector subcircuits = selected_subcircuits (); - - std::vector circuits = selected_circuits (); - - highlight (nets, devices, subcircuits, circuits); + QModelIndex current = directory_tree->selectionModel ()->currentIndex (); + highlight (model->netpath_from_index (current)); } void @@ -882,21 +874,15 @@ NetlistBrowserPage::setup_trees () } void -NetlistBrowserPage::highlight (const std::vector &nets, const std::vector &devices, const std::vector &subcircuits, const std::vector &circuits) +NetlistBrowserPage::highlight (const NetlistObjectPath &path) { - if (nets != m_current_nets || devices != m_current_devices || subcircuits != m_current_subcircuits || circuits != m_current_circuits) { + if (path != m_current_path) { - m_current_nets = nets; - m_current_devices = devices; - m_current_subcircuits = subcircuits; - m_current_circuits = circuits; + m_current_path = path; clear_markers (); - - if (! nets.empty () || ! devices.empty () || ! subcircuits.empty () || ! circuits.empty ()) { - adjust_view (); - update_highlights (); - } + adjust_view (); + update_highlights (); selection_changed (); @@ -926,7 +912,8 @@ bbox_for_device_abstract (const db::Layout *layout, const db::DeviceAbstract *de return db::Box (); } - return layout->cell (device_abstract->cell_index ()).bbox ().transformed (db::CplxTrans (layout->dbu ()).inverted () * trans * db::CplxTrans (layout->dbu ()));} + return layout->cell (device_abstract->cell_index ()).bbox ().transformed (db::CplxTrans (layout->dbu ()).inverted () * trans * db::CplxTrans (layout->dbu ())); +} static db::Box bbox_for_circuit (const db::Layout *layout, const db::Circuit *circuit) @@ -943,12 +930,6 @@ bbox_for_circuit (const db::Layout *layout, const db::Circuit *circuit) return layout->cell (circuit->cell_index ()).bbox (); } -static db::Box -bbox_for_subcircuit (const db::Layout *layout, const db::SubCircuit *subcircuit) -{ - return bbox_for_circuit (layout, subcircuit->circuit_ref ()); -} - void NetlistBrowserPage::adjust_view () { @@ -971,51 +952,67 @@ NetlistBrowserPage::adjust_view () return; } + const db::Circuit *circuit = m_current_path.root.first; + db::DCplxTrans trans; - db::Box bbox; + if (circuit) { - for (std::vector::const_iterator net = m_current_nets.begin (); net != m_current_nets.end (); ++net) { + trans = trans_for (circuit, *layout, *cell, m_cell_context_cache, db::DCplxTrans ()); - db::ICplxTrans net_trans = trans_for (*net, *layout, *cell, m_cell_context_cache); + for (std::list >::const_iterator p = m_current_path.path.begin (); p != m_current_path.path.end () && circuit; ++p) { + if (p->first) { + circuit = p->first->circuit_ref (); + trans = trans * p->first->trans (); + } else { + circuit = 0; + } + } - db::cell_index_type cell_index = (*net)->circuit ()->cell_index (); - size_t cluster_id = (*net)->cluster_id (); + } - const db::Connectivity &conn = mp_database->connectivity (); - for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) { + db::DBox bbox; - db::Box layer_bbox; - db::recursive_cluster_shape_iterator shapes (mp_database->net_clusters (), *layer, cell_index, cluster_id); - while (! shapes.at_end ()) { - layer_bbox += shapes->bbox (); - ++shapes; + if (circuit) { + + db::Box ebox; + + const db::Device *device = m_current_path.device.first; + const db::Net *net = m_current_path.net.first; + + if (device) { + + ebox += bbox_for_device_abstract (layout, device->device_abstract (), db::DCplxTrans ()); + + const std::vector &oda = device->other_abstracts (); + for (std::vector::const_iterator a = oda.begin (); a != oda.end (); ++a) { + ebox += bbox_for_device_abstract (layout, a->device_abstract, a->trans); } - bbox += net_trans * layer_bbox; + } else if (net) { + db::cell_index_type cell_index = net->circuit ()->cell_index (); + size_t cluster_id = net->cluster_id (); + + const db::Connectivity &conn = mp_database->connectivity (); + for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) { + + db::Box layer_bbox; + db::recursive_cluster_shape_iterator shapes (mp_database->net_clusters (), *layer, cell_index, cluster_id); + while (! shapes.at_end ()) { + layer_bbox += shapes->bbox (); + ++shapes; + } + + ebox += layer_bbox; + + } + + } else if (circuit) { + ebox += bbox_for_circuit (layout, circuit); } - } + bbox = trans * db::CplxTrans (layout->dbu ()) * ebox; - for (std::vector::const_iterator device = m_current_devices.begin (); device != m_current_devices.end (); ++device) { - - db::ICplxTrans trans = trans_for (*device, *layout, *cell, m_cell_context_cache, (*device)->trans ()); - - bbox += trans * bbox_for_device_abstract (layout, (*device)->device_abstract (), db::DCplxTrans ()); - - const std::vector &oda = (*device)->other_abstracts (); - for (std::vector::const_iterator a = oda.begin (); a != oda.end (); ++a) { - bbox += trans * bbox_for_device_abstract (layout, a->device_abstract, a->trans); - } - - } - - for (std::vector::const_iterator subcircuit = m_current_subcircuits.begin (); subcircuit != m_current_subcircuits.end (); ++subcircuit) { - bbox += trans_for (*subcircuit, *layout, *cell, m_cell_context_cache, (*subcircuit)->trans ()) * bbox_for_subcircuit (layout, *subcircuit); - } - - for (std::vector::const_iterator circuit = m_current_circuits.begin (); circuit != m_current_circuits.end (); ++circuit) { - bbox += trans_for (*circuit, *layout, *cell, m_cell_context_cache, db::DCplxTrans ()) * bbox_for_circuit (layout, *circuit); } if (! bbox.empty ()) { @@ -1023,9 +1020,8 @@ NetlistBrowserPage::adjust_view () std::vector tv = mp_view->cv_transform_variants (m_cv_index); db::DBox tv_bbox; - db::DBox dbu_bbox = db::CplxTrans (layout->dbu ()) * bbox; for (std::vector::const_iterator t = tv.begin (); t != tv.end (); ++t) { - tv_bbox += *t * dbu_bbox; + tv_bbox += *t * bbox; } if (m_window == lay::NetlistBrowserConfig::FitNet) { @@ -1063,12 +1059,10 @@ bool NetlistBrowserPage::produce_highlights_for_device (const db::Device *device, size_t &n_markers, const std::vector &tv) { const db::Layout *layout = mp_database->internal_layout (); - const db::Cell *cell = mp_database->internal_top_cell (); - db::ICplxTrans device_trans = trans_for (device, *layout, *cell, m_cell_context_cache, device->trans ()); QColor color = make_valid_color (m_colorizer.marker_color ()); - db::Box device_bbox = bbox_for_device_abstract (layout, device->device_abstract (), db::DCplxTrans ()); + db::Box device_bbox = bbox_for_device_abstract (layout, device->device_abstract (), device->trans ()); if (! device_bbox.empty ()) { if (n_markers == m_max_shape_count) { @@ -1078,7 +1072,7 @@ NetlistBrowserPage::produce_highlights_for_device (const db::Device *device, siz ++n_markers; mp_markers.push_back (new lay::Marker (mp_view, m_cv_index)); - mp_markers.back ()->set (device_bbox, device_trans, tv); + mp_markers.back ()->set (device_bbox, db::ICplxTrans (), tv); mp_markers.back ()->set_color (color); mp_markers.back ()->set_frame_color (color); configure_marker (mp_markers.back (), false); @@ -1088,7 +1082,7 @@ NetlistBrowserPage::produce_highlights_for_device (const db::Device *device, siz const std::vector &oda = device->other_abstracts (); for (std::vector::const_iterator a = oda.begin (); a != oda.end (); ++a) { - db::Box da_box = bbox_for_device_abstract (layout, a->device_abstract, a->trans); + db::Box da_box = bbox_for_device_abstract (layout, a->device_abstract, device->trans () * a->trans); if (! da_box.empty ()) { if (n_markers == m_max_shape_count) { @@ -1098,7 +1092,7 @@ NetlistBrowserPage::produce_highlights_for_device (const db::Device *device, siz ++n_markers; mp_markers.push_back (new lay::Marker (mp_view, m_cv_index)); - mp_markers.back ()->set (da_box, device_trans, tv); + mp_markers.back ()->set (da_box, db::ICplxTrans (), tv); mp_markers.back ()->set_color (color); mp_markers.back ()->set_frame_color (color); configure_marker (mp_markers.back (), false); @@ -1110,40 +1104,10 @@ NetlistBrowserPage::produce_highlights_for_device (const db::Device *device, siz return false; } -bool -NetlistBrowserPage::produce_highlights_for_subcircuit (const db::SubCircuit *subcircuit, size_t &n_markers, const std::vector &tv) -{ - const db::Layout *layout = mp_database->internal_layout (); - const db::Cell *cell = mp_database->internal_top_cell (); - db::ICplxTrans subcircuit_trans = trans_for (subcircuit, *layout, *cell, m_cell_context_cache, subcircuit->trans ()); - - QColor color = make_valid_color (m_colorizer.marker_color ()); - db::Box circuit_bbox = bbox_for_subcircuit (layout, subcircuit); - if (circuit_bbox.empty ()) { - return false; - } - - if (n_markers == m_max_shape_count) { - return true; - } - - ++n_markers; - - mp_markers.push_back (new lay::Marker (mp_view, m_cv_index)); - mp_markers.back ()->set (circuit_bbox, subcircuit_trans, tv); - mp_markers.back ()->set_color (color); - mp_markers.back ()->set_frame_color (color); - configure_marker (mp_markers.back (), false); - - return false; -} - bool NetlistBrowserPage::produce_highlights_for_circuit (const db::Circuit *circuit, size_t &n_markers, const std::vector &tv) { const db::Layout *layout = mp_database->internal_layout (); - const db::Cell *cell = mp_database->internal_top_cell (); - db::ICplxTrans circuit_trans = trans_for (circuit, *layout, *cell, m_cell_context_cache, db::DCplxTrans ()); QColor color = make_valid_color (m_colorizer.marker_color ()); db::Box circuit_bbox = bbox_for_circuit (layout, circuit); @@ -1158,7 +1122,7 @@ NetlistBrowserPage::produce_highlights_for_circuit (const db::Circuit *circuit, ++n_markers; mp_markers.push_back (new lay::Marker (mp_view, m_cv_index)); - mp_markers.back ()->set (circuit_bbox, circuit_trans, tv); + mp_markers.back ()->set (circuit_bbox, db::ICplxTrans (), tv); mp_markers.back ()->set_color (color); mp_markers.back ()->set_frame_color (color); configure_marker (mp_markers.back (), false); @@ -1170,8 +1134,6 @@ bool NetlistBrowserPage::produce_highlights_for_net (const db::Net *net, size_t &n_markers, const std::map &display_by_lp, const std::vector &tv) { const db::Layout *layout = mp_database->internal_layout (); - const db::Cell *cell = mp_database->internal_top_cell (); - db::ICplxTrans net_trans = trans_for (net, *layout, *cell, m_cell_context_cache); db::cell_index_type cell_index = net->circuit ()->cell_index (); size_t cluster_id = net->cluster_id (); @@ -1197,7 +1159,7 @@ NetlistBrowserPage::produce_highlights_for_net (const db::Net *net, size_t &n_ma } mp_markers.push_back (new lay::Marker (mp_view, m_cv_index)); - mp_markers.back ()->set (shapes->polygon_ref (), net_trans * shapes.trans (), tv); + mp_markers.back ()->set (shapes->polygon_ref (), shapes.trans (), tv); if (net_color.isValid ()) { @@ -1272,10 +1234,31 @@ NetlistBrowserPage::update_highlights () const db::Layout &original_layout = mp_view->cellview (m_cv_index)->layout (); const db::Layout *layout = mp_database->internal_layout (); - if (! layout) { + const db::Cell *cell = mp_database->internal_top_cell (); + if (! layout || ! cell) { return; } + // compute the transformation supplied by the path + + const db::Circuit *circuit = m_current_path.root.first; + db::DCplxTrans trans; + + if (circuit) { + + trans = trans_for (circuit, *layout, *cell, m_cell_context_cache, db::DCplxTrans ()); + + for (std::list >::const_iterator p = m_current_path.path.begin (); p != m_current_path.path.end () && circuit; ++p) { + if (p->first) { + circuit = p->first->circuit_ref (); + trans = trans * p->first->trans (); + } else { + circuit = 0; + } + } + + } + // a map of display properties vs. layer properties std::map display_by_lp; @@ -1289,32 +1272,18 @@ NetlistBrowserPage::update_highlights () // correct DBU differences between the storage layout and the original layout for (std::vector::iterator t = tv.begin (); t != tv.end (); ++t) { - *t = *t * db::DCplxTrans (layout->dbu () / original_layout.dbu ()); + *t = *t * trans * db::DCplxTrans (layout->dbu () / original_layout.dbu ()); } size_t n_markers = 0; bool not_all_shapes_are_shown = false; - for (std::vector::const_iterator net = m_current_nets.begin (); net != m_current_nets.end () && ! not_all_shapes_are_shown; ++net) { - if ((*net)->circuit ()) { - not_all_shapes_are_shown = produce_highlights_for_net (*net, n_markers, display_by_lp, tv); - } - } - - for (std::vector::const_iterator device = m_current_devices.begin (); device != m_current_devices.end () && ! not_all_shapes_are_shown; ++device) { - if ((*device)->circuit ()) { - not_all_shapes_are_shown = produce_highlights_for_device (*device, n_markers, tv); - } - } - - for (std::vector::const_iterator subcircuit = m_current_subcircuits.begin (); subcircuit != m_current_subcircuits.end () && ! not_all_shapes_are_shown; ++subcircuit) { - if ((*subcircuit)->circuit ()) { - not_all_shapes_are_shown = produce_highlights_for_subcircuit (*subcircuit, n_markers, tv); - } - } - - for (std::vector::const_iterator circuit = m_current_circuits.begin (); circuit != m_current_circuits.end () && ! not_all_shapes_are_shown; ++circuit) { - not_all_shapes_are_shown = produce_highlights_for_circuit (*circuit, n_markers, tv); + if (m_current_path.net.first) { + not_all_shapes_are_shown = produce_highlights_for_net (m_current_path.net.first, n_markers, display_by_lp, tv); + } else if (m_current_path.device.first) { + not_all_shapes_are_shown = produce_highlights_for_device (m_current_path.device.first, n_markers, tv); + } else if (circuit) { + not_all_shapes_are_shown = produce_highlights_for_circuit (circuit, n_markers, tv); } if (not_all_shapes_are_shown) { diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.h b/src/laybasic/laybasic/layNetlistBrowserPage.h index 6c4ef1d73..37aff1312 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.h +++ b/src/laybasic/laybasic/layNetlistBrowserPage.h @@ -234,6 +234,9 @@ private: std::vector mp_markers; bool m_enable_updates; bool m_update_needed; + // @@@ TODO: make multiple ... + lay::NetlistObjectPath m_current_path; + // @@@ TODO: remove std::vector m_current_nets; std::vector m_current_devices; std::vector m_current_subcircuits; @@ -248,7 +251,7 @@ private: void navigate_to (const QModelIndex &index, bool forward = true); void adjust_view (); void clear_markers (); - void highlight (const std::vector &nets, const std::vector &devices, const std::vector &subcircuits, const std::vector &circuits); + void highlight (const lay::NetlistObjectPath &path); std::vector selected_nets (); std::vector selected_devices (); std::vector selected_subcircuits (); @@ -258,7 +261,6 @@ private: QColor make_valid_color (const QColor &color); bool produce_highlights_for_net(const db::Net *net, size_t &n_markers, const std::map &display_by_lp, const std::vector &tv); bool produce_highlights_for_device (const db::Device *device, size_t &n_markers, const std::vector &tv); - bool produce_highlights_for_subcircuit (const db::SubCircuit *subcircuit, size_t &n_markers, const std::vector &tv); bool produce_highlights_for_circuit (const db::Circuit *circuit, size_t &n_markers, const std::vector &tv); void configure_marker (lay::Marker *marker, bool with_fill); void rerun_macro (); diff --git a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc index 07130eb5d..ad5d94aa4 100644 --- a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc +++ b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc @@ -123,8 +123,8 @@ TEST (1) QModelIndex inv2PinOutIndexNet = model->index (0, 0, inv2PinOutIndex); EXPECT_EQ (model->parent (inv2PinOutIndexNet) == inv2PinOutIndex, true); - EXPECT_EQ (model->hasChildren (inv2PinOutIndexNet), false); - EXPECT_EQ (model->rowCount (inv2PinOutIndexNet), 0); + EXPECT_EQ (model->hasChildren (inv2PinOutIndexNet), true); + EXPECT_EQ (model->rowCount (inv2PinOutIndexNet), 3); // NOUT net has 1 pin, 2 devices, 0 subcircuits QModelIndex inv2NOutIndex = model->index (1, 0, model->index (1, 0, inv2Index)); @@ -206,11 +206,12 @@ TEST (1) QModelIndex ringoSubcircuit1Index = model->index (0, 0, sn_subcircuits); EXPECT_EQ (model->parent (ringoSubcircuit1Index) == sn_subcircuits, true); EXPECT_EQ (model->hasChildren (ringoSubcircuit1Index), true); - EXPECT_EQ (model->rowCount (ringoSubcircuit1Index), 5); + EXPECT_EQ (model->rowCount (ringoSubcircuit1Index), 6); EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, ringoSubcircuit1Index), Qt::UserRole).toString ()), "OUT"); EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, ringoSubcircuit1Index), Qt::DisplayRole).toString ()), "OUT"); EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, ringoSubcircuit1Index), Qt::DisplayRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (5, 0, ringoSubcircuit1Index), Qt::DisplayRole).toString ()), "INV2"); QModelIndex ringoSubcircuit1OutPinIndex = model->index (2, 0, ringoSubcircuit1Index); EXPECT_EQ (model->parent (ringoSubcircuit1OutPinIndex) == ringoSubcircuit1Index, true); @@ -287,7 +288,7 @@ TEST (2) // INV2, pin 0 has one net node EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Pin0Index), Qt::UserRole).toString ()), "$1|1"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Pin0Index), Qt::DisplayRole).toString ()), "$1 ⇔ 1"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2Pin0Index), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2Pin0Index), Qt::DisplayRole).toString ()), "$1 (2)"); std::pair nets = model->net_from_index (model->index (0, 0, inv2Pin0Index)); EXPECT_EQ (nets.first != 0, true); if (nets.first != 0) { @@ -297,7 +298,7 @@ TEST (2) if (nets.second != 0) { EXPECT_EQ (nets.second->expanded_name (), "1"); } - EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2Pin0Index), Qt::DisplayRole).toString ()), "1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2Pin0Index), Qt::DisplayRole).toString ()), "1 (2)"); // first of nets in INV2 circuit EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::UserRole).toString ()), "$1|1"); @@ -422,3 +423,59 @@ TEST (2) EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2PairNet0SubCircuit0Index), Qt::DisplayRole).toString ()), "$7"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2PairNet0SubCircuit0Index), Qt::DisplayRole).toString ()), ""); } + +TEST (3) +{ + db::LayoutToNetlist l2n; + l2n.load (tl::testsrc () + "/testdata/lay/l2n_browser.l2n"); + + lay::NetColorizer colorizer; + std::auto_ptr model (new lay::NetlistBrowserModel (0, &l2n, &colorizer)); + + db::Circuit *root = l2n.netlist ()->circuit_by_name ("RINGO"); + EXPECT_EQ (root != 0, true); + + lay::NetlistObjectPath path; + EXPECT_EQ (model->index_from_netpath (path).isValid (), false); + + path.root.first = root; + + db::Net *net = root->net_by_name ("FB"); + EXPECT_EQ (net != 0, true); + + path.net.first = net; + + QModelIndex index = model->index_from_netpath (path); + EXPECT_EQ (index.isValid (), true); + + EXPECT_EQ (tl::to_string (model->data (index, Qt::UserRole).toString ()), "FB"); +} + +TEST (4) +{ + db::LayoutToNetlist l2n; + l2n.load (tl::testsrc () + "/testdata/lay/l2n_browser.l2n"); + + lay::NetColorizer colorizer; + std::auto_ptr model (new lay::NetlistBrowserModel (0, &l2n, &colorizer)); + + db::Circuit *root = l2n.netlist ()->circuit_by_name ("RINGO"); + EXPECT_EQ (root != 0, true); + + lay::NetlistObjectPath path; + path.root.first = root; + + db::SubCircuit *sc1 = root->begin_subcircuits ().operator-> (); + EXPECT_EQ (sc1 != 0, true); + path.path.push_back (std::make_pair (sc1, (db::SubCircuit *) 0)); + + db::Net *net = sc1->circuit_ref ()->net_by_name ("NOUT"); + EXPECT_EQ (net != 0, true); + + path.net.first = net; + + QModelIndex index = model->index_from_netpath (path); + EXPECT_EQ (index.isValid (), true); + + EXPECT_EQ (tl::to_string (model->data (index, Qt::UserRole).toString ()), "NOUT"); +}