From 880b9904cf9b54a2959eb19dd50c53f4a875db90 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 14 Jun 2020 22:04:16 +0200 Subject: [PATCH 01/32] WIP Netlist probing will deliver an instantiation path now. --- src/db/db/dbLayoutToNetlist.cc | 47 +++++++++---- src/db/db/dbLayoutToNetlist.h | 7 +- src/db/db/gsiDeclDbLayoutToNetlist.cc | 11 ++- src/db/db/gsiDeclDbNetlist.cc | 15 +++++ .../gsiDeclLayNetlistBrowserDialog.cc | 67 +++++++++++++++++++ src/laybasic/laybasic/laybasic.pro | 3 +- src/pya/pya/pyaMarshal.cc | 13 ++++ src/rba/rba/rbaMarshal.cc | 2 +- testdata/python/dbLayoutToNetlist.py | 54 +++++++++------ testdata/ruby/dbLayoutToNetlist.rb | 45 ++++++++----- 10 files changed, 208 insertions(+), 56 deletions(-) create mode 100644 src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 9e2d164d5..90d229f1f 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -1041,9 +1041,9 @@ LayoutToNetlist::build_nets (const std::vector *nets, const db: } } -db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point) +db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point, std::vector *sc_path_out) { - return probe_net (of_region, db::CplxTrans (internal_layout ()->dbu ()).inverted () * point); + return probe_net (of_region, db::CplxTrans (internal_layout ()->dbu ()).inverted () * point, sc_path_out); } size_t LayoutToNetlist::search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster &test_cluster, std::vector &rev_inst_path) @@ -1077,7 +1077,7 @@ size_t LayoutToNetlist::search_net (const db::ICplxTrans &trans, const db::Cell return 0; } -db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Point &point) +db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Point &point, std::vector *sc_path_out) { if (! m_netlist_extracted) { throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet"))); @@ -1142,38 +1142,57 @@ db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Poin } + std::vector sc_path; + + db::Net *topmost_net = net; + // follow the path up in the net hierarchy using the transformation and the upper cell index as the // guide line - while (! inst_path.empty () && net->pin_count () > 0) { + while (circuit && ! inst_path.empty ()) { cell_indexes.pop_back (); - const db::Pin *pin = circuit->pin_by_id (net->begin_pins ()->pin_id ()); - tl_assert (pin != 0); + const db::Pin *pin = 0; + if (net && net->pin_count () > 0) { + pin = circuit->pin_by_id (net->begin_pins ()->pin_id ()); + tl_assert (pin != 0); + } db::DCplxTrans dtrans = dbu_trans * inst_path.back ().complex_trans () * dbu_trans_inv; // try to find a parent circuit which connects to this net db::Circuit *upper_circuit = 0; + db::SubCircuit *subcircuit = 0; db::Net *upper_net = 0; - for (db::Circuit::refs_iterator r = circuit->begin_refs (); r != circuit->end_refs () && ! upper_net; ++r) { + for (db::Circuit::refs_iterator r = circuit->begin_refs (); r != circuit->end_refs () && ! upper_circuit; ++r) { if (r->trans ().equal (dtrans) && r->circuit () && r->circuit ()->cell_index () == cell_indexes.back ()) { - upper_net = r->net_for_pin (pin->id ()); - upper_circuit = r->circuit (); + subcircuit = r.operator-> (); + if (pin) { + upper_net = subcircuit->net_for_pin (pin->id ()); + } + upper_circuit = subcircuit->circuit (); } } + net = upper_net; + if (upper_net) { - circuit = upper_circuit; - net = upper_net; - inst_path.pop_back (); + topmost_net = upper_net; } else { - break; + sc_path.push_back (subcircuit); } + circuit = upper_circuit; + inst_path.pop_back (); + } - return net; + if (sc_path_out) { + std::reverse (sc_path.begin (), sc_path.end ()); + *sc_path_out = sc_path; + } + + return topmost_net; } else { return 0; diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index 63bf835aa..8b42b99f2 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -709,8 +709,11 @@ public: * * This variant accepts a micrometer-unit location. The location is given in the * coordinate space of the initial cell. + * + * The subcircuit path leading to the topmost net is stored in *sc_path_out if this + * pointer is non-null. */ - db::Net *probe_net (const db::Region &of_region, const db::DPoint &point); + db::Net *probe_net (const db::Region &of_region, const db::DPoint &point, std::vector *sc_path_out = 0); /** * @brief Finds the net by probing a specific location on the given layer @@ -718,7 +721,7 @@ public: * This variant accepts a database-unit location. The location is given in the * coordinate space of the initial cell. */ - db::Net *probe_net (const db::Region &of_region, const db::Point &point); + db::Net *probe_net (const db::Region &of_region, const db::Point &point, std::vector *sc_path_out = 0); /** * @brief Runs an antenna check on the extracted clusters diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index 1e5cce32d..703699536 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -543,7 +543,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", gsi::method_ext ("build_nets", &build_nets, gsi::arg ("nets"), gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::LayoutToNetlist::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"), "@brief Like \\build_all_nets, but with the ability to select some nets." ) + - gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), + gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &, std::vector *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector *) 0, "nil"), "@brief Finds the net by probing a specific location on the given layer\n" "\n" "This method will find a net looking at the given layer at the specific position.\n" @@ -557,14 +557,21 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "Optimization functions such as \\Netlist#purge will remove parts of the net which means\n" "shape to net probing may no longer work for these nets.\n" "\n" + "If non-null and an array, 'sc_path_out' will receive a list of \\SubCircuits objects which lead to the " + "net from the top circuit of the database.\n" + "\n" "This variant accepts a micrometer-unit location. The location is given in the\n" "coordinate space of the initial cell.\n" + "\n" + "The \\sc_path_out parameter has been added in version 0.27.\n" ) + - gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::Point &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), + gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::Point &, std::vector *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector *) 0, "nil"), "@brief Finds the net by probing a specific location on the given layer\n" "See the description of the other \\probe_net variant.\n" "This variant accepts a database-unit location. The location is given in the\n" "coordinate space of the initial cell.\n" + "\n" + "The \\sc_path_out parameter has been added in version 0.27.\n" ) + gsi::method ("write|write_l2n", &db::LayoutToNetlist::save, gsi::arg ("path"), gsi::arg ("short_format", false), "@brief Writes the extracted netlist to a file.\n" diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index b8b7636c9..77cd998a6 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -466,6 +466,21 @@ Class decl_dbSubCircuit (decl_dbNetlistObject, "db", "SubCircuit gsi::method_ext ("disconnect_pin", &gsi::subcircuit_disconnect_pin1, gsi::arg ("pin"), "@brief Disconnects the given pin from any net.\n" "This version takes a \\Pin reference instead of a pin ID." + ) + + gsi::method ("trans", &db::SubCircuit::trans, + "@brief Gets the physical transformation for the subcircuit.\n" + "\n" + "This property applies to subcircuits derived from a layout. It specifies the " + "placement of the respective cell.\n" + "\n" + "This property has been introduced in version 0.27." + ) + + gsi::method ("trans=", &db::SubCircuit::set_trans, gsi::arg ("trans"), + "@brief Sets the physical transformation for the subcircuit.\n" + "\n" + "See \\trans for details about this property.\n" + "\n" + "This property has been introduced in version 0.27." ), "@brief A subcircuit inside a circuit.\n" "Circuits may instantiate other circuits as subcircuits similar to cells " diff --git a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc new file mode 100644 index 000000000..14346efe4 --- /dev/null +++ b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc @@ -0,0 +1,67 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "gsiDecl.h" +#include "gsiDeclBasic.h" +#include "layNetlistBrowserDialog.h" +#include "layLayoutView.h" + +namespace tl +{ + +// disable copy and default constructor for NetlistBrowserDialog +template <> struct type_traits : public type_traits +{ + typedef tl::false_tag has_copy_constructor; + typedef tl::false_tag has_default_constructor; +}; + +} + +namespace gsi +{ + +Class decl_NetlistBrowserDialog ("lay", "NetlistBrowserDialog", + gsi::Methods (), + "@brief ..." +); + +static lay::NetlistBrowserDialog *netlist_browser (lay::LayoutView *lv) +{ + return lv->get_plugin (); +} + +// extend lay::LayoutView with the getter for the netlist browser +static +gsi::ClassExt decl_ext_layout_view ( + gsi::method_ext ("netlist_browser", &netlist_browser, + "@brief Gets the netlist browser object for the given layout view\n" + "\n" + "\nThis method has been added in version 0.27.\n" + ) +); + + + +} + diff --git a/src/laybasic/laybasic/laybasic.pro b/src/laybasic/laybasic/laybasic.pro index 7a7c8a92e..2e3e2b4c3 100644 --- a/src/laybasic/laybasic/laybasic.pro +++ b/src/laybasic/laybasic/laybasic.pro @@ -183,7 +183,8 @@ SOURCES = \ layGenericSyntaxHighlighter.cc \ layDispatcher.cc \ laySelectCellViewForm.cc \ - layLayoutStatisticsForm.cc + layLayoutStatisticsForm.cc \ + gsiDeclLayNetlistBrowserDialog.cc HEADERS = \ gtf.h \ diff --git a/src/pya/pya/pyaMarshal.cc b/src/pya/pya/pyaMarshal.cc index 029970e34..0cf4736b8 100644 --- a/src/pya/pya/pyaMarshal.cc +++ b/src/pya/pya/pyaMarshal.cc @@ -935,6 +935,12 @@ struct test_arg_func { void operator() (bool *ret, PyObject *arg, const gsi::ArgType &atype, bool loose) { + if ((atype.is_cptr () || atype.is_ptr ()) && arg == Py_None) { + // for ptr or cptr, null is an allowed value + *ret = true; + return; + } + if (! PyTuple_Check (arg) && ! PyList_Check (arg)) { *ret = false; return; @@ -971,6 +977,12 @@ struct test_arg_func { void operator () (bool *ret, PyObject *arg, const gsi::ArgType &atype, bool loose) { + if ((atype.is_cptr () || atype.is_ptr ()) && arg == Py_None) { + // for ptr or cptr, null is an allowed value + *ret = true; + return; + } + if (! PyDict_Check (arg)) { *ret = false; return; @@ -999,6 +1011,7 @@ struct test_arg_func } } }; + template <> struct test_arg_func { diff --git a/src/rba/rba/rbaMarshal.cc b/src/rba/rba/rbaMarshal.cc index 45963e4ac..631e58f63 100644 --- a/src/rba/rba/rbaMarshal.cc +++ b/src/rba/rba/rbaMarshal.cc @@ -956,7 +956,7 @@ struct test_arg_func if ((atype.is_cptr () || atype.is_ptr ()) && arg == Qnil) { // for pointers to vectors, nil is a valid value *ret = true; - } if (TYPE (arg) != T_ARRAY) { + } else if (TYPE (arg) != T_ARRAY) { *ret = false; } else { diff --git a/testdata/python/dbLayoutToNetlist.py b/testdata/python/dbLayoutToNetlist.py index 9532591cb..dc4095f19 100644 --- a/testdata/python/dbLayoutToNetlist.py +++ b/testdata/python/dbLayoutToNetlist.py @@ -69,7 +69,7 @@ class DBLayoutToNetlistTests(unittest.TestCase): ut_testsrc = os.getenv("TESTSRC") ly = pya.Layout() - ly.read(os.path.join(ut_testsrc, "testdata", "algo", "device_extract_l1.gds")) + ly.read(os.path.join(ut_testsrc, "testdata", "algo", "device_extract_l1_with_inv_nodes.gds")) l2n = pya.LayoutToNetlist(pya.RecursiveShapeIterator(ly, ly.top_cell(), [])) @@ -97,40 +97,56 @@ class DBLayoutToNetlistTests(unittest.TestCase): self.assertEqual(str(l2n.netlist()), """circuit TRANS ($1=$1,$2=$2); end; -circuit INV2 (OUT=OUT,$2=$2,$3=$3,$4=$4); +circuit INV2 (OUT=OUT,$2=$3,$3=$4); subcircuit TRANS $1 ($1=$4,$2=OUT); subcircuit TRANS $2 ($1=$3,$2=OUT); subcircuit TRANS $3 ($1=$2,$2=$4); subcircuit TRANS $4 ($1=$2,$2=$3); end; circuit RINGO (); - subcircuit INV2 $1 (OUT=OSC,$2=FB,$3=VSS,$4=VDD); - subcircuit INV2 $2 (OUT=$I29,$2=$I20,$3=VSS,$4=VDD); - subcircuit INV2 $3 (OUT=$I28,$2=$I19,$3=VSS,$4=VDD); - subcircuit INV2 $4 (OUT=$I30,$2=$I21,$3=VSS,$4=VDD); - subcircuit INV2 $5 (OUT=$I31,$2=$I22,$3=VSS,$4=VDD); - subcircuit INV2 $6 (OUT=$I32,$2=$I23,$3=VSS,$4=VDD); - subcircuit INV2 $7 (OUT=$I33,$2=$I24,$3=VSS,$4=VDD); - subcircuit INV2 $8 (OUT=$I34,$2=$I25,$3=VSS,$4=VDD); - subcircuit INV2 $9 (OUT=$I35,$2=$I26,$3=VSS,$4=VDD); - subcircuit INV2 $10 (OUT=$I36,$2=$I27,$3=VSS,$4=VDD); + subcircuit INV2 $1 (OUT='FB,OSC',$2=VSS,$3=VDD); + subcircuit INV2 $2 (OUT=$I20,$2=VSS,$3=VDD); + subcircuit INV2 $3 (OUT=$I19,$2=VSS,$3=VDD); + subcircuit INV2 $4 (OUT=$I21,$2=VSS,$3=VDD); + subcircuit INV2 $5 (OUT=$I22,$2=VSS,$3=VDD); + subcircuit INV2 $6 (OUT=$I23,$2=VSS,$3=VDD); + subcircuit INV2 $7 (OUT=$I24,$2=VSS,$3=VDD); + subcircuit INV2 $8 (OUT=$I25,$2=VSS,$3=VDD); + subcircuit INV2 $9 (OUT=$I26,$2=VSS,$3=VDD); + subcircuit INV2 $10 (OUT=$I27,$2=VSS,$3=VDD); end; """) - self.assertEqual(str(l2n.probe_net(rmetal2, pya.DPoint(0.0, 1.8))), "RINGO:FB") + self.assertEqual(str(l2n.probe_net(rmetal2, pya.DPoint(0.0, 1.8))), "RINGO:FB,OSC") + sc_path = [] + self.assertEqual(str(l2n.probe_net(rmetal2, pya.DPoint(0.0, 1.8), sc_path)), "RINGO:FB,OSC") + self.assertEqual(len(sc_path), 0) self.assertEqual(repr(l2n.probe_net(rmetal2, pya.DPoint(-2.0, 1.8))), "None") - n = l2n.probe_net(rmetal1, pya.Point(2600, 1000)) - self.assertEqual(str(n), "RINGO:$I20") + n = l2n.probe_net(rmetal1, pya.Point(2600, 1000), None) + self.assertEqual(str(n), "INV2:$2") + sc_path = [] + n = l2n.probe_net(rmetal1, pya.Point(2600, 1000), sc_path) + self.assertEqual(str(n), "INV2:$2") + self.assertEqual(len(sc_path), 1) + a = [] + t = pya.DCplxTrans() + for sc in sc_path: + a.append(sc.expanded_name()) + t = t * sc.trans + self.assertEqual(",".join(a), "$2") + self.assertEqual(str(t), "r0 *1 2.64,0") - self.assertEqual(str(l2n.shapes_of_net(n, rmetal1, True)), "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)") + self.assertEqual(str(l2n.shapes_of_net(n, rmetal1, True)), + "(-980,-420;-980,2420;-620,2420;-620,-420);(-800,820;-800,1180;580,1180;580,820);(-980,2420;-980,3180;-620,3180;-620,2420);(-980,-380;-980,380;-620,380;-620,-380)") shapes = pya.Shapes() l2n.shapes_of_net(n, rmetal1, True, shapes) r = pya.Region() - for s in shapes.each(): - r.insert(s.polygon) - self.assertEqual(str(r), "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)") + for s in shapes.each(): + r.insert(s.polygon) + self.assertEqual(str(r), + "(-980,-420;-980,2420;-620,2420;-620,-420);(-800,820;-800,1180;580,1180;580,820);(-980,2420;-980,3180;-620,3180;-620,2420);(-980,-380;-980,380;-620,380;-620,-380)") def test_10_LayoutToNetlistExtractionWithoutDevices(self): diff --git a/testdata/ruby/dbLayoutToNetlist.rb b/testdata/ruby/dbLayoutToNetlist.rb index 094eef598..9e61b84a9 100644 --- a/testdata/ruby/dbLayoutToNetlist.rb +++ b/testdata/ruby/dbLayoutToNetlist.rb @@ -104,7 +104,7 @@ class DBLayoutToNetlist_TestClass < TestBase def test_2_ShapesFromNet ly = RBA::Layout::new - ly.read(File.join($ut_testsrc, "testdata", "algo", "device_extract_l1.gds")) + ly.read(File.join($ut_testsrc, "testdata", "algo", "device_extract_l1_with_inv_nodes.gds")) l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, ly.top_cell, [])) @@ -133,39 +133,50 @@ class DBLayoutToNetlist_TestClass < TestBase assert_equal(l2n.netlist.to_s, < Date: Sun, 14 Jun 2020 23:31:44 +0200 Subject: [PATCH 02/32] WIP+Bugfix 1. Bugfix: avoid an internal error because in set_db highlight() was called before setup_trees(). Error was: Internal error: ../../../src/laybasic/laybasic/layNetlistBrowserPage.cc:387 model != 0 was not true in LayoutView::show_l2ndb 2. Provide GSI binding for lay::NetlistBrowserDialog --- .../gsiDeclLayNetlistBrowserDialog.cc | 36 ++++++- .../laybasic/layNetlistBrowserDialog.cc | 94 +++++++++++++++++-- .../laybasic/layNetlistBrowserDialog.h | 46 +++++++++ .../laybasic/layNetlistBrowserPage.cc | 10 +- src/laybasic/laybasic/layNetlistBrowserPage.h | 58 ++++++++---- 5 files changed, 218 insertions(+), 26 deletions(-) diff --git a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc index 14346efe4..d35d1743c 100644 --- a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc +++ b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc @@ -23,6 +23,7 @@ #include "gsiDecl.h" #include "gsiDeclBasic.h" +#include "gsiSignals.h" #include "layNetlistBrowserDialog.h" #include "layLayoutView.h" @@ -42,8 +43,39 @@ namespace gsi { Class decl_NetlistBrowserDialog ("lay", "NetlistBrowserDialog", - gsi::Methods (), - "@brief ..." + gsi::event ("current_db_changed_event", &lay::NetlistBrowserDialog::current_db_changed_event, + "@brief This event is triggered when the current database is changed.\n" + "The current database can be obtained with \\db." + ) + + gsi::event ("selection_changed_event", &lay::NetlistBrowserDialog::selection_changed_event, + "@brief This event is triggered when the selection changed.\n" + "The selection can be obtained with \\selected_nets, \\selected_devices, \\selected_subcircuits and \\selected_circuits." + ) + + gsi::event ("probe_event", &lay::NetlistBrowserDialog::probe_event, gsi::arg ("net"), gsi::arg ("subcircuit_path"), + "@brief This event is triggered when a net is probed.\n" + "'subcircuit_path' will contain the subcircuit objects leading to the probed net from the netlist databases' top circuit. " + "This path may not be complete - it may contain null entries if a cell instance can't be associated with a subcircuit." + ) + + gsi::method ("db", &lay::NetlistBrowserDialog::db, + "@brief Gets the database the browser is connected to.\n" + ) + + gsi::method ("selected_nets", &lay::NetlistBrowserDialog::selected_nets, + "@brief Gets the nets currently selected in the netlist database browser.\n" + ) + + gsi::method ("selected_nets", &lay::NetlistBrowserDialog::selected_devices, + "@brief Gets the devices currently selected in the netlist database browser.\n" + ) + + gsi::method ("selected_nets", &lay::NetlistBrowserDialog::selected_subcircuits, + "@brief Gets the subcircuits currently selected in the netlist database browser.\n" + ) + + gsi::method ("selected_nets", &lay::NetlistBrowserDialog::selected_circuits, + "@brief Gets the circuits currently selected in the netlist database browser.\n" + ), + "@brief Represents the netlist browser dialog.\n" + "This dialog is a part of the \\LayoutView class and can be obtained through \\LayoutView#netlist_browser.\n" + "This interface allows to interact with the browser - mainly to get information about state changes.\n" + "\n" + "This class has been introduced in version 0.27.\n" ); static lay::NetlistBrowserDialog *netlist_browser (lay::LayoutView *lv) diff --git a/src/laybasic/laybasic/layNetlistBrowserDialog.cc b/src/laybasic/laybasic/layNetlistBrowserDialog.cc index 50866fa8d..78644cfc3 100644 --- a/src/laybasic/laybasic/layNetlistBrowserDialog.cc +++ b/src/laybasic/laybasic/layNetlistBrowserDialog.cc @@ -120,6 +120,8 @@ NetlistBrowserDialog::NetlistBrowserDialog (lay::Dispatcher *root, lay::LayoutVi connect (sticky_cbx, SIGNAL (clicked ()), this, SLOT (sticky_mode_clicked ())); cellviews_changed (); + + browser_page->selection_changed_event.add (this, &NetlistBrowserDialog::selection_changed); } NetlistBrowserDialog::~NetlistBrowserDialog () @@ -127,6 +129,56 @@ NetlistBrowserDialog::~NetlistBrowserDialog () tl::Object::detach_from_all_events (); } +db::LayoutToNetlist * +NetlistBrowserDialog::db () +{ + return browser_page->db (); +} + +const std::vector & +NetlistBrowserDialog::selected_nets () const +{ + if (browser_page) { + return browser_page->current_nets (); + } else { + static std::vector empty; + return empty; + } +} + +const std::vector & +NetlistBrowserDialog::selected_devices () const +{ + if (browser_page) { + return browser_page->current_devices (); + } else { + static std::vector empty; + return empty; + } +} + +const std::vector & +NetlistBrowserDialog::selected_subcircuits () const +{ + if (browser_page) { + return browser_page->current_subcircuits (); + } else { + static std::vector empty; + return empty; + } +} + +const std::vector & +NetlistBrowserDialog::selected_circuits () const +{ + if (browser_page) { + return browser_page->current_circuits (); + } else { + static std::vector empty; + return empty; + } +} + void NetlistBrowserDialog::configure_clicked () { @@ -254,7 +306,8 @@ NetlistBrowserDialog::probe_net (const db::DPoint &p, bool trace_path) } - const db::Net *net = 0; + db::Net *net = 0; + std::vector sc_path; db::LayoutToNetlist *l2ndb = view ()->get_l2ndb (m_l2n_index); if (l2ndb) { @@ -281,13 +334,17 @@ NetlistBrowserDialog::probe_net (const db::DPoint &p, bool trace_path) // probe the net for (std::vector::const_iterator r = regions.begin (); r != regions.end () && !net; ++r) { - net = l2ndb->probe_net (**r, start_point); + sc_path.clear (); + net = l2ndb->probe_net (**r, start_point, &sc_path); } } // select the net if one was found browser_page->select_net (net); + + // emits the probe event + probe_event (net, sc_path); } void @@ -421,9 +478,15 @@ BEGIN_PROTECTED tl::log << tl::to_string (QObject::tr ("Loading file: ")) << l2ndb->filename (); tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Loading"))); - browser_page->set_l2ndb (0); - l2ndb->load (l2ndb->filename ()); - browser_page->set_l2ndb (l2ndb); + browser_page->set_db (0); + try { + l2ndb->load (l2ndb->filename ()); + browser_page->set_db (l2ndb); + current_db_changed_event (); + } catch (...) { + current_db_changed_event (); + throw; + } } @@ -707,6 +770,8 @@ NetlistBrowserDialog::update_content () central_stack->setCurrentIndex (1); } + bool db_changed = false; + m_saveas_action->setEnabled (l2ndb != 0); m_export_action->setEnabled (l2ndb != 0); m_unload_action->setEnabled (l2ndb != 0); @@ -714,7 +779,10 @@ NetlistBrowserDialog::update_content () m_reload_action->setEnabled (l2ndb != 0); browser_page->enable_updates (false); // Avoid building the internal lists several times ... - browser_page->set_l2ndb (l2ndb); + if (browser_page->db () != l2ndb) { + db_changed = true; + browser_page->set_db (l2ndb); + } browser_page->set_max_shape_count (m_max_shape_count); browser_page->set_highlight_style (m_marker_color, m_marker_line_width, m_marker_vertex_size, m_marker_halo, m_marker_dither_pattern, m_marker_intensity, m_use_original_colors, m_auto_color_enabled ? &m_auto_colors : 0); browser_page->set_window (m_window, m_window_dim); @@ -740,6 +808,10 @@ NetlistBrowserDialog::update_content () if (l2ndb_cb->currentIndex () != m_l2n_index) { l2ndb_cb->setCurrentIndex (m_l2n_index); } + + if (db_changed) { + current_db_changed_event (); + } } void @@ -751,8 +823,16 @@ NetlistBrowserDialog::deactivated () lay::Dispatcher::instance ()->config_set (cfg_l2ndb_window_state, lay::save_dialog_state (this, false /*don't store the section sizes*/).c_str ()); } - browser_page->set_l2ndb (0); + bool db_changed = false; + if (browser_page->db () != 0) { + db_changed = true; + browser_page->set_db (0); + } browser_page->set_view (0, 0); + + if (db_changed) { + current_db_changed_event (); + } } void diff --git a/src/laybasic/laybasic/layNetlistBrowserDialog.h b/src/laybasic/laybasic/layNetlistBrowserDialog.h index 73b0b5fe6..221408999 100644 --- a/src/laybasic/laybasic/layNetlistBrowserDialog.h +++ b/src/laybasic/laybasic/layNetlistBrowserDialog.h @@ -29,6 +29,7 @@ #include "layNetlistBrowser.h" #include "layViewObject.h" #include "layColorPalette.h" +#include "tlEvents.h" namespace lay { @@ -46,6 +47,46 @@ public: void load (int lay_index, int cv_index); + /** + * @brief This event is emitted after the current database changed + */ + tl::Event current_db_changed_event; + + /** + * @brief This event is emitted when a shape is probed + */ + tl::event > probe_event; + + /** + * @brief Gets the current database + */ + db::LayoutToNetlist *db (); + + /** + * @brief Gets the selected nets + */ + const std::vector &selected_nets () const; + + /** + * @brief Gets the selected devices + */ + const std::vector &selected_devices () const; + + /** + * @brief Gets the selected subcircuits + */ + const std::vector &selected_subcircuits () const; + + /** + * @brief Gets the selected circuits + */ + const std::vector &selected_circuits () const; + + /** + * @brief An event indicating that the selection has changed + */ + tl::Event selection_changed_event; + private: // implementation of the lay::Browser interface virtual void activated (); @@ -64,6 +105,11 @@ private: void cellview_changed (int index); void l2ndbs_changed (); + void selection_changed () + { + selection_changed_event (); + } + public slots: void cv_index_changed (int); void l2ndb_index_changed (int); diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index 3c0882ad0..f3c6f799d 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -795,11 +795,17 @@ NetlistBrowserPage::set_db (db::LayoutToNetlist *l2ndb) m_signals_enabled = se; clear_markers (); - highlight (std::vector (), std::vector (), std::vector (), std::vector ()); + + m_current_nets.clear (); + m_current_devices.clear (); + m_current_subcircuits.clear (); + m_current_circuits.clear (); m_cell_context_cache = db::ContextCache (mp_database.get () ? mp_database->internal_layout () : 0); setup_trees (); + + selection_changed_event (); } void @@ -902,6 +908,8 @@ NetlistBrowserPage::highlight (const std::vector &nets, const s update_highlights (); } + selection_changed (); + } } diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.h b/src/laybasic/laybasic/layNetlistBrowserPage.h index 9a1adccd6..4aef9bae8 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.h +++ b/src/laybasic/laybasic/layNetlistBrowserPage.h @@ -33,6 +33,7 @@ #include "dbLayoutUtils.h" #include "tlObject.h" +#include "tlEvents.h" #include @@ -90,25 +91,14 @@ public: /** * @brief Attaches the page to a L2N DB */ - void set_l2ndb (db::LayoutToNetlist *database) - { - set_db (database); - } + void set_db (db::LayoutToNetlist *database); /** - * @brief Attaches the page to a LVS DB + * @brief Gets the database the page is connected to */ - void set_lvsdb (db::LayoutVsSchematic *database) + db::LayoutToNetlist *db () { - set_db (database); - } - - /** - * @brief Detaches the page from any DB - */ - void reset_db () - { - set_db (0); + return mp_database.get (); } /** @@ -162,6 +152,43 @@ public: */ void update_highlights (); + /** + * @brief Gets the selected nets + */ + const std::vector ¤t_nets () const + { + return m_current_nets; + } + + /** + * @brief Gets the selected devices + */ + const std::vector ¤t_devices () const + { + return m_current_devices; + } + + /** + * @brief Gets the selected subcircuits + */ + const std::vector ¤t_subcircuits () const + { + return m_current_subcircuits; + } + + /** + * @brief Gets the selected circuits + */ + const std::vector ¤t_circuits () const + { + return m_current_circuits; + } + + /** + * @brief An event indicating that the selection has changed + */ + tl::Event selection_changed_event; + public slots: void export_all (); void export_selected (); @@ -216,7 +243,6 @@ private: tl::DeferredMethod dm_rerun_macro; db::ContextCache m_cell_context_cache; - void set_db (db::LayoutToNetlist *l2ndb); void setup_trees (); void add_to_history (void *id, bool fwd); void navigate_to (void *id, bool forward = true); From 84a9853435424f2aac46014a395ce8c50208d5c1 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 15 Jun 2020 01:26:49 +0200 Subject: [PATCH 03/32] Maybe fixed a potential segfault (0-1 as row index) --- src/lay/lay/layMacroEditorTree.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lay/lay/layMacroEditorTree.cc b/src/lay/lay/layMacroEditorTree.cc index 703cf7aaa..da5b3bcea 100644 --- a/src/lay/lay/layMacroEditorTree.cc +++ b/src/lay/lay/layMacroEditorTree.cc @@ -161,7 +161,10 @@ void MacroTreeModel::macro_changed () void MacroTreeModel::update_data () { - emit dataChanged (index (0, 0, QModelIndex ()), index (rowCount (QModelIndex()) - 1, 0, QModelIndex ())); + int rc = rowCount (QModelIndex()); + if (rc > 0) { + emit dataChanged (index (0, 0, QModelIndex ()), index (rc - 1, 0, QModelIndex ())); + } } void MacroTreeModel::about_to_change () From 3f1c3cf20920e59fd26d49cebcc30e14c7512747 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 15 Jun 2020 01:27:33 +0200 Subject: [PATCH 04/32] Extended NetlistCrossReference class so we can easily obtain the other_... objects. --- src/db/db/dbNetlistCrossReference.cc | 33 +++++++++++++++++++++ src/db/db/dbNetlistCrossReference.h | 3 ++ src/db/db/gsiDeclDbNetlistCrossReference.cc | 28 +++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/src/db/db/dbNetlistCrossReference.cc b/src/db/db/dbNetlistCrossReference.cc index a0a0464a6..479121ba5 100644 --- a/src/db/db/dbNetlistCrossReference.cc +++ b/src/db/db/dbNetlistCrossReference.cc @@ -55,6 +55,39 @@ NetlistCrossReference::per_circuit_data_for (const std::pair::const_iterator i = m_other_pin.find (pin); + if (i != m_other_pin.end ()) { + return i->second; + } else { + return 0; + } +} + +const db::Device * +NetlistCrossReference::other_device_for (const db::Device *device) const +{ + std::map::const_iterator i = m_other_device.find (device); + if (i != m_other_device.end ()) { + return i->second; + } else { + return 0; + } +} + +const db::SubCircuit * +NetlistCrossReference::other_subcircuit_for (const db::SubCircuit *subcircuit) const +{ + std::map::const_iterator i = m_other_subcircuit.find (subcircuit); + if (i != m_other_subcircuit.end ()) { + return i->second; + } else { + return 0; + } +} + const db::Circuit * NetlistCrossReference::other_circuit_for (const db::Circuit *circuit) const { diff --git a/src/db/db/dbNetlistCrossReference.h b/src/db/db/dbNetlistCrossReference.h index d61868445..c0e9be7eb 100644 --- a/src/db/db/dbNetlistCrossReference.h +++ b/src/db/db/dbNetlistCrossReference.h @@ -256,6 +256,9 @@ public: return m_circuits.end (); } + const db::Pin *other_pin_for (const db::Pin *pin) const; + const db::Device *other_device_for (const db::Device *device) const; + const db::SubCircuit *other_subcircuit_for (const db::SubCircuit *subcircuit) const; const db::Circuit *other_circuit_for (const db::Circuit *circuit) const; const db::Net *other_net_for (const db::Net *net) const; const PerNetData *per_net_data_for (const std::pair &nets) const; diff --git a/src/db/db/gsiDeclDbNetlistCrossReference.cc b/src/db/db/gsiDeclDbNetlistCrossReference.cc index 13078d5e1..de230a506 100644 --- a/src/db/db/gsiDeclDbNetlistCrossReference.cc +++ b/src/db/db/gsiDeclDbNetlistCrossReference.cc @@ -403,6 +403,34 @@ Class decl_dbNetlistCrossReference (decl_dbNetlistCom "The return value will be nil if no match is found. " "Otherwise it is the 'b' net for nets from the 'a' netlist and vice versa." ) + + gsi::method ("other_circuit_for", &db::NetlistCrossReference::other_circuit_for, gsi::arg ("circuit"), + "@brief Gets the matching other circuit for a given primary circuit.\n" + "The return value will be nil if no match is found. " + "Otherwise it is the 'b' circuit for circuits from the 'a' netlist and vice versa." + "\n\n" + "This method has been introduced in version 0.27.\n" + ) + + gsi::method ("other_device_for", &db::NetlistCrossReference::other_device_for, gsi::arg ("device"), + "@brief Gets the matching other device for a given primary device.\n" + "The return value will be nil if no match is found. " + "Otherwise it is the 'b' device for devices from the 'a' netlist and vice versa." + "\n\n" + "This method has been introduced in version 0.27.\n" + ) + + gsi::method ("other_pin_for", &db::NetlistCrossReference::other_pin_for, gsi::arg ("pin"), + "@brief Gets the matching other pin for a given primary pin.\n" + "The return value will be nil if no match is found. " + "Otherwise it is the 'b' pin for pins from the 'a' netlist and vice versa." + "\n\n" + "This method has been introduced in version 0.27.\n" + ) + + gsi::method ("other_subcircuit_for", &db::NetlistCrossReference::other_subcircuit_for, gsi::arg ("subcircuit"), + "@brief Gets the matching other subcircuit for a given primary subcircuit.\n" + "The return value will be nil if no match is found. " + "Otherwise it is the 'b' subcircuit for subcircuits from the 'a' netlist and vice versa." + "\n\n" + "This method has been introduced in version 0.27.\n" + ) + gsi::method ("clear", &db::NetlistCrossReference::clear, "@hide\n" ) + From fc75bf72f82ca112760b120b8eea152695703421 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 15 Jun 2020 01:28:49 +0200 Subject: [PATCH 05/32] Avoid a segfault when the owner of a callable went out of scope and got deleted (pya): null weak pointer happens --- src/pya/pya/pyaSignalHandler.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pya/pya/pyaSignalHandler.cc b/src/pya/pya/pyaSignalHandler.cc index 7ac472e62..b015e42e3 100644 --- a/src/pya/pya/pyaSignalHandler.cc +++ b/src/pya/pya/pyaSignalHandler.cc @@ -138,7 +138,10 @@ void SignalHandler::call (const gsi::MethodBase *meth, gsi::SerialArgs &args, gs std::vector callables; callables.reserve (m_cbfuncs.size ()); for (std::vector::const_iterator c = m_cbfuncs.begin (); c != m_cbfuncs.end (); ++c) { - callables.push_back (c->callable ()); + PythonRef callable = c->callable (); + if (callable) { + callables.push_back (c->callable ()); + } } PythonRef result; From 23e9932c87648fb44d5f21dbbe5a2eaf8cfa7b1a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 15 Jun 2020 01:29:05 +0200 Subject: [PATCH 06/32] Consistent naming of events: on_... --- src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc index d35d1743c..dfd7b08af 100644 --- a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc +++ b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc @@ -43,15 +43,15 @@ namespace gsi { Class decl_NetlistBrowserDialog ("lay", "NetlistBrowserDialog", - gsi::event ("current_db_changed_event", &lay::NetlistBrowserDialog::current_db_changed_event, + gsi::event ("on_current_db_changed", &lay::NetlistBrowserDialog::current_db_changed_event, "@brief This event is triggered when the current database is changed.\n" "The current database can be obtained with \\db." ) + - gsi::event ("selection_changed_event", &lay::NetlistBrowserDialog::selection_changed_event, + gsi::event ("on_selection_changed", &lay::NetlistBrowserDialog::selection_changed_event, "@brief This event is triggered when the selection changed.\n" "The selection can be obtained with \\selected_nets, \\selected_devices, \\selected_subcircuits and \\selected_circuits." ) + - gsi::event ("probe_event", &lay::NetlistBrowserDialog::probe_event, gsi::arg ("net"), gsi::arg ("subcircuit_path"), + gsi::event ("on_probe", &lay::NetlistBrowserDialog::probe_event, gsi::arg ("net"), gsi::arg ("subcircuit_path"), "@brief This event is triggered when a net is probed.\n" "'subcircuit_path' will contain the subcircuit objects leading to the probed net from the netlist databases' top circuit. " "This path may not be complete - it may contain null entries if a cell instance can't be associated with a subcircuit." From e37e3f6793938a7039cd75c9debac6b9800b841e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 15 Jun 2020 01:37:03 +0200 Subject: [PATCH 07/32] Fixed doc flaw: child classes were not properly cross-referenced as return values or arguments. Need qualified names. --- src/lay/lay/layGSIHelpProvider.cc | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/lay/lay/layGSIHelpProvider.cc b/src/lay/lay/layGSIHelpProvider.cc index 2307e7f3c..171b3fc6a 100644 --- a/src/lay/lay/layGSIHelpProvider.cc +++ b/src/lay/lay/layGSIHelpProvider.cc @@ -285,16 +285,6 @@ static DocumentationParser &cls_documentation (const gsi::ClassBase *cls) } } -static const std::string &aliased_name (const gsi::ClassBase *cls) -{ - const std::string &alias = cls_documentation (cls).alias; - if (alias.empty ()) { - return cls->name (); - } else { - return alias; - } -} - static std::string make_qualified_name (const gsi::ClassBase *cls) { std::string qname; @@ -703,9 +693,9 @@ type_to_s (const gsi::ArgType &a, bool linked, bool for_return) s += "new "; } if (linked) { - s += "" + escape_xml (aliased_name (a.cls ())) + ""; + s += "" + escape_xml (make_qualified_name (a.cls ())) + ""; } else { - s += aliased_name (a.cls ()); + s += make_qualified_name (a.cls ()); } break; case gsi::T_vector: From fd5c659ea6a6252db81c010732ce513a6755ac0b Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 16 Jun 2020 23:13:52 +0200 Subject: [PATCH 08/32] WIP: refactoring for more comfortable net browser --- .../laybasic/layNetlistBrowserModel.cc | 2820 ++++++++--------- .../laybasic/layNetlistBrowserModel.h | 119 + 2 files changed, 1426 insertions(+), 1513 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 6d2ca9d88..e0a00810b 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -158,585 +158,13 @@ NetColorizer::color_of_net (const db::Net *net) const } // ---------------------------------------------------------------------------------- -// NetlistBrowserModel implementation +// Implementation of the item classes -static inline void *make_id (size_t i1) +const std::string field_sep (" / "); + +static QString escaped (const std::string &s) { - return reinterpret_cast (i1); -} - -/* not used yet: -static inline void *make_id (size_t i1, size_t n1, size_t i2) -{ - return reinterpret_cast (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 (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 (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 (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 (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 (idp); - size_t i = id % n; - id /= n; - idp = reinterpret_cast (id); - return i; -} - -static inline bool always (bool) -{ - return true; -} - -static void *no_id = reinterpret_cast (-1); - -NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb, NetColorizer *colorizer) - : QAbstractItemModel (parent), mp_l2ndb (l2ndb), mp_lvsdb (0), mp_colorizer (colorizer) -{ - mp_indexer.reset (new SingleIndexedNetlistModel (l2ndb->netlist ())); - connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ())); - - m_object_column = 0; - m_status_column = -1; - m_first_column = 2; - m_second_column = -1; -} - -NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutVsSchematic *lvsdb, NetColorizer *colorizer) - : QAbstractItemModel (parent), mp_l2ndb (0), mp_lvsdb (lvsdb), mp_colorizer (colorizer) -{ - mp_indexer.reset (new NetlistCrossReferenceModel (lvsdb->cross_ref ())); - connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ())); - - m_object_column = 0; - m_status_column = 1; - m_first_column = 2; - m_second_column = 3; -} - -NetlistBrowserModel::~NetlistBrowserModel () -{ - // .. nothing yet .. -} - -void * -NetlistBrowserModel::make_id_circuit (size_t circuit_index) const -{ - if (circuit_index == lay::no_netlist_index) { - return no_id; - } else { - return make_id (circuit_index); - } -} - -void * -NetlistBrowserModel::make_id_circuit_pin (size_t circuit_index, size_t pin_index) const -{ - if (circuit_index == lay::no_netlist_index || pin_index == lay::no_netlist_index) { - return no_id; - } else { - return make_id (circuit_index, mp_indexer->circuit_count (), 1, 8, pin_index); - } -} - -void * -NetlistBrowserModel::make_id_circuit_pin_net (size_t circuit_index, size_t pin_index, size_t net_index) const -{ - if (circuit_index == lay::no_netlist_index || pin_index == lay::no_netlist_index || net_index == lay::no_netlist_index) { - return no_id; - } else { - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (make_id_circuit (circuit_index)); - return make_id (circuit_index, mp_indexer->circuit_count (), 1, 8, pin_index, mp_indexer->pin_count (circuits), net_index + 1); - } -} - -void * -NetlistBrowserModel::make_id_circuit_net (size_t circuit_index, size_t net_index) const -{ - if (circuit_index == lay::no_netlist_index || net_index == lay::no_netlist_index) { - return no_id; - } else { - return make_id (circuit_index, mp_indexer->circuit_count (), 2, 8, net_index); - } -} - -void * -NetlistBrowserModel::make_id_circuit_net_device_terminal (size_t circuit_index, size_t net_index, size_t terminal_ref_index) const -{ - if (circuit_index == lay::no_netlist_index || net_index == lay::no_netlist_index || terminal_ref_index == lay::no_netlist_index) { - return no_id; - } else { - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (make_id_circuit (circuit_index)); - return make_id (circuit_index, mp_indexer->circuit_count (), 2, 8, net_index, mp_indexer->net_count (circuits), 1, 4, terminal_ref_index); - } -} - -void * -NetlistBrowserModel::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 -{ - if (circuit_index == lay::no_netlist_index || net_index == lay::no_netlist_index || terminal_ref_index == lay::no_netlist_index || other_index == lay::no_netlist_index) { - return no_id; - } else { - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (make_id_circuit (circuit_index)); - IndexedNetlistModel::net_pair nets = nets_from_id (make_id_circuit_net (circuit_index, net_index)); - return make_id (circuit_index, mp_indexer->circuit_count (), 2, 8, net_index, mp_indexer->net_count (circuits), 1, 4, terminal_ref_index, mp_indexer->net_terminal_count (nets), other_index + 1); - } -} - -void * -NetlistBrowserModel::make_id_circuit_net_pin (size_t circuit_index, size_t net_index, size_t pin_index) const -{ - if (circuit_index == lay::no_netlist_index || net_index == lay::no_netlist_index || pin_index == lay::no_netlist_index) { - return no_id; - } else { - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (make_id_circuit (circuit_index)); - return make_id (circuit_index, mp_indexer->circuit_count (), 2, 8, net_index, mp_indexer->net_count (circuits), 2, 4, pin_index); - } -} - -void * -NetlistBrowserModel::make_id_circuit_net_subcircuit_pin (size_t circuit_index, size_t net_index, size_t pin_ref_index) const -{ - if (circuit_index == lay::no_netlist_index || net_index == lay::no_netlist_index || pin_ref_index == lay::no_netlist_index) { - return no_id; - } else { - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (make_id_circuit (circuit_index)); - return make_id (circuit_index, mp_indexer->circuit_count (), 2, 8, net_index, mp_indexer->net_count (circuits), 3, 4, pin_ref_index); - } -} - -void * -NetlistBrowserModel::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 -{ - if (circuit_index == lay::no_netlist_index || net_index == lay::no_netlist_index || pin_ref_index == lay::no_netlist_index || other_index == lay::no_netlist_index) { - return no_id; - } else { - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (make_id_circuit (circuit_index)); - IndexedNetlistModel::net_pair nets = nets_from_id (make_id_circuit_net (circuit_index, net_index)); - return make_id (circuit_index, mp_indexer->circuit_count (), 2, 8, net_index, mp_indexer->net_count (circuits), 3, 4, pin_ref_index, mp_indexer->net_subcircuit_pin_count (nets), other_index + 1); - } -} - -void * -NetlistBrowserModel::make_id_circuit_subcircuit (size_t circuit_index, size_t subcircuit_index) const -{ - if (circuit_index == lay::no_netlist_index || subcircuit_index == lay::no_netlist_index) { - return no_id; - } else { - return make_id (circuit_index, mp_indexer->circuit_count (), 3, 8, subcircuit_index); - } -} - -void * -NetlistBrowserModel::make_id_circuit_subcircuit_pin (size_t circuit_index, size_t subcircuit_index, size_t pin_index) const -{ - if (circuit_index == lay::no_netlist_index || subcircuit_index == lay::no_netlist_index || pin_index == lay::no_netlist_index) { - return no_id; - } else { - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (make_id_circuit (circuit_index)); - return make_id (circuit_index, mp_indexer->circuit_count (), 3, 8, subcircuit_index, mp_indexer->subcircuit_count (circuits), pin_index + 1); - } -} - -void * -NetlistBrowserModel::make_id_circuit_device (size_t circuit_index, size_t device_index) const -{ - if (circuit_index == lay::no_netlist_index || device_index == lay::no_netlist_index) { - return no_id; - } else { - return make_id (circuit_index, mp_indexer->circuit_count (), 4, 8, device_index); - } -} - -void * -NetlistBrowserModel::make_id_circuit_device_terminal (size_t circuit_index, size_t device_index, size_t terminal_index) const -{ - if (circuit_index == lay::no_netlist_index || device_index == lay::no_netlist_index || terminal_index == lay::no_netlist_index) { - return no_id; - } else { - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (make_id_circuit (circuit_index)); - return make_id (circuit_index, mp_indexer->circuit_count (), 4, 8, device_index, mp_indexer->device_count (circuits), terminal_index + 1); - } -} - -bool -NetlistBrowserModel::is_id_circuit (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - pop (id, mp_indexer->circuit_count ()); - return id == 0; -} - -bool -NetlistBrowserModel::is_id_circuit_pin (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - return (pop (id, 8) == 1 && always (pop (id, mp_indexer->pin_count (circuits))) && id == 0); -} - -bool -NetlistBrowserModel::is_id_circuit_pin_net (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - return (pop (id, 8) == 1 && always (pop (id, mp_indexer->pin_count (circuits))) && id != 0); -} - -bool -NetlistBrowserModel::is_id_circuit_net (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - return (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && id == 0); -} - -bool -NetlistBrowserModel::is_id_circuit_net_device_terminal (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - void *org_id = id; - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - if (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 1) { - IndexedNetlistModel::net_pair nets = nets_from_id (org_id); - pop (id, mp_indexer->net_terminal_count (nets)); - return id == 0; - } - - return false; -} - -bool -NetlistBrowserModel::is_id_circuit_net_device_terminal_others (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - void *org_id = id; - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - if (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 1) { - IndexedNetlistModel::net_pair nets = nets_from_id (org_id); - pop (id, mp_indexer->net_terminal_count (nets)); - return id != 0; - } - - return false; -} - -bool -NetlistBrowserModel::is_id_circuit_net_pin (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - return (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 2); -} - -bool -NetlistBrowserModel::is_id_circuit_net_subcircuit_pin (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - void *org_id = id; - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - if (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 3) { - IndexedNetlistModel::net_pair nets = nets_from_id (org_id); - pop (id, mp_indexer->net_subcircuit_pin_count (nets)); - return id == 0; - } - - return false; -} - -bool -NetlistBrowserModel::is_id_circuit_net_subcircuit_pin_others (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - void *org_id = id; - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - if (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 3) { - IndexedNetlistModel::net_pair nets = nets_from_id (org_id); - pop (id, mp_indexer->net_subcircuit_pin_count (nets)); - return id != 0; - } - - return false; -} - -bool -NetlistBrowserModel::is_id_circuit_subcircuit (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - return (pop (id, 8) == 3 && always (pop (id, mp_indexer->subcircuit_count (circuits))) && id == 0); -} - -bool -NetlistBrowserModel::is_id_circuit_subcircuit_pin (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - return (pop (id, 8) == 3 && always (pop (id, mp_indexer->subcircuit_count (circuits))) && id != 0); -} - -bool -NetlistBrowserModel::is_id_circuit_device (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - return (pop (id, 8) == 4 && always (pop (id, mp_indexer->device_count (circuits))) && id == 0); -} - -bool -NetlistBrowserModel::is_id_circuit_device_terminal (void *id) const -{ - if (mp_indexer->circuit_count () == 0) { - return false; - } - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - return (pop (id, 8) == 4 && always (pop (id, mp_indexer->device_count (circuits))) && id != 0); -} - -size_t -NetlistBrowserModel::circuit_index_from_id (void *id) const -{ - return pop (id, mp_indexer->circuit_count ()); -} - -size_t -NetlistBrowserModel::circuit_pin_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - return pop (id, mp_indexer->pin_count (circuits)); -} - -size_t -NetlistBrowserModel::circuit_device_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - return pop (id, mp_indexer->device_count (circuits)); -} - -size_t -NetlistBrowserModel::circuit_device_terminal_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - pop (id, mp_indexer->device_count (circuits)); - return reinterpret_cast (id) - 1; -} - -size_t -NetlistBrowserModel::circuit_subcircuit_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - return pop (id, mp_indexer->subcircuit_count (circuits)); -} - -size_t -NetlistBrowserModel::circuit_subcircuit_pin_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - pop (id, mp_indexer->subcircuit_count (circuits)); - return reinterpret_cast (id) - 1; -} - -size_t -NetlistBrowserModel::circuit_net_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - return pop (id, mp_indexer->net_count (circuits)); -} - -size_t -NetlistBrowserModel::circuit_net_pin_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - pop (id, mp_indexer->net_count (circuits)); - pop (id, 4); - return reinterpret_cast (id); -} - -size_t -NetlistBrowserModel::circuit_net_subcircuit_pin_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - IndexedNetlistModel::net_pair nets = nets_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - pop (id, mp_indexer->net_count (circuits)); - pop (id, 4); - return pop (id, mp_indexer->net_subcircuit_pin_count (nets)); -} - -size_t -NetlistBrowserModel::circuit_net_subcircuit_pin_other_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - IndexedNetlistModel::net_pair nets = nets_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - pop (id, mp_indexer->net_count (circuits)); - pop (id, 4); - pop (id, mp_indexer->net_subcircuit_pin_count (nets)); - return reinterpret_cast (id) - 1; -} - -size_t -NetlistBrowserModel::circuit_net_device_terminal_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - IndexedNetlistModel::net_pair nets = nets_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - pop (id, mp_indexer->net_count (circuits)); - pop (id, 4); - return pop (id, mp_indexer->net_terminal_count (nets)); -} - -size_t -NetlistBrowserModel::circuit_net_device_terminal_other_index_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - IndexedNetlistModel::net_pair nets = nets_from_id (id); - pop (id, mp_indexer->circuit_count ()); - pop (id, 8); - pop (id, mp_indexer->net_count (circuits)); - pop (id, 4); - pop (id, mp_indexer->net_terminal_count (nets)); - return reinterpret_cast (id) - 1; -} - -int -NetlistBrowserModel::columnCount (const QModelIndex & /*parent*/) const -{ - // Item type & icon, link or description - return mp_indexer->is_single () ? 3 : 4; -} - -QIcon icon_for_status (db::NetlistCrossReference::Status status) -{ - if (status == db::NetlistCrossReference::NoMatch || status == db::NetlistCrossReference::Mismatch) { - return QIcon (":/error2_16.png"); - } else if (status == db::NetlistCrossReference::MatchWithWarning || status == db::NetlistCrossReference::Skipped) { - return QIcon (":/warn_16.png"); - } else { - return QIcon (); - } -} - -QVariant -NetlistBrowserModel::data (const QModelIndex &index, int role) const -{ - if (! index.isValid ()) { - return QVariant (); - } - - if (role == Qt::DecorationRole && index.column () == m_object_column) { - return QVariant (icon (index)); - } else if (role == Qt::DecorationRole && index.column () == m_status_column) { - return QVariant (icon_for_status (status (index))); - } else if (role == Qt::DisplayRole) { - return QVariant (text (index)); - } else if (role == Qt::ToolTipRole && index.column () == m_status_column) { - return tooltip (index); - } else if (role == Qt::UserRole) { - return QVariant (search_text (index)); - } else if (role == Qt::FontRole) { - db::NetlistCrossReference::Status st = status (index); - if (st == db::NetlistCrossReference::NoMatch || st == db::NetlistCrossReference::Mismatch || st == db::NetlistCrossReference::Skipped) { - QFont font; - font.setWeight (QFont::Bold); - return QVariant (font); - } - } else if (role == Qt::ForegroundRole) { - db::NetlistCrossReference::Status st = status (index); - if (st == db::NetlistCrossReference::Match || st == db::NetlistCrossReference::MatchWithWarning) { - // taken from marker browser: - return QVariant (QColor (0, 192, 0)); - } - } - return QVariant (); + return tl::to_qstring (tl::escaped_to_html (s)); } template @@ -899,138 +327,6 @@ std::string devices_string (const std::pair"; - - s += tl::escaped_to_html (title); - - s += ""; - - return tl::to_qstring (s); -} - -QString -NetlistBrowserModel::make_link_to (const std::pair &nets, int column) const -{ - if ((! nets.first || column == m_second_column) && (! nets.second || column == m_first_column)) { - return QString (); - } else { - - IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (nets); - void *id = no_id; - // NOTE: the nets may not be a valid net pair. In this case, circuits is (0, 0) and - // no link is generated - if (circuits.first || circuits.second) { - id = make_id_circuit_net (mp_indexer->circuit_index (circuits), mp_indexer->net_index (nets)); - } - - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "net", str_from_expanded_name (nets.first)); - } else if (column == m_second_column) { - return build_url (id, "net", str_from_expanded_name (nets.second)); - } else { - return build_url (id, "net", str_from_expanded_names (nets, mp_indexer->is_single ())); - } - - } -} - -QString -NetlistBrowserModel::make_link_to (const std::pair &devices, int column) const -{ - if ((! devices.first || column == m_second_column) && (! devices.second || column == m_first_column)) { - return QString (); - } else { - - IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (devices); - void *id = no_id; - // NOTE: the devices may not be a valid device pair. In this case, circuits is (0, 0) and - // no link is generated - if (circuits.first || circuits.second) { - id = make_id_circuit_device (mp_indexer->circuit_index (circuits), mp_indexer->device_index (devices)); - } - - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "device", str_from_expanded_name (devices.first)); - } else if (column == m_second_column) { - return build_url (id, "device", str_from_expanded_name (devices.second)); - } else { - return build_url (id, "device", str_from_expanded_names (devices, mp_indexer->is_single ())); - } - - } -} - -QString -NetlistBrowserModel::make_link_to (const std::pair &pins, const std::pair &circuits, int column) const -{ - if ((! pins.first || column == m_second_column) && (! pins.second || column == m_first_column)) { - return QString (); - } else { - void *id = make_id_circuit_pin (mp_indexer->circuit_index (circuits), mp_indexer->pin_index (pins, circuits)); - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "pin", str_from_expanded_name (pins.first)); - } else if (column == m_second_column) { - return build_url (id, "pin", str_from_expanded_name (pins.second)); - } else { - return build_url (id, "pin", str_from_expanded_names (pins, mp_indexer->is_single ())); - } - } -} - -QString -NetlistBrowserModel::make_link_to (const std::pair &circuits, int column) const -{ - if ((! circuits.first || column == m_second_column) && (! circuits.second || column == m_first_column)) { - return QString (); - } else { - void *id = make_id_circuit (mp_indexer->circuit_index (circuits)); - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "circuit", str_from_name (circuits.first)); - } else if (column == m_second_column) { - return build_url (id, "circuit", str_from_name (circuits.second)); - } else { - return build_url (id, "circuit", str_from_names (circuits, mp_indexer->is_single ())); - } - } -} - -QString -NetlistBrowserModel::make_link_to (const std::pair &subcircuits, int column) const -{ - if ((! subcircuits.first || column == m_second_column) && (! subcircuits.second || column == m_first_column)) { - return QString (); - } else { - - IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (subcircuits); - void *id = no_id; - // NOTE: the subcircuits may not be a valid subcircuit pair. In this case, circuits is (0, 0) and - // no link is generated - if (circuits.first || circuits.second) { - id = make_id_circuit_subcircuit (mp_indexer->circuit_index (circuits), mp_indexer->subcircuit_index (subcircuits)); - } - - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.first)); - } else if (column == m_second_column) { - return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.second)); - } else { - return build_url (id, "subcircuit", str_from_expanded_names (subcircuits, mp_indexer->is_single ())); - } - - } -} - static IndexedNetlistModel::circuit_pair circuit_refs_from_subcircuits (const IndexedNetlistModel::subcircuit_pair &subcircuits) { @@ -1164,222 +460,15 @@ IndexedNetlistModel::net_pair nets_from_device_terminals (const IndexedNetlistMo return std::make_pair (net1, net2); } -const std::string field_sep (" / "); - -static QString escaped (const std::string &s) -{ - return tl::to_qstring (tl::escaped_to_html (s)); -} - QString NetlistBrowserModel::text (const QModelIndex &index) const { - void *id = index.internalPointer (); - - if (is_id_circuit (id)) { - - // circuit: - // + single mode: name | | - // + dual mode: name(a)/name(b) | name(a) | name(b) - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - if (index.column () == m_object_column) { - return escaped (str_from_names (circuits, mp_indexer->is_single ())); - } else if (!mp_indexer->is_single () && (index.column () == m_first_column || index.column () == m_second_column)) { - return escaped (str_from_name (index.column () == m_first_column ? circuits.first : circuits.second)); - } - - } else if (is_id_circuit_pin (id)) { - - // pin: - // + single mode: xname | | - // + dual mode: xname(a)/xname(b) | xname(a) | xname(b) - IndexedNetlistModel::pin_pair pins = pins_from_id (id); - if (index.column () == m_object_column) { - return escaped (str_from_expanded_names (pins, mp_indexer->is_single ())); - } else if (!mp_indexer->is_single () && (index.column () == m_first_column || index.column () == m_second_column)) { - return escaped (str_from_expanded_name (index.column () == m_first_column ? pins.first : pins.second)); - } - - } else if (is_id_circuit_pin_net (id)) { - - // circuit/pin/net: header column = name, second column link to net - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - IndexedNetlistModel::pin_pair pins = pins_from_id (id); - IndexedNetlistModel::net_pair nets = nets_from_circuit_pins (circuits, pins); - - if (index.column () == m_object_column) { - return escaped (str_from_expanded_names (nets, mp_indexer->is_single ())); - } else if (index.column () == m_first_column || index.column () == m_second_column) { - return make_link_to (nets, index.column ()); - } - - } else if (is_id_circuit_device (id)) { - - // circuit/device: header column = class + parameters, second column device name - IndexedNetlistModel::device_pair devices = devices_from_id (id); - - if (mp_indexer->is_single ()) { - - if (index.column () == m_object_column) { - return escaped (device_string (devices.first)); - } else if (index.column () == m_first_column) { - return escaped (str_from_expanded_name (devices.first)); - } - - } else { - - if (index.column () == m_object_column) { - return escaped (devices_string (devices, mp_indexer->is_single (), false /*without parameters*/)); - } else if (index.column () == m_first_column) { - return escaped (str_from_expanded_name (devices.first) + field_sep + device_string (devices.first)); - } else if (index.column () == m_second_column) { - return escaped (str_from_expanded_name (devices.second) + field_sep + device_string (devices.second)); - } - - } - - } else if (is_id_circuit_device_terminal (id)) { - - // circuit/device/terminal: header column = terminal name, second column link to net - IndexedNetlistModel::device_pair devices = devices_from_id (id); - size_t terminal = circuit_device_terminal_index_from_id (id); - - std::pair device_classes = device_classes_from_devices (devices); - std::pair termdefs = terminal_defs_from_device_classes (device_classes, terminal); - - if (index.column () == m_object_column) { - - return escaped (str_from_names (termdefs, mp_indexer->is_single ())); - - } else if (index.column () == m_first_column || index.column () == m_second_column) { - - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (devices, termdefs); - return make_link_to (nets, index.column ()); - - } - - } else if (is_id_circuit_subcircuit (id)) { - - // circuit/subcircuit: header column = circuit name, second column subcircuit name - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_id (id); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - if (index.column () == m_object_column) { - return make_link_to (circuit_refs); - } else if (index.column () == m_first_column) { - return escaped (str_from_expanded_name (subcircuits.first)); - } else if (index.column () == m_second_column) { - return escaped (str_from_expanded_name (subcircuits.second)); - } - - } else if (is_id_circuit_subcircuit_pin (id)) { - - // circuit/pin: header column = pin name, other columns net name - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_id (id); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::pin_pair pins = pins_from_id (id); - - if (index.column () == m_object_column) { - return make_link_to (pins, circuit_refs); - } else if (index.column () == m_first_column || index.column () == m_second_column) { - return make_link_to (nets_from_subcircuit_pins (subcircuits, pins), index.column ()); - } - - } else if (is_id_circuit_net (id)) { - - // circuit/net: header column = node count, second column net name - IndexedNetlistModel::net_pair nets = nets_from_id (id); - if (index.column () == m_object_column) { - return escaped (str_from_expanded_names (nets, mp_indexer->is_single ())); - } else if (index.column () == m_first_column && nets.first) { - return escaped (nets.first->expanded_name () + " (" + tl::to_string (nets.first->pin_count () + nets.first->terminal_count () + nets.first->subcircuit_pin_count ()) + ")"); - } else if (index.column () == m_second_column && nets.second) { - return escaped (nets.second->expanded_name () + " (" + tl::to_string (nets.second->pin_count () + nets.second->terminal_count () + nets.second->subcircuit_pin_count ()) + ")"); - } - - } else if (is_id_circuit_net_pin (id)) { - - // circuit/net/pin: header column = pin name, second column empty (for now) - IndexedNetlistModel::net_pin_pair pinrefs = net_pinrefs_from_id (id); - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - if (mp_indexer->is_single () && index.column () == m_object_column) { - return make_link_to (pins_from_pinrefs (pinrefs), circuits); - } else if (! mp_indexer->is_single () && (index.column () == m_first_column || index.column () == m_second_column)) { - return make_link_to (pins_from_pinrefs (pinrefs), circuits, index.column ()); - } - - } else if (is_id_circuit_net_subcircuit_pin (id)) { - - // circuit/net/pin: header column = pin name, second column empty (for now) - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - - if (index.column () == m_object_column) { - return make_link_to (pins_from_pinrefs (pinrefs), circuit_refs) + tl::to_qstring (field_sep) + make_link_to (circuit_refs); - } else if (index.column () == m_first_column || index.column () == m_second_column) { - return make_link_to (subcircuits_from_pinrefs (pinrefs), index.column ()); - } - - } else if (is_id_circuit_net_subcircuit_pin_others (id)) { - - // circuit/net/device terminal/more: header column = pin name, second column = net link - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs); - size_t other_index = circuit_net_subcircuit_pin_other_index_from_id (id); - - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::pin_pair pins = mp_indexer->pin_from_index (circuit_refs, other_index).first; - - if (index.column () == m_object_column) { - return make_link_to (pins, circuit_refs); - } else if (index.column () == m_first_column || index.column () == m_second_column) { - return make_link_to (nets_from_subcircuit_pins (subcircuits, pins), index.column ()); - } - - } else if (is_id_circuit_net_device_terminal (id)) { - - // circuit/net/device terminal: header column = terminal and device string, second column = device name - IndexedNetlistModel::net_terminal_pair refs = net_terminalrefs_from_id (id); - IndexedNetlistModel::device_pair devices = devices_from_termrefs (refs); - - if (index.column () == m_object_column) { - - std::pair termdefs = terminal_defs_from_terminal_refs (refs); - - if (mp_indexer->is_single ()) { - return escaped (str_from_name (termdefs.first) + field_sep + device_string (devices.first)); - } else { - return escaped (str_from_names (termdefs, mp_indexer->is_single ()) + field_sep + devices_string (devices, mp_indexer->is_single (), true /*with parameters*/)); - } - - } else if (index.column () == m_first_column || index.column () == m_second_column) { - return make_link_to (devices, index.column ()); - } - - } else if (is_id_circuit_net_device_terminal_others (id)) { - - // circuit/net/device terminal/more: header column = terminal name, second column = net link - IndexedNetlistModel::net_terminal_pair refs = net_terminalrefs_from_id (id); - size_t other_index = circuit_net_device_terminal_other_index_from_id (id); - - IndexedNetlistModel::device_pair devices = devices_from_termrefs (refs); - std::pair device_classes = device_classes_from_devices (devices); - std::pair termdefs = terminal_defs_from_device_classes (device_classes, other_index); - - if (index.column () == m_object_column) { - - return escaped (str_from_names (termdefs, mp_indexer->is_single ())); - - } else if (index.column () == m_first_column || index.column () == m_second_column) { - - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (devices, termdefs); - return make_link_to (nets, index.column ()); - - } - + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d) { + return QString (); + } else { + return d->text (this); } - - return QString (); } static std::string combine_search_strings (const std::string &s1, const std::string &s2) @@ -1393,6 +482,1268 @@ static std::string combine_search_strings (const std::string &s1, const std::str } } +static size_t rows_for (const db::Device *device) +{ + if (! device || ! device->device_class ()) { + return 0; + } else { + return device->device_class ()->terminal_definitions ().size (); + } +} + +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::NetSubcircuitPinRef *ref) +{ + if (! ref || ! ref->subcircuit () || ! ref->subcircuit ()->circuit_ref ()) { + return 0; + } else { + return ref->subcircuit ()->circuit_ref ()->pin_count (); + } +} + +static size_t rows_for (const db::NetTerminalRef *ref) +{ + if (! ref || ! ref->device_class ()) { + return 0; + } else { + return ref->device_class ()->terminal_definitions ().size (); + } +} + +// ---------------------------------------------------------------------------------- +// item class declarations + +// ---------------------------------------------------------------------------------- +// item class implementations + +class CircuitItemData + : public NetlistModelItemData +{ +private: + CircuitItemData (const IndexedNetlistModel::circuit_pair &cp) + : NetlistModelItemData (), m_cp (cp) + { } + + virtual void do_ensure_children (NetlistBrowserModel *model) + { + size_t n; + + n = model->indexer ()->pin_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitPinItemData (this, model->indexer ()->pin_from_index (cp (), i))); + } + + n = model->indexer ()->net_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitNetItemData (this, model->indexer ()->net_from_index (cp (), i))); + } + + n = model->indexer ()->subcircuit_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitSubCircuitItemData (this, model->indexer ()->subcircuit_from_index (cp (), i))); + } + + n = model->indexer ()->device_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitDeviceItemData (this, model->indexer ()->device_from_index (cp (), i))); + } + } + + virtual QIcon icon () + { + return icon_for_circuit (); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit: + // + single mode: name | | + // + dual mode: name(a)/name(b) | name(a) | name(b) + if (column == model->object_column ()) { + return escaped (str_from_names (m_cp, model->indexer ()->is_single ())); + } else if (!model->indexer ()->is_single () && (column == model->first_column () || column == model->second_column ())) { + return escaped (str_from_name (column == model->first_column () ? m_cp.first : m_cp.second)); + } + } + + virtual QString search_text () + { + return tl::to_qstring (search_string_from_names (cp ())); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + size_t index = model->indexer ()->circuit_index (m_cp); + return model->indexer ()->circuit_status_hint (index); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) + { + size_t index = model->indexer ()->circuit_index (m_cp); + return model->indexer ()->circuit_from_index (index).second; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + return m_cp; + } + +private: + IndexedNetlistModel::circuit_pair m_cp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitPinItemData + : public NetlistModelItemData +{ +private: + CircuitPinItemData (CircuitItemData *parent, const IndexedNetlistModel::pin_pair &pp) + : NetlistModelItemData (parent), m_pp (pp) + { } + + virtual void do_ensure_children (NetlistBrowserModel * /*model*/) + { + push_back (new CircuitPinNetItemData (this, nets_from_circuit_pins (cp (), pp ()))); + } + + virtual QIcon icon () + { + return icon_for_pin (); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // pin: + // + 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 ())); + } 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)); + } + + return QString (); + } + + virtual QString search_text () + { + return tl::to_qstring (search_string_from_expanded_names (pp ())); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + size_t index = model->indexer ()->pin_index (pp (), cp ()); + return model->indexer ()->pin_status_hint (cp (), index); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) + { + size_t index = model->indexer ()->pin_index (pp (), cp ()); + return model->indexer ()->pin_from_index (cp (), index).second; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::pin_pair &pp () + { + return m_pp; + } + +private: + IndexedNetlistModel::pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitPinNetItemData + : public NetlistModelItemData +{ +private: + CircuitPinNetItemData (CircuitPinItemData *parent, const IndexedNetlistModel::net_pair &np) + : NetlistModelItemData (parent), m_np (np) + { } + + virtual void do_ensure_children (NetlistBrowserModel *model) + { + // nothing (leaf node) + } + + virtual QIcon icon () + { + return icon_for_connection (m_np); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/pin/net: header column = name, second column link to net + if (column == model->object_column ()) { + return escaped (str_from_expanded_names (m_np, model->indexer ()->is_single ())); + } else if (column == model->first_column () || column == model->second_column ()) { + return make_link_to (m_np, column); + } + + return QString (); + } + + virtual QString search_text () + { + return tl::to_qstring (search_string_from_expanded_names (nets_from_circuit_pins (cp (), pp ()))); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + return std::string (); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) + { + return db::NetlistCrossReference::None; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitPinItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::pin_pair &pp () + { + CircuitPinItemData *p = static_cast (parent ()); + return p->pp (); + } + +private: + IndexedNetlistModel::net_pair m_np; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetItemData + : public NetlistModelItemData +{ +private: + CircuitNetItemData (CircuitItemData *parent, const IndexedNetlistModel::net_pair &np) + : NetlistModelItemData (parent), m_np (np) + { } + + virtual void do_ensure_children (NetlistBrowserModel *model) + { + size_t n; + + n = model->indexer ()->net_terminal_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitNetDeviceTerminalItemData (this, model->indexer ()->net_terminalref_from_index (np (), i))); + } + + n = model->indexer ()->net_pin_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitNetPinItemData (this, model->indexer ()->net_pinref_from_index (np (), i))); + } + + n = model->indexer ()->net_subcircuit_pin_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitNetSubCircuitPinItemData (this, model->indexer ()->net_subcircuit_pinref_from_index (np (), i))); + } + } + + virtual QIcon icon () + { + return icon_for_nets (m_np); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/net: header column = node count, second column net name + if (column == model->object_column ()) { + return escaped (str_from_expanded_names (m_np, model->indexer ()->is_single ())); + } else if (column == model->first_column () && m_np.first) { + return escaped (m_np.first->expanded_name () + " (" + tl::to_string (m_np.first->pin_count () + m_np.first->terminal_count () + m_np.first->subcircuit_pin_count ()) + ")"); + } else if (column == model->second_column () && m_np.second) { + return escaped (m_np.second->expanded_name () + " (" + tl::to_string (m_np.second->pin_count () + m_np.second->terminal_count () + m_np.second->subcircuit_pin_count ()) + ")"); + } + + return QString (); + } + + virtual QString search_text () + { + return tl::to_qstring (search_string_from_expanded_names (m_np)); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + size_t index = model->indexer ()->net_index (m_np); + return model->indexer ()->net_status_hint (cp (), index); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) + { + size_t index = model->indexer ()->net_index (m_np); + return model->indexer ()->net_from_index (cp (), index).second; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::net_pair &np () + { + return m_np; + } + +private: + IndexedNetlistModel::net_pair m_np; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetDeviceTerminalItemData + : public NetlistModelItemData +{ +private: + CircuitNetDeviceTerminalItemData (CircuitNetItemData *parent, const IndexedNetlistModel::device_pair &dp, const IndexedNetlistModel::net_terminal_pair &tp) + : NetlistModelItemData (parent), m_dp (dp), m_tp (tp) + { } + + virtual void do_ensure_children (NetlistBrowserModel * /*model*/) + { + 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 termdefs = terminal_defs_from_terminal_refs (m_tp); + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), termdefs); + push_back (new CircuitNetDeviceTerminalOthersItemData (this, nets, termdefs)); + } + } + + virtual QIcon icon () + { + std::pair device_classes = device_classes_from_devices (m_dp); + return icon_for_devices (device_classes); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/net/device terminal: header column = terminal and device string, second column = device name + IndexedNetlistModel::device_pair devices = devices_from_termrefs (m_tp); + + if (column == model->object_column ()) { + + std::pair termdefs = terminal_defs_from_terminal_refs (m_tp); + + if (model->indexer ()->is_single ()) { + return escaped (str_from_name (termdefs.first) + field_sep + device_string (m_dp.first)); + } else { + return escaped (str_from_names (termdefs, model->indexer ()->is_single ()) + field_sep + devices_string (m_dp, model->indexer ()->is_single (), true /*with parameters*/)); + } + + } else if (column == model->first_column () || column == model->second_column ()) { + return make_link_to (m_dp, column); + } + + return QString (); + } + + virtual QString search_text () + { + std::pair device_classes = device_classes_from_devices (dp ()); + std::pair termdefs = terminal_defs_from_terminal_refs (tp ()); + return tl::to_qstring (combine_search_strings (combine_search_strings (search_string_from_names (termdefs), search_string_from_names (device_classes)), search_string_from_expanded_names (dp ()))); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + return model->indexer ()->device_status_hint (cp (), model->indexer ()->device_index (dp ())); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) + { + return model->indexer ()->device_from_index (cp (), model->indexer ()->device_index (dp ())).second; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitNetItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::net_pair &np () + { + CircuitNetItemData *p = static_cast (parent ()); + return p->np (); + } + + IndexedNetlistModel::device_pair dp () + { + return devices_from_termrefs (tp ()); + } + + const IndexedNetlistModel::net_terminal_pair &tp () + { + return m_tp; + } + +private: + IndexedNetlistModel::device_pair m_dp; + IndexedNetlistModel::net_terminal_pair m_tp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetDeviceTerminalOthersItemData + : public NetlistModelItemData +{ +private: + CircuitNetDeviceTerminalOthersItemData (CircuitNetItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp) + : NetlistModelItemData (parent), m_np (np), m_tp (tp) + { } + + virtual void do_ensure_children (NetlistBrowserModel *) + { + // nothing (leaf node) + } + + virtual QIcon icon () + { + return icon_for_connection (nets_from_device_terminals (dp (), m_tp)); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/net/device terminal/more: header column = terminal name, second column = net link + if (column == model->object_column ()) { + + return escaped (str_from_names (m_tp, model->indexer ()->is_single ())); + + } else if (column == model->first_column () || column == model->second_column ()) { + + return make_link_to (m_np, column); + + } + + return QString (); + } + + virtual QString search_text () + { + std::pair termdefs = terminal_defs_from_terminal_refs (m_tp); + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), termdefs); + return tl::to_qstring (combine_search_strings (search_string_from_names (termdefs), search_string_from_expanded_names (nets))); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + return std::string (); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/) + { + if (! is_valid_net_pair (nets_from_device_terminals (dp (), m_tp))) { + // This indicates a wrong connection: the nets are associated in a way which is a not + // corresponding to a mapped net pair. Report Mismatch here. + return db::NetlistCrossReference::NoMatch; + } + + return db::NetlistCrossReference::None; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitNetDeviceTerminalItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::device_pair &dp () + { + CircuitNetDeviceTerminalItemData *p = static_cast (parent ()); + return p->dp (); + } + +private: + std::pair m_tp; + IndexedNetlistModel::net_pair m_np; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetSubCircuitPinItemData + : public NetlistModelItemData +{ +private: + CircuitNetSubCircuitPinItemData (CircuitNetItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp) + : NetlistModelItemData (parent), m_pp (pp) + { } + + virtual void do_ensure_children (NetlistBrowserModel *model) + { + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (m_pp); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); + + size_t n = model->indexer ()->pin_count (circuit_refs); + for (size_t i = 0; i < n; ++i) { + IndexedNetlistModel::pin_pair pp = model->indexer ()->pin_from_index (circuit_refs, i); + push_back (new CircuitNetSubCircuitPinOthersItemData (this, pp)); + } + } + + virtual QIcon icon () + { + return icon_for_pin (); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/net/pin: header column = pin name, second column empty (for now) + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (m_pp); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); + + if (column == model->object_column ()) { + return make_link_to (pins_from_pinrefs (m_pp), circuit_refs) + tl::to_qstring (field_sep) + make_link_to (circuit_refs); + } else if (column == model->first_column () || column == model->second_column ()) { + return make_link_to (subcircuits, column); + } + + return QString (); + } + + virtual QString search_text () + { + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (m_sp); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); + return tl::to_qstring (combine_search_strings (combine_search_strings (search_string_from_names (m_pp), search_string_from_names (circuit_refs)), search_string_from_expanded_names (subcircuits))); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); + return model->indexer ()->subcircuit_status_hint (cp (), model->indexer ()->subcircuit_index (subcircuits)); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) + { + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); + return model->indexer ()->subcircuit_from_index (cp (), model->indexer ()->subcircuit_index (subcircuits)).second; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitNetItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::net_pair &np () + { + CircuitNetItemData *p = static_cast (parent ()); + return p->np (); + } + + const IndexedNetlistModel::net_subcircuit_pin_pair &pp () + { + return m_pp; + } + +private: + IndexedNetlistModel::net_subcircuit_pin_pair m_sp; + IndexedNetlistModel::pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetSubCircuitPinOthersItemData + : public NetlistModelItemData +{ +private: + CircuitNetSubCircuitPinOthersItemData (CircuitNetItemData *parent, const IndexedNetlistModel::pin_pair &pp) + : NetlistModelItemData (parent), m_pp (pp) + { } + + virtual void do_ensure_children (NetlistBrowserModel *) + { + // nothing (leaf node) + } + + virtual QIcon icon () + { + CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); + return icon_for_connection (nets_from_subcircuit_pins (subcircuits_from_pinrefs (p->pp ()), m_pp)); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/net/device terminal/more: header column = pin name, second column = net link + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); + + if (column == model->object_column ()) { + return make_link_to (m_pp, circuit_refs); + } else if (column == model->first_column () || column == model->second_column ()) { + return make_link_to (nets_from_subcircuit_pins (subcircuits, m_pp), column); + } + + return QString (); + } + + virtual QString search_text () + { + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); + IndexedNetlistModel::net_pair nets = nets_from_circuit_pins (circuit_refs, m_pp); + return tl::to_qstring (combine_search_strings (search_string_from_names (m_pp), search_string_from_expanded_names (nets))); + } + + virtual std::string tooltip (NetlistBrowserModel * /*model*/) + { + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); + std::string hint; + + if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, m_pp))) { + // This indicates a wrong connection: the nets are associated in a way which is a not + // corresponding to a mapped net pair. Report Mismatch here. + hint = rewire_subcircuit_pins_status_hint (); + } + + return hint; + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/) + { + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); + if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, m_pp))) { + // This indicates a wrong connection: the nets are associated in a way which is a not + // corresponding to a mapped net pair. Report Mismatch here. + return db::NetlistCrossReference::NoMatch; + } + + return db::NetlistCrossReference::None; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::device_pair &dp () + { + CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); + return p->dp (); + } + + const IndexedNetlistModel::net_subcircuit_pin_pair &pp () + { + CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); + return p->pp (); + } + +private: + IndexedNetlistModel::pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetPinItemData + : public NetlistModelItemData +{ +private: + CircuitNetPinItemData (CircuitNetItemData *parent, const IndexedNetlistModel::net_pin_pair &pp) + : NetlistModelItemData (parent), m_pp (pp) + { } + + virtual void do_ensure_children (NetlistBrowserModel *) + { + // nothing (leaf node) + } + + virtual QIcon icon () + { + return icon_for_pin (); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/net/pin: header column = pin name, second column empty (for now) + IndexedNetlistModel::circuit_pair circuits (m_pp.first && m_pp.first->net () ? m_pp.first->net ()->circuit () : 0, m_pp.second && m_pp.second->net () ? m_pp.second->net ()->circuit () : 0); + if (model->indexer ()->is_single () && column == model->object_column ()) { + return make_link_to (pins_from_pinrefs (m_pp), circuits); + } else if (! model->indexer ()->is_single () && (column == model->first_column () || column == model->second_column ())) { + return make_link_to (pins_from_pinrefs (m_pp), circuits, column); + } + + return QString (); + } + + virtual QString search_text () + { + return tl::to_qstring (search_string_from_names (m_pp)); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + return std::string (); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) + { + return db::NetlistCrossReference::None; + } + +private: + IndexedNetlistModel::net_pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitSubCircuitItemData + : public NetlistModelItemData +{ +private: + CircuitSubCircuitItemData (CircuitItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp) + : NetlistModelItemData (parent), m_sp (sp) + { } + + virtual void do_ensure_children (NetlistBrowserModel *model) + { + size_t n = std::max (rows_for (sp ().first), rows_for (sp ().second)); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); + for (size_t i = 0; i < n; ++i) { + IndexedNetlistModel::pin_pair pp = model->indexer ()->pin_from_index (circuit_refs, i).first; + push_back (new CircuitSubCircuitPinItemData (this, pp)); + } + } + + virtual QIcon icon () + { + return icon_for_circuit (); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/subcircuit: header column = circuit name, second column subcircuit name + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (m_sp); + if (column == model->object_column ()) { + return make_link_to (circuit_refs); + } else if (column == model->first_column ()) { + return escaped (str_from_expanded_name (m_sp.first)); + } else if (column == model->second_column ()) { + return escaped (str_from_expanded_name (subcircuits.second)); + } + + return QString (); + } + + virtual QString search_text () + { + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); + return tl::to_qstring (combine_search_strings (search_string_from_names (circuit_refs), search_string_from_expanded_names (sp ()))); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + size_t index = model->indexer ()->subcircuit_index (sp ()); + return model->indexer ()->subcircuit_status_hint (cp (), index); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) + { + size_t index = model->indexer ()->subcircuit_index (sp ()); + return model->indexer ()->subcircuit_from_index (cp (), index).second; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::subcircuit_pair &sp () + { + return m_sp; + } + +private: + IndexedNetlistModel::subcircuit_pair m_sp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitSubCircuitPinItemData + : public NetlistModelItemData +{ +private: + CircuitSubCircuitPinItemData (CircuitItemData *parent, const IndexedNetlistModel::pin_pair &pp) + : NetlistModelItemData (parent), m_pp (pp) + { } + + virtual void do_ensure_children (NetlistBrowserModel *) + { + // nothing (leaf node) + } + + virtual QIcon icon () + { + return icon_for_pin (); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/pin: header column = pin name, other columns net name + const IndexedNetlistModel::subcircuit_pair &sp = static_cast (parent ())->sp (); + + if (column == model->object_column ()) { + return make_link_to (m_pp, circuit_refs_from_subcircuits (sp)); + } else if (column == model->first_column () || column == model->second_column ()) { + return make_link_to (nets_from_subcircuit_pins (sp, m_pp), column); + } + + return QString (); + } + + virtual QString search_text () + { + IndexedNetlistModel::net_pair nets = nets_from_subcircuit_pins (sp (), m_pp); + return tl::to_qstring (combine_search_strings (search_string_from_names (m_pp), search_string_from_expanded_names (nets))); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); + + std::string hint = model->indexer ()->pin_status_hint (circuit_refs, model->indexer ()->pin_index (m_pp, circuit_refs)); + if (hint.empty ()) { + + // Another test here is to check whether the pins may be attached to an invalid net pair + if (! is_valid_net_pair (nets_from_subcircuit_pins (sp (), m_pp))) { + hint = rewire_subcircuit_pins_status_hint (); + } + + } + + return hint; + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) + { + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); + + db::NetlistCrossReference::Status status = model->indexer ()->pin_from_index (circuit_refs, model->indexer ()->pin_index (m_pp, circuit_refs)).second; + if (status == db::NetlistCrossReference::Mismatch || status == db::NetlistCrossReference::NoMatch) { + return status; + } + + // Another test here is to check whether the pins may be attached to an invalid net pair + if (! is_valid_net_pair (nets_from_subcircuit_pins (sp (), m_pp))) { + // This indicates a wrong connection: the nets are associated in a way which is a not + // corresponding to a mapped net pair. Report Mismatch here. + return db::NetlistCrossReference::NoMatch; + } + + return db::NetlistCrossReference::None; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitSubCircuitItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::subcircuit_pair &sp () + { + CircuitSubCircuitItemData *p = static_cast (parent ()); + return p->sp (); + } + +private: + IndexedNetlistModel::pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitDeviceItemData + : public NetlistModelItemData +{ +private: + CircuitDeviceItemData (CircuitItemData *parent, const IndexedNetlistModel::device_pair &dp) + : NetlistModelItemData (parent), m_dp (dp) + { } + + virtual void do_ensure_children (NetlistBrowserModel * /*model*/) + { + size_t n = std::max (rows_for (dp ().first), rows_for (dp ().second)); + for (size_t i = 0; i < n; ++i) { + std::pair tp = terminal_defs_from_device_classes (dp (), i); + push_back (new CircuitDeviceTerminalItemData (this, tp)); + } + } + + virtual QIcon icon () + { + std::pair device_classes = device_classes_from_devices (m_dp); + return icon_for_devices (device_classes); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/device: header column = class + parameters, second column device name + if (model->indexer ()->is_single ()) { + + if (column == model->object_column ()) { + return escaped (device_string (m_dp.first)); + } else if (column == model->first_column ()) { + return escaped (str_from_expanded_name (m_dp.first)); + } + + } else { + + if (column == model->object_column ()) { + return escaped (devices_string (m_dp, model->indexer ()->is_single (), false /*without parameters*/)); + } else if (column == model->first_column ()) { + return escaped (str_from_expanded_name (m_dp.first) + field_sep + device_string (m_dp.first)); + } else if (column == model->second_column ()) { + return escaped (str_from_expanded_name (m_dp.second) + field_sep + device_string (m_dp.second)); + } + + } + } + + virtual QString search_text () + { + std::pair device_classes = device_classes_from_devices (dp ()); + return tl::to_qstring (combine_search_strings (search_string_from_expanded_names (dp ()), search_string_from_names (device_classes))); + } + + virtual std::string tooltip (NetlistBrowserModel *model) + { + size_t index = model->indexer ()->device_index (m_dp); + hint = model->indexer ()->device_status_hint (cp (), index); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) + { + size_t index = model->indexer ()->device_index (m_dp); + return model->indexer ()->device_from_index (cp (), index).second; + } + + const IndexedNetlistModel::device_pair &dp () + { + return m_dp; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitItemData *p = static_cast (parent ()); + return p->cp (); + } + +private: + IndexedNetlistModel::device_pair m_dp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitDeviceTerminalItemData + : public NetlistModelItemData +{ +private: + CircuitDeviceTerminalItemData (CircuitDeviceItemData *parent, const std::pair &tp) + : NetlistModelItemData (parent), m_tp (tp) + { } + + virtual void do_ensure_children (NetlistBrowserModel *) + { + // nothing (leaf node) + } + + virtual QIcon icon () + { + const IndexedNetlistModel::device_pair &dp = static_cast (parent ())->dp (); + std::pair termdefs (m_tp.first ? m_tp.first->terminal_def () : 0, m_tp.second ? m_tp.second->terminal_def () : 0); + return icon_for_connection (nets_from_device_terminals (dp, termdefs)); + } + + virtual QString text (int column, NetlistBrowserModel *model) + { + // circuit/device/terminal: header column = terminal name, second column link to net + std::pair termdefs = terminal_defs_from_terminal_refs (m_tp);; + + if (column == model->object_column ()) { + + return escaped (str_from_names (termdefs, model->indexer ()->is_single ())); + + } else if (column == model->first_column () || column == model->second_column ()) { + + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), termdefs); + return make_link_to (nets, column); + + } + + return QString (); + } + + virtual QString search_text () + { + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); + return tl::to_qstring (combine_search_strings (search_string_from_names (m_tp), search_string_from_expanded_names (nets))); + } + + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/) + { + if (! is_valid_net_pair (nets_from_device_terminals (dp (), m_tp))) { + // This indicates a wrong connection: the nets are associated in a way which is a not + // corresponding to a mapped net pair. Report Mismatch here. + return db::NetlistCrossReference::NoMatch; + } + + return db::NetlistCrossReference::None; + } + + const IndexedNetlistModel::device_pair &dp () + { + CircuitDeviceItemData *p = static_cast (parent ()); + return p->dp (); + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitDeviceItemData *p = static_cast (parent ()); + return p->cp (); + } + +private: + std::pair m_tp; +}; + +// ---------------------------------------------------------------------------------- +// NetlistBrowserModel implementation + +static void *no_id = reinterpret_cast (-1); + +NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb, NetColorizer *colorizer) + : QAbstractItemModel (parent), mp_l2ndb (l2ndb), mp_lvsdb (0), mp_colorizer (colorizer) +{ + mp_indexer.reset (new SingleIndexedNetlistModel (l2ndb->netlist ())); + connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ())); + + m_object_column = 0; + m_status_column = -1; + m_first_column = 2; + m_second_column = -1; +} + +NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutVsSchematic *lvsdb, NetColorizer *colorizer) + : QAbstractItemModel (parent), mp_l2ndb (0), mp_lvsdb (lvsdb), mp_colorizer (colorizer) +{ + mp_indexer.reset (new NetlistCrossReferenceModel (lvsdb->cross_ref ())); + connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ())); + + m_object_column = 0; + m_status_column = 1; + m_first_column = 2; + m_second_column = 3; +} + +NetlistBrowserModel::~NetlistBrowserModel () +{ + // .. nothing yet .. +} + +int +NetlistBrowserModel::columnCount (const QModelIndex & /*parent*/) const +{ + // Item type & icon, link or description + return mp_indexer->is_single () ? 3 : 4; +} + +QIcon icon_for_status (db::NetlistCrossReference::Status status) +{ + if (status == db::NetlistCrossReference::NoMatch || status == db::NetlistCrossReference::Mismatch) { + return QIcon (":/error2_16.png"); + } else if (status == db::NetlistCrossReference::MatchWithWarning || status == db::NetlistCrossReference::Skipped) { + return QIcon (":/warn_16.png"); + } else { + return QIcon (); + } +} + +QVariant +NetlistBrowserModel::data (const QModelIndex &index, int role) const +{ + if (! index.isValid ()) { + return QVariant (); + } + + if (role == Qt::DecorationRole && index.column () == m_object_column) { + return QVariant (icon (index)); + } else if (role == Qt::DecorationRole && index.column () == m_status_column) { + return QVariant (icon_for_status (status (index))); + } else if (role == Qt::DisplayRole) { + return QVariant (text (index)); + } else if (role == Qt::ToolTipRole && index.column () == m_status_column) { + return tooltip (index); + } else if (role == Qt::UserRole) { + return QVariant (search_text (index)); + } else if (role == Qt::FontRole) { + db::NetlistCrossReference::Status st = status (index); + if (st == db::NetlistCrossReference::NoMatch || st == db::NetlistCrossReference::Mismatch || st == db::NetlistCrossReference::Skipped) { + QFont font; + font.setWeight (QFont::Bold); + return QVariant (font); + } + } else if (role == Qt::ForegroundRole) { + db::NetlistCrossReference::Status st = status (index); + if (st == db::NetlistCrossReference::Match || st == db::NetlistCrossReference::MatchWithWarning) { + // taken from marker browser: + return QVariant (QColor (0, 192, 0)); + } + } + return QVariant (); +} + +static QString build_url (void *id, const std::string &tag, const std::string &title) +{ + if (id == no_id) { + // no link + return tl::to_qstring (tl::escaped_to_html (title)); + } + + std::string s = std::string (""; + + s += tl::escaped_to_html (title); + + s += ""; + + return tl::to_qstring (s); +} + +QString +NetlistBrowserModel::make_link_to (const std::pair &nets, int column) const +{ + if ((! nets.first || column == m_second_column) && (! nets.second || column == m_first_column)) { + return QString (); + } else { + + IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (nets); + void *id = no_id; + // NOTE: the nets may not be a valid net pair. In this case, circuits is (0, 0) and + // no link is generated + if (circuits.first || circuits.second) { + id = make_id_circuit_net (mp_indexer->circuit_index (circuits), mp_indexer->net_index (nets)); + } + + if (mp_indexer->is_single () || column == m_first_column) { + return build_url (id, "net", str_from_expanded_name (nets.first)); + } else if (column == m_second_column) { + return build_url (id, "net", str_from_expanded_name (nets.second)); + } else { + return build_url (id, "net", str_from_expanded_names (nets, mp_indexer->is_single ())); + } + + } +} + +QString +NetlistBrowserModel::make_link_to (const std::pair &devices, int column) const +{ + if ((! devices.first || column == m_second_column) && (! devices.second || column == m_first_column)) { + return QString (); + } else { + + IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (devices); + void *id = no_id; + // NOTE: the devices may not be a valid device pair. In this case, circuits is (0, 0) and + // no link is generated + if (circuits.first || circuits.second) { + id = make_id_circuit_device (mp_indexer->circuit_index (circuits), mp_indexer->device_index (devices)); + } + + if (mp_indexer->is_single () || column == m_first_column) { + return build_url (id, "device", str_from_expanded_name (devices.first)); + } else if (column == m_second_column) { + return build_url (id, "device", str_from_expanded_name (devices.second)); + } else { + return build_url (id, "device", str_from_expanded_names (devices, mp_indexer->is_single ())); + } + + } +} + +QString +NetlistBrowserModel::make_link_to (const std::pair &pins, const std::pair &circuits, int column) const +{ + if ((! pins.first || column == m_second_column) && (! pins.second || column == m_first_column)) { + return QString (); + } else { + void *id = make_id_circuit_pin (mp_indexer->circuit_index (circuits), mp_indexer->pin_index (pins, circuits)); + if (mp_indexer->is_single () || column == m_first_column) { + return build_url (id, "pin", str_from_expanded_name (pins.first)); + } else if (column == m_second_column) { + return build_url (id, "pin", str_from_expanded_name (pins.second)); + } else { + return build_url (id, "pin", str_from_expanded_names (pins, mp_indexer->is_single ())); + } + } +} + +QString +NetlistBrowserModel::make_link_to (const std::pair &circuits, int column) const +{ + if ((! circuits.first || column == m_second_column) && (! circuits.second || column == m_first_column)) { + return QString (); + } else { + void *id = make_id_circuit (mp_indexer->circuit_index (circuits)); + if (mp_indexer->is_single () || column == m_first_column) { + return build_url (id, "circuit", str_from_name (circuits.first)); + } else if (column == m_second_column) { + return build_url (id, "circuit", str_from_name (circuits.second)); + } else { + return build_url (id, "circuit", str_from_names (circuits, mp_indexer->is_single ())); + } + } +} + +QString +NetlistBrowserModel::make_link_to (const std::pair &subcircuits, int column) const +{ + if ((! subcircuits.first || column == m_second_column) && (! subcircuits.second || column == m_first_column)) { + return QString (); + } else { + + IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (subcircuits); + void *id = no_id; + // NOTE: the subcircuits may not be a valid subcircuit pair. In this case, circuits is (0, 0) and + // no link is generated + if (circuits.first || circuits.second) { + id = make_id_circuit_subcircuit (mp_indexer->circuit_index (circuits), mp_indexer->subcircuit_index (subcircuits)); + } + + if (mp_indexer->is_single () || column == m_first_column) { + return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.first)); + } else if (column == m_second_column) { + return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.second)); + } else { + return build_url (id, "subcircuit", str_from_expanded_names (subcircuits, mp_indexer->is_single ())); + } + + } +} + template static std::string search_string_from_expanded_names (const std::pair &objs) { @@ -1437,118 +1788,12 @@ NetlistBrowserModel::is_valid_net_pair (const std::paircircuit_from_index (index).second; - - } else if (is_id_circuit_pin (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_pin_index_from_id (id); - return mp_indexer->pin_from_index (circuits, index).second; - - } else if (is_id_circuit_device (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_device_index_from_id (id); - return mp_indexer->device_from_index (circuits, index).second; - - } else if (is_id_circuit_device_terminal (id)) { - - IndexedNetlistModel::device_pair devices = devices_from_id (id); - std::pair device_classes = device_classes_from_devices (devices); - size_t terminal = circuit_device_terminal_index_from_id (id); - - std::pair termdefs = terminal_defs_from_device_classes (device_classes, terminal); - - if (! is_valid_net_pair (nets_from_device_terminals (devices, termdefs))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - } else if (is_id_circuit_subcircuit (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_subcircuit_index_from_id (id); - return mp_indexer->subcircuit_from_index (circuits, index).second; - - } else if (is_id_circuit_subcircuit_pin (id)) { - - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_id (id); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::pin_pair pins = pins_from_id (id); - - db::NetlistCrossReference::Status status = mp_indexer->pin_from_index (circuit_refs, mp_indexer->pin_index (pins, circuit_refs)).second; - if (status == db::NetlistCrossReference::Mismatch || status == db::NetlistCrossReference::NoMatch) { - return status; - } - - // Another test here is to check whether the pins may be attached to an invalid net pair - if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, pins))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - } else if (is_id_circuit_net (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_net_index_from_id (id); - return mp_indexer->net_from_index (circuits, index).second; - - } else if (is_id_circuit_net_device_terminal (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - IndexedNetlistModel::net_terminal_pair termrefs = net_terminalrefs_from_id (id); - IndexedNetlistModel::device_pair devices = devices_from_termrefs (termrefs); - - return mp_indexer->device_from_index (circuits, mp_indexer->device_index (devices)).second; - - } else if (is_id_circuit_net_device_terminal_others (id)) { - - IndexedNetlistModel::net_terminal_pair termrefs = net_terminalrefs_from_id (id); - size_t other_index = circuit_net_device_terminal_other_index_from_id (id); - - IndexedNetlistModel::device_pair devices = devices_from_termrefs (termrefs); - std::pair device_classes = device_classes_from_devices (devices); - std::pair termdefs = terminal_defs_from_device_classes (device_classes, other_index); - - if (! is_valid_net_pair (nets_from_device_terminals (devices, termdefs))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - } else if (is_id_circuit_net_subcircuit_pin (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs); - - return mp_indexer->subcircuit_from_index (circuits, mp_indexer->subcircuit_index (subcircuits)).second; - - } else if (is_id_circuit_net_subcircuit_pin_others (id)) { - - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs); - size_t other_index = circuit_net_subcircuit_pin_other_index_from_id (id); - - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::pin_pair pins = mp_indexer->pin_from_index (circuit_refs, other_index).first; - - if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, pins))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d) { + return db::NetlistCrossReference::None; + } else { + return d->status (this); } - - return db::NetlistCrossReference::None; } static std::string rewire_subcircuit_pins_status_hint () @@ -1559,85 +1804,10 @@ static std::string rewire_subcircuit_pins_status_hint () QVariant NetlistBrowserModel::tooltip (const QModelIndex &index) const { - void *id = index.internalPointer (); std::string hint; - - if (is_id_circuit (id)) { - - size_t index = circuit_index_from_id (id); - hint = mp_indexer->circuit_status_hint (index); - - } else if (is_id_circuit_pin (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_pin_index_from_id (id); - hint = mp_indexer->pin_status_hint (circuits, index); - - } else if (is_id_circuit_device (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_device_index_from_id (id); - hint = mp_indexer->device_status_hint (circuits, index); - - } else if (is_id_circuit_subcircuit (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_subcircuit_index_from_id (id); - hint = mp_indexer->subcircuit_status_hint (circuits, index); - - } else if (is_id_circuit_subcircuit_pin (id)) { - - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_id (id); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::pin_pair pins = pins_from_id (id); - - hint = mp_indexer->pin_status_hint (circuit_refs, mp_indexer->pin_index (pins, circuit_refs)); - if (hint.empty ()) { - - // Another test here is to check whether the pins may be attached to an invalid net pair - if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, pins))) { - hint = rewire_subcircuit_pins_status_hint (); - } - - } - - } else if (is_id_circuit_net (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_net_index_from_id (id); - hint = mp_indexer->net_status_hint (circuits, index); - - } else if (is_id_circuit_net_device_terminal (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - IndexedNetlistModel::net_terminal_pair termrefs = net_terminalrefs_from_id (id); - IndexedNetlistModel::device_pair devices = devices_from_termrefs (termrefs); - - hint = mp_indexer->device_status_hint (circuits, mp_indexer->device_index (devices)); - - } else if (is_id_circuit_net_subcircuit_pin (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs); - - hint = mp_indexer->subcircuit_status_hint (circuits, mp_indexer->subcircuit_index (subcircuits)); - - } else if (is_id_circuit_net_subcircuit_pin_others (id)) { - - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs); - size_t other_index = circuit_net_subcircuit_pin_other_index_from_id (id); - - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::pin_pair pins = mp_indexer->pin_from_index (circuit_refs, other_index).first; - - if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, pins))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - hint = rewire_subcircuit_pins_status_hint (); - } - + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (d) { + hint = d->tooltip (this); } if (hint.empty ()) { @@ -1650,110 +1820,12 @@ NetlistBrowserModel::tooltip (const QModelIndex &index) const QString NetlistBrowserModel::search_text (const QModelIndex &index) const { - void *id = index.internalPointer (); - - if (is_id_circuit (id)) { - - return tl::to_qstring (search_string_from_names (circuits_from_id (id))); - - } else if (is_id_circuit_pin (id)) { - - return tl::to_qstring (search_string_from_expanded_names (pins_from_id (id))); - - } else if (is_id_circuit_pin_net (id)) { - - return tl::to_qstring (search_string_from_expanded_names (nets_from_circuit_pins (circuits_from_id (id), pins_from_id (id)))); - - } else if (is_id_circuit_device (id)) { - - IndexedNetlistModel::device_pair devices = devices_from_id (id); - std::pair device_classes = device_classes_from_devices (devices); - return tl::to_qstring (combine_search_strings (search_string_from_expanded_names (devices), search_string_from_names (device_classes))); - - } else if (is_id_circuit_device_terminal (id)) { - - IndexedNetlistModel::device_pair devices = devices_from_id (id); - std::pair device_classes = device_classes_from_devices (devices); - size_t terminal = circuit_device_terminal_index_from_id (id); - - std::pair termdefs = terminal_defs_from_device_classes (device_classes, terminal); - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (devices, termdefs); - - return tl::to_qstring (combine_search_strings (search_string_from_names (termdefs), search_string_from_expanded_names (nets))); - - } else if (is_id_circuit_subcircuit (id)) { - - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_id (id); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - - return tl::to_qstring (combine_search_strings (search_string_from_names (circuit_refs), search_string_from_expanded_names (subcircuits))); - - } else if (is_id_circuit_subcircuit_pin (id)) { - - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_id (id); - IndexedNetlistModel::pin_pair pins = pins_from_id (id); - IndexedNetlistModel::net_pair nets = nets_from_subcircuit_pins (subcircuits, pins); - - return tl::to_qstring (combine_search_strings (search_string_from_names (pins), search_string_from_expanded_names (nets))); - - } else if (is_id_circuit_net (id)) { - - return tl::to_qstring (search_string_from_expanded_names (nets_from_id (id))); - - } else if (is_id_circuit_net_pin (id)) { - - IndexedNetlistModel::net_pin_pair pinrefs = net_pinrefs_from_id (id); - IndexedNetlistModel::pin_pair pins = pins_from_pinrefs (pinrefs); - - return tl::to_qstring (search_string_from_names (pins)); - - } else if (is_id_circuit_net_subcircuit_pin (id)) { - - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::pin_pair pins = pins_from_pinrefs (pinrefs); - - return tl::to_qstring (combine_search_strings (combine_search_strings (search_string_from_names (pins), search_string_from_names (circuit_refs)), search_string_from_expanded_names (subcircuits))); - - } else if (is_id_circuit_net_subcircuit_pin_others (id)) { - - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - size_t other_index = circuit_net_subcircuit_pin_other_index_from_id (id); - - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - - IndexedNetlistModel::pin_pair pins = mp_indexer->pin_from_index (circuit_refs, other_index).first; - IndexedNetlistModel::net_pair nets = nets_from_circuit_pins (circuit_refs, pins); - - return tl::to_qstring (combine_search_strings (search_string_from_names (pins), search_string_from_expanded_names (nets))); - - } else if (is_id_circuit_net_device_terminal (id)) { - - IndexedNetlistModel::net_terminal_pair termrefs = net_terminalrefs_from_id (id); - IndexedNetlistModel::device_pair devices = devices_from_termrefs (termrefs); - std::pair device_classes = device_classes_from_devices (devices); - std::pair termdefs = terminal_defs_from_terminal_refs (termrefs); - - return tl::to_qstring (combine_search_strings (combine_search_strings (search_string_from_names (termdefs), search_string_from_names (device_classes)), search_string_from_expanded_names (devices))); - - } else if (is_id_circuit_net_device_terminal_others (id)) { - - IndexedNetlistModel::net_terminal_pair termrefs = net_terminalrefs_from_id (id); - size_t other_index = circuit_net_device_terminal_other_index_from_id (id); - - IndexedNetlistModel::device_pair devices = devices_from_termrefs (termrefs); - std::pair device_classes = device_classes_from_devices (devices); - std::pair termdefs = terminal_defs_from_device_classes (device_classes, other_index); - - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (devices, termdefs); - - return tl::to_qstring (combine_search_strings (search_string_from_names (termdefs), search_string_from_expanded_names (nets))); - + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (d) { + return d->search_text (); + } else { + return QString (); } - - return QString (); } static QIcon icon_for_net () @@ -1951,46 +2023,12 @@ NetlistBrowserModel::icon_for_connection (const std::pair device_classes = device_classes_from_devices (devices); - - return icon_for_devices (device_classes); - - } else if (is_id_circuit_pin_net (id) || is_id_circuit_device_terminal (id) || is_id_circuit_net_device_terminal_others (id) || is_id_circuit_net_subcircuit_pin_others (id)) { - - IndexedNetlistModel::net_pair nets = net_from_index (index); - return icon_for_connection (nets); - - } else if (is_id_circuit_subcircuit (id)) { - return icon_for_circuit (); - } else if (is_id_circuit_subcircuit_pin (id) || is_id_circuit_net_pin (id)) { - return icon_for_pin (); - } else if (is_id_circuit_net_subcircuit_pin (id)) { - return icon_for_circuit (); - } else if (is_id_circuit_net_device_terminal (id)) { - - IndexedNetlistModel::net_terminal_pair termrefs = net_terminalrefs_from_id (id); - IndexedNetlistModel::device_pair devices = devices_from_termrefs (termrefs); - std::pair device_classes = device_classes_from_devices (devices); - - return icon_for_devices (device_classes); - + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d) { + return QIcon (); + } else { + return d->icon (); } - - return QIcon (); } Qt::ItemFlags @@ -1999,96 +2037,15 @@ NetlistBrowserModel::flags (const QModelIndex & /*index*/) const return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } -static size_t rows_for (const db::Device *device) -{ - if (! device || ! device->device_class ()) { - return 0; - } else { - return device->device_class ()->terminal_definitions ().size (); - } -} - -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::NetSubcircuitPinRef *ref) -{ - if (! ref || ! ref->subcircuit () || ! ref->subcircuit ()->circuit_ref ()) { - return 0; - } else { - return ref->subcircuit ()->circuit_ref ()->pin_count (); - } -} - -static size_t rows_for (const db::NetTerminalRef *ref) -{ - if (! ref || ! ref->device_class ()) { - return 0; - } else { - return ref->device_class ()->terminal_definitions ().size (); - } -} - bool NetlistBrowserModel::hasChildren (const QModelIndex &parent) const { - if (! parent.isValid ()) { - - return mp_indexer.get () && mp_indexer->circuit_count () > 0; - + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d) { + return false; } else { - - void *id = parent.internalPointer (); - - if (is_id_circuit (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - return mp_indexer->device_count (circuits) > 0 || - mp_indexer->subcircuit_count (circuits) > 0 || - mp_indexer->pin_count (circuits) > 0 || - mp_indexer->net_count (circuits) > 0; - - } else if (is_id_circuit_pin (id)) { - - return true; - - } else if (is_id_circuit_device (id)) { - - IndexedNetlistModel::device_pair devices = devices_from_id (id); - return rows_for (devices.first) > 0 || rows_for (devices.second) > 0; - - } else if (is_id_circuit_subcircuit (id)) { - - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_id (id); - return rows_for (subcircuits.first) > 0 || rows_for (subcircuits.second) > 0; - - } else if (is_id_circuit_net (id)) { - - IndexedNetlistModel::net_pair nets = nets_from_id (id); - return mp_indexer->net_pin_count (nets) > 0 || - mp_indexer->net_terminal_count (nets) > 0 || - mp_indexer->net_subcircuit_pin_count (nets) > 0; - - } else if (is_id_circuit_net_subcircuit_pin (id)) { - - IndexedNetlistModel::net_subcircuit_pin_pair refs = net_subcircuit_pinrefs_from_id (id); - return rows_for (refs.first) > 0 || rows_for (refs.second) > 0; - - } else if (is_id_circuit_net_device_terminal (id)) { - - IndexedNetlistModel::net_terminal_pair refs = net_terminalrefs_from_id (id); - return rows_for (refs.first) > 0 || rows_for (refs.second) > 0; - - } else { - return false; - } - + d->ensure_children (this); + return d->begin () != d->end (); } } @@ -2123,90 +2080,12 @@ NetlistBrowserModel::headerData (int section, Qt::Orientation /*orientation*/, i QModelIndex NetlistBrowserModel::index (int row, int column, const QModelIndex &parent) const { - void *new_id = no_id; - - if (! parent.isValid ()) { - - new_id = make_id_circuit (row); - - } else { - - void *id = parent.internalPointer (); - - if (is_id_circuit (id)) { - - int r = row; - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - int rpins = int (mp_indexer->pin_count (circuits)); - if (r < rpins) { - new_id = make_id_circuit_pin (circuit_index_from_id (id), size_t (r)); - } else { - r -= rpins; - int rnets = int (mp_indexer->net_count (circuits)); - if (r < int (rnets)) { - new_id = make_id_circuit_net (circuit_index_from_id (id), size_t (r)); - } else { - r -= int (rnets); - int rsubcircuits = int (mp_indexer->subcircuit_count (circuits)); - if (r < rsubcircuits) { - new_id = make_id_circuit_subcircuit (circuit_index_from_id (id), size_t (r)); - } else { - r -= rsubcircuits; - if (r < int (mp_indexer->device_count (circuits))) { - new_id = make_id_circuit_device (circuit_index_from_id (id), size_t (r)); - } - } - } - } - - } else if (is_id_circuit_pin (id)) { - - new_id = make_id_circuit_pin_net (circuit_index_from_id (id), circuit_pin_index_from_id (id), size_t (row)); - - } else if (is_id_circuit_device (id)) { - - new_id = make_id_circuit_device_terminal (circuit_index_from_id (id), circuit_device_index_from_id (id), size_t (row)); - - } else if (is_id_circuit_subcircuit (id)) { - - new_id = make_id_circuit_subcircuit_pin (circuit_index_from_id (id), circuit_subcircuit_index_from_id (id), size_t (row)); - - } else if (is_id_circuit_net (id)) { - - int r = row; - IndexedNetlistModel::net_pair nets = nets_from_id (id); - int rterminals = int (mp_indexer->net_terminal_count (nets)); - if (r < rterminals){ - new_id = make_id_circuit_net_device_terminal (circuit_index_from_id (id), circuit_net_index_from_id (id), size_t (r)); - } else { - r -= rterminals; - int rpins = int (mp_indexer->net_pin_count (nets)); - if (r < rpins) { - new_id = make_id_circuit_net_pin (circuit_index_from_id (id), circuit_net_index_from_id (id), size_t (r)); - } else { - r -= rpins; - if (r < int (mp_indexer->net_subcircuit_pin_count (nets))) { - new_id = make_id_circuit_net_subcircuit_pin (circuit_index_from_id (id), circuit_net_index_from_id (id), size_t (r)); - } - } - } - - } else if (is_id_circuit_net_subcircuit_pin (id)) { - - new_id = 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), size_t (row)); - - } else if (is_id_circuit_net_device_terminal (id)) { - - new_id = 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), size_t (row)); - - } - - } - - if (new_id != no_id) { - return createIndex (row, column, new_id); - } else { + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d) { return QModelIndex (); + } else { + d->ensure_children (this); + return createIndex (row, column, (void *) d->child (size_t (row))); } } @@ -2416,108 +2295,23 @@ NetlistBrowserModel::index_from_id (void *id, int column) const QModelIndex NetlistBrowserModel::parent (const QModelIndex &index) const { - if (! index.isValid ()) { - + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d || ! d->parent ()) { return QModelIndex (); - } else { - - void *id = index.internalPointer (); - int column = 0; - - 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)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - return createIndex (int (mp_indexer->pin_count (circuits) + 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)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - return createIndex (int (mp_indexer->pin_count (circuits) + mp_indexer->net_count (circuits) + 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)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - return createIndex (int (mp_indexer->pin_count (circuits) + mp_indexer->net_count (circuits) + mp_indexer->subcircuit_count (circuits) + circuit_device_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)) { - - IndexedNetlistModel::net_pair nets = nets_from_id (id); - return createIndex (size_t (mp_indexer->net_terminal_count (nets) + mp_indexer->net_pin_count (nets) + 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 createIndex (d->parent ()->index (), column, (void *) d->parent ()); } - - return QModelIndex (); } int NetlistBrowserModel::rowCount (const QModelIndex &parent) const { - if (! parent.isValid ()) { - - return int (mp_indexer.get () ? mp_indexer->circuit_count () : 0); - + NetlistModelItemData *d = (NetlistModelItemData *) (parent.internalPointer ()); + if (! d) { + return 0; } else { - - void *id = parent.internalPointer (); - - if (is_id_circuit (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - return int (mp_indexer->pin_count (circuits) + mp_indexer->net_count (circuits) + mp_indexer->subcircuit_count (circuits) + mp_indexer->device_count (circuits)); - - } else if (is_id_circuit_pin (id)) { - - return 1; - - } else if (is_id_circuit_device (id)) { - - IndexedNetlistModel::device_pair devices = devices_from_id (id); - return int (std::max (rows_for (devices.first), rows_for (devices.second))); - - } else if (is_id_circuit_subcircuit (id)) { - - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_id (id); - return int (std::max (rows_for (subcircuits.first), rows_for (subcircuits.second))); - - } else if (is_id_circuit_net_subcircuit_pin (id)) { - - IndexedNetlistModel::net_subcircuit_pin_pair refs = net_subcircuit_pinrefs_from_id (id); - return std::max (rows_for (refs.first), rows_for (refs.second)); - - } else if (is_id_circuit_net_device_terminal (id)) { - - IndexedNetlistModel::net_terminal_pair refs = net_terminalrefs_from_id (id); - return std::max (rows_for (refs.first), rows_for (refs.second)); - - } else if (is_id_circuit_net (id)) { - - IndexedNetlistModel::net_pair nets = nets_from_id (id); - return int (mp_indexer->net_terminal_count (nets) + mp_indexer->net_pin_count (nets) + mp_indexer->net_subcircuit_pin_count (nets)); - - } - + return int (d->child_count ()); } - - return 0; } std::pair diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.h b/src/laybasic/laybasic/layNetlistBrowserModel.h index ac38f461a..52df8f104 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.h +++ b/src/laybasic/laybasic/layNetlistBrowserModel.h @@ -30,6 +30,9 @@ #include "dbLayoutToNetlist.h" #include "dbLayoutVsSchematic.h" +#include "tlList.h" +#include "tlTypeTraits.h" + #include #include @@ -88,6 +91,101 @@ private: // ---------------------------------------------------------------------------------- // NetlistBrowserModel definition +class NetlistBrowserModel; + +/** + * @brief A base class for the item data object + */ +class NetlistModelItemData + : public tl::list_node +{ +public: + typedef tl::list::iterator iterator; + + NetlistModelItemData () + : mp_parent (0), m_children_made (false), m_index (0) + { } + + NetlistModelItemData (NetlistModelItemData *parent) + : mp_parent (parent), m_children_made (false), m_index (0) + { } + + virtual int children () = 0; + virtual NetlistModelItemData *parent () { return mp_parent; } + + virtual QIcon icon () = 0; + virtual QString text (int column, NetlistBrowserModel *model) = 0; + virtual QString search_text () = 0; + virtual std::string tooltip (NetlistBrowserModel *model) = 0; + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) = 0; + + void ensure_children (NetlistBrowserModel *model) + { + if (! m_children_made) { + + m_children.clear (); + m_children_per_index.clear (); + + do_ensure_children (model); + + size_t n = 0; + for (iterator i = begin (); i != end (); ++i) { + ++n; + } + m_children_per_index.reserve (n); + + size_t index = 0; + for (iterator i = begin (); i != end (); ++i) { + m_children_per_index.push_back (i.operator-> ()); + i->set_index (index++); + } + + m_children_made = true; + + } + } + + void push_back (NetlistModelItemData *child) + { + m_children.push_back (child); + } + + iterator begin () { return m_children.begin (); } + iterator end () { return m_children.end (); } + + size_t child_count () { return m_children_per_index.size (); } + size_t index () { return m_index; } + + NetlistModelItemData *child (size_t n) + { + return (n < m_children_per_index.size () ? m_children_per_index [n] : 0); + } + +private: + NetlistModelItemData *mp_parent; + tl::list m_children; + std::vector m_children_per_index; + bool m_children_made; + size_t m_index; + + void set_index (size_t index) { m_index = index; } + + virtual void do_ensure_children (NetlistBrowserModel *model) = 0; +}; + +} + +namespace tl { + // disable copying for NetlistModelItemData + template<> struct type_traits + { + typedef false_tag has_copy_constructor; + }; +} + +namespace lay +{ + /** * @brief The NetlistBrowserModel * @@ -132,6 +230,26 @@ public: return m_status_column; } + int object_column () const + { + return m_object_column; + } + + int first_column () const + { + return m_first_column; + } + + int second_column () const + { + return m_second_column; + } + + IndexedNetlistModel *indexer () + { + return mp_indexer.get (); + } + std::pair net_from_index (const QModelIndex &index) const; QModelIndex index_from_net (const std::pair &net) const; QModelIndex index_from_net (const db::Net *net) const; @@ -236,6 +354,7 @@ private: int m_status_column; int m_first_column; int m_second_column; + std::auto_ptr m_root; }; } // namespace lay From 03bf0a557e76d2f32002d231909f4cbff94d414d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 17 Jun 2020 23:14:20 +0200 Subject: [PATCH 09/32] WIP: refactoring for more comfortable net browser --- .../laybasic/layNetlistBrowserModel.cc | 3513 +++++++++-------- .../laybasic/layNetlistBrowserModel.h | 230 +- .../laybasic/layNetlistBrowserPage.cc | 2 +- 3 files changed, 2012 insertions(+), 1733 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index e0a00810b..028ead3d3 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -467,7 +467,7 @@ NetlistBrowserModel::text (const QModelIndex &index) const if (! d) { return QString (); } else { - return d->text (this); + return d->text (index.column (), const_cast (this)); } } @@ -500,15 +500,6 @@ static size_t rows_for (const db::SubCircuit *subcircuit) } } -static size_t rows_for (const db::NetSubcircuitPinRef *ref) -{ - if (! ref || ! ref->subcircuit () || ! ref->subcircuit ()->circuit_ref ()) { - return 0; - } else { - return ref->subcircuit ()->circuit_ref ()->pin_count (); - } -} - static size_t rows_for (const db::NetTerminalRef *ref) { if (! ref || ! ref->device_class ()) { @@ -518,1316 +509,6 @@ static size_t rows_for (const db::NetTerminalRef *ref) } } -// ---------------------------------------------------------------------------------- -// item class declarations - -// ---------------------------------------------------------------------------------- -// item class implementations - -class CircuitItemData - : public NetlistModelItemData -{ -private: - CircuitItemData (const IndexedNetlistModel::circuit_pair &cp) - : NetlistModelItemData (), m_cp (cp) - { } - - virtual void do_ensure_children (NetlistBrowserModel *model) - { - size_t n; - - n = model->indexer ()->pin_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitPinItemData (this, model->indexer ()->pin_from_index (cp (), i))); - } - - n = model->indexer ()->net_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitNetItemData (this, model->indexer ()->net_from_index (cp (), i))); - } - - n = model->indexer ()->subcircuit_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitSubCircuitItemData (this, model->indexer ()->subcircuit_from_index (cp (), i))); - } - - n = model->indexer ()->device_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitDeviceItemData (this, model->indexer ()->device_from_index (cp (), i))); - } - } - - virtual QIcon icon () - { - return icon_for_circuit (); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit: - // + single mode: name | | - // + dual mode: name(a)/name(b) | name(a) | name(b) - if (column == model->object_column ()) { - return escaped (str_from_names (m_cp, model->indexer ()->is_single ())); - } else if (!model->indexer ()->is_single () && (column == model->first_column () || column == model->second_column ())) { - return escaped (str_from_name (column == model->first_column () ? m_cp.first : m_cp.second)); - } - } - - virtual QString search_text () - { - return tl::to_qstring (search_string_from_names (cp ())); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - size_t index = model->indexer ()->circuit_index (m_cp); - return model->indexer ()->circuit_status_hint (index); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) - { - size_t index = model->indexer ()->circuit_index (m_cp); - return model->indexer ()->circuit_from_index (index).second; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - return m_cp; - } - -private: - IndexedNetlistModel::circuit_pair m_cp; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitPinItemData - : public NetlistModelItemData -{ -private: - CircuitPinItemData (CircuitItemData *parent, const IndexedNetlistModel::pin_pair &pp) - : NetlistModelItemData (parent), m_pp (pp) - { } - - virtual void do_ensure_children (NetlistBrowserModel * /*model*/) - { - push_back (new CircuitPinNetItemData (this, nets_from_circuit_pins (cp (), pp ()))); - } - - virtual QIcon icon () - { - return icon_for_pin (); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // pin: - // + 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 ())); - } 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)); - } - - return QString (); - } - - virtual QString search_text () - { - return tl::to_qstring (search_string_from_expanded_names (pp ())); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - size_t index = model->indexer ()->pin_index (pp (), cp ()); - return model->indexer ()->pin_status_hint (cp (), index); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) - { - size_t index = model->indexer ()->pin_index (pp (), cp ()); - return model->indexer ()->pin_from_index (cp (), index).second; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitItemData *p = static_cast (parent ()); - return p->cp (); - } - - const IndexedNetlistModel::pin_pair &pp () - { - return m_pp; - } - -private: - IndexedNetlistModel::pin_pair m_pp; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitPinNetItemData - : public NetlistModelItemData -{ -private: - CircuitPinNetItemData (CircuitPinItemData *parent, const IndexedNetlistModel::net_pair &np) - : NetlistModelItemData (parent), m_np (np) - { } - - virtual void do_ensure_children (NetlistBrowserModel *model) - { - // nothing (leaf node) - } - - virtual QIcon icon () - { - return icon_for_connection (m_np); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/pin/net: header column = name, second column link to net - if (column == model->object_column ()) { - return escaped (str_from_expanded_names (m_np, model->indexer ()->is_single ())); - } else if (column == model->first_column () || column == model->second_column ()) { - return make_link_to (m_np, column); - } - - return QString (); - } - - virtual QString search_text () - { - return tl::to_qstring (search_string_from_expanded_names (nets_from_circuit_pins (cp (), pp ()))); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - return std::string (); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) - { - return db::NetlistCrossReference::None; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitPinItemData *p = static_cast (parent ()); - return p->cp (); - } - - const IndexedNetlistModel::pin_pair &pp () - { - CircuitPinItemData *p = static_cast (parent ()); - return p->pp (); - } - -private: - IndexedNetlistModel::net_pair m_np; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitNetItemData - : public NetlistModelItemData -{ -private: - CircuitNetItemData (CircuitItemData *parent, const IndexedNetlistModel::net_pair &np) - : NetlistModelItemData (parent), m_np (np) - { } - - virtual void do_ensure_children (NetlistBrowserModel *model) - { - size_t n; - - n = model->indexer ()->net_terminal_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitNetDeviceTerminalItemData (this, model->indexer ()->net_terminalref_from_index (np (), i))); - } - - n = model->indexer ()->net_pin_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitNetPinItemData (this, model->indexer ()->net_pinref_from_index (np (), i))); - } - - n = model->indexer ()->net_subcircuit_pin_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitNetSubCircuitPinItemData (this, model->indexer ()->net_subcircuit_pinref_from_index (np (), i))); - } - } - - virtual QIcon icon () - { - return icon_for_nets (m_np); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/net: header column = node count, second column net name - if (column == model->object_column ()) { - return escaped (str_from_expanded_names (m_np, model->indexer ()->is_single ())); - } else if (column == model->first_column () && m_np.first) { - return escaped (m_np.first->expanded_name () + " (" + tl::to_string (m_np.first->pin_count () + m_np.first->terminal_count () + m_np.first->subcircuit_pin_count ()) + ")"); - } else if (column == model->second_column () && m_np.second) { - return escaped (m_np.second->expanded_name () + " (" + tl::to_string (m_np.second->pin_count () + m_np.second->terminal_count () + m_np.second->subcircuit_pin_count ()) + ")"); - } - - return QString (); - } - - virtual QString search_text () - { - return tl::to_qstring (search_string_from_expanded_names (m_np)); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - size_t index = model->indexer ()->net_index (m_np); - return model->indexer ()->net_status_hint (cp (), index); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) - { - size_t index = model->indexer ()->net_index (m_np); - return model->indexer ()->net_from_index (cp (), index).second; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitItemData *p = static_cast (parent ()); - return p->cp (); - } - - const IndexedNetlistModel::net_pair &np () - { - return m_np; - } - -private: - IndexedNetlistModel::net_pair m_np; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitNetDeviceTerminalItemData - : public NetlistModelItemData -{ -private: - CircuitNetDeviceTerminalItemData (CircuitNetItemData *parent, const IndexedNetlistModel::device_pair &dp, const IndexedNetlistModel::net_terminal_pair &tp) - : NetlistModelItemData (parent), m_dp (dp), m_tp (tp) - { } - - virtual void do_ensure_children (NetlistBrowserModel * /*model*/) - { - 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 termdefs = terminal_defs_from_terminal_refs (m_tp); - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), termdefs); - push_back (new CircuitNetDeviceTerminalOthersItemData (this, nets, termdefs)); - } - } - - virtual QIcon icon () - { - std::pair device_classes = device_classes_from_devices (m_dp); - return icon_for_devices (device_classes); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/net/device terminal: header column = terminal and device string, second column = device name - IndexedNetlistModel::device_pair devices = devices_from_termrefs (m_tp); - - if (column == model->object_column ()) { - - std::pair termdefs = terminal_defs_from_terminal_refs (m_tp); - - if (model->indexer ()->is_single ()) { - return escaped (str_from_name (termdefs.first) + field_sep + device_string (m_dp.first)); - } else { - return escaped (str_from_names (termdefs, model->indexer ()->is_single ()) + field_sep + devices_string (m_dp, model->indexer ()->is_single (), true /*with parameters*/)); - } - - } else if (column == model->first_column () || column == model->second_column ()) { - return make_link_to (m_dp, column); - } - - return QString (); - } - - virtual QString search_text () - { - std::pair device_classes = device_classes_from_devices (dp ()); - std::pair termdefs = terminal_defs_from_terminal_refs (tp ()); - return tl::to_qstring (combine_search_strings (combine_search_strings (search_string_from_names (termdefs), search_string_from_names (device_classes)), search_string_from_expanded_names (dp ()))); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - return model->indexer ()->device_status_hint (cp (), model->indexer ()->device_index (dp ())); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) - { - return model->indexer ()->device_from_index (cp (), model->indexer ()->device_index (dp ())).second; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitNetItemData *p = static_cast (parent ()); - return p->cp (); - } - - const IndexedNetlistModel::net_pair &np () - { - CircuitNetItemData *p = static_cast (parent ()); - return p->np (); - } - - IndexedNetlistModel::device_pair dp () - { - return devices_from_termrefs (tp ()); - } - - const IndexedNetlistModel::net_terminal_pair &tp () - { - return m_tp; - } - -private: - IndexedNetlistModel::device_pair m_dp; - IndexedNetlistModel::net_terminal_pair m_tp; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitNetDeviceTerminalOthersItemData - : public NetlistModelItemData -{ -private: - CircuitNetDeviceTerminalOthersItemData (CircuitNetItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp) - : NetlistModelItemData (parent), m_np (np), m_tp (tp) - { } - - virtual void do_ensure_children (NetlistBrowserModel *) - { - // nothing (leaf node) - } - - virtual QIcon icon () - { - return icon_for_connection (nets_from_device_terminals (dp (), m_tp)); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/net/device terminal/more: header column = terminal name, second column = net link - if (column == model->object_column ()) { - - return escaped (str_from_names (m_tp, model->indexer ()->is_single ())); - - } else if (column == model->first_column () || column == model->second_column ()) { - - return make_link_to (m_np, column); - - } - - return QString (); - } - - virtual QString search_text () - { - std::pair termdefs = terminal_defs_from_terminal_refs (m_tp); - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), termdefs); - return tl::to_qstring (combine_search_strings (search_string_from_names (termdefs), search_string_from_expanded_names (nets))); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - return std::string (); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/) - { - if (! is_valid_net_pair (nets_from_device_terminals (dp (), m_tp))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - return db::NetlistCrossReference::None; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitNetDeviceTerminalItemData *p = static_cast (parent ()); - return p->cp (); - } - - const IndexedNetlistModel::device_pair &dp () - { - CircuitNetDeviceTerminalItemData *p = static_cast (parent ()); - return p->dp (); - } - -private: - std::pair m_tp; - IndexedNetlistModel::net_pair m_np; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitNetSubCircuitPinItemData - : public NetlistModelItemData -{ -private: - CircuitNetSubCircuitPinItemData (CircuitNetItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp) - : NetlistModelItemData (parent), m_pp (pp) - { } - - virtual void do_ensure_children (NetlistBrowserModel *model) - { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (m_pp); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - - size_t n = model->indexer ()->pin_count (circuit_refs); - for (size_t i = 0; i < n; ++i) { - IndexedNetlistModel::pin_pair pp = model->indexer ()->pin_from_index (circuit_refs, i); - push_back (new CircuitNetSubCircuitPinOthersItemData (this, pp)); - } - } - - virtual QIcon icon () - { - return icon_for_pin (); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/net/pin: header column = pin name, second column empty (for now) - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (m_pp); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - - if (column == model->object_column ()) { - return make_link_to (pins_from_pinrefs (m_pp), circuit_refs) + tl::to_qstring (field_sep) + make_link_to (circuit_refs); - } else if (column == model->first_column () || column == model->second_column ()) { - return make_link_to (subcircuits, column); - } - - return QString (); - } - - virtual QString search_text () - { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (m_sp); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - return tl::to_qstring (combine_search_strings (combine_search_strings (search_string_from_names (m_pp), search_string_from_names (circuit_refs)), search_string_from_expanded_names (subcircuits))); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); - return model->indexer ()->subcircuit_status_hint (cp (), model->indexer ()->subcircuit_index (subcircuits)); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) - { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); - return model->indexer ()->subcircuit_from_index (cp (), model->indexer ()->subcircuit_index (subcircuits)).second; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitNetItemData *p = static_cast (parent ()); - return p->cp (); - } - - const IndexedNetlistModel::net_pair &np () - { - CircuitNetItemData *p = static_cast (parent ()); - return p->np (); - } - - const IndexedNetlistModel::net_subcircuit_pin_pair &pp () - { - return m_pp; - } - -private: - IndexedNetlistModel::net_subcircuit_pin_pair m_sp; - IndexedNetlistModel::pin_pair m_pp; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitNetSubCircuitPinOthersItemData - : public NetlistModelItemData -{ -private: - CircuitNetSubCircuitPinOthersItemData (CircuitNetItemData *parent, const IndexedNetlistModel::pin_pair &pp) - : NetlistModelItemData (parent), m_pp (pp) - { } - - virtual void do_ensure_children (NetlistBrowserModel *) - { - // nothing (leaf node) - } - - virtual QIcon icon () - { - CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); - return icon_for_connection (nets_from_subcircuit_pins (subcircuits_from_pinrefs (p->pp ()), m_pp)); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/net/device terminal/more: header column = pin name, second column = net link - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - - if (column == model->object_column ()) { - return make_link_to (m_pp, circuit_refs); - } else if (column == model->first_column () || column == model->second_column ()) { - return make_link_to (nets_from_subcircuit_pins (subcircuits, m_pp), column); - } - - return QString (); - } - - virtual QString search_text () - { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::net_pair nets = nets_from_circuit_pins (circuit_refs, m_pp); - return tl::to_qstring (combine_search_strings (search_string_from_names (m_pp), search_string_from_expanded_names (nets))); - } - - virtual std::string tooltip (NetlistBrowserModel * /*model*/) - { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); - std::string hint; - - if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, m_pp))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - hint = rewire_subcircuit_pins_status_hint (); - } - - return hint; - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/) - { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); - if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, m_pp))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - return db::NetlistCrossReference::None; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); - return p->cp (); - } - - const IndexedNetlistModel::device_pair &dp () - { - CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); - return p->dp (); - } - - const IndexedNetlistModel::net_subcircuit_pin_pair &pp () - { - CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); - return p->pp (); - } - -private: - IndexedNetlistModel::pin_pair m_pp; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitNetPinItemData - : public NetlistModelItemData -{ -private: - CircuitNetPinItemData (CircuitNetItemData *parent, const IndexedNetlistModel::net_pin_pair &pp) - : NetlistModelItemData (parent), m_pp (pp) - { } - - virtual void do_ensure_children (NetlistBrowserModel *) - { - // nothing (leaf node) - } - - virtual QIcon icon () - { - return icon_for_pin (); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/net/pin: header column = pin name, second column empty (for now) - IndexedNetlistModel::circuit_pair circuits (m_pp.first && m_pp.first->net () ? m_pp.first->net ()->circuit () : 0, m_pp.second && m_pp.second->net () ? m_pp.second->net ()->circuit () : 0); - if (model->indexer ()->is_single () && column == model->object_column ()) { - return make_link_to (pins_from_pinrefs (m_pp), circuits); - } else if (! model->indexer ()->is_single () && (column == model->first_column () || column == model->second_column ())) { - return make_link_to (pins_from_pinrefs (m_pp), circuits, column); - } - - return QString (); - } - - virtual QString search_text () - { - return tl::to_qstring (search_string_from_names (m_pp)); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - return std::string (); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) - { - return db::NetlistCrossReference::None; - } - -private: - IndexedNetlistModel::net_pin_pair m_pp; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitSubCircuitItemData - : public NetlistModelItemData -{ -private: - CircuitSubCircuitItemData (CircuitItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp) - : NetlistModelItemData (parent), m_sp (sp) - { } - - virtual void do_ensure_children (NetlistBrowserModel *model) - { - size_t n = std::max (rows_for (sp ().first), rows_for (sp ().second)); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); - for (size_t i = 0; i < n; ++i) { - IndexedNetlistModel::pin_pair pp = model->indexer ()->pin_from_index (circuit_refs, i).first; - push_back (new CircuitSubCircuitPinItemData (this, pp)); - } - } - - virtual QIcon icon () - { - return icon_for_circuit (); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/subcircuit: header column = circuit name, second column subcircuit name - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (m_sp); - if (column == model->object_column ()) { - return make_link_to (circuit_refs); - } else if (column == model->first_column ()) { - return escaped (str_from_expanded_name (m_sp.first)); - } else if (column == model->second_column ()) { - return escaped (str_from_expanded_name (subcircuits.second)); - } - - return QString (); - } - - virtual QString search_text () - { - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); - return tl::to_qstring (combine_search_strings (search_string_from_names (circuit_refs), search_string_from_expanded_names (sp ()))); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - size_t index = model->indexer ()->subcircuit_index (sp ()); - return model->indexer ()->subcircuit_status_hint (cp (), index); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) - { - size_t index = model->indexer ()->subcircuit_index (sp ()); - return model->indexer ()->subcircuit_from_index (cp (), index).second; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitItemData *p = static_cast (parent ()); - return p->cp (); - } - - const IndexedNetlistModel::subcircuit_pair &sp () - { - return m_sp; - } - -private: - IndexedNetlistModel::subcircuit_pair m_sp; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitSubCircuitPinItemData - : public NetlistModelItemData -{ -private: - CircuitSubCircuitPinItemData (CircuitItemData *parent, const IndexedNetlistModel::pin_pair &pp) - : NetlistModelItemData (parent), m_pp (pp) - { } - - virtual void do_ensure_children (NetlistBrowserModel *) - { - // nothing (leaf node) - } - - virtual QIcon icon () - { - return icon_for_pin (); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/pin: header column = pin name, other columns net name - const IndexedNetlistModel::subcircuit_pair &sp = static_cast (parent ())->sp (); - - if (column == model->object_column ()) { - return make_link_to (m_pp, circuit_refs_from_subcircuits (sp)); - } else if (column == model->first_column () || column == model->second_column ()) { - return make_link_to (nets_from_subcircuit_pins (sp, m_pp), column); - } - - return QString (); - } - - virtual QString search_text () - { - IndexedNetlistModel::net_pair nets = nets_from_subcircuit_pins (sp (), m_pp); - return tl::to_qstring (combine_search_strings (search_string_from_names (m_pp), search_string_from_expanded_names (nets))); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); - - std::string hint = model->indexer ()->pin_status_hint (circuit_refs, model->indexer ()->pin_index (m_pp, circuit_refs)); - if (hint.empty ()) { - - // Another test here is to check whether the pins may be attached to an invalid net pair - if (! is_valid_net_pair (nets_from_subcircuit_pins (sp (), m_pp))) { - hint = rewire_subcircuit_pins_status_hint (); - } - - } - - return hint; - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) - { - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); - - db::NetlistCrossReference::Status status = model->indexer ()->pin_from_index (circuit_refs, model->indexer ()->pin_index (m_pp, circuit_refs)).second; - if (status == db::NetlistCrossReference::Mismatch || status == db::NetlistCrossReference::NoMatch) { - return status; - } - - // Another test here is to check whether the pins may be attached to an invalid net pair - if (! is_valid_net_pair (nets_from_subcircuit_pins (sp (), m_pp))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - return db::NetlistCrossReference::None; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitSubCircuitItemData *p = static_cast (parent ()); - return p->cp (); - } - - const IndexedNetlistModel::subcircuit_pair &sp () - { - CircuitSubCircuitItemData *p = static_cast (parent ()); - return p->sp (); - } - -private: - IndexedNetlistModel::pin_pair m_pp; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitDeviceItemData - : public NetlistModelItemData -{ -private: - CircuitDeviceItemData (CircuitItemData *parent, const IndexedNetlistModel::device_pair &dp) - : NetlistModelItemData (parent), m_dp (dp) - { } - - virtual void do_ensure_children (NetlistBrowserModel * /*model*/) - { - size_t n = std::max (rows_for (dp ().first), rows_for (dp ().second)); - for (size_t i = 0; i < n; ++i) { - std::pair tp = terminal_defs_from_device_classes (dp (), i); - push_back (new CircuitDeviceTerminalItemData (this, tp)); - } - } - - virtual QIcon icon () - { - std::pair device_classes = device_classes_from_devices (m_dp); - return icon_for_devices (device_classes); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/device: header column = class + parameters, second column device name - if (model->indexer ()->is_single ()) { - - if (column == model->object_column ()) { - return escaped (device_string (m_dp.first)); - } else if (column == model->first_column ()) { - return escaped (str_from_expanded_name (m_dp.first)); - } - - } else { - - if (column == model->object_column ()) { - return escaped (devices_string (m_dp, model->indexer ()->is_single (), false /*without parameters*/)); - } else if (column == model->first_column ()) { - return escaped (str_from_expanded_name (m_dp.first) + field_sep + device_string (m_dp.first)); - } else if (column == model->second_column ()) { - return escaped (str_from_expanded_name (m_dp.second) + field_sep + device_string (m_dp.second)); - } - - } - } - - virtual QString search_text () - { - std::pair device_classes = device_classes_from_devices (dp ()); - return tl::to_qstring (combine_search_strings (search_string_from_expanded_names (dp ()), search_string_from_names (device_classes))); - } - - virtual std::string tooltip (NetlistBrowserModel *model) - { - size_t index = model->indexer ()->device_index (m_dp); - hint = model->indexer ()->device_status_hint (cp (), index); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) - { - size_t index = model->indexer ()->device_index (m_dp); - return model->indexer ()->device_from_index (cp (), index).second; - } - - const IndexedNetlistModel::device_pair &dp () - { - return m_dp; - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitItemData *p = static_cast (parent ()); - return p->cp (); - } - -private: - IndexedNetlistModel::device_pair m_dp; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitDeviceTerminalItemData - : public NetlistModelItemData -{ -private: - CircuitDeviceTerminalItemData (CircuitDeviceItemData *parent, const std::pair &tp) - : NetlistModelItemData (parent), m_tp (tp) - { } - - virtual void do_ensure_children (NetlistBrowserModel *) - { - // nothing (leaf node) - } - - virtual QIcon icon () - { - const IndexedNetlistModel::device_pair &dp = static_cast (parent ())->dp (); - std::pair termdefs (m_tp.first ? m_tp.first->terminal_def () : 0, m_tp.second ? m_tp.second->terminal_def () : 0); - return icon_for_connection (nets_from_device_terminals (dp, termdefs)); - } - - virtual QString text (int column, NetlistBrowserModel *model) - { - // circuit/device/terminal: header column = terminal name, second column link to net - std::pair termdefs = terminal_defs_from_terminal_refs (m_tp);; - - if (column == model->object_column ()) { - - return escaped (str_from_names (termdefs, model->indexer ()->is_single ())); - - } else if (column == model->first_column () || column == model->second_column ()) { - - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), termdefs); - return make_link_to (nets, column); - - } - - return QString (); - } - - virtual QString search_text () - { - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); - return tl::to_qstring (combine_search_strings (search_string_from_names (m_tp), search_string_from_expanded_names (nets))); - } - - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/) - { - if (! is_valid_net_pair (nets_from_device_terminals (dp (), m_tp))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - return db::NetlistCrossReference::None; - } - - const IndexedNetlistModel::device_pair &dp () - { - CircuitDeviceItemData *p = static_cast (parent ()); - return p->dp (); - } - - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitDeviceItemData *p = static_cast (parent ()); - return p->cp (); - } - -private: - std::pair m_tp; -}; - -// ---------------------------------------------------------------------------------- -// NetlistBrowserModel implementation - -static void *no_id = reinterpret_cast (-1); - -NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb, NetColorizer *colorizer) - : QAbstractItemModel (parent), mp_l2ndb (l2ndb), mp_lvsdb (0), mp_colorizer (colorizer) -{ - mp_indexer.reset (new SingleIndexedNetlistModel (l2ndb->netlist ())); - connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ())); - - m_object_column = 0; - m_status_column = -1; - m_first_column = 2; - m_second_column = -1; -} - -NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutVsSchematic *lvsdb, NetColorizer *colorizer) - : QAbstractItemModel (parent), mp_l2ndb (0), mp_lvsdb (lvsdb), mp_colorizer (colorizer) -{ - mp_indexer.reset (new NetlistCrossReferenceModel (lvsdb->cross_ref ())); - connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ())); - - m_object_column = 0; - m_status_column = 1; - m_first_column = 2; - m_second_column = 3; -} - -NetlistBrowserModel::~NetlistBrowserModel () -{ - // .. nothing yet .. -} - -int -NetlistBrowserModel::columnCount (const QModelIndex & /*parent*/) const -{ - // Item type & icon, link or description - return mp_indexer->is_single () ? 3 : 4; -} - -QIcon icon_for_status (db::NetlistCrossReference::Status status) -{ - if (status == db::NetlistCrossReference::NoMatch || status == db::NetlistCrossReference::Mismatch) { - return QIcon (":/error2_16.png"); - } else if (status == db::NetlistCrossReference::MatchWithWarning || status == db::NetlistCrossReference::Skipped) { - return QIcon (":/warn_16.png"); - } else { - return QIcon (); - } -} - -QVariant -NetlistBrowserModel::data (const QModelIndex &index, int role) const -{ - if (! index.isValid ()) { - return QVariant (); - } - - if (role == Qt::DecorationRole && index.column () == m_object_column) { - return QVariant (icon (index)); - } else if (role == Qt::DecorationRole && index.column () == m_status_column) { - return QVariant (icon_for_status (status (index))); - } else if (role == Qt::DisplayRole) { - return QVariant (text (index)); - } else if (role == Qt::ToolTipRole && index.column () == m_status_column) { - return tooltip (index); - } else if (role == Qt::UserRole) { - return QVariant (search_text (index)); - } else if (role == Qt::FontRole) { - db::NetlistCrossReference::Status st = status (index); - if (st == db::NetlistCrossReference::NoMatch || st == db::NetlistCrossReference::Mismatch || st == db::NetlistCrossReference::Skipped) { - QFont font; - font.setWeight (QFont::Bold); - return QVariant (font); - } - } else if (role == Qt::ForegroundRole) { - db::NetlistCrossReference::Status st = status (index); - if (st == db::NetlistCrossReference::Match || st == db::NetlistCrossReference::MatchWithWarning) { - // taken from marker browser: - return QVariant (QColor (0, 192, 0)); - } - } - return QVariant (); -} - -static QString build_url (void *id, const std::string &tag, const std::string &title) -{ - if (id == no_id) { - // no link - return tl::to_qstring (tl::escaped_to_html (title)); - } - - std::string s = std::string (""; - - s += tl::escaped_to_html (title); - - s += ""; - - return tl::to_qstring (s); -} - -QString -NetlistBrowserModel::make_link_to (const std::pair &nets, int column) const -{ - if ((! nets.first || column == m_second_column) && (! nets.second || column == m_first_column)) { - return QString (); - } else { - - IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (nets); - void *id = no_id; - // NOTE: the nets may not be a valid net pair. In this case, circuits is (0, 0) and - // no link is generated - if (circuits.first || circuits.second) { - id = make_id_circuit_net (mp_indexer->circuit_index (circuits), mp_indexer->net_index (nets)); - } - - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "net", str_from_expanded_name (nets.first)); - } else if (column == m_second_column) { - return build_url (id, "net", str_from_expanded_name (nets.second)); - } else { - return build_url (id, "net", str_from_expanded_names (nets, mp_indexer->is_single ())); - } - - } -} - -QString -NetlistBrowserModel::make_link_to (const std::pair &devices, int column) const -{ - if ((! devices.first || column == m_second_column) && (! devices.second || column == m_first_column)) { - return QString (); - } else { - - IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (devices); - void *id = no_id; - // NOTE: the devices may not be a valid device pair. In this case, circuits is (0, 0) and - // no link is generated - if (circuits.first || circuits.second) { - id = make_id_circuit_device (mp_indexer->circuit_index (circuits), mp_indexer->device_index (devices)); - } - - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "device", str_from_expanded_name (devices.first)); - } else if (column == m_second_column) { - return build_url (id, "device", str_from_expanded_name (devices.second)); - } else { - return build_url (id, "device", str_from_expanded_names (devices, mp_indexer->is_single ())); - } - - } -} - -QString -NetlistBrowserModel::make_link_to (const std::pair &pins, const std::pair &circuits, int column) const -{ - if ((! pins.first || column == m_second_column) && (! pins.second || column == m_first_column)) { - return QString (); - } else { - void *id = make_id_circuit_pin (mp_indexer->circuit_index (circuits), mp_indexer->pin_index (pins, circuits)); - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "pin", str_from_expanded_name (pins.first)); - } else if (column == m_second_column) { - return build_url (id, "pin", str_from_expanded_name (pins.second)); - } else { - return build_url (id, "pin", str_from_expanded_names (pins, mp_indexer->is_single ())); - } - } -} - -QString -NetlistBrowserModel::make_link_to (const std::pair &circuits, int column) const -{ - if ((! circuits.first || column == m_second_column) && (! circuits.second || column == m_first_column)) { - return QString (); - } else { - void *id = make_id_circuit (mp_indexer->circuit_index (circuits)); - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "circuit", str_from_name (circuits.first)); - } else if (column == m_second_column) { - return build_url (id, "circuit", str_from_name (circuits.second)); - } else { - return build_url (id, "circuit", str_from_names (circuits, mp_indexer->is_single ())); - } - } -} - -QString -NetlistBrowserModel::make_link_to (const std::pair &subcircuits, int column) const -{ - if ((! subcircuits.first || column == m_second_column) && (! subcircuits.second || column == m_first_column)) { - return QString (); - } else { - - IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (subcircuits); - void *id = no_id; - // NOTE: the subcircuits may not be a valid subcircuit pair. In this case, circuits is (0, 0) and - // no link is generated - if (circuits.first || circuits.second) { - id = make_id_circuit_subcircuit (mp_indexer->circuit_index (circuits), mp_indexer->subcircuit_index (subcircuits)); - } - - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.first)); - } else if (column == m_second_column) { - return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.second)); - } else { - return build_url (id, "subcircuit", str_from_expanded_names (subcircuits, mp_indexer->is_single ())); - } - - } -} - -template -static std::string search_string_from_expanded_names (const std::pair &objs) -{ - if (objs.first && objs.second) { - return combine_search_strings (objs.first->expanded_name (), objs.second->expanded_name ()); - } else if (objs.first) { - return objs.first->expanded_name (); - } else if (objs.second) { - return objs.second->expanded_name (); - } else { - return std::string (); - } -} - -template -static std::string search_string_from_names (const std::pair &objs) -{ - if (objs.first && objs.second) { - return combine_search_strings (objs.first->name (), objs.second->name ()); - } else if (objs.first) { - return objs.first->name (); - } else if (objs.second) { - return objs.second->name (); - } else { - return std::string (); - } -} - -bool -NetlistBrowserModel::is_valid_net_pair (const std::pair &nets) const -{ - if (! nets.first && ! nets.second) { - // this is a valid case: e.g. two matching subcircuit pins without nets attached - // to them - return true; - } else { - IndexedNetlistModel::circuit_pair net_parent = mp_indexer->parent_of (nets); - return (net_parent.first != 0 || net_parent.second != 0); - } -} - -db::NetlistCrossReference::Status -NetlistBrowserModel::status (const QModelIndex &index) const -{ - NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); - if (! d) { - return db::NetlistCrossReference::None; - } else { - return d->status (this); - } -} - -static std::string rewire_subcircuit_pins_status_hint () -{ - return tl::to_string (tr ("Either pins or nets don't form a good pair.\nThis means either pin swapping happens (in this case, the nets will still match)\nor the subcircuit wiring is not correct (you'll see an error on the net).")); -} - -QVariant -NetlistBrowserModel::tooltip (const QModelIndex &index) const -{ - std::string hint; - NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); - if (d) { - hint = d->tooltip (this); - } - - if (hint.empty ()) { - return QVariant (); - } else { - return QVariant (tl::to_qstring (hint)); - } -} - -QString -NetlistBrowserModel::search_text (const QModelIndex &index) const -{ - NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); - if (d) { - return d->search_text (); - } else { - return QString (); - } -} - static QIcon icon_for_net () { QIcon icon; @@ -1976,6 +657,1879 @@ static QIcon connection_icon_with_color (const QColor &color) return colored_icon (color, light_icon_for_connection ()); } +template +static std::string search_string_from_expanded_names (const std::pair &objs) +{ + if (objs.first && objs.second) { + return combine_search_strings (objs.first->expanded_name (), objs.second->expanded_name ()); + } else if (objs.first) { + return objs.first->expanded_name (); + } else if (objs.second) { + return objs.second->expanded_name (); + } else { + return std::string (); + } +} + +template +static std::string search_string_from_names (const std::pair &objs) +{ + if (objs.first && objs.second) { + return combine_search_strings (objs.first->name (), objs.second->name ()); + } else if (objs.first) { + return objs.first->name (); + } else if (objs.second) { + return objs.second->name (); + } else { + return std::string (); + } +} + +static std::string rewire_subcircuit_pins_status_hint () +{ + return tl::to_string (tr ("Either pins or nets don't form a good pair.\nThis means either pin swapping happens (in this case, the nets will still match)\nor the subcircuit wiring is not correct (you'll see an error on the net).")); +} + +// ---------------------------------------------------------------------------------- +// item class declarations + +class RootItemData + : public NetlistModelItemData +{ +public: + RootItemData (); + + virtual void do_ensure_children (NetlistBrowserModel *model); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + CircuitItemData *circuit_item (NetlistBrowserModel *model, const IndexedNetlistModel::circuit_pair &cp); +}; + +// ---------------------------------------------------------------------------------- + +class CircuitItemData + : public NetlistModelItemData +{ +public: + CircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::circuit_pair &cp); + + virtual void do_ensure_children (NetlistBrowserModel *model); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + const IndexedNetlistModel::circuit_pair &cp () + { + return m_cp; + } + + virtual std::pair circuits () + { + return cp (); + } + + 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; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitPinItemData + : public NetlistModelItemData +{ +public: + CircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp); + + virtual void do_ensure_children (NetlistBrowserModel * /*model*/); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::pin_pair &pp () + { + return m_pp; + } + + virtual std::pair pins () + { + return pp (); + } + +private: + IndexedNetlistModel::pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitPinNetItemData + : public NetlistModelItemData +{ +public: + CircuitPinNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np); + + virtual void do_ensure_children (NetlistBrowserModel *model); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitPinItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::pin_pair &pp () + { + CircuitPinItemData *p = static_cast (parent ()); + return p->pp (); + } + + virtual std::pair nets () + { + return m_np; + } + +private: + IndexedNetlistModel::net_pair m_np; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetItemData + : public NetlistModelItemData +{ +public: + CircuitNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np); + + virtual void do_ensure_children (NetlistBrowserModel *model); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::net_pair &np () + { + return m_np; + } + + virtual std::pair nets () + { + return m_np; + } + +private: + IndexedNetlistModel::net_pair m_np; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetDeviceTerminalItemData + : public NetlistModelItemData +{ +public: + CircuitNetDeviceTerminalItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_terminal_pair &tp); + + virtual void do_ensure_children (NetlistBrowserModel * /*model*/); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitNetItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::net_pair &np () + { + CircuitNetItemData *p = static_cast (parent ()); + return p->np (); + } + + IndexedNetlistModel::device_pair dp () + { + return devices_from_termrefs (tp ()); + } + + const IndexedNetlistModel::net_terminal_pair &tp () + { + return m_tp; + } + + virtual std::pair devices () + { + return dp (); + } + +private: + IndexedNetlistModel::net_terminal_pair m_tp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetDeviceTerminalOthersItemData + : public NetlistModelItemData +{ +public: + CircuitNetDeviceTerminalOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp); + + virtual void do_ensure_children (NetlistBrowserModel *); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/); + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitNetDeviceTerminalItemData *p = static_cast (parent ()); + return p->cp (); + } + + IndexedNetlistModel::device_pair dp () + { + CircuitNetDeviceTerminalItemData *p = static_cast (parent ()); + return p->dp (); + } + + virtual std::pair nets () + { + return m_np; + } + +private: + std::pair m_tp; + IndexedNetlistModel::net_pair m_np; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetSubCircuitPinItemData + : public NetlistModelItemData +{ +public: + CircuitNetSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp); + + virtual void do_ensure_children (NetlistBrowserModel *model); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitNetItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::net_pair &np () + { + CircuitNetItemData *p = static_cast (parent ()); + return p->np (); + } + + const IndexedNetlistModel::net_subcircuit_pin_pair &sp () + { + return m_sp; + } + + IndexedNetlistModel::pin_pair pp () + { + return pins_from_pinrefs (m_sp); + } + + virtual std::pair subcircuits () + { + return subcircuits_from_pinrefs (m_sp); + } + + virtual std::pair pins () + { + return m_pp; + } + +private: + IndexedNetlistModel::net_subcircuit_pin_pair m_sp; + IndexedNetlistModel::pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetSubCircuitPinOthersItemData + : public NetlistModelItemData +{ +public: + CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp); + + virtual void do_ensure_children (NetlistBrowserModel *); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel * /*model*/); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/); + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); + return p->cp (); + } + + IndexedNetlistModel::pin_pair pp () + { + CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); + return p->pp (); + } + + const IndexedNetlistModel::net_subcircuit_pin_pair &sp () + { + CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); + return p->sp (); + } + + virtual std::pair pins () + { + return m_pp; + } + +private: + IndexedNetlistModel::pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitNetPinItemData + : public NetlistModelItemData +{ +public: + CircuitNetPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pin_pair &pp); + + virtual void do_ensure_children (NetlistBrowserModel *); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + virtual std::pair pins () + { + return pins_from_pinrefs (m_pp); + } + +private: + IndexedNetlistModel::net_pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitSubCircuitItemData + : public NetlistModelItemData +{ +public: + CircuitSubCircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp); + + virtual void do_ensure_children (NetlistBrowserModel *model); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::subcircuit_pair &sp () + { + return m_sp; + } + + virtual std::pair subcircuits () + { + return m_sp; + } + +private: + IndexedNetlistModel::subcircuit_pair m_sp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitSubCircuitPinItemData + : public NetlistModelItemData +{ +public: + CircuitSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp); + + virtual void do_ensure_children (NetlistBrowserModel *); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitSubCircuitItemData *p = static_cast (parent ()); + return p->cp (); + } + + const IndexedNetlistModel::subcircuit_pair &sp () + { + CircuitSubCircuitItemData *p = static_cast (parent ()); + return p->sp (); + } + + virtual std::pair pins () + { + return m_pp; + } + +private: + IndexedNetlistModel::pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitDeviceItemData + : public NetlistModelItemData +{ +public: + CircuitDeviceItemData (NetlistModelItemData *parent, const IndexedNetlistModel::device_pair &dp); + + virtual void do_ensure_children (NetlistBrowserModel * /*model*/); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + const IndexedNetlistModel::device_pair &dp () + { + return m_dp; + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitItemData *p = static_cast (parent ()); + return p->cp (); + } + + virtual std::pair devices () + { + return m_dp; + } + +private: + IndexedNetlistModel::device_pair m_dp; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitDeviceTerminalItemData + : public NetlistModelItemData +{ +public: + CircuitDeviceTerminalItemData (NetlistModelItemData *parent, const std::pair &tp); + + virtual void do_ensure_children (NetlistBrowserModel *); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/); + + const IndexedNetlistModel::device_pair &dp () + { + CircuitDeviceItemData *p = static_cast (parent ()); + return p->dp (); + } + + const IndexedNetlistModel::circuit_pair &cp () + { + CircuitDeviceItemData *p = static_cast (parent ()); + return p->cp (); + } + +private: + std::pair m_tp; +}; + +// ---------------------------------------------------------------------------------- +// item class implementations + +NetlistModelItemData::NetlistModelItemData () + : mp_parent (0), m_children_made (false), m_index (0) +{ } + +NetlistModelItemData::NetlistModelItemData (NetlistModelItemData *parent) + : mp_parent (parent), m_children_made (false), m_index (0) +{ } + +NetlistModelItemData::~NetlistModelItemData () +{ } + +void +NetlistModelItemData::ensure_children (NetlistBrowserModel *model) +{ + if (! m_children_made) { + + m_children.clear (); + m_children_per_index.clear (); + + do_ensure_children (model); + + size_t n = 0; + for (iterator i = begin (); i != end (); ++i) { + ++n; + } + m_children_per_index.reserve (n); + + size_t index = 0; + for (iterator i = begin (); i != end (); ++i) { + m_children_per_index.push_back (i.operator-> ()); + i->set_index (index++); + } + + m_children_made = true; + + } +} + +void +NetlistModelItemData::push_back (NetlistModelItemData *child) +{ + m_children.push_back (child); +} + +NetlistModelItemData * +NetlistModelItemData::child (size_t n) +{ + return (n < m_children_per_index.size () ? m_children_per_index [n] : 0); +} + +std::pair +NetlistModelItemData::circuits () +{ + return mp_parent ? mp_parent->circuits () : std::pair (0, 0); +} + +std::pair +NetlistModelItemData::devices () +{ + return mp_parent ? mp_parent->devices () : std::pair (0, 0); +} + +std::pair +NetlistModelItemData::pins () +{ + return mp_parent ? mp_parent->pins () : std::pair (0, 0); +} + +std::pair +NetlistModelItemData::subcircuits () +{ + return mp_parent ? mp_parent->subcircuits () : std::pair (0, 0); +} + +std::pair +NetlistModelItemData::nets () +{ + return mp_parent ? mp_parent->nets () : std::pair (0, 0); +} + +// ---------------------------------------------------------------------------------- + +RootItemData::RootItemData () +{ + // .. nothing yet .. +} + +void +RootItemData::do_ensure_children (NetlistBrowserModel *model) +{ + size_t n = model->indexer ()->circuit_count (); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitItemData (0 /*intentionally*/, model->indexer ()->circuit_from_index (i).first)); + } +} + +QIcon +RootItemData::icon (NetlistBrowserModel * /*model*/) +{ + return QIcon (); +} + +QString +RootItemData::text (int /*column*/, NetlistBrowserModel * /*model*/) +{ + return QString (); +} + +QString +RootItemData::search_text () +{ + return QString (); +} + +std::string +RootItemData::tooltip (NetlistBrowserModel * /*model*/) +{ + return std::string (); +} + +db::NetlistCrossReference::Status +RootItemData::status (NetlistBrowserModel * /*model*/) +{ + return db::NetlistCrossReference::None; +} + +CircuitItemData * +RootItemData::circuit_item (NetlistBrowserModel *model, const IndexedNetlistModel::circuit_pair &cp) +{ + size_t index = model->indexer ()->circuit_index (cp); + ensure_children (model); + return dynamic_cast (child (index)); +} + +// ---------------------------------------------------------------------------------- + +CircuitItemData::CircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::circuit_pair &cp) + : NetlistModelItemData (parent), m_cp (cp) +{ } + +void +CircuitItemData::do_ensure_children (NetlistBrowserModel *model) +{ + size_t n; + + n = model->indexer ()->pin_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitPinItemData (this, model->indexer ()->pin_from_index (cp (), i).first)); + } + + n = model->indexer ()->net_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitNetItemData (this, model->indexer ()->net_from_index (cp (), i).first)); + } + + n = model->indexer ()->subcircuit_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitSubCircuitItemData (this, model->indexer ()->subcircuit_from_index (cp (), i).first)); + } + + n = model->indexer ()->device_count (cp ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitDeviceItemData (this, model->indexer ()->device_from_index (cp (), i).first)); + } +} + +QIcon +CircuitItemData::icon (NetlistBrowserModel * /*model*/) +{ + return icon_for_circuit (); +} + +QString +CircuitItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit: + // + single mode: name | | + // + dual mode: name(a)/name(b) | name(a) | name(b) + if (column == model->object_column ()) { + return escaped (str_from_names (m_cp, model->indexer ()->is_single ())); + } else if (!model->indexer ()->is_single () && (column == model->first_column () || column == model->second_column ())) { + return escaped (str_from_name (column == model->first_column () ? m_cp.first : m_cp.second)); + } else { + return QString (); + } +} + +QString +CircuitItemData::search_text () +{ + return tl::to_qstring (search_string_from_names (cp ())); +} + +std::string +CircuitItemData::tooltip (NetlistBrowserModel *model) +{ + size_t index = model->indexer ()->circuit_index (m_cp); + return model->indexer ()->circuit_status_hint (index); +} + +db::NetlistCrossReference::Status +CircuitItemData::status (NetlistBrowserModel *model) +{ + size_t index = model->indexer ()->circuit_index (m_cp); + return model->indexer ()->circuit_from_index (index).second; +} + +CircuitNetItemData * +CircuitItemData::circuit_net_item (NetlistBrowserModel *model, const IndexedNetlistModel::net_pair &np) +{ + ensure_children (model); + size_t index = model->indexer ()->net_index (np); + index += model->indexer ()->pin_count (cp ()); + return dynamic_cast (child (index)); +} + +CircuitDeviceItemData * +CircuitItemData::circuit_device_item (NetlistBrowserModel *model, const IndexedNetlistModel::device_pair &dp) +{ + ensure_children (model); + size_t index = model->indexer ()->device_index (dp); + index += model->indexer ()->pin_count (cp ()); + index += model->indexer ()->net_count (cp ()); + index += model->indexer ()->subcircuit_count (cp ()); + return dynamic_cast (child (index)); +} + +CircuitSubCircuitItemData * +CircuitItemData::circuit_subcircuit_item (NetlistBrowserModel *model, const IndexedNetlistModel::subcircuit_pair &sp) +{ + ensure_children (model); + size_t index = model->indexer ()->subcircuit_index (sp); + index += model->indexer ()->pin_count (cp ()); + index += model->indexer ()->net_count (cp ()); + return dynamic_cast (child (index)); +} + +// ---------------------------------------------------------------------------------- + +CircuitPinItemData::CircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp) + : NetlistModelItemData (parent), m_pp (pp) +{ } + +void +CircuitPinItemData::do_ensure_children (NetlistBrowserModel * /*model*/) +{ + push_back (new CircuitPinNetItemData (this, nets_from_circuit_pins (cp (), pp ()))); +} + +QIcon +CircuitPinItemData::icon (NetlistBrowserModel * /*model*/) +{ + return icon_for_pin (); +} + +QString +CircuitPinItemData::text (int column, NetlistBrowserModel *model) +{ + // pin: + // + 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 ())); + } 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)); + } + + return QString (); +} + +QString +CircuitPinItemData::search_text () +{ + return tl::to_qstring (search_string_from_expanded_names (pp ())); +} + +std::string +CircuitPinItemData::tooltip (NetlistBrowserModel *model) +{ + size_t index = model->indexer ()->pin_index (pp (), cp ()); + return model->indexer ()->pin_status_hint (cp (), index); +} + +db::NetlistCrossReference::Status +CircuitPinItemData::status (NetlistBrowserModel *model) +{ + size_t index = model->indexer ()->pin_index (pp (), cp ()); + return model->indexer ()->pin_from_index (cp (), index).second; +} + +// ---------------------------------------------------------------------------------- + +CircuitPinNetItemData::CircuitPinNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np) + : NetlistModelItemData (parent), m_np (np) +{ } + +void +CircuitPinNetItemData::do_ensure_children (NetlistBrowserModel * /*model*/) +{ + // nothing (leaf node) +} + +QIcon +CircuitPinNetItemData::icon (NetlistBrowserModel *model) +{ + return model->icon_for_connection (m_np); +} + +QString +CircuitPinNetItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/pin/net: header column = name, second column link to net + if (column == model->object_column ()) { + return escaped (str_from_expanded_names (m_np, model->indexer ()->is_single ())); + } else if (column == model->first_column () || column == model->second_column ()) { + return model->make_link_to (m_np, column); + } + + return QString (); +} + +QString +CircuitPinNetItemData::search_text () +{ + return tl::to_qstring (search_string_from_expanded_names (nets_from_circuit_pins (cp (), pp ()))); +} + +std::string +CircuitPinNetItemData::tooltip (NetlistBrowserModel * /*model*/) +{ + return std::string (); +} + +db::NetlistCrossReference::Status +CircuitPinNetItemData::status (NetlistBrowserModel * /*model*/) +{ + return db::NetlistCrossReference::None; +} + +// ---------------------------------------------------------------------------------- + +CircuitNetItemData::CircuitNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np) + : NetlistModelItemData (parent), m_np (np) +{ } + +void +CircuitNetItemData::do_ensure_children (NetlistBrowserModel *model) +{ + size_t n; + + n = model->indexer ()->net_terminal_count (np ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitNetDeviceTerminalItemData (this, model->indexer ()->net_terminalref_from_index (np (), i))); + } + + n = model->indexer ()->net_pin_count (np ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitNetPinItemData (this, model->indexer ()->net_pinref_from_index (np (), i))); + } + + n = model->indexer ()->net_subcircuit_pin_count (np ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitNetSubCircuitPinItemData (this, model->indexer ()->net_subcircuit_pinref_from_index (np (), i))); + } +} + +QIcon +CircuitNetItemData::icon (NetlistBrowserModel *model) +{ + return model->icon_for_nets (m_np); +} + +QString +CircuitNetItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/net: header column = node count, second column net name + if (column == model->object_column ()) { + return escaped (str_from_expanded_names (m_np, model->indexer ()->is_single ())); + } else if (column == model->first_column () && m_np.first) { + return escaped (m_np.first->expanded_name () + " (" + tl::to_string (m_np.first->pin_count () + m_np.first->terminal_count () + m_np.first->subcircuit_pin_count ()) + ")"); + } else if (column == model->second_column () && m_np.second) { + return escaped (m_np.second->expanded_name () + " (" + tl::to_string (m_np.second->pin_count () + m_np.second->terminal_count () + m_np.second->subcircuit_pin_count ()) + ")"); + } + + return QString (); +} + +QString +CircuitNetItemData::search_text () +{ + return tl::to_qstring (search_string_from_expanded_names (m_np)); +} + +std::string +CircuitNetItemData::tooltip (NetlistBrowserModel *model) +{ + size_t index = model->indexer ()->net_index (m_np); + return model->indexer ()->net_status_hint (cp (), index); +} + +db::NetlistCrossReference::Status +CircuitNetItemData::status (NetlistBrowserModel *model) +{ + size_t index = model->indexer ()->net_index (m_np); + return model->indexer ()->net_from_index (cp (), index).second; +} + +// ---------------------------------------------------------------------------------- + +CircuitNetDeviceTerminalItemData::CircuitNetDeviceTerminalItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_terminal_pair &tp) + : NetlistModelItemData (parent), m_tp (tp) +{ } + +void +CircuitNetDeviceTerminalItemData::do_ensure_children (NetlistBrowserModel * /*model*/) +{ + 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 termdefs = terminal_defs_from_terminal_refs (m_tp); + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), termdefs); + push_back (new CircuitNetDeviceTerminalOthersItemData (this, nets, termdefs)); + } +} + +QIcon +CircuitNetDeviceTerminalItemData::icon (NetlistBrowserModel * /*model*/) +{ + std::pair device_classes = device_classes_from_devices (dp ()); + return icon_for_devices (device_classes); +} + +QString +CircuitNetDeviceTerminalItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/net/device terminal: header column = terminal and device string, second column = device name + if (column == model->object_column ()) { + + std::pair termdefs = terminal_defs_from_terminal_refs (m_tp); + + if (model->indexer ()->is_single ()) { + return escaped (str_from_name (termdefs.first) + field_sep + device_string (dp ().first)); + } else { + return escaped (str_from_names (termdefs, model->indexer ()->is_single ()) + field_sep + devices_string (dp (), model->indexer ()->is_single (), true /*with parameters*/)); + } + + } else if (column == model->first_column () || column == model->second_column ()) { + return model->make_link_to (dp (), column); + } + + return QString (); +} + +QString +CircuitNetDeviceTerminalItemData::search_text () +{ + std::pair device_classes = device_classes_from_devices (dp ()); + std::pair termdefs = terminal_defs_from_terminal_refs (tp ()); + return tl::to_qstring (combine_search_strings (combine_search_strings (search_string_from_names (termdefs), search_string_from_names (device_classes)), search_string_from_expanded_names (dp ()))); +} + +std::string +CircuitNetDeviceTerminalItemData::tooltip (NetlistBrowserModel *model) +{ + return model->indexer ()->device_status_hint (cp (), model->indexer ()->device_index (dp ())); +} + +db::NetlistCrossReference::Status +CircuitNetDeviceTerminalItemData::status (NetlistBrowserModel *model) +{ + return model->indexer ()->device_from_index (cp (), model->indexer ()->device_index (dp ())).second; +} + +// ---------------------------------------------------------------------------------- + +CircuitNetDeviceTerminalOthersItemData::CircuitNetDeviceTerminalOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp) + : NetlistModelItemData (parent), m_tp (tp), m_np (np) +{ } + +void +CircuitNetDeviceTerminalOthersItemData::do_ensure_children (NetlistBrowserModel *) +{ + // nothing (leaf node) +} + +QIcon +CircuitNetDeviceTerminalOthersItemData::icon (NetlistBrowserModel *model) +{ + return model->icon_for_connection (nets_from_device_terminals (dp (), m_tp)); +} + +QString +CircuitNetDeviceTerminalOthersItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/net/device terminal/more: header column = terminal name, second column = net link + if (column == model->object_column ()) { + + return escaped (str_from_names (m_tp, model->indexer ()->is_single ())); + + } else if (column == model->first_column () || column == model->second_column ()) { + + return model->make_link_to (m_np, column); + + } + + return QString (); +} + +QString +CircuitNetDeviceTerminalOthersItemData::search_text () +{ + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); + return tl::to_qstring (combine_search_strings (search_string_from_names (m_tp), search_string_from_expanded_names (nets))); +} + +std::string +CircuitNetDeviceTerminalOthersItemData::tooltip (NetlistBrowserModel * /*model*/) +{ + return std::string (); +} + +db::NetlistCrossReference::Status +CircuitNetDeviceTerminalOthersItemData::status (NetlistBrowserModel *model) +{ + if (! model->is_valid_net_pair (nets_from_device_terminals (dp (), m_tp))) { + // This indicates a wrong connection: the nets are associated in a way which is a not + // corresponding to a mapped net pair. Report Mismatch here. + return db::NetlistCrossReference::NoMatch; + } + + return db::NetlistCrossReference::None; +} + +// ---------------------------------------------------------------------------------- + +CircuitNetSubCircuitPinItemData::CircuitNetSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &sp) + : NetlistModelItemData (parent), m_sp (sp) +{ } + +void +CircuitNetSubCircuitPinItemData::do_ensure_children (NetlistBrowserModel *model) +{ + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); + + size_t n = model->indexer ()->pin_count (circuit_refs); + for (size_t i = 0; i < n; ++i) { + IndexedNetlistModel::pin_pair pp = model->indexer ()->pin_from_index (circuit_refs, i).first; + push_back (new CircuitNetSubCircuitPinOthersItemData (this, pp)); + } +} + +QIcon +CircuitNetSubCircuitPinItemData::icon (NetlistBrowserModel * /*model*/) +{ + return icon_for_pin (); +} + +QString +CircuitNetSubCircuitPinItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/net/pin: header column = pin name, second column empty (for now) + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + 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); + } else if (column == model->first_column () || column == model->second_column ()) { + return model->make_link_to (subcircuits, column); + } + + return QString (); +} + +QString +CircuitNetSubCircuitPinItemData::search_text () +{ + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); + return tl::to_qstring (combine_search_strings (combine_search_strings (search_string_from_names (pp ()), search_string_from_names (circuit_refs)), search_string_from_expanded_names (subcircuits))); +} + +std::string +CircuitNetSubCircuitPinItemData::tooltip (NetlistBrowserModel *model) +{ + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + return model->indexer ()->subcircuit_status_hint (cp (), model->indexer ()->subcircuit_index (subcircuits)); +} + +db::NetlistCrossReference::Status +CircuitNetSubCircuitPinItemData::status (NetlistBrowserModel *model) +{ + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + return model->indexer ()->subcircuit_from_index (cp (), model->indexer ()->subcircuit_index (subcircuits)).second; +} + +// ---------------------------------------------------------------------------------- + +CircuitNetSubCircuitPinOthersItemData::CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp) + : NetlistModelItemData (parent), m_pp (pp) +{ } + +void +CircuitNetSubCircuitPinOthersItemData::do_ensure_children (NetlistBrowserModel *) +{ + // nothing (leaf node) +} + +QIcon +CircuitNetSubCircuitPinOthersItemData::icon (NetlistBrowserModel *model) +{ + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + return model->icon_for_connection (nets_from_subcircuit_pins (subcircuits, m_pp)); +} + +QString +CircuitNetSubCircuitPinOthersItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/net/device terminal/more: header column = pin name, second column = net link + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); + + if (column == model->object_column ()) { + return model->make_link_to (m_pp, circuit_refs); + } else if (column == model->first_column () || column == model->second_column ()) { + return model->make_link_to (nets_from_subcircuit_pins (subcircuits, m_pp), column); + } + + return QString (); +} + +QString +CircuitNetSubCircuitPinOthersItemData::search_text () +{ + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); + IndexedNetlistModel::net_pair nets = nets_from_circuit_pins (circuit_refs, m_pp); + return tl::to_qstring (combine_search_strings (search_string_from_names (m_pp), search_string_from_expanded_names (nets))); +} + +std::string +CircuitNetSubCircuitPinOthersItemData::tooltip (NetlistBrowserModel *model) +{ + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + std::string hint; + + if (! model->is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, m_pp))) { + // This indicates a wrong connection: the nets are associated in a way which is a not + // corresponding to a mapped net pair. Report Mismatch here. + hint = rewire_subcircuit_pins_status_hint (); + } + + return hint; +} + +db::NetlistCrossReference::Status +CircuitNetSubCircuitPinOthersItemData::status (NetlistBrowserModel *model) +{ + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + if (! model->is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, m_pp))) { + // This indicates a wrong connection: the nets are associated in a way which is a not + // corresponding to a mapped net pair. Report Mismatch here. + return db::NetlistCrossReference::NoMatch; + } + + return db::NetlistCrossReference::None; +} + +// ---------------------------------------------------------------------------------- + +CircuitNetPinItemData::CircuitNetPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pin_pair &pp) + : NetlistModelItemData (parent), m_pp (pp) +{ } + +void +CircuitNetPinItemData::do_ensure_children (NetlistBrowserModel *) +{ + // nothing (leaf node) +} + +QIcon +CircuitNetPinItemData::icon (NetlistBrowserModel * /*model*/) +{ + return icon_for_pin (); +} + +QString +CircuitNetPinItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/net/pin: header column = pin name, second column empty (for now) + IndexedNetlistModel::circuit_pair circuits (m_pp.first && m_pp.first->net () ? m_pp.first->net ()->circuit () : 0, m_pp.second && m_pp.second->net () ? m_pp.second->net ()->circuit () : 0); + if (model->indexer ()->is_single () && column == model->object_column ()) { + return model->make_link_to (pins_from_pinrefs (m_pp), circuits); + } else if (! model->indexer ()->is_single () && (column == model->first_column () || column == model->second_column ())) { + return model->make_link_to (pins_from_pinrefs (m_pp), circuits, column); + } + + return QString (); +} + +QString +CircuitNetPinItemData::search_text () +{ + return tl::to_qstring (search_string_from_names (pins_from_pinrefs (m_pp))); +} + +std::string +CircuitNetPinItemData::tooltip (NetlistBrowserModel * /*model*/) +{ + return std::string (); +} + +db::NetlistCrossReference::Status +CircuitNetPinItemData::status (NetlistBrowserModel * /*model*/) +{ + return db::NetlistCrossReference::None; +} + +// ---------------------------------------------------------------------------------- + +CircuitSubCircuitItemData::CircuitSubCircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp) + : NetlistModelItemData (parent), m_sp (sp) +{ } + +void +CircuitSubCircuitItemData::do_ensure_children (NetlistBrowserModel *model) +{ + size_t n = std::max (rows_for (sp ().first), rows_for (sp ().second)); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); + for (size_t i = 0; i < n; ++i) { + IndexedNetlistModel::pin_pair pp = model->indexer ()->pin_from_index (circuit_refs, i).first; + push_back (new CircuitSubCircuitPinItemData (this, pp)); + } +} + +QIcon +CircuitSubCircuitItemData::icon (NetlistBrowserModel * /*model*/) +{ + return icon_for_circuit (); +} + +QString +CircuitSubCircuitItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/subcircuit: header column = circuit name, second column subcircuit name + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (m_sp); + if (column == model->object_column ()) { + return model->make_link_to (circuit_refs); + } else if (column == model->first_column ()) { + return escaped (str_from_expanded_name (m_sp.first)); + } else if (column == model->second_column ()) { + return escaped (str_from_expanded_name (m_sp.second)); + } + + return QString (); +} + +QString +CircuitSubCircuitItemData::search_text () +{ + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); + return tl::to_qstring (combine_search_strings (search_string_from_names (circuit_refs), search_string_from_expanded_names (sp ()))); +} + +std::string +CircuitSubCircuitItemData::tooltip (NetlistBrowserModel *model) +{ + size_t index = model->indexer ()->subcircuit_index (sp ()); + return model->indexer ()->subcircuit_status_hint (cp (), index); +} + +db::NetlistCrossReference::Status +CircuitSubCircuitItemData::status (NetlistBrowserModel *model) +{ + size_t index = model->indexer ()->subcircuit_index (sp ()); + return model->indexer ()->subcircuit_from_index (cp (), index).second; +} + +// ---------------------------------------------------------------------------------- + +CircuitSubCircuitPinItemData::CircuitSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp) + : NetlistModelItemData (parent), m_pp (pp) +{ } + +void +CircuitSubCircuitPinItemData::do_ensure_children (NetlistBrowserModel *) +{ + // nothing (leaf node) +} + +QIcon +CircuitSubCircuitPinItemData::icon (NetlistBrowserModel * /*model*/) +{ + return icon_for_pin (); +} + +QString +CircuitSubCircuitPinItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/pin: header column = pin name, other columns net name + const IndexedNetlistModel::subcircuit_pair &sp = static_cast (parent ())->sp (); + + if (column == model->object_column ()) { + return model->make_link_to (m_pp, circuit_refs_from_subcircuits (sp)); + } else if (column == model->first_column () || column == model->second_column ()) { + return model->make_link_to (nets_from_subcircuit_pins (sp, m_pp), column); + } + + return QString (); +} + +QString +CircuitSubCircuitPinItemData::search_text () +{ + IndexedNetlistModel::net_pair nets = nets_from_subcircuit_pins (sp (), m_pp); + return tl::to_qstring (combine_search_strings (search_string_from_names (m_pp), search_string_from_expanded_names (nets))); +} + +std::string +CircuitSubCircuitPinItemData::tooltip (NetlistBrowserModel *model) +{ + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); + + std::string hint = model->indexer ()->pin_status_hint (circuit_refs, model->indexer ()->pin_index (m_pp, circuit_refs)); + if (hint.empty ()) { + + // Another test here is to check whether the pins may be attached to an invalid net pair + if (! model->is_valid_net_pair (nets_from_subcircuit_pins (sp (), m_pp))) { + hint = rewire_subcircuit_pins_status_hint (); + } + + } + + return hint; +} + +db::NetlistCrossReference::Status +CircuitSubCircuitPinItemData::status (NetlistBrowserModel *model) +{ + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); + + db::NetlistCrossReference::Status status = model->indexer ()->pin_from_index (circuit_refs, model->indexer ()->pin_index (m_pp, circuit_refs)).second; + if (status == db::NetlistCrossReference::Mismatch || status == db::NetlistCrossReference::NoMatch) { + return status; + } + + // Another test here is to check whether the pins may be attached to an invalid net pair + if (! model->is_valid_net_pair (nets_from_subcircuit_pins (sp (), m_pp))) { + // This indicates a wrong connection: the nets are associated in a way which is a not + // corresponding to a mapped net pair. Report Mismatch here. + return db::NetlistCrossReference::NoMatch; + } + + return db::NetlistCrossReference::None; +} + +// ---------------------------------------------------------------------------------- + +CircuitDeviceItemData::CircuitDeviceItemData (NetlistModelItemData *parent, const IndexedNetlistModel::device_pair &dp) + : NetlistModelItemData (parent), m_dp (dp) +{ } + +void +CircuitDeviceItemData::do_ensure_children (NetlistBrowserModel * /*model*/) +{ + size_t n = std::max (rows_for (dp ().first), rows_for (dp ().second)); + for (size_t i = 0; i < n; ++i) { + std::pair tp = terminal_defs_from_device_classes (device_classes_from_devices (dp ()), i); + push_back (new CircuitDeviceTerminalItemData (this, tp)); + } +} + +QIcon +CircuitDeviceItemData::icon (NetlistBrowserModel * /*model*/) +{ + std::pair device_classes = device_classes_from_devices (m_dp); + return icon_for_devices (device_classes); +} + +QString +CircuitDeviceItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/device: header column = class + parameters, second column device name + if (model->indexer ()->is_single ()) { + + if (column == model->object_column ()) { + return escaped (device_string (m_dp.first)); + } else if (column == model->first_column ()) { + return escaped (str_from_expanded_name (m_dp.first)); + } + + } else { + + if (column == model->object_column ()) { + return escaped (devices_string (m_dp, model->indexer ()->is_single (), false /*without parameters*/)); + } else if (column == model->first_column ()) { + return escaped (str_from_expanded_name (m_dp.first) + field_sep + device_string (m_dp.first)); + } else if (column == model->second_column ()) { + return escaped (str_from_expanded_name (m_dp.second) + field_sep + device_string (m_dp.second)); + } + + } + + return QString (); +} + +QString +CircuitDeviceItemData::search_text () +{ + std::pair device_classes = device_classes_from_devices (dp ()); + return tl::to_qstring (combine_search_strings (search_string_from_expanded_names (dp ()), search_string_from_names (device_classes))); +} + +std::string +CircuitDeviceItemData::tooltip (NetlistBrowserModel *model) +{ + size_t index = model->indexer ()->device_index (m_dp); + return model->indexer ()->device_status_hint (cp (), index); +} + +db::NetlistCrossReference::Status +CircuitDeviceItemData::status (NetlistBrowserModel *model) +{ + size_t index = model->indexer ()->device_index (m_dp); + return model->indexer ()->device_from_index (cp (), index).second; +} + +// ---------------------------------------------------------------------------------- + +CircuitDeviceTerminalItemData::CircuitDeviceTerminalItemData (NetlistModelItemData *parent, const std::pair &tp) + : NetlistModelItemData (parent), m_tp (tp) +{ } + +void +CircuitDeviceTerminalItemData::do_ensure_children (NetlistBrowserModel *) +{ + // nothing (leaf node) +} + +QIcon +CircuitDeviceTerminalItemData::icon (NetlistBrowserModel *model) +{ + const IndexedNetlistModel::device_pair &dp = static_cast (parent ())->dp (); + return model->icon_for_connection (nets_from_device_terminals (dp, m_tp)); +} + +QString +CircuitDeviceTerminalItemData::text (int column, NetlistBrowserModel *model) +{ + // circuit/device/terminal: header column = terminal name, second column link to net + if (column == model->object_column ()) { + + return escaped (str_from_names (m_tp, model->indexer ()->is_single ())); + + } else if (column == model->first_column () || column == model->second_column ()) { + + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); + return model->make_link_to (nets, column); + + } + + return QString (); +} + +QString +CircuitDeviceTerminalItemData::search_text () +{ + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); + return tl::to_qstring (combine_search_strings (search_string_from_names (m_tp), search_string_from_expanded_names (nets))); +} + +std::string +CircuitDeviceTerminalItemData::tooltip (NetlistBrowserModel * /*model*/) +{ + return std::string (); +} + +db::NetlistCrossReference::Status +CircuitDeviceTerminalItemData::status (NetlistBrowserModel *model) +{ + if (! model->is_valid_net_pair (nets_from_device_terminals (dp (), m_tp))) { + // This indicates a wrong connection: the nets are associated in a way which is a not + // corresponding to a mapped net pair. Report Mismatch here. + return db::NetlistCrossReference::NoMatch; + } + + return db::NetlistCrossReference::None; +} + +// ---------------------------------------------------------------------------------- +// NetlistBrowserModel implementation + +static void *no_id = reinterpret_cast (-1); + +NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb, NetColorizer *colorizer) + : QAbstractItemModel (parent), mp_l2ndb (l2ndb), mp_lvsdb (0), mp_colorizer (colorizer) +{ + mp_root.reset (new RootItemData ()); + mp_indexer.reset (new SingleIndexedNetlistModel (l2ndb->netlist ())); + connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ())); + + m_object_column = 0; + m_status_column = -1; + m_first_column = 2; + m_second_column = -1; +} + +NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutVsSchematic *lvsdb, NetColorizer *colorizer) + : QAbstractItemModel (parent), mp_l2ndb (0), mp_lvsdb (lvsdb), mp_colorizer (colorizer) +{ + mp_root.reset (new RootItemData ()); + mp_indexer.reset (new NetlistCrossReferenceModel (lvsdb->cross_ref ())); + connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ())); + + m_object_column = 0; + m_status_column = 1; + m_first_column = 2; + m_second_column = 3; +} + +NetlistBrowserModel::~NetlistBrowserModel () +{ + // .. nothing yet .. +} + +RootItemData * +NetlistBrowserModel::root () +{ + return dynamic_cast (mp_root.get ()); +} + +int +NetlistBrowserModel::columnCount (const QModelIndex & /*parent*/) const +{ + // Item type & icon, link or description + return mp_indexer->is_single () ? 3 : 4; +} + +QIcon icon_for_status (db::NetlistCrossReference::Status status) +{ + if (status == db::NetlistCrossReference::NoMatch || status == db::NetlistCrossReference::Mismatch) { + return QIcon (":/error2_16.png"); + } else if (status == db::NetlistCrossReference::MatchWithWarning || status == db::NetlistCrossReference::Skipped) { + return QIcon (":/warn_16.png"); + } else { + return QIcon (); + } +} + +QVariant +NetlistBrowserModel::data (const QModelIndex &index, int role) const +{ + if (! index.isValid ()) { + return QVariant (); + } + + if (role == Qt::DecorationRole && index.column () == m_object_column) { + return QVariant (icon (index)); + } else if (role == Qt::DecorationRole && index.column () == m_status_column) { + return QVariant (icon_for_status (status (index))); + } else if (role == Qt::DisplayRole) { + return QVariant (text (index)); + } else if (role == Qt::ToolTipRole && index.column () == m_status_column) { + return tooltip (index); + } else if (role == Qt::UserRole) { + return QVariant (search_text (index)); + } else if (role == Qt::FontRole) { + db::NetlistCrossReference::Status st = status (index); + if (st == db::NetlistCrossReference::NoMatch || st == db::NetlistCrossReference::Mismatch || st == db::NetlistCrossReference::Skipped) { + QFont font; + font.setWeight (QFont::Bold); + return QVariant (font); + } + } else if (role == Qt::ForegroundRole) { + db::NetlistCrossReference::Status st = status (index); + if (st == db::NetlistCrossReference::Match || st == db::NetlistCrossReference::MatchWithWarning) { + // taken from marker browser: + return QVariant (QColor (0, 192, 0)); + } + } + return QVariant (); +} + +static QString build_url (void *id, const std::string &tag, const std::string &title) +{ + if (id == no_id) { + // no link + return tl::to_qstring (tl::escaped_to_html (title)); + } + + std::string s = std::string (""; + + s += tl::escaped_to_html (title); + + s += ""; + + return tl::to_qstring (s); +} + +QString +NetlistBrowserModel::make_link_to (const std::pair &nets, int column) const +{ +#if 0 // @@@ + if ((! nets.first || column == m_second_column) && (! nets.second || column == m_first_column)) { + return QString (); + } else { + + IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (nets); + void *id = no_id; + // NOTE: the nets may not be a valid net pair. In this case, circuits is (0, 0) and + // no link is generated + if (circuits.first || circuits.second) { + id = make_id_circuit_net (mp_indexer->circuit_index (circuits), mp_indexer->net_index (nets)); + } + + if (mp_indexer->is_single () || column == m_first_column) { + return build_url (id, "net", str_from_expanded_name (nets.first)); + } else if (column == m_second_column) { + return build_url (id, "net", str_from_expanded_name (nets.second)); + } else { + return build_url (id, "net", str_from_expanded_names (nets, mp_indexer->is_single ())); + } + + } +#else + if ((! nets.first || column == m_second_column) && (! nets.second || column == m_first_column)) { + return QString (); + } else { + + if (mp_indexer->is_single () || column == m_first_column) { + return tl::to_qstring (str_from_expanded_name (nets.first)); + } else if (column == m_second_column) { + return tl::to_qstring (str_from_expanded_name (nets.second)); + } else { + return tl::to_qstring (str_from_expanded_names (nets, mp_indexer->is_single ())); + } + + } +#endif +} + +QString +NetlistBrowserModel::make_link_to (const std::pair &devices, int column) const +{ +#if 0 + if ((! devices.first || column == m_second_column) && (! devices.second || column == m_first_column)) { + return QString (); + } else { + + IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (devices); + void *id = no_id; + // NOTE: the devices may not be a valid device pair. In this case, circuits is (0, 0) and + // no link is generated + if (circuits.first || circuits.second) { + id = make_id_circuit_device (mp_indexer->circuit_index (circuits), mp_indexer->device_index (devices)); + } + + if (mp_indexer->is_single () || column == m_first_column) { + return build_url (id, "device", str_from_expanded_name (devices.first)); + } else if (column == m_second_column) { + return build_url (id, "device", str_from_expanded_name (devices.second)); + } else { + return build_url (id, "device", str_from_expanded_names (devices, mp_indexer->is_single ())); + } + + } +#else + if ((! devices.first || column == m_second_column) && (! devices.second || column == m_first_column)) { + return QString (); + } else { + + if (mp_indexer->is_single () || column == m_first_column) { + return tl::to_qstring (str_from_expanded_name (devices.first)); + } else if (column == m_second_column) { + return tl::to_qstring (str_from_expanded_name (devices.second)); + } else { + return tl::to_qstring (str_from_expanded_names (devices, mp_indexer->is_single ())); + } + + } +#endif +} + +QString +NetlistBrowserModel::make_link_to (const std::pair &pins, const std::pair & /*circuits*/, int column) const +{ +#if 0 + if ((! pins.first || column == m_second_column) && (! pins.second || column == m_first_column)) { + return QString (); + } else { + void *id = make_id_circuit_pin (mp_indexer->circuit_index (circuits), mp_indexer->pin_index (pins, circuits)); + if (mp_indexer->is_single () || column == m_first_column) { + return build_url (id, "pin", str_from_expanded_name (pins.first)); + } else if (column == m_second_column) { + return build_url (id, "pin", str_from_expanded_name (pins.second)); + } else { + return build_url (id, "pin", str_from_expanded_names (pins, mp_indexer->is_single ())); + } + } +#else + if ((! pins.first || column == m_second_column) && (! pins.second || column == m_first_column)) { + return QString (); + } else { + if (mp_indexer->is_single () || column == m_first_column) { + return tl::to_qstring (str_from_expanded_name (pins.first)); + } else if (column == m_second_column) { + return tl::to_qstring (str_from_expanded_name (pins.second)); + } else { + return tl::to_qstring (str_from_expanded_names (pins, mp_indexer->is_single ())); + } + } +#endif +} + +QString +NetlistBrowserModel::make_link_to (const std::pair &circuits, int column) const +{ +#if 0 + if ((! circuits.first || column == m_second_column) && (! circuits.second || column == m_first_column)) { + return QString (); + } else { + void *id = make_id_circuit (mp_indexer->circuit_index (circuits)); + if (mp_indexer->is_single () || column == m_first_column) { + return build_url (id, "circuit", str_from_name (circuits.first)); + } else if (column == m_second_column) { + return build_url (id, "circuit", str_from_name (circuits.second)); + } else { + return build_url (id, "circuit", str_from_names (circuits, mp_indexer->is_single ())); + } + } +#else + if ((! circuits.first || column == m_second_column) && (! circuits.second || column == m_first_column)) { + return QString (); + } else { + if (mp_indexer->is_single () || column == m_first_column) { + return tl::to_qstring (str_from_name (circuits.first)); + } else if (column == m_second_column) { + return tl::to_qstring (str_from_name (circuits.second)); + } else { + return tl::to_qstring (str_from_names (circuits, mp_indexer->is_single ())); + } + } +#endif +} + +QString +NetlistBrowserModel::make_link_to (const std::pair &subcircuits, int column) const +{ +#if 0 + if ((! subcircuits.first || column == m_second_column) && (! subcircuits.second || column == m_first_column)) { + return QString (); + } else { + + IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (subcircuits); + void *id = no_id; + // NOTE: the subcircuits may not be a valid subcircuit pair. In this case, circuits is (0, 0) and + // no link is generated + if (circuits.first || circuits.second) { + id = make_id_circuit_subcircuit (mp_indexer->circuit_index (circuits), mp_indexer->subcircuit_index (subcircuits)); + } + + if (mp_indexer->is_single () || column == m_first_column) { + return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.first)); + } else if (column == m_second_column) { + return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.second)); + } else { + return build_url (id, "subcircuit", str_from_expanded_names (subcircuits, mp_indexer->is_single ())); + } + + } +#else + if ((! subcircuits.first || column == m_second_column) && (! subcircuits.second || column == m_first_column)) { + return QString (); + } else { + + if (mp_indexer->is_single () || column == m_first_column) { + return tl::to_qstring (str_from_expanded_name (subcircuits.first)); + } else if (column == m_second_column) { + return tl::to_qstring (str_from_expanded_name (subcircuits.second)); + } else { + return tl::to_qstring (str_from_expanded_names (subcircuits, mp_indexer->is_single ())); + } + + } +#endif +} + +bool +NetlistBrowserModel::is_valid_net_pair (const std::pair &nets) const +{ + if (! nets.first && ! nets.second) { + // this is a valid case: e.g. two matching subcircuit pins without nets attached + // to them + return true; + } else { + IndexedNetlistModel::circuit_pair net_parent = mp_indexer->parent_of (nets); + return (net_parent.first != 0 || net_parent.second != 0); + } +} + +db::NetlistCrossReference::Status +NetlistBrowserModel::status (const QModelIndex &index) const +{ + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d) { + return db::NetlistCrossReference::None; + } else { + return d->status (const_cast (this)); + } +} + +QVariant +NetlistBrowserModel::tooltip (const QModelIndex &index) const +{ + std::string hint; + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (d) { + hint = d->tooltip (const_cast (this)); + } + + if (hint.empty ()) { + return QVariant (); + } else { + return QVariant (tl::to_qstring (hint)); + } +} + +QString +NetlistBrowserModel::search_text (const QModelIndex &index) const +{ + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (d) { + return d->search_text (); + } else { + return QString (); + } +} + QIcon NetlistBrowserModel::icon_for_nets (const std::pair &nets) const { @@ -2027,7 +2581,7 @@ NetlistBrowserModel::icon (const QModelIndex &index) const if (! d) { return QIcon (); } else { - return d->icon (); + return d->icon (const_cast (this)); } } @@ -2040,11 +2594,11 @@ NetlistBrowserModel::flags (const QModelIndex & /*index*/) const bool NetlistBrowserModel::hasChildren (const QModelIndex &parent) const { - NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + NetlistModelItemData *d = (NetlistModelItemData *) (parent.internalPointer ()); if (! d) { return false; } else { - d->ensure_children (this); + d->ensure_children (const_cast (this)); return d->begin () != d->end (); } } @@ -2080,13 +2634,16 @@ NetlistBrowserModel::headerData (int section, Qt::Orientation /*orientation*/, i QModelIndex NetlistBrowserModel::index (int row, int column, const QModelIndex &parent) const { - NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); - if (! d) { - return QModelIndex (); - } else { - d->ensure_children (this); - return createIndex (row, column, (void *) d->child (size_t (row))); + NetlistModelItemData *d = 0; + if (parent.isValid ()) { + d = (NetlistModelItemData *) (parent.internalPointer ()); } + if (! d) { + d = mp_root.get (); + } + + d->ensure_children (const_cast (this)); + return createIndex (row, column, (void *) d->child (size_t (row))); } void @@ -2096,200 +2653,85 @@ NetlistBrowserModel::colors_changed () } QModelIndex -NetlistBrowserModel::index_from_net (const std::pair &nets) const +NetlistBrowserModel::index_from_net (const std::pair &nets) { IndexedNetlistModel::circuit_pair circuits (nets.first ? nets.first->circuit () : 0, nets.second ? nets.second->circuit () : 0); - void *id = make_id_circuit_net (mp_indexer->circuit_index (circuits), mp_indexer->net_index (nets)); - return index_from_id (id, 0); + CircuitItemData *ci = root ()->circuit_item (this, circuits); + if (ci) { + CircuitNetItemData *ni = ci->circuit_net_item (this, nets); + if (ni) { + return createIndex (int (ni->index ()), 0, (void *) ni); + } + } + + return QModelIndex (); } QModelIndex -NetlistBrowserModel::index_from_net (const db::Net *net) const +NetlistBrowserModel::index_from_net (const db::Net *net) { return index_from_net (std::make_pair (net, mp_indexer->second_net_for (net))); } QModelIndex -NetlistBrowserModel::index_from_circuit (const std::pair &circuits) const +NetlistBrowserModel::index_from_circuit (const std::pair &circuits) { - void *id = make_id_circuit (mp_indexer->circuit_index (circuits)); - return index_from_id (id, 0); + CircuitItemData *ci = root ()->circuit_item (this, circuits); + if (ci) { + return createIndex (int (ci->index ()), 0, (void *) ci); + } + + return QModelIndex (); } QModelIndex -NetlistBrowserModel::index_from_circuit (const db::Circuit *net) const +NetlistBrowserModel::index_from_circuit (const db::Circuit *net) { return index_from_circuit (std::make_pair (net, mp_indexer->second_circuit_for (net))); } std::pair -NetlistBrowserModel::circuit_from_index (const QModelIndex &index) const +NetlistBrowserModel::circuit_from_index (const QModelIndex &index) { - return circuits_from_id (index.internalPointer ()); + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d) { + return std::pair (0, 0); + } else { + return d->circuits (); + } } std::pair -NetlistBrowserModel::net_from_index (const QModelIndex &index) const +NetlistBrowserModel::net_from_index (const QModelIndex &index) { - void *id = index.internalPointer (); - if (is_id_circuit_net (id)) { - - return nets_from_id (id); - - } else if (is_id_circuit_device_terminal (id)) { - - IndexedNetlistModel::device_pair devices = devices_from_id (id); - std::pair device_classes = device_classes_from_devices (devices); - - size_t terminal = circuit_device_terminal_index_from_id (id); - std::pair termdefs = terminal_defs_from_device_classes (device_classes, terminal); - - return nets_from_device_terminals (devices, termdefs); - - } else if (is_id_circuit_pin_net (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - IndexedNetlistModel::pin_pair pins = pins_from_id (id); - return nets_from_circuit_pins (circuits, pins); - - } else if (is_id_circuit_subcircuit_pin (id)) { - - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_id (id); - IndexedNetlistModel::pin_pair pins = pins_from_id (id); - return nets_from_subcircuit_pins (subcircuits, pins); - - } else if (is_id_circuit_net_subcircuit_pin_others (id)) { - - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - size_t other_index = circuit_net_subcircuit_pin_other_index_from_id (id); - - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::pin_pair pins = mp_indexer->pin_from_index (circuit_refs, other_index).first; - - return nets_from_subcircuit_pins (subcircuits, pins); - - } else if (is_id_circuit_net_device_terminal_others (id)) { - - IndexedNetlistModel::net_terminal_pair termrefs = net_terminalrefs_from_id (id); - size_t other_index = circuit_net_device_terminal_other_index_from_id (id); - - IndexedNetlistModel::device_pair devices = devices_from_termrefs (termrefs); - std::pair device_classes = device_classes_from_devices (devices); - std::pair termdefs = terminal_defs_from_device_classes (device_classes, other_index); - - return nets_from_device_terminals (devices, termdefs); - + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d) { + return std::pair (0, 0); + } else { + return d->nets (); } - - return std::make_pair ((const db::Net *) 0, (const db::Net *) 0); } std::pair -NetlistBrowserModel::device_from_index (const QModelIndex &index) const +NetlistBrowserModel::device_from_index (const QModelIndex &index) { - void *id = index.internalPointer (); - - if (is_id_circuit_device (id)) { - - return devices_from_id (id); - - } else if (is_id_circuit_net_device_terminal (id)) { - - IndexedNetlistModel::net_terminal_pair termrefs = net_terminalrefs_from_id (id); - return devices_from_termrefs (termrefs); - + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d) { + return std::pair (0, 0); + } else { + return d->devices (); } - - return std::make_pair ((const db::Device *) 0, (const db::Device *) 0); } std::pair -NetlistBrowserModel::subcircuit_from_index (const QModelIndex &index) const +NetlistBrowserModel::subcircuit_from_index (const QModelIndex &index) { - void *id = index.internalPointer (); - - if (is_id_circuit_subcircuit (id)) { - - return subcircuits_from_id (id); - - } else if (is_id_circuit_net_subcircuit_pin (id)) { - - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - return subcircuits_from_pinrefs (pinrefs); - + NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); + if (! d) { + return std::pair (0, 0); + } else { + return d->subcircuits (); } - - return std::make_pair ((const db::SubCircuit *) 0, (const db::SubCircuit *) 0); -} - -QModelIndex -NetlistBrowserModel::index_from_id (void *id, int column) const -{ - if (id == no_id) { - - return QModelIndex (); - - } else if (is_id_circuit (id)) { - - return createIndex (circuit_index_from_id (id), column, id); - - } else if (is_id_circuit_pin (id)) { - - return createIndex (int (circuit_pin_index_from_id (id)), column, id); - - } else if (is_id_circuit_pin_net (id)) { - - return createIndex (0, column, id); - - } else if (is_id_circuit_net (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - return createIndex (int (mp_indexer->pin_count (circuits) + circuit_net_index_from_id (id)), column, id); - - } else if (is_id_circuit_net_device_terminal (id)) { - - return createIndex (circuit_net_device_terminal_index_from_id (id), column, id); - - } else if (is_id_circuit_net_device_terminal_others (id)) { - - return createIndex (circuit_net_device_terminal_other_index_from_id (id), column, id); - - } else if (is_id_circuit_net_pin (id)) { - - IndexedNetlistModel::net_pair nets = nets_from_id (id); - return createIndex (int (mp_indexer->net_terminal_count (nets) + circuit_net_pin_index_from_id (id)), column, id); - - } else if (is_id_circuit_net_subcircuit_pin (id)) { - - IndexedNetlistModel::net_pair nets = nets_from_id (id); - return createIndex (int (mp_indexer->net_terminal_count (nets) + mp_indexer->net_pin_count (nets) + circuit_net_subcircuit_pin_index_from_id (id)), column, id); - - } else if (is_id_circuit_net_subcircuit_pin_others (id)) { - - return createIndex (circuit_net_subcircuit_pin_other_index_from_id (id), column, id); - - } else if (is_id_circuit_subcircuit (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - return createIndex (int (mp_indexer->pin_count (circuits) + mp_indexer->net_count (circuits) + circuit_subcircuit_index_from_id (id)), column, id); - - } else if (is_id_circuit_subcircuit_pin (id)) { - - return createIndex (int (circuit_subcircuit_pin_index_from_id (id)), column, id); - - } else if (is_id_circuit_device (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - return createIndex (int (mp_indexer->pin_count (circuits) + mp_indexer->net_count (circuits) + mp_indexer->subcircuit_count (circuits) + circuit_device_index_from_id (id)), column, id); - - } else if (is_id_circuit_device_terminal (id)) { - - return createIndex (int (circuit_device_terminal_index_from_id (id)), column, id); - - } - - return QModelIndex (); } QModelIndex @@ -2299,7 +2741,7 @@ NetlistBrowserModel::parent (const QModelIndex &index) const if (! d || ! d->parent ()) { return QModelIndex (); } else { - return createIndex (d->parent ()->index (), column, (void *) d->parent ()); + return createIndex (d->parent ()->index (), index.column (), (void *) d->parent ()); } } @@ -2314,99 +2756,6 @@ NetlistBrowserModel::rowCount (const QModelIndex &parent) const } } -std::pair -NetlistBrowserModel::circuits_from_id (void *id) const -{ - size_t index = circuit_index_from_id (id); - return mp_indexer->circuit_from_index (index).first; -} - -std::pair -NetlistBrowserModel::nets_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_net_index_from_id (id); - - return mp_indexer->net_from_index (circuits, index).first; -} - -std::pair -NetlistBrowserModel::net_subcircuit_pinrefs_from_id (void *id) const -{ - IndexedNetlistModel::net_pair nets = nets_from_id (id); - size_t index = circuit_net_subcircuit_pin_index_from_id (id); - - return mp_indexer->net_subcircuit_pinref_from_index (nets, index); -} - -std::pair -NetlistBrowserModel::net_pinrefs_from_id (void *id) const -{ - IndexedNetlistModel::net_pair nets = nets_from_id (id); - size_t index = circuit_net_pin_index_from_id (id); - - return mp_indexer->net_pinref_from_index (nets, index); -} - -std::pair -NetlistBrowserModel::net_terminalrefs_from_id (void *id) const -{ - IndexedNetlistModel::net_pair nets = nets_from_id (id); - size_t index = circuit_net_device_terminal_index_from_id (id); - - return mp_indexer->net_terminalref_from_index (nets, index); -} - -std::pair -NetlistBrowserModel::devices_from_id (void *id) const -{ - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_device_index_from_id (id); - - return mp_indexer->device_from_index (circuits, index).first; -} - -std::pair -NetlistBrowserModel::pins_from_id (void *id) const -{ - if (is_id_circuit_subcircuit_pin (id)) { - - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_id (id); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - - size_t index = circuit_subcircuit_pin_index_from_id (id); - - return mp_indexer->pin_from_index (circuit_refs, index).first; - - } else { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - - size_t index = circuit_pin_index_from_id (id); - - return mp_indexer->pin_from_index (circuits, index).first; - - } -} - -std::pair -NetlistBrowserModel::subcircuits_from_id (void *id) const -{ - if (is_id_circuit_subcircuit_pin (id) || is_id_circuit_subcircuit (id)) { - - IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id); - size_t index = circuit_subcircuit_index_from_id (id); - - return mp_indexer->subcircuit_from_index (circuits, index).first; - - } else { - - IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id); - return subcircuits_from_pinrefs (pinrefs); - - } -} - void NetlistBrowserModel::show_or_hide_items (QTreeView *view, const QModelIndex &parent, bool show_all, bool with_warnings, bool with_children) { diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.h b/src/laybasic/laybasic/layNetlistBrowserModel.h index 52df8f104..b360a8f6b 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.h +++ b/src/laybasic/laybasic/layNetlistBrowserModel.h @@ -92,86 +92,12 @@ private: // NetlistBrowserModel definition class NetlistBrowserModel; - -/** - * @brief A base class for the item data object - */ -class NetlistModelItemData - : public tl::list_node -{ -public: - typedef tl::list::iterator iterator; - - NetlistModelItemData () - : mp_parent (0), m_children_made (false), m_index (0) - { } - - NetlistModelItemData (NetlistModelItemData *parent) - : mp_parent (parent), m_children_made (false), m_index (0) - { } - - virtual int children () = 0; - virtual NetlistModelItemData *parent () { return mp_parent; } - - virtual QIcon icon () = 0; - virtual QString text (int column, NetlistBrowserModel *model) = 0; - virtual QString search_text () = 0; - virtual std::string tooltip (NetlistBrowserModel *model) = 0; - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) = 0; - - void ensure_children (NetlistBrowserModel *model) - { - if (! m_children_made) { - - m_children.clear (); - m_children_per_index.clear (); - - do_ensure_children (model); - - size_t n = 0; - for (iterator i = begin (); i != end (); ++i) { - ++n; - } - m_children_per_index.reserve (n); - - size_t index = 0; - for (iterator i = begin (); i != end (); ++i) { - m_children_per_index.push_back (i.operator-> ()); - i->set_index (index++); - } - - m_children_made = true; - - } - } - - void push_back (NetlistModelItemData *child) - { - m_children.push_back (child); - } - - iterator begin () { return m_children.begin (); } - iterator end () { return m_children.end (); } - - size_t child_count () { return m_children_per_index.size (); } - size_t index () { return m_index; } - - NetlistModelItemData *child (size_t n) - { - return (n < m_children_per_index.size () ? m_children_per_index [n] : 0); - } - -private: - NetlistModelItemData *mp_parent; - tl::list m_children; - std::vector m_children_per_index; - bool m_children_made; - size_t m_index; - - void set_index (size_t index) { m_index = index; } - - virtual void do_ensure_children (NetlistBrowserModel *model) = 0; -}; +class NetlistModelItemData; +class RootItemData; +class CircuitItemData; +class CircuitNetItemData; +class CircuitDeviceItemData; +class CircuitSubCircuitItemData; } @@ -186,6 +112,58 @@ namespace tl { namespace lay { +/** + * @brief A base class for the item data object + */ +class NetlistModelItemData + : public tl::list_node +{ +public: + typedef tl::list::iterator iterator; + + NetlistModelItemData (); + NetlistModelItemData (NetlistModelItemData *parent); + + virtual ~NetlistModelItemData (); + + virtual NetlistModelItemData *parent () { return mp_parent; } + + virtual QIcon icon (NetlistBrowserModel *model) = 0; + virtual QString text (int column, NetlistBrowserModel *model) = 0; + virtual QString search_text () = 0; + virtual std::string tooltip (NetlistBrowserModel *model) = 0; + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) = 0; + + void ensure_children (NetlistBrowserModel *model); + + void push_back (NetlistModelItemData *child); + + iterator begin () { return m_children.begin (); } + iterator end () { return m_children.end (); } + + size_t child_count () { return m_children_per_index.size (); } + size_t index () { return m_index; } + + 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 (); + +private: + NetlistModelItemData *mp_parent; + tl::list m_children; + std::vector m_children_per_index; + bool m_children_made; + size_t m_index; + + void set_index (size_t index) { m_index = index; } + + virtual void do_ensure_children (NetlistBrowserModel *model) = 0; +}; + /** * @brief The NetlistBrowserModel * @@ -250,24 +228,30 @@ public: return mp_indexer.get (); } - std::pair net_from_index (const QModelIndex &index) 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; - QModelIndex index_from_circuit (const std::pair &circuit) const; - QModelIndex index_from_circuit (const db::Circuit *circuit) const; + std::pair net_from_index (const QModelIndex &index); + QModelIndex index_from_net (const std::pair &net); + QModelIndex index_from_net (const db::Net *net); + std::pair circuit_from_index (const QModelIndex &index); + QModelIndex index_from_circuit (const std::pair &circuit); + QModelIndex index_from_circuit (const db::Circuit *circuit); - std::pair subcircuit_from_index (const QModelIndex &index) const; + std::pair subcircuit_from_index (const QModelIndex &index); - std::pair device_from_index (const QModelIndex &index) const; - - bool is_circuit_index (const QModelIndex &index) const - { - return is_id_circuit (index.internalPointer ()); - } + std::pair device_from_index (const QModelIndex &index); void set_item_visibility (QTreeView *view, bool show_all, bool with_warnings); + QString make_link_to (const std::pair &nets, int column = 0) const; + QString make_link_to (const std::pair &devices, int column = 0) const; + QString make_link_to (const std::pair &pins, const std::pair &circuits, int column = 0) const; + QString make_link_to (const std::pair &circuits, int column = 0) const; + QString make_link_to (const std::pair &sub_circuits, int column = 0) const; + + bool is_valid_net_pair (const std::pair &net) const; + + QIcon icon_for_nets (const std::pair &net) const; + QIcon icon_for_connection (const std::pair &net) const; + private slots: void colors_changed (); @@ -275,73 +259,17 @@ private: NetlistBrowserModel (const NetlistBrowserModel &); NetlistBrowserModel &operator= (const NetlistBrowserModel &); - void *make_id_circuit (size_t circuit_index) const; - void *make_id_circuit_pin (size_t circuit_index, size_t pin_index) const; - void *make_id_circuit_pin_net (size_t circuit_index, size_t pin_index, size_t net_index) const; - void *make_id_circuit_net (size_t circuit_index, size_t net_index) const; - void *make_id_circuit_net_device_terminal (size_t circuit_index, size_t net_index, size_t terminal_ref_index) const; - 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; - void *make_id_circuit_net_pin (size_t circuit_index, size_t net_index, size_t pin_index) const; - void *make_id_circuit_net_subcircuit_pin (size_t circuit_index, size_t net_index, size_t pin_ref_index) const; - 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; - void *make_id_circuit_subcircuit (size_t circuit_index, size_t subcircuit_index) const; - void *make_id_circuit_subcircuit_pin (size_t circuit_index, size_t subcircuit_index, size_t pin_index) const; - void *make_id_circuit_device (size_t circuit_index, size_t device_index) const; - void *make_id_circuit_device_terminal (size_t circuit_index, size_t device_index, size_t terminal_index) const; - bool is_id_circuit (void *id) const; - bool is_id_circuit_pin (void *id) const; - bool is_id_circuit_pin_net (void *id) const; - bool is_id_circuit_net (void *id) const; - bool is_id_circuit_net_device_terminal (void *id) const; - bool is_id_circuit_net_device_terminal_others (void *id) const; - bool is_id_circuit_net_pin (void *id) const; - bool is_id_circuit_net_subcircuit_pin (void *id) const; - bool is_id_circuit_net_subcircuit_pin_others (void *id) const; - bool is_id_circuit_subcircuit (void *id) const; - bool is_id_circuit_subcircuit_pin (void *id) const; - bool is_id_circuit_device (void *id) const; - bool is_id_circuit_device_terminal (void *id) const; - size_t circuit_index_from_id (void *id) const; - size_t circuit_pin_index_from_id (void *id) const; - size_t circuit_device_index_from_id (void *id) const; - size_t circuit_device_terminal_index_from_id (void *id) const; - size_t circuit_subcircuit_index_from_id (void *id) const; - size_t circuit_subcircuit_pin_index_from_id (void *id) const; - size_t circuit_net_index_from_id (void *id) const; - size_t circuit_net_pin_index_from_id (void *id) const; - size_t circuit_net_subcircuit_pin_index_from_id (void *id) const; - size_t circuit_net_subcircuit_pin_other_index_from_id (void *id) const; - size_t circuit_net_device_terminal_index_from_id (void *id) const; - size_t circuit_net_device_terminal_other_index_from_id (void *id) const; - std::pair circuits_from_id (void *id) const; - std::pair nets_from_id (void *id) const; - std::pair net_subcircuit_pinrefs_from_id (void *id) const; - std::pair net_terminalrefs_from_id (void *id) const; - std::pair net_pinrefs_from_id (void *id) const; - std::pair devices_from_id (void *id) const; - std::pair pins_from_id (void *id) const; - std::pair subcircuits_from_id (void *id) const; QString text (const QModelIndex &index) const; QVariant tooltip (const QModelIndex &index) const; QString search_text (const QModelIndex &index) const; db::NetlistCrossReference::Status status (const QModelIndex &index) const; QIcon icon (const QModelIndex &index) const; - QString make_link_to (const std::pair &nets, int column = 0) const; - QString make_link_to (const std::pair &devices, int column = 0) const; - QString make_link_to (const std::pair &pins, const std::pair &circuits, int column = 0) const; - QString make_link_to (const std::pair &circuits, int column = 0) const; - QString make_link_to (const std::pair &sub_circuits, int column = 0) const; std::pair netlists () const { return std::pair (mp_l2ndb->netlist (), (const db::Netlist *)0); } - bool is_valid_net_pair (const std::pair &net) const; - - QIcon icon_for_nets (const std::pair &net) const; - QIcon icon_for_connection (const std::pair &net) const; - void show_or_hide_items (QTreeView *view, const QModelIndex &parent, bool show_all, bool with_warnings, bool with_children); db::LayoutToNetlist *mp_l2ndb; @@ -354,7 +282,9 @@ private: int m_status_column; int m_first_column; int m_second_column; - std::auto_ptr m_root; + std::auto_ptr mp_root; + + RootItemData *root (); }; } // namespace lay diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index f3c6f799d..6cea8041f 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -411,7 +411,7 @@ NetlistBrowserPage::selected_circuits () QModelIndexList selection = directory_tree->selectionModel ()->selectedIndexes (); for (QModelIndexList::const_iterator i = selection.begin (); i != selection.end (); ++i) { - if (i->column () == 0 && model->is_circuit_index (*i)) { + if (i->column () == 0) { const db::Circuit *circuit = model->circuit_from_index (*i).first; if (circuit) { circuits.push_back (circuit); From f4495274abfc777a409970455595561bcac8cf95 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 17 Jun 2020 23:20:43 +0200 Subject: [PATCH 10/32] WIP: refactoring for more comfortable net browser --- .../laybasic/layNetlistBrowserModel.cc | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 028ead3d3..a99b2f359 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -2271,6 +2271,7 @@ NetlistBrowserModel::data (const QModelIndex &index, int role) const return QVariant (); } +// @@@ static QString build_url (void *id, const std::string &tag, const std::string &title) { if (id == no_id) { @@ -2594,10 +2595,13 @@ NetlistBrowserModel::flags (const QModelIndex & /*index*/) const bool NetlistBrowserModel::hasChildren (const QModelIndex &parent) const { - NetlistModelItemData *d = (NetlistModelItemData *) (parent.internalPointer ()); - if (! d) { - return false; + NetlistModelItemData *d = 0; + if (parent.isValid ()) { + d = (NetlistModelItemData *) (parent.internalPointer ()); } else { + d = mp_root.get (); + } + if (d) { d->ensure_children (const_cast (this)); return d->begin () != d->end (); } @@ -2635,15 +2639,17 @@ QModelIndex NetlistBrowserModel::index (int row, int column, const QModelIndex &parent) const { NetlistModelItemData *d = 0; - if (parent.isValid ()) { + if (! parent.isValid ()) { + d = mp_root.get (); + } else { d = (NetlistModelItemData *) (parent.internalPointer ()); } - if (! d) { - d = mp_root.get (); + if (d) { + d->ensure_children (const_cast (this)); + return createIndex (row, column, (void *) d->child (size_t (row))); + } else { + return QModelIndex (); } - - d->ensure_children (const_cast (this)); - return createIndex (row, column, (void *) d->child (size_t (row))); } void @@ -2748,10 +2754,14 @@ NetlistBrowserModel::parent (const QModelIndex &index) const int NetlistBrowserModel::rowCount (const QModelIndex &parent) const { - NetlistModelItemData *d = (NetlistModelItemData *) (parent.internalPointer ()); - if (! d) { - return 0; + NetlistModelItemData *d = 0; + if (parent.isValid ()) { + d = (NetlistModelItemData *) (parent.internalPointer ()); } else { + d = mp_root.get (); + } + if (d) { + d->ensure_children (const_cast (this)); return int (d->child_count ()); } } From 649b234644276786aedc838ca02d581cfcb1f473 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 18 Jun 2020 23:46:50 +0200 Subject: [PATCH 11/32] WIP: enhanced netlist model --- src/laybasic/laybasic/layNetlistBrowserModel.cc | 4 +++- src/laybasic/laybasic/layNetlistBrowserModel.h | 2 -- src/laybasic/laybasic/layNetlistBrowserPage.cc | 2 ++ .../laybasic/layNetlistBrowserTreeModel.cc | 2 +- .../unit_tests/layNetlistBrowserModelTests.cc | 14 ++++++++++++-- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index a99b2f359..aae0f9c7a 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -2604,6 +2604,8 @@ NetlistBrowserModel::hasChildren (const QModelIndex &parent) const if (d) { d->ensure_children (const_cast (this)); return d->begin () != d->end (); + } else { + return false; } } @@ -2747,7 +2749,7 @@ NetlistBrowserModel::parent (const QModelIndex &index) const if (! d || ! d->parent ()) { return QModelIndex (); } else { - return createIndex (d->parent ()->index (), index.column (), (void *) d->parent ()); + return createIndex (d->parent ()->index (), 0, (void *) d->parent ()); } } diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.h b/src/laybasic/laybasic/layNetlistBrowserModel.h index b360a8f6b..3c21535b9 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.h +++ b/src/laybasic/laybasic/layNetlistBrowserModel.h @@ -201,8 +201,6 @@ public: virtual QModelIndex parent (const QModelIndex &index) const; virtual int rowCount (const QModelIndex &parent) const; - QModelIndex index_from_id (void *id, int column) const; - int status_column () const { return m_status_column; diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index 6cea8041f..dac9529f6 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -520,6 +520,7 @@ NetlistBrowserPage::select_color_for_net () void NetlistBrowserPage::navigate_to (void *id, bool fwd) { +#if 0 // @@@ NetlistBrowserTreeModel *tree_model = dynamic_cast (hierarchy_tree->model ()); NetlistBrowserModel *netlist_model = dynamic_cast (directory_tree->model ()); if (! tree_model || ! netlist_model) { @@ -547,6 +548,7 @@ NetlistBrowserPage::navigate_to (void *id, bool fwd) add_to_history (id, fwd); selection_changed (); +#endif } void diff --git a/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc b/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc index c8d26f5dd..24cfb3c34 100644 --- a/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc @@ -382,7 +382,7 @@ NetlistBrowserTreeModel::parent (const QModelIndex &index) const nprod /= nnlast; - return createIndex (int (ids / nprod - 1), index.column (), reinterpret_cast (ids)); + return createIndex (int (ids / nprod - 1), 0, reinterpret_cast (ids)); } diff --git a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc index c22a3ba73..c7a2bbd6a 100644 --- a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc +++ b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc @@ -48,6 +48,7 @@ TEST (1) EXPECT_EQ (model->rowCount (inv2Index), 14); // Pins EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Index), Qt::UserRole).toString ()), "IN"); + EXPECT_EQ (model->parent (model->index (0, 0, inv2Index)) == model->parent (model->index (0, 3, inv2Index)), true); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Index), Qt::DisplayRole).toString ()), "IN"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Index), Qt::DisplayRole).toString ()), "$1"); EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, inv2Index), Qt::DisplayRole).toString ()), "OUT"); @@ -55,6 +56,7 @@ TEST (1) EXPECT_EQ (tl::to_string (model->data (model->index (4, 0, inv2Index), Qt::DisplayRole).toString ()), "$4"); // Nets EXPECT_EQ (tl::to_string (model->data (model->index (5, 0, inv2Index), Qt::UserRole).toString ()), "NIN"); + EXPECT_EQ (model->parent (model->index (5, 0, inv2Index)) == model->parent (model->index (5, 3, inv2Index)), true); EXPECT_EQ (tl::to_string (model->data (model->index (5, 0, inv2Index), Qt::DisplayRole).toString ()), "NIN"); EXPECT_EQ (tl::to_string (model->data (model->index (5, 2, inv2Index), Qt::DisplayRole).toString ()), "NIN (3)"); EXPECT_EQ (tl::to_string (model->data (model->index (6, 0, inv2Index), Qt::DisplayRole).toString ()), "NOUT"); @@ -68,6 +70,7 @@ TEST (1) // No Subcircuits // Devices EXPECT_EQ (tl::to_string (model->data (model->index (10, 0, inv2Index), Qt::UserRole).toString ()), "$1|PMOS"); + EXPECT_EQ (model->parent (model->index (10, 0, inv2Index)) == model->parent (model->index (10, 3, inv2Index)), true); EXPECT_EQ (tl::to_string (model->data (model->index (10, 0, inv2Index), Qt::DisplayRole).toString ()), "PMOS [L=0.25, W=0.95, AS=0.49875, AD=0.26125, PS=2.95, PD=1.5]"); EXPECT_EQ (tl::to_string (model->data (model->index (10, 2, inv2Index), Qt::DisplayRole).toString ()), "$1"); EXPECT_EQ (tl::to_string (model->data (model->index (11, 0, inv2Index), Qt::DisplayRole).toString ()), "PMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); @@ -83,6 +86,7 @@ TEST (1) // Pins // Nets EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoIndex), Qt::UserRole).toString ()), "FB"); + EXPECT_EQ (model->parent (model->index (0, 0, ringoIndex)) == model->parent (model->index (0, 3, ringoIndex)), true); EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoIndex), Qt::DisplayRole).toString ()), "FB (2)"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, ringoIndex), Qt::DisplayRole).toString ()), "VDD (10)"); EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, ringoIndex), Qt::DisplayRole).toString ()), "VSS (10)"); @@ -97,6 +101,7 @@ TEST (1) EXPECT_EQ (tl::to_string (model->data (model->index (11, 2, ringoIndex), Qt::DisplayRole).toString ()), "$12 (2)"); // Subcircuits EXPECT_EQ (tl::to_string (model->data (model->index (12, 0, ringoIndex), Qt::UserRole).toString ()), "INV2|$1"); + EXPECT_EQ (model->parent (model->index (12, 0, ringoIndex)) == model->parent (model->index (12, 3, ringoIndex)), true); EXPECT_EQ (tl::to_string (model->data (model->index (12, 0, ringoIndex), Qt::DisplayRole).toString ()), "INV2"); EXPECT_EQ (tl::to_string (model->data (model->index (12, 2, ringoIndex), Qt::DisplayRole).toString ()), "$1"); EXPECT_EQ (tl::to_string (model->data (model->index (21, 0, ringoIndex), Qt::DisplayRole).toString ()), "INV2"); @@ -122,12 +127,14 @@ TEST (1) EXPECT_EQ (model->rowCount (inv2NOutIndex), 3); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2NOutIndex), Qt::UserRole).toString ()), "D|PMOS|$2"); + EXPECT_EQ (model->parent (model->index (0, 0, inv2NOutIndex)) == model->parent (model->index (0, 3, inv2NOutIndex)), true); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2NOutIndex), Qt::DisplayRole).toString ()), "D / PMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2NOutIndex), Qt::DisplayRole).toString ()), "$2"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2NOutIndex), Qt::DisplayRole).toString ()), "D / NMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2NOutIndex), Qt::DisplayRole).toString ()), "$4"); EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, inv2NOutIndex), Qt::DisplayRole).toString ()), "OUT"); EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, inv2NOutIndex), Qt::DisplayRole).toString ()), ""); + EXPECT_EQ (model->parent (model->index (2, 0, inv2NOutIndex)) == model->parent (model->index (2, 3, inv2NOutIndex)), true); // no children for pins on nets QModelIndex inv2NOutPinOutIndex = model->index (2, 0, inv2NOutIndex); @@ -136,7 +143,10 @@ TEST (1) EXPECT_EQ (model->rowCount (inv2NOutPinOutIndex), 0); // a MOS3 transistor has three other terminals - QModelIndex inv2NOutDeviceIndex = model->index (0, 0, inv2NOutIndex); + QModelIndex inv2NOutDeviceIndex = model->index (0, 2, inv2NOutIndex); + QModelIndex b = model->index (0, 0, inv2NOutIndex); + EXPECT_EQ (b.parent () == inv2NOutDeviceIndex.parent (), true); + EXPECT_EQ (b.model () == inv2NOutDeviceIndex.model (), true); EXPECT_EQ (model->parent (inv2NOutDeviceIndex) == inv2NOutIndex, true); EXPECT_EQ (model->hasChildren (inv2NOutDeviceIndex), true); EXPECT_EQ (model->rowCount (inv2NOutDeviceIndex), 3); @@ -264,7 +274,7 @@ TEST (2) 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"); - std::pair nets = model->net_from_index (model->index_from_id ((void *) 9, 0)); + std::pair nets = model->net_from_index (model->index (0, 0, inv2Pin0Index)); EXPECT_EQ (nets.first != 0, true); if (nets.first != 0) { EXPECT_EQ (nets.first->expanded_name (), "$1"); From 613c95e9a3a1ccf92d829a2acf251b1938159c09 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 18 Jun 2020 23:50:50 +0200 Subject: [PATCH 12/32] WIP: enhanced netlist model --- src/laybasic/laybasic/layNetlistBrowserModel.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index aae0f9c7a..c50fcb4f4 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -1607,7 +1607,8 @@ CircuitNetDeviceTerminalItemData::do_ensure_children (NetlistBrowserModel * /*mo { 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 termdefs = terminal_defs_from_terminal_refs (m_tp); + std::pair device_classes = device_classes_from_devices (dp ()); + std::pair termdefs = terminal_defs_from_device_classes (device_classes, i); IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), termdefs); push_back (new CircuitNetDeviceTerminalOthersItemData (this, nets, termdefs)); } From 6021a66c40f3cdc0d3efe46234e9f84ae6967a87 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 9 Jul 2020 00:55:38 +0200 Subject: [PATCH 13/32] New node hierarchy for netlist browser. --- .../laybasic/layNetlistBrowserModel.cc | 322 +++++++++++------- 1 file changed, 201 insertions(+), 121 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index c50fcb4f4..519cecb52 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -724,14 +724,9 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - const IndexedNetlistModel::circuit_pair &cp () - { - return m_cp; - } - virtual std::pair circuits () { - return cp (); + return m_cp; } CircuitNetItemData *circuit_net_item (NetlistBrowserModel *model, const IndexedNetlistModel::net_pair &np); @@ -744,6 +739,31 @@ private: // ---------------------------------------------------------------------------------- +class CircuitItemNodeData + : public NetlistModelItemData +{ +public: + enum type { Nets, Devices, Pins, SubCircuits }; + + CircuitItemNodeData (NetlistModelItemData *parent, type t); + + virtual void do_ensure_children (NetlistBrowserModel *model); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + 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: + type m_type; +}; + +// ---------------------------------------------------------------------------------- + class CircuitPinItemData : public NetlistModelItemData { @@ -757,12 +777,6 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitItemData *p = static_cast (parent ()); - return p->cp (); - } - const IndexedNetlistModel::pin_pair &pp () { return m_pp; @@ -792,12 +806,6 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitPinItemData *p = static_cast (parent ()); - return p->cp (); - } - const IndexedNetlistModel::pin_pair &pp () { CircuitPinItemData *p = static_cast (parent ()); @@ -828,12 +836,6 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitItemData *p = static_cast (parent ()); - return p->cp (); - } - const IndexedNetlistModel::net_pair &np () { return m_np; @@ -863,12 +865,6 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitNetItemData *p = static_cast (parent ()); - return p->cp (); - } - const IndexedNetlistModel::net_pair &np () { CircuitNetItemData *p = static_cast (parent ()); @@ -909,12 +905,6 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/); - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitNetDeviceTerminalItemData *p = static_cast (parent ()); - return p->cp (); - } - IndexedNetlistModel::device_pair dp () { CircuitNetDeviceTerminalItemData *p = static_cast (parent ()); @@ -946,12 +936,6 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitNetItemData *p = static_cast (parent ()); - return p->cp (); - } - const IndexedNetlistModel::net_pair &np () { CircuitNetItemData *p = static_cast (parent ()); @@ -998,12 +982,6 @@ public: virtual std::string tooltip (NetlistBrowserModel * /*model*/); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/); - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); - return p->cp (); - } - IndexedNetlistModel::pin_pair pp () { CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); @@ -1064,12 +1042,6 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitItemData *p = static_cast (parent ()); - return p->cp (); - } - const IndexedNetlistModel::subcircuit_pair &sp () { return m_sp; @@ -1099,12 +1071,6 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitSubCircuitItemData *p = static_cast (parent ()); - return p->cp (); - } - const IndexedNetlistModel::subcircuit_pair &sp () { CircuitSubCircuitItemData *p = static_cast (parent ()); @@ -1140,12 +1106,6 @@ public: return m_dp; } - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitItemData *p = static_cast (parent ()); - return p->cp (); - } - virtual std::pair devices () { return m_dp; @@ -1176,12 +1136,6 @@ public: return p->dp (); } - const IndexedNetlistModel::circuit_pair &cp () - { - CircuitDeviceItemData *p = static_cast (parent ()); - return p->cp (); - } - private: std::pair m_tp; }; @@ -1332,26 +1286,17 @@ CircuitItemData::CircuitItemData (NetlistModelItemData *parent, const IndexedNet void CircuitItemData::do_ensure_children (NetlistBrowserModel *model) { - size_t n; - - n = model->indexer ()->pin_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitPinItemData (this, model->indexer ()->pin_from_index (cp (), i).first)); + if (model->indexer ()->pin_count (circuits ()) > 0) { + push_back (new CircuitItemNodeData (this, CircuitItemNodeData::Pins)); } - - n = model->indexer ()->net_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitNetItemData (this, model->indexer ()->net_from_index (cp (), i).first)); + if (model->indexer ()->net_count (circuits ()) > 0) { + push_back (new CircuitItemNodeData (this, CircuitItemNodeData::Nets)); } - - n = model->indexer ()->subcircuit_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitSubCircuitItemData (this, model->indexer ()->subcircuit_from_index (cp (), i).first)); + if (model->indexer ()->subcircuit_count (circuits ()) > 0) { + push_back (new CircuitItemNodeData (this, CircuitItemNodeData::SubCircuits)); } - - n = model->indexer ()->device_count (cp ()); - for (size_t i = 0; i < n; ++i) { - push_back (new CircuitDeviceItemData (this, model->indexer ()->device_from_index (cp (), i).first)); + if (model->indexer ()->device_count (circuits ()) > 0) { + push_back (new CircuitItemNodeData (this, CircuitItemNodeData::Devices)); } } @@ -1379,7 +1324,7 @@ CircuitItemData::text (int column, NetlistBrowserModel *model) QString CircuitItemData::search_text () { - return tl::to_qstring (search_string_from_names (cp ())); + return tl::to_qstring (search_string_from_names (circuits ())); } std::string @@ -1399,31 +1344,166 @@ CircuitItemData::status (NetlistBrowserModel *model) CircuitNetItemData * CircuitItemData::circuit_net_item (NetlistBrowserModel *model, const IndexedNetlistModel::net_pair &np) { - ensure_children (model); - size_t index = model->indexer ()->net_index (np); - index += model->indexer ()->pin_count (cp ()); - return dynamic_cast (child (index)); + for (size_t i = 0; i < child_count (); ++i) { + CircuitNetItemData *d = static_cast (child (i))->circuit_net_item (model, np); + if (d) { + return d; + } + } + return 0; } CircuitDeviceItemData * CircuitItemData::circuit_device_item (NetlistBrowserModel *model, const IndexedNetlistModel::device_pair &dp) { - ensure_children (model); - size_t index = model->indexer ()->device_index (dp); - index += model->indexer ()->pin_count (cp ()); - index += model->indexer ()->net_count (cp ()); - index += model->indexer ()->subcircuit_count (cp ()); - return dynamic_cast (child (index)); + for (size_t i = 0; i < child_count (); ++i) { + CircuitDeviceItemData *d = static_cast (child (i))->circuit_device_item (model, dp); + if (d) { + return d; + } + } + return 0; } CircuitSubCircuitItemData * CircuitItemData::circuit_subcircuit_item (NetlistBrowserModel *model, const IndexedNetlistModel::subcircuit_pair &sp) { - ensure_children (model); - size_t index = model->indexer ()->subcircuit_index (sp); - index += model->indexer ()->pin_count (cp ()); - index += model->indexer ()->net_count (cp ()); - return dynamic_cast (child (index)); + for (size_t i = 0; i < child_count (); ++i) { + CircuitSubCircuitItemData *d = static_cast (child (i))->circuit_subcircuit_item (model, sp); + if (d) { + return d; + } + } + return 0; +} + +// ---------------------------------------------------------------------------------- + +CircuitItemNodeData::CircuitItemNodeData (NetlistModelItemData *parent, CircuitItemNodeData::type t) + : NetlistModelItemData (parent), m_type (t) +{ } + +void +CircuitItemNodeData::do_ensure_children (NetlistBrowserModel *model) +{ + size_t n; + + if (m_type == Pins) { + + n = model->indexer ()->pin_count (circuits ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitPinItemData (this, model->indexer ()->pin_from_index (circuits (), i).first)); + } + + } else if (m_type == Nets) { + + n = model->indexer ()->net_count (circuits ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitNetItemData (this, model->indexer ()->net_from_index (circuits (), i).first)); + } + + } else if (m_type == SubCircuits) { + + n = model->indexer ()->subcircuit_count (circuits ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitSubCircuitItemData (this, model->indexer ()->subcircuit_from_index (circuits (), i).first)); + } + + } else if (m_type == Devices) { + + n = model->indexer ()->device_count (circuits ()); + for (size_t i = 0; i < n; ++i) { + push_back (new CircuitDeviceItemData (this, model->indexer ()->device_from_index (circuits (), i).first)); + } + + } +} + +QIcon +CircuitItemNodeData::icon (NetlistBrowserModel * /*model*/) +{ + if (m_type == Pins) { + return icon_for_pin (); + } else if (m_type == SubCircuits) { + return icon_for_circuit (); + } else if (m_type == Devices) { + return icon_for_device (0); + } else if (m_type == Nets) { + return icon_for_net (); + } else { + return QIcon (); + } +} + +QString +CircuitItemNodeData::text (int column, NetlistBrowserModel *model) +{ + if (column == model->object_column ()) { + if (m_type == Pins) { + return tr ("Pins"); + } else if (m_type == Devices) { + return tr ("Devices"); + } else if (m_type == Nets) { + return tr ("Nets"); + } else if (m_type == SubCircuits) { + return tr ("Subcircuits"); + } + } + return QString (); +} + +QString +CircuitItemNodeData::search_text () +{ + return QString (); +} + +std::string +CircuitItemNodeData::tooltip (NetlistBrowserModel * /*model*/) +{ + return std::string (); +} + +db::NetlistCrossReference::Status +CircuitItemNodeData::status (NetlistBrowserModel * /*model*/) +{ + return db::NetlistCrossReference::None; +} + +CircuitNetItemData * +CircuitItemNodeData::circuit_net_item (NetlistBrowserModel *model, const IndexedNetlistModel::net_pair &np) +{ + if (m_type == Nets) { + ensure_children (model); + size_t index = model->indexer ()->net_index (np); + return dynamic_cast (child (index)); + } else { + return 0; + } +} + +CircuitDeviceItemData * +CircuitItemNodeData::circuit_device_item (NetlistBrowserModel *model, const IndexedNetlistModel::device_pair &dp) +{ + if (m_type == Devices) { + ensure_children (model); + size_t index = model->indexer ()->device_index (dp); + return dynamic_cast (child (index)); + } else { + return 0; + } +} + +CircuitSubCircuitItemData * +CircuitItemNodeData::circuit_subcircuit_item (NetlistBrowserModel *model, const IndexedNetlistModel::subcircuit_pair &sp) +{ + if (m_type == SubCircuits) { + ensure_children (model); + size_t index = model->indexer ()->subcircuit_index (sp); + return dynamic_cast (child (index)); + } else { + return 0; + } } // ---------------------------------------------------------------------------------- @@ -1435,7 +1515,7 @@ CircuitPinItemData::CircuitPinItemData (NetlistModelItemData *parent, const Inde void CircuitPinItemData::do_ensure_children (NetlistBrowserModel * /*model*/) { - push_back (new CircuitPinNetItemData (this, nets_from_circuit_pins (cp (), pp ()))); + push_back (new CircuitPinNetItemData (this, nets_from_circuit_pins (circuits (), pp ()))); } QIcon @@ -1468,15 +1548,15 @@ CircuitPinItemData::search_text () std::string CircuitPinItemData::tooltip (NetlistBrowserModel *model) { - size_t index = model->indexer ()->pin_index (pp (), cp ()); - return model->indexer ()->pin_status_hint (cp (), index); + size_t index = model->indexer ()->pin_index (pp (), circuits ()); + return model->indexer ()->pin_status_hint (circuits (), index); } db::NetlistCrossReference::Status CircuitPinItemData::status (NetlistBrowserModel *model) { - size_t index = model->indexer ()->pin_index (pp (), cp ()); - return model->indexer ()->pin_from_index (cp (), index).second; + size_t index = model->indexer ()->pin_index (pp (), circuits ()); + return model->indexer ()->pin_from_index (circuits (), index).second; } // ---------------------------------------------------------------------------------- @@ -1513,7 +1593,7 @@ CircuitPinNetItemData::text (int column, NetlistBrowserModel *model) QString CircuitPinNetItemData::search_text () { - return tl::to_qstring (search_string_from_expanded_names (nets_from_circuit_pins (cp (), pp ()))); + return tl::to_qstring (search_string_from_expanded_names (nets_from_circuit_pins (circuits (), pp ()))); } std::string @@ -1586,14 +1666,14 @@ std::string CircuitNetItemData::tooltip (NetlistBrowserModel *model) { size_t index = model->indexer ()->net_index (m_np); - return model->indexer ()->net_status_hint (cp (), index); + return model->indexer ()->net_status_hint (circuits (), index); } db::NetlistCrossReference::Status CircuitNetItemData::status (NetlistBrowserModel *model) { size_t index = model->indexer ()->net_index (m_np); - return model->indexer ()->net_from_index (cp (), index).second; + return model->indexer ()->net_from_index (circuits (), index).second; } // ---------------------------------------------------------------------------------- @@ -1653,13 +1733,13 @@ CircuitNetDeviceTerminalItemData::search_text () std::string CircuitNetDeviceTerminalItemData::tooltip (NetlistBrowserModel *model) { - return model->indexer ()->device_status_hint (cp (), model->indexer ()->device_index (dp ())); + return model->indexer ()->device_status_hint (circuits (), model->indexer ()->device_index (dp ())); } db::NetlistCrossReference::Status CircuitNetDeviceTerminalItemData::status (NetlistBrowserModel *model) { - return model->indexer ()->device_from_index (cp (), model->indexer ()->device_index (dp ())).second; + return model->indexer ()->device_from_index (circuits (), model->indexer ()->device_index (dp ())).second; } // ---------------------------------------------------------------------------------- @@ -1775,14 +1855,14 @@ std::string CircuitNetSubCircuitPinItemData::tooltip (NetlistBrowserModel *model) { IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - return model->indexer ()->subcircuit_status_hint (cp (), model->indexer ()->subcircuit_index (subcircuits)); + return model->indexer ()->subcircuit_status_hint (circuits (), model->indexer ()->subcircuit_index (subcircuits)); } db::NetlistCrossReference::Status CircuitNetSubCircuitPinItemData::status (NetlistBrowserModel *model) { IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - return model->indexer ()->subcircuit_from_index (cp (), model->indexer ()->subcircuit_index (subcircuits)).second; + return model->indexer ()->subcircuit_from_index (circuits (), model->indexer ()->subcircuit_index (subcircuits)).second; } // ---------------------------------------------------------------------------------- @@ -1957,14 +2037,14 @@ std::string CircuitSubCircuitItemData::tooltip (NetlistBrowserModel *model) { size_t index = model->indexer ()->subcircuit_index (sp ()); - return model->indexer ()->subcircuit_status_hint (cp (), index); + return model->indexer ()->subcircuit_status_hint (circuits (), index); } db::NetlistCrossReference::Status CircuitSubCircuitItemData::status (NetlistBrowserModel *model) { size_t index = model->indexer ()->subcircuit_index (sp ()); - return model->indexer ()->subcircuit_from_index (cp (), index).second; + return model->indexer ()->subcircuit_from_index (circuits (), index).second; } // ---------------------------------------------------------------------------------- @@ -2106,14 +2186,14 @@ std::string CircuitDeviceItemData::tooltip (NetlistBrowserModel *model) { size_t index = model->indexer ()->device_index (m_dp); - return model->indexer ()->device_status_hint (cp (), index); + return model->indexer ()->device_status_hint (circuits (), index); } db::NetlistCrossReference::Status CircuitDeviceItemData::status (NetlistBrowserModel *model) { size_t index = model->indexer ()->device_index (m_dp); - return model->indexer ()->device_from_index (cp (), index).second; + return model->indexer ()->device_from_index (circuits (), index).second; } // ---------------------------------------------------------------------------------- From aaa8352a402d5b2d4600a1416cee7ee46f658dde Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 11 Jul 2020 00:54:26 +0200 Subject: [PATCH 14/32] Enhancements for netlist tree view - deep hierarchy, no 'failing' terminals on ambiguous device terminals --- .../laybasic/layNetlistBrowserModel.cc | 327 +++++++++++++----- .../laybasic/layNetlistBrowserModel.h | 5 +- .../laybasic/layNetlistBrowserPage.cc | 3 +- 3 files changed, 241 insertions(+), 94 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 519cecb52..f9774ec36 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -434,15 +434,39 @@ static std::pairterminal_def () : 0, termrefs.second ? termrefs.second->terminal_def () : 0); } -static std::pair terminal_defs_from_device_classes (const std::pair &device_classes, size_t terminal_id) +static std::pair terminal_defs_from_device_classes (IndexedNetlistModel *model, const std::pair &device_classes, const std::pair &devices, size_t terminal_id) { const db::DeviceTerminalDefinition *td1 = 0, *td2 = 0; if (device_classes.first && device_classes.first->terminal_definitions ().size () > terminal_id) { td1 = &device_classes.first->terminal_definitions () [terminal_id]; } - if (device_classes.second && device_classes.second->terminal_definitions ().size () > terminal_id) { - td2 = &device_classes.second->terminal_definitions () [terminal_id]; + + if (device_classes.second) { + + size_t second_terminal_id = terminal_id; + + // Because of terminal swapping we need to look up the second terminal by looking for equivalent terminals which carry the corresponding net + if (td1 && devices.first && devices.second) { + + size_t td1_id_norm = device_classes.first->normalize_terminal_id (td1->id ()); + const db::Net *n2 = model->second_net_for (devices.first->net_for_terminal (terminal_id)); + + for (size_t i = 0; i < device_classes.second->terminal_definitions ().size (); ++i) { + const db::DeviceTerminalDefinition &td = device_classes.second->terminal_definitions () [i]; + if (device_classes.second->normalize_terminal_id (td.id ()) == td1_id_norm) { + if (devices.second->net_for_terminal (i) == n2) { + second_terminal_id = i; + break; + } + } + } + + } + + td2 = &device_classes.second->terminal_definitions () [second_terminal_id]; + } + return std::make_pair (td1, td2); } @@ -511,91 +535,151 @@ static size_t rows_for (const db::NetTerminalRef *ref) static QIcon icon_for_net () { - QIcon icon; - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_16.png"))); + static QIcon icon; + if (icon.isNull ()) { + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_48.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_32.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_24.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_16.png"))); + } return icon; } static QIcon light_icon_for_net () { - QIcon icon; - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_16.png"))); + static QIcon icon; + if (icon.isNull ()) { + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_48.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_32.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_24.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_16.png"))); + } return icon; } static QIcon icon_for_connection () { - QIcon icon; - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_16.png"))); + static QIcon icon; + if (icon.isNull ()) { + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_48.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_32.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_24.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_16.png"))); + } return icon; } static QIcon light_icon_for_connection () { - QIcon icon; - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_light_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_light_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_light_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_light_16.png"))); + static QIcon icon; + if (icon.isNull ()) { + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_light_48.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_light_32.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_light_24.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_conn_light_16.png"))); + } return icon; } static QIcon icon_for_pin () { - QIcon icon; - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_pin_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_pin_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_pin_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_pin_16.png"))); + static QIcon icon; + if (icon.isNull ()) { + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_pin_48.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_pin_32.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_pin_24.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_pin_16.png"))); + } return icon; } -static QIcon icon_for_device (const db::DeviceClass *dc) +static QIcon icon_for_device (const db::DeviceClass *dc, size_t term_id = 0) { - QIcon icon; - // TODO: inductor, generic device ... - if (dynamic_cast (dc)) { - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_16.png"))); - } else if (dynamic_cast (dc)) { - // fake ... - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_16.png"))); - } else if (dynamic_cast (dc)) { - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_16.png"))); - } else if (dynamic_cast (dc)) { - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_diode_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_diode_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_diode_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_diode_16.png"))); - } else if (dynamic_cast (dc)) { - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_bjt_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_bjt_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_bjt_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_bjt_16.png"))); - } else { - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_mos_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_mos_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_mos_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_mos_16.png"))); + static QIcon icon_for_res; + static QIcon icon_for_ind; + static QIcon icon_for_cap; + static QIcon icons_for_diode[2]; + static QIcon icons_for_bjt[4]; + static QIcon icons_for_mos[4]; + + if (icon_for_res.isNull ()) { + icon_for_res.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_48.png"))); + icon_for_res.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_32.png"))); + icon_for_res.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_24.png"))); + icon_for_res.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_16.png"))); + } + if (icon_for_ind.isNull ()) { + // fake ... + icon_for_ind.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_48.png"))); + icon_for_ind.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_32.png"))); + icon_for_ind.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_24.png"))); + icon_for_ind.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_16.png"))); + } + if (icon_for_cap.isNull ()) { + icon_for_cap.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_48.png"))); + icon_for_cap.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_32.png"))); + icon_for_cap.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_24.png"))); + icon_for_cap.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_16.png"))); + } + if (icons_for_diode[0].isNull ()) { + QImage i48 (QString::fromUtf8 (":/images/icon_device_diode_48.png")); + QImage i32 (QString::fromUtf8 (":/images/icon_device_diode_32.png")); + QImage i24 (QString::fromUtf8 (":/images/icon_device_diode_24.png")); + QImage i16 (QString::fromUtf8 (":/images/icon_device_diode_16.png")); + QTransform tr; + for (size_t i = 0; i < sizeof (icons_for_diode) / sizeof (icons_for_diode [0]); ++i) { + icons_for_diode[i].addPixmap (QPixmap::fromImage (i48.transformed (tr))); + icons_for_diode[i].addPixmap (QPixmap::fromImage (i32.transformed (tr))); + icons_for_diode[i].addPixmap (QPixmap::fromImage (i24.transformed (tr))); + icons_for_diode[i].addPixmap (QPixmap::fromImage (i16.transformed (tr))); + tr.rotate (180.0); + } + } + if (icons_for_bjt[0].isNull ()) { + QImage i48 (QString::fromUtf8 (":/images/icon_device_bjt_48.png")); + QImage i32 (QString::fromUtf8 (":/images/icon_device_bjt_32.png")); + QImage i24 (QString::fromUtf8 (":/images/icon_device_bjt_24.png")); + QImage i16 (QString::fromUtf8 (":/images/icon_device_bjt_16.png")); + QTransform tr; + for (size_t i = 0; i < sizeof (icons_for_bjt) / sizeof (icons_for_bjt [0]); ++i) { + icons_for_bjt[i].addPixmap (QPixmap::fromImage (i48.transformed (tr))); + icons_for_bjt[i].addPixmap (QPixmap::fromImage (i32.transformed (tr))); + icons_for_bjt[i].addPixmap (QPixmap::fromImage (i24.transformed (tr))); + icons_for_bjt[i].addPixmap (QPixmap::fromImage (i16.transformed (tr))); + tr.rotate (90.0); + } + } + if (icons_for_mos[0].isNull ()) { + QImage i48 (QString::fromUtf8 (":/images/icon_device_mos_48.png")); + QImage i32 (QString::fromUtf8 (":/images/icon_device_mos_32.png")); + QImage i24 (QString::fromUtf8 (":/images/icon_device_mos_24.png")); + QImage i16 (QString::fromUtf8 (":/images/icon_device_mos_16.png")); + QTransform tr; + for (size_t i = 0; i < sizeof (icons_for_mos) / sizeof (icons_for_mos [0]); ++i) { + icons_for_mos[i].addPixmap (QPixmap::fromImage (i48.transformed (tr))); + icons_for_mos[i].addPixmap (QPixmap::fromImage (i32.transformed (tr))); + icons_for_mos[i].addPixmap (QPixmap::fromImage (i24.transformed (tr))); + icons_for_mos[i].addPixmap (QPixmap::fromImage (i16.transformed (tr))); + tr.rotate (90.0); + } + } + + // TODO: generic device ... + if (dynamic_cast (dc)) { + return icon_for_res; + } else if (dynamic_cast (dc)) { + return icon_for_ind; + } else if (dynamic_cast (dc)) { + return icon_for_cap; + } else if (dynamic_cast (dc)) { + return icons_for_diode [term_id >= sizeof (icons_for_diode) / sizeof (icons_for_diode [0]) ? sizeof (icons_for_diode) / sizeof (icons_for_diode [0]) - 1 : term_id]; + } else if (dynamic_cast (dc) || dynamic_cast (dc)) { + return icons_for_bjt [term_id >= sizeof (icons_for_bjt) / sizeof (icons_for_bjt [0]) ? sizeof (icons_for_bjt) / sizeof (icons_for_bjt [0]) - 1 : term_id]; + } else if (dynamic_cast (dc) || dynamic_cast (dc)) { + return icons_for_mos [term_id >= sizeof (icons_for_mos) / sizeof (icons_for_mos [0]) ? sizeof (icons_for_mos) / sizeof (icons_for_mos [0]) - 1 : term_id]; + } else { + return icons_for_mos [0]; } - return icon; } static QIcon icon_for_devices (const std::pair &device_classes) @@ -603,13 +687,35 @@ static QIcon icon_for_devices (const std::pair &device_classes, + const std::pair &terminal_defs) +{ + return icon_for_device (device_classes.first ? device_classes.first : device_classes.second, terminal_defs.first ? terminal_defs.first->id () : (terminal_defs.second ? terminal_defs.second->id () : 0)); +} + static QIcon icon_for_circuit () { - QIcon icon; - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_circuit_48.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_circuit_32.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_circuit_24.png"))); - icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_circuit_16.png"))); + static QIcon icon; + if (icon.isNull ()) { + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_circuit_48.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_circuit_32.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_circuit_24.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_circuit_16.png"))); + } + return icon; +} + +static QIcon icon_for_subcircuit () +{ + static QIcon icon; + if (icon.isNull ()) { + QTransform tr; + tr.rotate (90.0); + icon.addPixmap (QPixmap::fromImage (QImage (QString::fromUtf8 (":/images/icon_circuit_48.png"))).transformed (tr)); + icon.addPixmap (QPixmap::fromImage (QImage (QString::fromUtf8 (":/images/icon_circuit_32.png"))).transformed (tr)); + icon.addPixmap (QPixmap::fromImage (QImage (QString::fromUtf8 (":/images/icon_circuit_24.png"))).transformed (tr)); + icon.addPixmap (QPixmap::fromImage (QImage (QString::fromUtf8 (":/images/icon_circuit_16.png"))).transformed (tr)); + } return icon; } @@ -812,7 +918,7 @@ public: return p->pp (); } - virtual std::pair nets () + virtual std::pair nets_of_this () { return m_np; } @@ -841,7 +947,7 @@ public: return m_np; } - virtual std::pair nets () + virtual std::pair nets_of_this () { return m_np; } @@ -896,7 +1002,7 @@ class CircuitNetDeviceTerminalOthersItemData : public NetlistModelItemData { public: - CircuitNetDeviceTerminalOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp); + CircuitNetDeviceTerminalOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp, bool is_self); virtual void do_ensure_children (NetlistBrowserModel *); virtual QIcon icon (NetlistBrowserModel *model); @@ -911,7 +1017,7 @@ public: return p->dp (); } - virtual std::pair nets () + virtual std::pair nets_of_this () { return m_np; } @@ -919,6 +1025,7 @@ public: private: std::pair m_tp; IndexedNetlistModel::net_pair m_np; + bool m_net_seen; }; // ---------------------------------------------------------------------------------- @@ -973,7 +1080,7 @@ class CircuitNetSubCircuitPinOthersItemData : public NetlistModelItemData { public: - CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp); + CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp, bool is_self); virtual void do_ensure_children (NetlistBrowserModel *); virtual QIcon icon (NetlistBrowserModel *model); @@ -1001,6 +1108,7 @@ public: private: IndexedNetlistModel::pin_pair m_pp; + bool m_net_seen; }; // ---------------------------------------------------------------------------------- @@ -1217,10 +1325,33 @@ NetlistModelItemData::subcircuits () return mp_parent ? mp_parent->subcircuits () : std::pair (0, 0); } +std::pair +NetlistModelItemData::nets_of_this () +{ + return std::pair (0, 0); +} + std::pair NetlistModelItemData::nets () { - return mp_parent ? mp_parent->nets () : std::pair (0, 0); + std::pair r = nets_of_this (); + if (! mp_parent || r.first || r.second) { + return r; + } else { + return mp_parent->nets (); + } +} + +bool +NetlistModelItemData::derived_from_nets (const std::pair &np) +{ + if (nets_of_this () == np) { + return true; + } else if (mp_parent) { + return mp_parent->derived_from_nets (np); + } else { + return false; + } } // ---------------------------------------------------------------------------------- @@ -1683,14 +1814,14 @@ CircuitNetDeviceTerminalItemData::CircuitNetDeviceTerminalItemData (NetlistModel { } void -CircuitNetDeviceTerminalItemData::do_ensure_children (NetlistBrowserModel * /*model*/) +CircuitNetDeviceTerminalItemData::do_ensure_children (NetlistBrowserModel *model) { 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 ()); - std::pair termdefs = terminal_defs_from_device_classes (device_classes, i); + std::pair termdefs = terminal_defs_from_device_classes (model->indexer (), device_classes, dp (), i); IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), termdefs); - push_back (new CircuitNetDeviceTerminalOthersItemData (this, nets, termdefs)); + push_back (new CircuitNetDeviceTerminalOthersItemData (this, nets, termdefs, derived_from_nets (nets))); } } @@ -1698,7 +1829,7 @@ QIcon CircuitNetDeviceTerminalItemData::icon (NetlistBrowserModel * /*model*/) { std::pair device_classes = device_classes_from_devices (dp ()); - return icon_for_devices (device_classes); + return icon_for_devices (device_classes, terminal_defs_from_terminal_refs (m_tp)); } QString @@ -1744,14 +1875,16 @@ CircuitNetDeviceTerminalItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- -CircuitNetDeviceTerminalOthersItemData::CircuitNetDeviceTerminalOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp) - : NetlistModelItemData (parent), m_tp (tp), m_np (np) +CircuitNetDeviceTerminalOthersItemData::CircuitNetDeviceTerminalOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp, bool net_seen) + : NetlistModelItemData (parent), m_tp (tp), m_np (np), m_net_seen (net_seen) { } void CircuitNetDeviceTerminalOthersItemData::do_ensure_children (NetlistBrowserModel *) { - // nothing (leaf node) + if (! m_net_seen) { + push_back (new CircuitNetItemData (this, nets_from_device_terminals (dp (), m_tp))); + } } QIcon @@ -1766,7 +1899,7 @@ CircuitNetDeviceTerminalOthersItemData::text (int column, NetlistBrowserModel *m // circuit/net/device terminal/more: header column = terminal name, second column = net link if (column == model->object_column ()) { - return escaped (str_from_names (m_tp, model->indexer ()->is_single ())); + return escaped (str_from_names (m_tp, model->indexer ()->is_single ())) + (m_net_seen ? tr (" (already seen)") : QString ()); } else if (column == model->first_column () || column == model->second_column ()) { @@ -1817,14 +1950,15 @@ CircuitNetSubCircuitPinItemData::do_ensure_children (NetlistBrowserModel *model) size_t n = model->indexer ()->pin_count (circuit_refs); for (size_t i = 0; i < n; ++i) { IndexedNetlistModel::pin_pair pp = model->indexer ()->pin_from_index (circuit_refs, i).first; - push_back (new CircuitNetSubCircuitPinOthersItemData (this, pp)); + bool is_seen = derived_from_nets (nets_from_subcircuit_pins (subcircuits, pp)); + push_back (new CircuitNetSubCircuitPinOthersItemData (this, pp, is_seen)); } } QIcon CircuitNetSubCircuitPinItemData::icon (NetlistBrowserModel * /*model*/) { - return icon_for_pin (); + return icon_for_subcircuit (); } QString @@ -1867,14 +2001,19 @@ CircuitNetSubCircuitPinItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- -CircuitNetSubCircuitPinOthersItemData::CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp) - : NetlistModelItemData (parent), m_pp (pp) +CircuitNetSubCircuitPinOthersItemData::CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp, bool net_seen) + : NetlistModelItemData (parent), m_pp (pp), m_net_seen (net_seen) { } void CircuitNetSubCircuitPinOthersItemData::do_ensure_children (NetlistBrowserModel *) { - // nothing (leaf node) + if (! m_net_seen) { + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); + IndexedNetlistModel::net_pair nets = nets_from_circuit_pins (circuit_refs, m_pp); + push_back (new CircuitNetItemData (this, nets)); + } } QIcon @@ -1892,7 +2031,7 @@ CircuitNetSubCircuitPinOthersItemData::text (int column, NetlistBrowserModel *mo IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); if (column == model->object_column ()) { - return model->make_link_to (m_pp, circuit_refs); + return model->make_link_to (m_pp, circuit_refs) + (m_net_seen ? tr (" (already seen)") : QString ()); } else if (column == model->first_column () || column == model->second_column ()) { return model->make_link_to (nets_from_subcircuit_pins (subcircuits, m_pp), column); } @@ -2056,7 +2195,8 @@ CircuitSubCircuitPinItemData::CircuitSubCircuitPinItemData (NetlistModelItemData void CircuitSubCircuitPinItemData::do_ensure_children (NetlistBrowserModel *) { - // nothing (leaf node) + IndexedNetlistModel::net_pair nets = nets_from_subcircuit_pins (sp (), m_pp); + push_back (new CircuitNetItemData (this, nets)); } QIcon @@ -2132,11 +2272,11 @@ CircuitDeviceItemData::CircuitDeviceItemData (NetlistModelItemData *parent, cons { } void -CircuitDeviceItemData::do_ensure_children (NetlistBrowserModel * /*model*/) +CircuitDeviceItemData::do_ensure_children (NetlistBrowserModel *model) { size_t n = std::max (rows_for (dp ().first), rows_for (dp ().second)); for (size_t i = 0; i < n; ++i) { - std::pair tp = terminal_defs_from_device_classes (device_classes_from_devices (dp ()), i); + std::pair tp = terminal_defs_from_device_classes (model->indexer (), device_classes_from_devices (dp ()), dp (), i); push_back (new CircuitDeviceTerminalItemData (this, tp)); } } @@ -2205,7 +2345,8 @@ CircuitDeviceTerminalItemData::CircuitDeviceTerminalItemData (NetlistModelItemDa void CircuitDeviceTerminalItemData::do_ensure_children (NetlistBrowserModel *) { - // nothing (leaf node) + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); + push_back (new CircuitNetItemData (this, nets)); } QIcon @@ -2846,6 +2987,8 @@ NetlistBrowserModel::rowCount (const QModelIndex &parent) const if (d) { d->ensure_children (const_cast (this)); return int (d->child_count ()); + } else { + return 0; } } diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.h b/src/laybasic/laybasic/layNetlistBrowserModel.h index 3c21535b9..44117f258 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.h +++ b/src/laybasic/laybasic/layNetlistBrowserModel.h @@ -150,7 +150,10 @@ public: virtual std::pair devices (); virtual std::pair pins (); virtual std::pair subcircuits (); - virtual std::pair nets (); + virtual std::pair nets_of_this (); + + std::pair nets (); + bool derived_from_nets (const std::pair &np); private: NetlistModelItemData *mp_parent; diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index dac9529f6..c29cdbde6 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -142,7 +142,8 @@ NetlistBrowserPage::NetlistBrowserPage (QWidget * /*parent*/) QAction *sep; directory_tree->addAction (m_show_all_action); directory_tree->addAction (actionCollapseAll); - directory_tree->addAction (actionExpandAll); + // TODO: this gives a too big tree - confine to single branches? + // directory_tree->addAction (actionExpandAll); sep = new QAction (directory_tree); sep->setSeparator (true); directory_tree->addAction (sep); From fde90c66e190f67d20262cba3a7304c348f2d2db Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 11 Jul 2020 13:21:23 +0200 Subject: [PATCH 15/32] Better handling of pin swapping in netlist browser --- src/db/db/dbNetlistCrossReference.cc | 10 ++ src/db/db/dbSubCircuit.cc | 11 ++ src/db/db/dbSubCircuit.h | 15 ++ .../laybasic/layIndexedNetlistModel.cc | 12 ++ .../laybasic/layIndexedNetlistModel.h | 4 + .../laybasic/layNetlistBrowserModel.cc | 138 +++++++++--------- .../laybasic/layNetlistCrossReferenceModel.cc | 97 ++++++++++++ .../laybasic/layNetlistCrossReferenceModel.h | 10 ++ .../unit_tests/layNetlistBrowserModelTests.cc | 130 +++++++++-------- 9 files changed, 292 insertions(+), 135 deletions(-) diff --git a/src/db/db/dbNetlistCrossReference.cc b/src/db/db/dbNetlistCrossReference.cc index 479121ba5..9982fdc40 100644 --- a/src/db/db/dbNetlistCrossReference.cc +++ b/src/db/db/dbNetlistCrossReference.cc @@ -601,6 +601,16 @@ NetlistCrossReference::build_subcircuit_pin_refs (const std::pair, const db::NetSubcircuitPinRef *>::iterator b = s2t_b.lower_bound (std::make_pair (sb, 0)); + if (b != s2t_b.end () && b->first.first == sb) { + 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)); diff --git a/src/db/db/dbSubCircuit.cc b/src/db/db/dbSubCircuit.cc index 3d7dd7a7d..bf736f80d 100644 --- a/src/db/db/dbSubCircuit.cc +++ b/src/db/db/dbSubCircuit.cc @@ -119,6 +119,17 @@ const Net *SubCircuit::net_for_pin (size_t pin_id) const return 0; } +const NetSubcircuitPinRef *SubCircuit::netref_for_pin (size_t pin_id) const +{ + if (pin_id < m_pin_refs.size ()) { + Net::subcircuit_pin_iterator p = m_pin_refs [pin_id]; + if (p != Net::subcircuit_pin_iterator ()) { + return p.operator-> (); + } + } + return 0; +} + void SubCircuit::connect_pin (size_t pin_id, Net *net) { if (net_for_pin (pin_id) == net) { diff --git a/src/db/db/dbSubCircuit.h b/src/db/db/dbSubCircuit.h index fa16d971e..c69a8e1e0 100644 --- a/src/db/db/dbSubCircuit.h +++ b/src/db/db/dbSubCircuit.h @@ -171,6 +171,21 @@ public: return const_cast (((const SubCircuit *) this)->net_for_pin (pin_id)); } + /** + * @brief Gets the net attached to a specific pin as a subcircuit pin ref object + * Returns 0 if no net is attached. + */ + const NetSubcircuitPinRef *netref_for_pin (size_t pin_id) const; + + /** + * @brief Gets the net attached to a specific pin as a subcircuit pin ref object (non-const version) + * Returns 0 if no net is attached. + */ + NetSubcircuitPinRef *netref_for_pin (size_t pin_id) + { + return const_cast (((const SubCircuit *) this)->netref_for_pin (pin_id)); + } + /** * @brief Connects the given pin to the given net * If the net is 0 the pin is disconnected. diff --git a/src/laybasic/laybasic/layIndexedNetlistModel.cc b/src/laybasic/laybasic/layIndexedNetlistModel.cc index 9fbd69fd0..8fc5810f4 100644 --- a/src/laybasic/laybasic/layIndexedNetlistModel.cc +++ b/src/laybasic/laybasic/layIndexedNetlistModel.cc @@ -263,6 +263,12 @@ SingleIndexedNetlistModel::device_count (const circuit_pair &circuits) const return circuits.first->device_count (); } +size_t +SingleIndexedNetlistModel::subcircuit_pin_count (const subcircuit_pair &subcircuits) const +{ + return subcircuits.first->circuit_ref ()->pin_count (); +} + size_t SingleIndexedNetlistModel::pin_count (const circuit_pair &circuits) const { @@ -346,6 +352,12 @@ SingleIndexedNetlistModel::net_subcircuit_pinref_from_index (const net_pair &net 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_subcircuit_pin_pair +SingleIndexedNetlistModel::subcircuit_pinref_from_index (const subcircuit_pair &subcircuits, size_t index) const +{ + return IndexedNetlistModel::net_subcircuit_pin_pair (subcircuits.first->netref_for_pin (index), 0); +} + IndexedNetlistModel::net_terminal_pair SingleIndexedNetlistModel::net_terminalref_from_index (const net_pair &nets, size_t index) const { diff --git a/src/laybasic/laybasic/layIndexedNetlistModel.h b/src/laybasic/laybasic/layIndexedNetlistModel.h index 1ccfcc901..e045ead03 100644 --- a/src/laybasic/laybasic/layIndexedNetlistModel.h +++ b/src/laybasic/laybasic/layIndexedNetlistModel.h @@ -80,6 +80,7 @@ public: 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 subcircuit_pin_count (const subcircuit_pair &subcircuits) 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 size_t child_circuit_count (const circuit_pair &circuits) const = 0; @@ -95,6 +96,7 @@ public: virtual const db::Net *second_net_for (const db::Net *first) const = 0; virtual const db::Circuit *second_circuit_for (const db::Circuit *first) const = 0; virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const = 0; + virtual net_subcircuit_pin_pair subcircuit_pinref_from_index (const subcircuit_pair &subcircuits, 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 std::pair device_from_index (const circuit_pair &circuits, size_t index) const = 0; @@ -149,6 +151,7 @@ public: 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_pin_count (const subcircuit_pair &subcircuits) const; virtual size_t subcircuit_count (const circuit_pair &circuits) const; virtual size_t child_circuit_count (const circuit_pair &circuits) const; @@ -163,6 +166,7 @@ public: virtual const db::Net *second_net_for (const db::Net *first) const; virtual const db::Circuit *second_circuit_for (const db::Circuit *first) const; virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const; + virtual net_subcircuit_pin_pair subcircuit_pinref_from_index (const subcircuit_pair &subcircuits, 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 std::pair device_from_index (const circuit_pair &circuits, size_t index) const; diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index f9774ec36..6717ce08a 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -354,6 +354,20 @@ IndexedNetlistModel::subcircuit_pair subcircuits_from_pinrefs (const IndexedNetl return std::make_pair (subcircuit1, subcircuit2); } +static +IndexedNetlistModel::net_pair nets_from_pinrefs (const IndexedNetlistModel::net_subcircuit_pin_pair &pinrefs) +{ + const db::Net *net1 = 0, *net2 = 0; + if (pinrefs.first) { + net1 = pinrefs.first->net (); + } + if (pinrefs.second) { + net2 = pinrefs.second->net (); + } + + return std::make_pair (net1, net2); +} + static IndexedNetlistModel::device_pair devices_from_termrefs (const IndexedNetlistModel::net_terminal_pair &termrefs) { @@ -396,6 +410,20 @@ IndexedNetlistModel::pin_pair pins_from_pinrefs (const IndexedNetlistModel::net_ return std::make_pair (pin1, pin2); } +static +IndexedNetlistModel::pin_pair pins_from_netrefs (const IndexedNetlistModel::net_subcircuit_pin_pair &netrefs) +{ + const db::Pin *pin1 = 0, *pin2 = 0; + if (netrefs.first) { + pin1 = netrefs.first->pin (); + } + if (netrefs.second) { + pin2 = netrefs.second->pin (); + } + + return std::make_pair (pin1, pin2); +} + static IndexedNetlistModel::net_pair nets_from_subcircuit_pins (const IndexedNetlistModel::subcircuit_pair &subcircuits, const IndexedNetlistModel::pin_pair &pins) { @@ -1080,7 +1108,7 @@ class CircuitNetSubCircuitPinOthersItemData : public NetlistModelItemData { public: - CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp, bool is_self); + CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp, bool is_self); virtual void do_ensure_children (NetlistBrowserModel *); virtual QIcon icon (NetlistBrowserModel *model); @@ -1089,25 +1117,18 @@ public: virtual std::string tooltip (NetlistBrowserModel * /*model*/); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/); - IndexedNetlistModel::pin_pair pp () - { - CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); - return p->pp (); - } - - const IndexedNetlistModel::net_subcircuit_pin_pair &sp () - { - CircuitNetSubCircuitPinItemData *p = static_cast (parent ()); - return p->sp (); - } - - virtual std::pair pins () + const IndexedNetlistModel::net_subcircuit_pin_pair &pp () { return m_pp; } + virtual std::pair pins () + { + return std::pair (pins_from_netrefs (m_pp)); + } + private: - IndexedNetlistModel::pin_pair m_pp; + IndexedNetlistModel::net_subcircuit_pin_pair m_pp; bool m_net_seen; }; @@ -1170,7 +1191,7 @@ class CircuitSubCircuitPinItemData : public NetlistModelItemData { public: - CircuitSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp); + CircuitSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp); virtual void do_ensure_children (NetlistBrowserModel *); virtual QIcon icon (NetlistBrowserModel *model); @@ -1179,19 +1200,18 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - const IndexedNetlistModel::subcircuit_pair &sp () + IndexedNetlistModel::subcircuit_pair sp () { - CircuitSubCircuitItemData *p = static_cast (parent ()); - return p->sp (); + return subcircuits_from_pinrefs (m_pp); } virtual std::pair pins () { - return m_pp; + return pins_from_netrefs (m_pp); } private: - IndexedNetlistModel::pin_pair m_pp; + IndexedNetlistModel::net_subcircuit_pin_pair m_pp; }; // ---------------------------------------------------------------------------------- @@ -1945,12 +1965,11 @@ void CircuitNetSubCircuitPinItemData::do_ensure_children (NetlistBrowserModel *model) { IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - size_t n = model->indexer ()->pin_count (circuit_refs); + size_t n = model->indexer ()->subcircuit_pin_count (subcircuits); for (size_t i = 0; i < n; ++i) { - IndexedNetlistModel::pin_pair pp = model->indexer ()->pin_from_index (circuit_refs, i).first; - bool is_seen = derived_from_nets (nets_from_subcircuit_pins (subcircuits, pp)); + 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)); } } @@ -2001,7 +2020,7 @@ CircuitNetSubCircuitPinItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- -CircuitNetSubCircuitPinOthersItemData::CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp, bool net_seen) +CircuitNetSubCircuitPinOthersItemData::CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp, bool net_seen) : NetlistModelItemData (parent), m_pp (pp), m_net_seen (net_seen) { } @@ -2009,31 +2028,27 @@ void CircuitNetSubCircuitPinOthersItemData::do_ensure_children (NetlistBrowserModel *) { if (! m_net_seen) { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::net_pair nets = nets_from_circuit_pins (circuit_refs, m_pp); - push_back (new CircuitNetItemData (this, nets)); + push_back (new CircuitNetItemData (this, nets_from_pinrefs (pp ()))); } } QIcon CircuitNetSubCircuitPinOthersItemData::icon (NetlistBrowserModel *model) { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - return model->icon_for_connection (nets_from_subcircuit_pins (subcircuits, m_pp)); + return model->icon_for_connection (nets_from_pinrefs (pp ())); } QString CircuitNetSubCircuitPinOthersItemData::text (int column, NetlistBrowserModel *model) { // circuit/net/device terminal/more: header column = pin name, second column = net link - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); + IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); if (column == model->object_column ()) { - return model->make_link_to (m_pp, circuit_refs) + (m_net_seen ? tr (" (already seen)") : QString ()); + return model->make_link_to (pins (), circuit_refs) + (m_net_seen ? tr (" (already seen)") : QString ()); } else if (column == model->first_column () || column == model->second_column ()) { - return model->make_link_to (nets_from_subcircuit_pins (subcircuits, m_pp), column); + return model->make_link_to (nets_from_pinrefs (pp ()), column); } return QString (); @@ -2042,19 +2057,15 @@ CircuitNetSubCircuitPinOthersItemData::text (int column, NetlistBrowserModel *mo QString CircuitNetSubCircuitPinOthersItemData::search_text () { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - IndexedNetlistModel::net_pair nets = nets_from_circuit_pins (circuit_refs, m_pp); - return tl::to_qstring (combine_search_strings (search_string_from_names (m_pp), search_string_from_expanded_names (nets))); + return tl::to_qstring (combine_search_strings (search_string_from_names (pins ()), search_string_from_expanded_names (nets_from_pinrefs (pp ())))); } std::string CircuitNetSubCircuitPinOthersItemData::tooltip (NetlistBrowserModel *model) { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); std::string hint; - if (! model->is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, m_pp))) { + if (! model->is_valid_net_pair (nets_from_pinrefs (pp ()))) { // This indicates a wrong connection: the nets are associated in a way which is a not // corresponding to a mapped net pair. Report Mismatch here. hint = rewire_subcircuit_pins_status_hint (); @@ -2066,8 +2077,7 @@ CircuitNetSubCircuitPinOthersItemData::tooltip (NetlistBrowserModel *model) db::NetlistCrossReference::Status CircuitNetSubCircuitPinOthersItemData::status (NetlistBrowserModel *model) { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - if (! model->is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, m_pp))) { + if (! model->is_valid_net_pair (nets_from_pinrefs (pp ()))) { // This indicates a wrong connection: the nets are associated in a way which is a not // corresponding to a mapped net pair. Report Mismatch here. return db::NetlistCrossReference::NoMatch; @@ -2135,10 +2145,9 @@ CircuitSubCircuitItemData::CircuitSubCircuitItemData (NetlistModelItemData *pare void CircuitSubCircuitItemData::do_ensure_children (NetlistBrowserModel *model) { - size_t n = std::max (rows_for (sp ().first), rows_for (sp ().second)); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); + size_t n = model->indexer ()->subcircuit_pin_count (sp ()); for (size_t i = 0; i < n; ++i) { - IndexedNetlistModel::pin_pair pp = model->indexer ()->pin_from_index (circuit_refs, i).first; + IndexedNetlistModel::net_subcircuit_pin_pair pp = model->indexer ()->subcircuit_pinref_from_index (sp (), i); push_back (new CircuitSubCircuitPinItemData (this, pp)); } } @@ -2188,14 +2197,14 @@ CircuitSubCircuitItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- -CircuitSubCircuitPinItemData::CircuitSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp) +CircuitSubCircuitPinItemData::CircuitSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp) : NetlistModelItemData (parent), m_pp (pp) { } void CircuitSubCircuitPinItemData::do_ensure_children (NetlistBrowserModel *) { - IndexedNetlistModel::net_pair nets = nets_from_subcircuit_pins (sp (), m_pp); + IndexedNetlistModel::net_pair nets = nets_from_pinrefs (m_pp); push_back (new CircuitNetItemData (this, nets)); } @@ -2208,13 +2217,10 @@ CircuitSubCircuitPinItemData::icon (NetlistBrowserModel * /*model*/) QString CircuitSubCircuitPinItemData::text (int column, NetlistBrowserModel *model) { - // circuit/pin: header column = pin name, other columns net name - const IndexedNetlistModel::subcircuit_pair &sp = static_cast (parent ())->sp (); - if (column == model->object_column ()) { - return model->make_link_to (m_pp, circuit_refs_from_subcircuits (sp)); + return model->make_link_to (pins (), circuit_refs_from_subcircuits (sp ())); } else if (column == model->first_column () || column == model->second_column ()) { - return model->make_link_to (nets_from_subcircuit_pins (sp, m_pp), column); + return model->make_link_to (nets_from_pinrefs (m_pp), column); } return QString (); @@ -2223,23 +2229,17 @@ CircuitSubCircuitPinItemData::text (int column, NetlistBrowserModel *model) QString CircuitSubCircuitPinItemData::search_text () { - IndexedNetlistModel::net_pair nets = nets_from_subcircuit_pins (sp (), m_pp); - return tl::to_qstring (combine_search_strings (search_string_from_names (m_pp), search_string_from_expanded_names (nets))); + return tl::to_qstring (combine_search_strings (search_string_from_names (pins ()), search_string_from_expanded_names (nets_from_pinrefs (m_pp)))); } std::string CircuitSubCircuitPinItemData::tooltip (NetlistBrowserModel *model) { - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); - - std::string hint = model->indexer ()->pin_status_hint (circuit_refs, model->indexer ()->pin_index (m_pp, circuit_refs)); - if (hint.empty ()) { - - // Another test here is to check whether the pins may be attached to an invalid net pair - if (! model->is_valid_net_pair (nets_from_subcircuit_pins (sp (), m_pp))) { - hint = rewire_subcircuit_pins_status_hint (); - } + std::string hint; + // Check whether the pins may be attached to an invalid net pair + if (! model->is_valid_net_pair (nets_from_pinrefs (m_pp))) { + hint = rewire_subcircuit_pins_status_hint (); } return hint; @@ -2248,15 +2248,7 @@ CircuitSubCircuitPinItemData::tooltip (NetlistBrowserModel *model) db::NetlistCrossReference::Status CircuitSubCircuitPinItemData::status (NetlistBrowserModel *model) { - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (sp ()); - - db::NetlistCrossReference::Status status = model->indexer ()->pin_from_index (circuit_refs, model->indexer ()->pin_index (m_pp, circuit_refs)).second; - if (status == db::NetlistCrossReference::Mismatch || status == db::NetlistCrossReference::NoMatch) { - return status; - } - - // Another test here is to check whether the pins may be attached to an invalid net pair - if (! model->is_valid_net_pair (nets_from_subcircuit_pins (sp (), m_pp))) { + if (! model->is_valid_net_pair (nets_from_pinrefs (m_pp))) { // This indicates a wrong connection: the nets are associated in a way which is a not // corresponding to a mapped net pair. Report Mismatch here. return db::NetlistCrossReference::NoMatch; diff --git a/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc b/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc index 6216c70f7..60a989c07 100644 --- a/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc +++ b/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc @@ -308,6 +308,103 @@ const db::Circuit *NetlistCrossReferenceModel::second_circuit_for (const db::Cir return mp_cross_ref->other_circuit_for (first); } +namespace { + + struct CompareNetRefsByPins + { + bool operator () (const std::pair &a, + const std::pair &b) + { + size_t pin_id1 = a.first ? a.first->pin_id () : (a.second ? a.second->pin_id () : std::numeric_limits::max ()); + size_t pin_id2 = b.first ? b.first->pin_id () : (b.second ? b.second->pin_id () : std::numeric_limits::max ()); + return pin_id1 < pin_id2; + } + }; + +} + +void NetlistCrossReferenceModel::ensure_subcircuit_data_built () const +{ + if (! m_per_subcircuit_data.empty ()) { + return; + } + + // Build the net to subcircuit ref table + for (db::NetlistCrossReference::circuits_iterator c = mp_cross_ref->begin_circuits (); c != mp_cross_ref->end_circuits (); ++c) { + + const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (*c); + if (! data) { + continue; + } + + for (db::NetlistCrossReference::PerCircuitData::subcircuit_pairs_type::const_iterator sc = data->subcircuits.begin (); sc != data->subcircuits.end (); ++sc) { + + const std::pair &sc_pair = sc->pair; + if (sc_pair.first && sc_pair.second) { + + PerSubCircuitCacheData &sc_data = m_per_subcircuit_data [sc_pair]; + + std::multimap first_net_to_other_netref; + for (size_t i = 0; i < sc_pair.second->circuit_ref ()->pin_count (); ++i) { + const db::NetSubcircuitPinRef *n2 = sc_pair.second->netref_for_pin (i); + if (n2) { + const db::Net *n1 = mp_cross_ref->other_net_for (n2->net ()); + if (n1) { + first_net_to_other_netref.insert (std::make_pair (n1, n2)); + } else { + sc_data.nets_per_pins.push_back (std::pair (0, n2)); + } + } + } + + for (size_t i = 0; i < sc_pair.first->circuit_ref ()->pin_count (); ++i) { + const db::NetSubcircuitPinRef *n1 = sc_pair.first->netref_for_pin (i); + const db::NetSubcircuitPinRef *n2 = 0; + std::multimap::iterator m = first_net_to_other_netref.find (n1->net ()); + if (m != first_net_to_other_netref.end () && m->first == n1->net ()) { + n2 = m->second; + first_net_to_other_netref.erase (m); + } + sc_data.nets_per_pins.push_back (std::make_pair (n1, n2)); + } + + std::sort (sc_data.nets_per_pins.begin (), sc_data.nets_per_pins.end (), CompareNetRefsByPins ()); + + } + + } + + } +} + +size_t NetlistCrossReferenceModel::subcircuit_pin_count (const subcircuit_pair &subcircuits) const +{ + ensure_subcircuit_data_built (); + + std::map, PerSubCircuitCacheData>::const_iterator sc = m_per_subcircuit_data.find (subcircuits); + if (sc != m_per_subcircuit_data.end ()) { + return sc->second.nets_per_pins.size (); + } else { + return std::max (subcircuits.first ? subcircuits.first->circuit_ref ()->pin_count () : 0, subcircuits.second ? subcircuits.second->circuit_ref ()->pin_count () : 0); + } +} + +IndexedNetlistModel::net_subcircuit_pin_pair NetlistCrossReferenceModel::subcircuit_pinref_from_index (const subcircuit_pair &subcircuits, size_t index) const +{ + ensure_subcircuit_data_built (); + + std::map, PerSubCircuitCacheData>::const_iterator sc = m_per_subcircuit_data.find (subcircuits); + if (sc != m_per_subcircuit_data.end ()) { + if (index < sc->second.nets_per_pins.size ()) { + return sc->second.nets_per_pins [index]; + } else { + return IndexedNetlistModel::net_subcircuit_pin_pair (0, 0); + } + } else { + return IndexedNetlistModel::net_subcircuit_pin_pair (subcircuits.first ? subcircuits.first->netref_for_pin (index) : 0, subcircuits.second ? subcircuits.second->netref_for_pin (index) : 0); + } +} + 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); diff --git a/src/laybasic/laybasic/layNetlistCrossReferenceModel.h b/src/laybasic/laybasic/layNetlistCrossReferenceModel.h index 34eb8a571..43df8fb2a 100644 --- a/src/laybasic/laybasic/layNetlistCrossReferenceModel.h +++ b/src/laybasic/laybasic/layNetlistCrossReferenceModel.h @@ -48,6 +48,7 @@ public: 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 subcircuit_pin_count (const subcircuit_pair &subcircuits) 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; @@ -65,6 +66,7 @@ public: virtual const db::Net *second_net_for (const db::Net *first) const; virtual const db::Circuit *second_circuit_for (const db::Circuit *first) const; virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const; + virtual net_subcircuit_pin_pair subcircuit_pinref_from_index (const subcircuit_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 std::pair device_from_index (const circuit_pair &circuits, size_t index) const; @@ -95,6 +97,11 @@ public: std::map, size_t> index_of_subcircuits; }; + struct PerSubCircuitCacheData + { + std::vector > nets_per_pins; + }; + tl::weak_ptr mp_cross_ref; mutable std::map m_parents_of_nets; mutable std::map m_parents_of_devices; @@ -104,6 +111,9 @@ public: mutable std::vector m_top_level_circuits; mutable std::map, PerCircuitCacheData> m_per_circuit_data; mutable std::map, size_t> m_index_of_circuits; + mutable std::map, PerSubCircuitCacheData> m_per_subcircuit_data; + + void ensure_subcircuit_data_built () const; }; } diff --git a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc index c7a2bbd6a..f44d76938 100644 --- a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc +++ b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc @@ -44,73 +44,79 @@ TEST (1) QModelIndex inv2Index = model->index (0, 0, QModelIndex ()); EXPECT_EQ (model->hasChildren (inv2Index), true); + // 4 subnodes + EXPECT_EQ (model->rowCount (inv2Index), 3); // 5 pins, 5 nets, 0 subcircuits, 4 devices - EXPECT_EQ (model->rowCount (inv2Index), 14); + QModelIndex sn_pins = model->index (0, 0, inv2Index); + QModelIndex sn_nets = model->index (1, 0, inv2Index); + QModelIndex sn_subcircuits = model->index (2, 0, inv2Index); // Pins - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Index), Qt::UserRole).toString ()), "IN"); - EXPECT_EQ (model->parent (model->index (0, 0, inv2Index)) == model->parent (model->index (0, 3, inv2Index)), true); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Index), Qt::DisplayRole).toString ()), "IN"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Index), Qt::DisplayRole).toString ()), "$1"); - EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, inv2Index), Qt::DisplayRole).toString ()), "OUT"); - EXPECT_EQ (tl::to_string (model->data (model->index (3, 0, inv2Index), Qt::DisplayRole).toString ()), "$3"); - EXPECT_EQ (tl::to_string (model->data (model->index (4, 0, inv2Index), Qt::DisplayRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::UserRole).toString ()), "IN"); + EXPECT_EQ (model->parent (model->index (0, 0, sn_pins)) == model->parent (model->index (0, 3, sn_pins)), true); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::DisplayRole).toString ()), "IN"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, sn_pins), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, sn_pins), Qt::DisplayRole).toString ()), "OUT"); + EXPECT_EQ (tl::to_string (model->data (model->index (3, 0, sn_pins), Qt::DisplayRole).toString ()), "$3"); + EXPECT_EQ (tl::to_string (model->data (model->index (4, 0, sn_pins), Qt::DisplayRole).toString ()), "$4"); // Nets - EXPECT_EQ (tl::to_string (model->data (model->index (5, 0, inv2Index), Qt::UserRole).toString ()), "NIN"); - EXPECT_EQ (model->parent (model->index (5, 0, inv2Index)) == model->parent (model->index (5, 3, inv2Index)), true); - EXPECT_EQ (tl::to_string (model->data (model->index (5, 0, inv2Index), Qt::DisplayRole).toString ()), "NIN"); - EXPECT_EQ (tl::to_string (model->data (model->index (5, 2, inv2Index), Qt::DisplayRole).toString ()), "NIN (3)"); - EXPECT_EQ (tl::to_string (model->data (model->index (6, 0, inv2Index), Qt::DisplayRole).toString ()), "NOUT"); - EXPECT_EQ (tl::to_string (model->data (model->index (6, 2, inv2Index), Qt::DisplayRole).toString ()), "NOUT (3)"); - EXPECT_EQ (tl::to_string (model->data (model->index (7, 0, inv2Index), Qt::DisplayRole).toString ()), "$2"); - EXPECT_EQ (tl::to_string (model->data (model->index (7, 2, inv2Index), Qt::DisplayRole).toString ()), "$2 (5)"); - EXPECT_EQ (tl::to_string (model->data (model->index (8, 0, inv2Index), Qt::DisplayRole).toString ()), "$4"); - EXPECT_EQ (tl::to_string (model->data (model->index (8, 2, inv2Index), Qt::DisplayRole).toString ()), "$4 (3)"); - EXPECT_EQ (tl::to_string (model->data (model->index (9, 0, inv2Index), Qt::DisplayRole).toString ()), "$5"); - EXPECT_EQ (tl::to_string (model->data (model->index (9, 2, inv2Index), Qt::DisplayRole).toString ()), "$5 (3)"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::UserRole).toString ()), "NIN"); + EXPECT_EQ (model->parent (model->index (0, 0, sn_nets)) == model->parent (model->index (0, 3, sn_nets)), true); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::DisplayRole).toString ()), "NIN"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_nets), Qt::DisplayRole).toString ()), "NIN (3)"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, sn_nets), Qt::DisplayRole).toString ()), "NOUT"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, sn_nets), Qt::DisplayRole).toString ()), "NOUT (3)"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, sn_nets), Qt::DisplayRole).toString ()), "$2"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, sn_nets), Qt::DisplayRole).toString ()), "$2 (5)"); + EXPECT_EQ (tl::to_string (model->data (model->index (3, 0, sn_nets), Qt::DisplayRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (3, 2, sn_nets), Qt::DisplayRole).toString ()), "$4 (3)"); + EXPECT_EQ (tl::to_string (model->data (model->index (4, 0, sn_nets), Qt::DisplayRole).toString ()), "$5"); + EXPECT_EQ (tl::to_string (model->data (model->index (4, 2, sn_nets), Qt::DisplayRole).toString ()), "$5 (3)"); // No Subcircuits // Devices - EXPECT_EQ (tl::to_string (model->data (model->index (10, 0, inv2Index), Qt::UserRole).toString ()), "$1|PMOS"); - EXPECT_EQ (model->parent (model->index (10, 0, inv2Index)) == model->parent (model->index (10, 3, inv2Index)), true); - EXPECT_EQ (tl::to_string (model->data (model->index (10, 0, inv2Index), Qt::DisplayRole).toString ()), "PMOS [L=0.25, W=0.95, AS=0.49875, AD=0.26125, PS=2.95, PD=1.5]"); - EXPECT_EQ (tl::to_string (model->data (model->index (10, 2, inv2Index), Qt::DisplayRole).toString ()), "$1"); - EXPECT_EQ (tl::to_string (model->data (model->index (11, 0, inv2Index), Qt::DisplayRole).toString ()), "PMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); - EXPECT_EQ (tl::to_string (model->data (model->index (11, 2, inv2Index), Qt::DisplayRole).toString ()), "$2"); - EXPECT_EQ (tl::to_string (model->data (model->index (12, 0, inv2Index), Qt::DisplayRole).toString ()), "NMOS [L=0.25, W=0.95, AS=0.49875, AD=0.26125, PS=2.95, PD=1.5]"); - EXPECT_EQ (tl::to_string (model->data (model->index (12, 2, inv2Index), Qt::DisplayRole).toString ()), "$3"); - EXPECT_EQ (tl::to_string (model->data (model->index (13, 0, inv2Index), Qt::DisplayRole).toString ()), "NMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); - EXPECT_EQ (tl::to_string (model->data (model->index (13, 2, inv2Index), Qt::DisplayRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_subcircuits), Qt::UserRole).toString ()), "$1|PMOS"); + EXPECT_EQ (model->parent (model->index (0, 0, sn_subcircuits)) == model->parent (model->index (0, 3, sn_subcircuits)), true); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "PMOS [L=0.25, W=0.95, AS=0.49875, AD=0.26125, PS=2.95, PD=1.5]"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "PMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$2"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "NMOS [L=0.25, W=0.95, AS=0.49875, AD=0.26125, PS=2.95, PD=1.5]"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$3"); + EXPECT_EQ (tl::to_string (model->data (model->index (3, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "NMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); + EXPECT_EQ (tl::to_string (model->data (model->index (3, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$4"); EXPECT_EQ (model->hasChildren (ringoIndex), true); // 0 pins, 12 nets, 10 subcircuits, 0 devices - EXPECT_EQ (model->rowCount (ringoIndex), 22); + EXPECT_EQ (model->rowCount (ringoIndex), 2); + sn_nets = model->index (0, 0, ringoIndex); + sn_subcircuits = model->index (1, 0, ringoIndex); // Pins // Nets - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoIndex), Qt::UserRole).toString ()), "FB"); - EXPECT_EQ (model->parent (model->index (0, 0, ringoIndex)) == model->parent (model->index (0, 3, ringoIndex)), true); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoIndex), Qt::DisplayRole).toString ()), "FB (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, ringoIndex), Qt::DisplayRole).toString ()), "VDD (10)"); - EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, ringoIndex), Qt::DisplayRole).toString ()), "VSS (10)"); - EXPECT_EQ (tl::to_string (model->data (model->index (3, 2, ringoIndex), Qt::DisplayRole).toString ()), "$4 (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (4, 2, ringoIndex), Qt::DisplayRole).toString ()), "$5 (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (5, 2, ringoIndex), Qt::DisplayRole).toString ()), "$6 (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (6, 2, ringoIndex), Qt::DisplayRole).toString ()), "$7 (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (7, 2, ringoIndex), Qt::DisplayRole).toString ()), "$8 (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (8, 2, ringoIndex), Qt::DisplayRole).toString ()), "$9 (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (9, 2, ringoIndex), Qt::DisplayRole).toString ()), "$10 (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (10, 2, ringoIndex), Qt::DisplayRole).toString ()), "$11 (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (11, 2, ringoIndex), Qt::DisplayRole).toString ()), "$12 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::UserRole).toString ()), "FB"); + EXPECT_EQ (model->parent (model->index (0, 0, sn_nets)) == model->parent (model->index (0, 3, sn_nets)), true); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_nets), Qt::DisplayRole).toString ()), "FB (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, sn_nets), Qt::DisplayRole).toString ()), "VDD (10)"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, sn_nets), Qt::DisplayRole).toString ()), "VSS (10)"); + EXPECT_EQ (tl::to_string (model->data (model->index (3, 2, sn_nets), Qt::DisplayRole).toString ()), "$4 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (4, 2, sn_nets), Qt::DisplayRole).toString ()), "$5 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (5, 2, sn_nets), Qt::DisplayRole).toString ()), "$6 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (6, 2, sn_nets), Qt::DisplayRole).toString ()), "$7 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (7, 2, sn_nets), Qt::DisplayRole).toString ()), "$8 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (8, 2, sn_nets), Qt::DisplayRole).toString ()), "$9 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (9, 2, sn_nets), Qt::DisplayRole).toString ()), "$10 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (10, 2, sn_nets), Qt::DisplayRole).toString ()), "$11 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (11, 2, sn_nets), Qt::DisplayRole).toString ()), "$12 (2)"); // Subcircuits - EXPECT_EQ (tl::to_string (model->data (model->index (12, 0, ringoIndex), Qt::UserRole).toString ()), "INV2|$1"); - EXPECT_EQ (model->parent (model->index (12, 0, ringoIndex)) == model->parent (model->index (12, 3, ringoIndex)), true); - EXPECT_EQ (tl::to_string (model->data (model->index (12, 0, ringoIndex), Qt::DisplayRole).toString ()), "INV2"); - EXPECT_EQ (tl::to_string (model->data (model->index (12, 2, ringoIndex), Qt::DisplayRole).toString ()), "$1"); - EXPECT_EQ (tl::to_string (model->data (model->index (21, 0, ringoIndex), Qt::DisplayRole).toString ()), "INV2"); - EXPECT_EQ (tl::to_string (model->data (model->index (21, 2, ringoIndex), Qt::DisplayRole).toString ()), "$10"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_subcircuits), Qt::UserRole).toString ()), "INV2|$1"); + EXPECT_EQ (model->parent (model->index (0, 0, sn_subcircuits)) == model->parent (model->index (0, 3, sn_subcircuits)), true); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "INV2"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (9, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "INV2"); + EXPECT_EQ (tl::to_string (model->data (model->index (9, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$10"); // Devices // OUT pin of INV2 has a single child node which is the "NOUT" net - QModelIndex inv2PinOutIndex = model->index (2, 0, inv2Index); - EXPECT_EQ (model->parent (inv2PinOutIndex) == inv2Index, true); + QModelIndex inv2PinOutIndex = model->index (2, 0, model->index (0, 0, inv2Index)); + EXPECT_EQ (model->parent (inv2PinOutIndex) == model->index (0, 0, inv2Index), true); EXPECT_EQ (model->hasChildren (inv2PinOutIndex), true); EXPECT_EQ (model->rowCount (inv2PinOutIndex), 1); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PinOutIndex), Qt::DisplayRole).toString ()), "NOUT"); @@ -121,8 +127,8 @@ TEST (1) EXPECT_EQ (model->rowCount (inv2PinOutIndexNet), 0); // NOUT net has 1 pin, 2 devices, 0 subcircuits - QModelIndex inv2NOutIndex = model->index (6, 0, inv2Index); - EXPECT_EQ (model->parent (inv2NOutIndex) == inv2Index, true); + QModelIndex inv2NOutIndex = model->index (1, 0, model->index (1, 0, inv2Index)); + EXPECT_EQ (model->parent (inv2NOutIndex) == model->index (1, 0, inv2Index), true); EXPECT_EQ (model->hasChildren (inv2NOutIndex), true); EXPECT_EQ (model->rowCount (inv2NOutIndex), 3); @@ -143,7 +149,7 @@ TEST (1) EXPECT_EQ (model->rowCount (inv2NOutPinOutIndex), 0); // a MOS3 transistor has three other terminals - QModelIndex inv2NOutDeviceIndex = model->index (0, 2, inv2NOutIndex); + QModelIndex inv2NOutDeviceIndex = model->index (0, 0, inv2NOutIndex); QModelIndex b = model->index (0, 0, inv2NOutIndex); EXPECT_EQ (b.parent () == inv2NOutDeviceIndex.parent (), true); EXPECT_EQ (b.model () == inv2NOutDeviceIndex.model (), true); @@ -154,16 +160,16 @@ TEST (1) EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2NOutDeviceIndex), Qt::UserRole).toString ()), "S|$5"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2NOutDeviceIndex), Qt::DisplayRole).toString ()), "S"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2NOutDeviceIndex), Qt::DisplayRole).toString ()), "G"); - EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, inv2NOutDeviceIndex), Qt::DisplayRole).toString ()), "D"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, inv2NOutDeviceIndex), Qt::DisplayRole).toString ()), "D (already seen)"); QModelIndex inv2NOutDeviceGateIndex = model->index (1, 0, inv2NOutDeviceIndex); EXPECT_EQ (model->parent (inv2NOutDeviceGateIndex) == inv2NOutDeviceIndex, true); - EXPECT_EQ (model->hasChildren (inv2NOutDeviceGateIndex), false); - EXPECT_EQ (model->rowCount (inv2NOutDeviceGateIndex), 0); + EXPECT_EQ (model->hasChildren (inv2NOutDeviceGateIndex), true); // @@@ -> children: nets + EXPECT_EQ (model->rowCount (inv2NOutDeviceGateIndex), 1); // FB net has 0 pin, 0 devices, 2 subcircuits - QModelIndex ringoFbIndex = model->index (0, 0, ringoIndex); - EXPECT_EQ (model->parent (ringoFbIndex) == ringoIndex, true); + QModelIndex ringoFbIndex = model->index (0, 0, sn_nets); + EXPECT_EQ (model->parent (ringoFbIndex) == sn_nets, true); EXPECT_EQ (model->hasChildren (ringoFbIndex), true); EXPECT_EQ (model->rowCount (ringoFbIndex), 2); @@ -178,7 +184,7 @@ TEST (1) EXPECT_EQ (model->hasChildren (ringoFbSubcircuit2Index), true); EXPECT_EQ (model->rowCount (ringoFbSubcircuit2Index), 5); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbSubcircuit2Index), Qt::UserRole).toString ()), "IN|NIN"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbSubcircuit2Index), Qt::UserRole).toString ()), "IN|FB"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "IN"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "FB"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$1"); From 74b87d536ee7e09241a3375950bfc484d29dc81e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 11 Jul 2020 14:31:56 +0200 Subject: [PATCH 16/32] Fixed unit tests partially. --- .../laybasic/layIndexedNetlistModel.cc | 48 ++++++-- .../laybasic/layIndexedNetlistModel.h | 2 + .../laybasic/layNetlistBrowserModel.cc | 14 ++- .../unit_tests/layNetlistBrowserModelTests.cc | 115 ++++++++++-------- 4 files changed, 111 insertions(+), 68 deletions(-) diff --git a/src/laybasic/laybasic/layIndexedNetlistModel.cc b/src/laybasic/laybasic/layIndexedNetlistModel.cc index 8fc5810f4..4dd2ea7c3 100644 --- a/src/laybasic/laybasic/layIndexedNetlistModel.cc +++ b/src/laybasic/laybasic/layIndexedNetlistModel.cc @@ -236,73 +236,73 @@ SingleIndexedNetlistModel::top_circuit_count () const size_t SingleIndexedNetlistModel::net_count (const circuit_pair &circuits) const { - return circuits.first->net_count (); + return circuits.first ? circuits.first->net_count () : 0; } size_t SingleIndexedNetlistModel::net_terminal_count (const net_pair &nets) const { - return nets.first->terminal_count (); + return nets.first ? nets.first->terminal_count () : 0; } size_t SingleIndexedNetlistModel::net_subcircuit_pin_count (const net_pair &nets) const { - return nets.first->subcircuit_pin_count (); + return nets.first ? nets.first->subcircuit_pin_count () : 0; } size_t SingleIndexedNetlistModel::net_pin_count (const net_pair &nets) const { - return nets.first->pin_count (); + return nets.first ? nets.first->pin_count () : 0; } size_t SingleIndexedNetlistModel::device_count (const circuit_pair &circuits) const { - return circuits.first->device_count (); + return circuits.first ? circuits.first->device_count () : 0; } size_t SingleIndexedNetlistModel::subcircuit_pin_count (const subcircuit_pair &subcircuits) const { - return subcircuits.first->circuit_ref ()->pin_count (); + return subcircuits.first ? subcircuits.first->circuit_ref ()->pin_count () : 0; } size_t SingleIndexedNetlistModel::pin_count (const circuit_pair &circuits) const { - return circuits.first->pin_count (); + return circuits.first ? circuits.first->pin_count () : 0; } size_t SingleIndexedNetlistModel::subcircuit_count (const circuit_pair &circuits) const { - return circuits.first->subcircuit_count (); + return circuits.first ? circuits.first->subcircuit_count () : 0; } size_t SingleIndexedNetlistModel::child_circuit_count (const circuit_pair &circuits) const { - return circuits.first->end_children () - circuits.first->begin_children (); + return circuits.first ? (circuits.first->end_children () - circuits.first->begin_children ()) : 0; } IndexedNetlistModel::circuit_pair SingleIndexedNetlistModel::parent_of (const net_pair &nets) const { - return std::make_pair (nets.first->circuit (), (const db::Circuit *) 0); + return std::make_pair (nets.first ? nets.first->circuit () : 0, (const db::Circuit *) 0); } IndexedNetlistModel::circuit_pair SingleIndexedNetlistModel::parent_of (const device_pair &devices) const { - return std::make_pair (devices.first->circuit (), (const db::Circuit *) 0); + return std::make_pair (devices.first ? devices.first->circuit () : 0, (const db::Circuit *) 0); } IndexedNetlistModel::circuit_pair SingleIndexedNetlistModel::parent_of (const subcircuit_pair &subcircuits) const { - return std::make_pair (subcircuits.first->circuit (), (const db::Circuit *) 0); + return std::make_pair (subcircuits.first ? subcircuits.first->circuit () : 0, (const db::Circuit *) 0); } std::pair @@ -355,7 +355,29 @@ SingleIndexedNetlistModel::net_subcircuit_pinref_from_index (const net_pair &net IndexedNetlistModel::net_subcircuit_pin_pair SingleIndexedNetlistModel::subcircuit_pinref_from_index (const subcircuit_pair &subcircuits, size_t index) const { - return IndexedNetlistModel::net_subcircuit_pin_pair (subcircuits.first->netref_for_pin (index), 0); + if (! subcircuits.first) { + return IndexedNetlistModel::net_subcircuit_pin_pair (0, 0); + } + + std::map >::iterator i = m_subcircuit_pins_by_index.find (subcircuits); + if (i == m_subcircuit_pins_by_index.end ()) { + + i = m_subcircuit_pins_by_index.insert (std::make_pair (subcircuits, std::vector ())).first; + + std::vector &refs = i->second; + const db::Circuit *circuit = subcircuits.first->circuit_ref (); + for (db::Circuit::const_pin_iterator p = circuit->begin_pins (); p != circuit->end_pins (); ++p) { + const db::NetSubcircuitPinRef *ref = subcircuits.first->netref_for_pin (p->id ()); + if (! ref) { + m_synthetic_pinrefs.push_back (db::NetSubcircuitPinRef (const_cast (subcircuits.first), p->id ())); + ref = & m_synthetic_pinrefs.back (); + } + refs.push_back (net_subcircuit_pin_pair (ref, 0)); + } + + } + + return index < i->second.size () ? i->second [index] : IndexedNetlistModel::net_subcircuit_pin_pair (0, 0); } IndexedNetlistModel::net_terminal_pair diff --git a/src/laybasic/laybasic/layIndexedNetlistModel.h b/src/laybasic/laybasic/layIndexedNetlistModel.h index e045ead03..e874c3ca7 100644 --- a/src/laybasic/laybasic/layIndexedNetlistModel.h +++ b/src/laybasic/laybasic/layIndexedNetlistModel.h @@ -198,6 +198,8 @@ private: mutable std::map m_pin_index_by_object; mutable std::map m_subcircuit_index_by_object; mutable std::map m_device_index_by_object; + mutable std::map > m_subcircuit_pins_by_index; + mutable std::list m_synthetic_pinrefs; }; } diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 6717ce08a..7e0a4c40d 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -1903,7 +1903,10 @@ void CircuitNetDeviceTerminalOthersItemData::do_ensure_children (NetlistBrowserModel *) { if (! m_net_seen) { - push_back (new CircuitNetItemData (this, nets_from_device_terminals (dp (), m_tp))); + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); + if (nets.first || nets.second) { + push_back (new CircuitNetItemData (this, nets)); + } } } @@ -2028,7 +2031,10 @@ void CircuitNetSubCircuitPinOthersItemData::do_ensure_children (NetlistBrowserModel *) { if (! m_net_seen) { - push_back (new CircuitNetItemData (this, nets_from_pinrefs (pp ()))); + IndexedNetlistModel::net_pair nets = nets_from_pinrefs (pp ()); + if (nets.first || nets.second) { + push_back (new CircuitNetItemData (this, nets)); + } } } @@ -2205,7 +2211,9 @@ void CircuitSubCircuitPinItemData::do_ensure_children (NetlistBrowserModel *) { IndexedNetlistModel::net_pair nets = nets_from_pinrefs (m_pp); - push_back (new CircuitNetItemData (this, nets)); + if (nets.first || nets.second) { + push_back (new CircuitNetItemData (this, nets)); + } } QIcon diff --git a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc index f44d76938..7b39e9446 100644 --- a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc +++ b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc @@ -49,7 +49,7 @@ TEST (1) // 5 pins, 5 nets, 0 subcircuits, 4 devices QModelIndex sn_pins = model->index (0, 0, inv2Index); QModelIndex sn_nets = model->index (1, 0, inv2Index); - QModelIndex sn_subcircuits = model->index (2, 0, inv2Index); + QModelIndex sn_devices = model->index (2, 0, inv2Index); // Pins EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::UserRole).toString ()), "IN"); EXPECT_EQ (model->parent (model->index (0, 0, sn_pins)) == model->parent (model->index (0, 3, sn_pins)), true); @@ -73,22 +73,22 @@ TEST (1) EXPECT_EQ (tl::to_string (model->data (model->index (4, 2, sn_nets), Qt::DisplayRole).toString ()), "$5 (3)"); // No Subcircuits // Devices - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_subcircuits), Qt::UserRole).toString ()), "$1|PMOS"); - EXPECT_EQ (model->parent (model->index (0, 0, sn_subcircuits)) == model->parent (model->index (0, 3, sn_subcircuits)), true); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "PMOS [L=0.25, W=0.95, AS=0.49875, AD=0.26125, PS=2.95, PD=1.5]"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$1"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "PMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$2"); - EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "NMOS [L=0.25, W=0.95, AS=0.49875, AD=0.26125, PS=2.95, PD=1.5]"); - EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$3"); - EXPECT_EQ (tl::to_string (model->data (model->index (3, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "NMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); - EXPECT_EQ (tl::to_string (model->data (model->index (3, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_devices), Qt::UserRole).toString ()), "$1|PMOS"); + EXPECT_EQ (model->parent (model->index (0, 0, sn_devices)) == model->parent (model->index (0, 3, sn_devices)), true); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_devices), Qt::DisplayRole).toString ()), "PMOS [L=0.25, W=0.95, AS=0.49875, AD=0.26125, PS=2.95, PD=1.5]"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_devices), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, sn_devices), Qt::DisplayRole).toString ()), "PMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, sn_devices), Qt::DisplayRole).toString ()), "$2"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, sn_devices), Qt::DisplayRole).toString ()), "NMOS [L=0.25, W=0.95, AS=0.49875, AD=0.26125, PS=2.95, PD=1.5]"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, sn_devices), Qt::DisplayRole).toString ()), "$3"); + EXPECT_EQ (tl::to_string (model->data (model->index (3, 0, sn_devices), Qt::DisplayRole).toString ()), "NMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); + EXPECT_EQ (tl::to_string (model->data (model->index (3, 2, sn_devices), Qt::DisplayRole).toString ()), "$4"); EXPECT_EQ (model->hasChildren (ringoIndex), true); // 0 pins, 12 nets, 10 subcircuits, 0 devices EXPECT_EQ (model->rowCount (ringoIndex), 2); sn_nets = model->index (0, 0, ringoIndex); - sn_subcircuits = model->index (1, 0, ringoIndex); + QModelIndex sn_subcircuits = model->index (1, 0, ringoIndex); // Pins // Nets EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::UserRole).toString ()), "FB"); @@ -203,8 +203,8 @@ TEST (1) // Subcircuit 1 of RINGO has 5 pins - QModelIndex ringoSubcircuit1Index = model->index (12, 0, ringoIndex); - EXPECT_EQ (model->parent (ringoSubcircuit1Index) == ringoIndex, true); + 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); @@ -219,8 +219,8 @@ TEST (1) // Device 1 of INV2 has 3 pins - QModelIndex inv2Device1Index = model->index (10, 0, inv2Index); - EXPECT_EQ (model->parent (inv2Device1Index) == inv2Index, true); + QModelIndex inv2Device1Index = model->index (0, 0, sn_devices); + EXPECT_EQ (model->parent (inv2Device1Index) == sn_devices, true); EXPECT_EQ (model->hasChildren (inv2Device1Index), true); EXPECT_EQ (model->rowCount (inv2Device1Index), 3); @@ -229,8 +229,8 @@ TEST (1) QModelIndex inv2Device1GateIndex = model->index (1, 0, inv2Device1Index); EXPECT_EQ (model->parent (inv2Device1GateIndex) == inv2Device1Index, true); - EXPECT_EQ (model->hasChildren (inv2Device1GateIndex), false); - EXPECT_EQ (model->rowCount (inv2Device1GateIndex), 0); + EXPECT_EQ (model->hasChildren (inv2Device1GateIndex), true); + EXPECT_EQ (model->rowCount (inv2Device1GateIndex), 1); } TEST (2) @@ -244,6 +244,7 @@ TEST (2) EXPECT_EQ (model->hasChildren (QModelIndex ()), true); // two circuits EXPECT_EQ (model->rowCount (QModelIndex ()), 4); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, QModelIndex ()), Qt::UserRole).toString ()), "INV2PAIRX"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, QModelIndex ()), Qt::DisplayRole).toString ()), "- ⇔ INV2PAIRX"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, QModelIndex ()), Qt::DisplayRole).toString ()), ""); @@ -261,20 +262,27 @@ TEST (2) // INV2 circuit node EXPECT_EQ (model->hasChildren (inv2Index), true); - EXPECT_EQ (model->rowCount (inv2Index), 14); + EXPECT_EQ (model->rowCount (inv2Index), 3); EXPECT_EQ (model->parent (inv2Index).isValid (), false); + QModelIndex sn_pins = model->index (0, 0, inv2Index); + QModelIndex sn_nets = model->index (1, 0, inv2Index); + QModelIndex sn_devices = model->index (2, 0, inv2Index); + EXPECT_EQ (model->rowCount (sn_pins), 6); + EXPECT_EQ (model->rowCount (sn_nets), 6); + EXPECT_EQ (model->rowCount (sn_devices), 2); + // first of pins in INV2 circuit - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Index), Qt::UserRole).toString ()), "$0|$0"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Index), Qt::DisplayRole).toString ()), "$0"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2Index), Qt::DisplayRole).toString ()), "$0"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2Index), Qt::DisplayRole).toString ()), "$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::UserRole).toString ()), "$0|$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::DisplayRole).toString ()), "$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_pins), Qt::DisplayRole).toString ()), "$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, sn_pins), Qt::DisplayRole).toString ()), "$0"); // INV2, pin 0 node - QModelIndex inv2Pin0Index = model->index (0, 0, inv2Index); + QModelIndex inv2Pin0Index = model->index (0, 0, sn_pins); EXPECT_EQ (model->hasChildren (inv2Pin0Index), true); EXPECT_EQ (model->rowCount (inv2Pin0Index), 1); - EXPECT_EQ (model->parent (inv2Pin0Index) == inv2Index, true); + EXPECT_EQ (model->parent (inv2Pin0Index) == sn_pins, true); // INV2, pin 0 has one net node EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Pin0Index), Qt::UserRole).toString ()), "$1|1"); @@ -292,16 +300,16 @@ TEST (2) EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2Pin0Index), Qt::DisplayRole).toString ()), "1"); // first of nets in INV2 circuit - EXPECT_EQ (tl::to_string (model->data (model->index (6, 0, inv2Index), Qt::UserRole).toString ()), "$1|1"); - EXPECT_EQ (tl::to_string (model->data (model->index (6, 0, inv2Index), Qt::DisplayRole).toString ()), "$1 ⇔ 1"); - EXPECT_EQ (tl::to_string (model->data (model->index (6, 2, inv2Index), Qt::DisplayRole).toString ()), "$1 (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (6, 3, inv2Index), Qt::DisplayRole).toString ()), "1 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::UserRole).toString ()), "$1|1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::DisplayRole).toString ()), "$1 ⇔ 1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_nets), Qt::DisplayRole).toString ()), "$1 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, sn_nets), Qt::DisplayRole).toString ()), "1 (2)"); // INV2, net 1 node - QModelIndex inv2Net0Index = model->index (6, 0, inv2Index); + QModelIndex inv2Net0Index = model->index (0, 0, sn_nets); EXPECT_EQ (model->hasChildren (inv2Net0Index), true); EXPECT_EQ (model->rowCount (inv2Net0Index), 2); - EXPECT_EQ (model->parent (inv2Net0Index) == inv2Index, true); + EXPECT_EQ (model->parent (inv2Net0Index) == sn_nets, true); // INV2, net 1 has one pin and one terminal at BULK EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Net0Index), Qt::UserRole).toString ()), "B|B|PMOS|PMOS|$1|$1"); @@ -333,35 +341,38 @@ TEST (2) EXPECT_EQ (model->parent (inv2Net0PinIndex) == inv2Net0Index, true); // second of nets in INV2 circuit - EXPECT_EQ (tl::to_string (model->data (model->index (7, 0, inv2Index), Qt::UserRole).toString ()), "BULK|6"); - EXPECT_EQ (tl::to_string (model->data (model->index (7, 0, inv2Index), Qt::DisplayRole).toString ()), "BULK ⇔ 6"); - EXPECT_EQ (tl::to_string (model->data (model->index (7, 2, inv2Index), Qt::DisplayRole).toString ()), "BULK (2)"); - EXPECT_EQ (tl::to_string (model->data (model->index (7, 3, inv2Index), Qt::DisplayRole).toString ()), "6 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, sn_nets), Qt::UserRole).toString ()), "BULK|6"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, sn_nets), Qt::DisplayRole).toString ()), "BULK ⇔ 6"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, sn_nets), Qt::DisplayRole).toString ()), "BULK (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, sn_nets), Qt::DisplayRole).toString ()), "6 (2)"); // first of devices in INV2 circuit - EXPECT_EQ (tl::to_string (model->data (model->index (12, 0, inv2Index), Qt::UserRole).toString ()), "$1|$1|PMOS|PMOS"); - EXPECT_EQ (tl::to_string (model->data (model->index (12, 0, inv2Index), Qt::DisplayRole).toString ()), "PMOS"); - EXPECT_EQ (tl::to_string (model->data (model->index (12, 2, inv2Index), Qt::DisplayRole).toString ()), "$1 / PMOS [L=0.25, W=3.5]"); - EXPECT_EQ (tl::to_string (model->data (model->index (12, 3, inv2Index), Qt::DisplayRole).toString ()), "$1 / PMOS [L=0.25, W=3.5]"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_devices), Qt::UserRole).toString ()), "$1|$1|PMOS|PMOS"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_devices), Qt::DisplayRole).toString ()), "PMOS"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_devices), Qt::DisplayRole).toString ()), "$1 / PMOS [L=0.25, W=3.5]"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, sn_devices), Qt::DisplayRole).toString ()), "$1 / PMOS [L=0.25, W=3.5]"); QModelIndex inv2PairIndex = model->index (2, 0, QModelIndex ()); EXPECT_EQ (model->parent (inv2PairIndex).isValid (), false); // INV2PAIR circuit node EXPECT_EQ (model->hasChildren (inv2PairIndex), true); - EXPECT_EQ (model->rowCount (inv2PairIndex), 18); + EXPECT_EQ (model->rowCount (inv2PairIndex), 3); + + sn_pins = model->index (0, 0, inv2PairIndex); + sn_nets = model->index (1, 0, inv2PairIndex); // first of pins in INV2 circuit - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairIndex), Qt::UserRole).toString ()), "$4"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairIndex), Qt::DisplayRole).toString ()), "- ⇔ $4"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2PairIndex), Qt::DisplayRole).toString ()), ""); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2PairIndex), Qt::DisplayRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::UserRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::DisplayRole).toString ()), "- ⇔ $4"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_pins), Qt::DisplayRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, sn_pins), Qt::DisplayRole).toString ()), "$4"); // INV2, pin 0 node - QModelIndex inv2PairPin0Index = model->index (0, 0, inv2PairIndex); + QModelIndex inv2PairPin0Index = model->index (0, 0, sn_pins); EXPECT_EQ (model->hasChildren (inv2PairPin0Index), true); EXPECT_EQ (model->rowCount (inv2PairPin0Index), 1); - EXPECT_EQ (model->parent (inv2PairPin0Index) == inv2PairIndex, true); + EXPECT_EQ (model->parent (inv2PairPin0Index) == sn_pins, true); // INV2, pin 0 has one net node // The pin isnt't connected to any net, left side because there is no match, right side because the pin isn't connected @@ -371,16 +382,16 @@ TEST (2) EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2PairPin0Index), Qt::DisplayRole).toString ()), ""); // first of nets in INV2 circuit - EXPECT_EQ (tl::to_string (model->data (model->index (8, 0, inv2PairIndex), Qt::UserRole).toString ()), "$4"); - EXPECT_EQ (tl::to_string (model->data (model->index (8, 0, inv2PairIndex), Qt::DisplayRole).toString ()), "$4 ⇔ -"); - EXPECT_EQ (tl::to_string (model->data (model->index (8, 2, inv2PairIndex), Qt::DisplayRole).toString ()), "$4 (3)"); - EXPECT_EQ (tl::to_string (model->data (model->index (8, 3, inv2PairIndex), Qt::DisplayRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::UserRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::DisplayRole).toString ()), "$4 ⇔ -"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_nets), Qt::DisplayRole).toString ()), "$4 (3)"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, sn_nets), Qt::DisplayRole).toString ()), ""); // This net has only left side which has one pin and two subcircuits - QModelIndex inv2PairNet0Index = model->index (8, 0, inv2PairIndex); + QModelIndex inv2PairNet0Index = model->index (0, 0, sn_nets); EXPECT_EQ (model->hasChildren (inv2PairNet0Index), true); EXPECT_EQ (model->rowCount (inv2PairNet0Index), 3); - EXPECT_EQ (model->parent (inv2PairNet0Index) == inv2PairIndex, true); + EXPECT_EQ (model->parent (inv2PairNet0Index) == sn_nets, true); // The pin EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0Index), Qt::UserRole).toString ()), ""); From f9fa3d3aa348f3764c1dc4a02457da44fc5b8012 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 11 Jul 2020 14:41:42 +0200 Subject: [PATCH 17/32] WIP: some safety --- .../laybasic/layNetlistCrossReferenceModel.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc b/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc index 60a989c07..fc82a79a6 100644 --- a/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc +++ b/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc @@ -359,13 +359,15 @@ void NetlistCrossReferenceModel::ensure_subcircuit_data_built () const for (size_t i = 0; i < sc_pair.first->circuit_ref ()->pin_count (); ++i) { const db::NetSubcircuitPinRef *n1 = sc_pair.first->netref_for_pin (i); - const db::NetSubcircuitPinRef *n2 = 0; - std::multimap::iterator m = first_net_to_other_netref.find (n1->net ()); - if (m != first_net_to_other_netref.end () && m->first == n1->net ()) { - n2 = m->second; - first_net_to_other_netref.erase (m); + if (n1) { + const db::NetSubcircuitPinRef *n2 = 0; + std::multimap::iterator m = first_net_to_other_netref.find (n1->net ()); + if (m != first_net_to_other_netref.end () && m->first == n1->net ()) { + n2 = m->second; + first_net_to_other_netref.erase (m); + } + sc_data.nets_per_pins.push_back (std::make_pair (n1, n2)); } - sc_data.nets_per_pins.push_back (std::make_pair (n1, n2)); } std::sort (sc_data.nets_per_pins.begin (), sc_data.nets_per_pins.end (), CompareNetRefsByPins ()); From 62ed7b9def2b0c91235e6752f3a78b25ebab0fe9 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 11 Jul 2020 19:07:28 +0200 Subject: [PATCH 18/32] Fixed tests. --- .../laybasic/layNetlistBrowserModel.cc | 218 +++++++----------- .../laybasic/layNetlistBrowserModel.h | 21 +- .../laybasic/layNetlistBrowserPage.cc | 53 ++--- src/laybasic/laybasic/layNetlistBrowserPage.h | 6 +- .../unit_tests/layNetlistBrowserModelTests.cc | 66 +++--- 5 files changed, 151 insertions(+), 213 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 7e0a4c40d..541e5aeb2 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -30,6 +30,8 @@ #include #include #include +#include +#include namespace lay { @@ -2402,8 +2404,6 @@ CircuitDeviceTerminalItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- // NetlistBrowserModel implementation -static void *no_id = reinterpret_cast (-1); - NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb, NetColorizer *colorizer) : QAbstractItemModel (parent), mp_l2ndb (l2ndb), mp_lvsdb (0), mp_colorizer (colorizer) { @@ -2436,7 +2436,7 @@ NetlistBrowserModel::~NetlistBrowserModel () } RootItemData * -NetlistBrowserModel::root () +NetlistBrowserModel::root () const { return dynamic_cast (mp_root.get ()); } @@ -2493,18 +2493,56 @@ NetlistBrowserModel::data (const QModelIndex &index, int role) const return QVariant (); } -// @@@ -static QString build_url (void *id, const std::string &tag, const std::string &title) +QModelIndex +NetlistBrowserModel::index_from_url (const QString &a) { - if (id == no_id) { + QUrl url (a); + + std::string ids; +#if QT_VERSION >= 0x050000 + ids = tl::to_string (QUrlQuery (url.query ()).queryItemValue (QString::fromUtf8 ("path"))); +#else + ids = tl::to_string (url.queryItemValue (QString::fromUtf8 ("path"))); +#endif + + QModelIndex idx; + + tl::Extractor ex (ids.c_str ()); + while (! ex.at_end ()) { + int n = 0; + if (! ex.try_read (n)) { + break; + } + idx = index (n, 0, idx); + ex.test (","); + } + + return idx; +} + +QString +NetlistBrowserModel::build_url (const QModelIndex &index, const std::string &title) const +{ + if (! index.isValid ()) { // no link return tl::to_qstring (tl::escaped_to_html (title)); } - std::string s = std::string (" &nets, int column) const { -#if 0 // @@@ if ((! nets.first || column == m_second_column) && (! nets.second || column == m_first_column)) { return QString (); } else { - IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (nets); - void *id = no_id; - // NOTE: the nets may not be a valid net pair. In this case, circuits is (0, 0) and - // no link is generated - if (circuits.first || circuits.second) { - id = make_id_circuit_net (mp_indexer->circuit_index (circuits), mp_indexer->net_index (nets)); - } + QModelIndex idx = index_from_net (nets); if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "net", str_from_expanded_name (nets.first)); + return build_url (idx, str_from_expanded_name (nets.first)); } else if (column == m_second_column) { - return build_url (id, "net", str_from_expanded_name (nets.second)); + return build_url (idx, str_from_expanded_name (nets.second)); } else { - return build_url (id, "net", str_from_expanded_names (nets, mp_indexer->is_single ())); + return build_url (idx, str_from_expanded_names (nets, mp_indexer->is_single ())); } } -#else - if ((! nets.first || column == m_second_column) && (! nets.second || column == m_first_column)) { - return QString (); - } else { - - if (mp_indexer->is_single () || column == m_first_column) { - return tl::to_qstring (str_from_expanded_name (nets.first)); - } else if (column == m_second_column) { - return tl::to_qstring (str_from_expanded_name (nets.second)); - } else { - return tl::to_qstring (str_from_expanded_names (nets, mp_indexer->is_single ())); - } - - } -#endif } QString NetlistBrowserModel::make_link_to (const std::pair &devices, int column) const { -#if 0 - if ((! devices.first || column == m_second_column) && (! devices.second || column == m_first_column)) { - return QString (); - } else { + QModelIndex idx; - IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (devices); - void *id = no_id; - // NOTE: the devices may not be a valid device pair. In this case, circuits is (0, 0) and - // no link is generated - if (circuits.first || circuits.second) { - id = make_id_circuit_device (mp_indexer->circuit_index (circuits), mp_indexer->device_index (devices)); - } - - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "device", str_from_expanded_name (devices.first)); - } else if (column == m_second_column) { - return build_url (id, "device", str_from_expanded_name (devices.second)); - } else { - return build_url (id, "device", str_from_expanded_names (devices, mp_indexer->is_single ())); - } - - } -#else if ((! devices.first || column == m_second_column) && (! devices.second || column == m_first_column)) { return QString (); } else { if (mp_indexer->is_single () || column == m_first_column) { - return tl::to_qstring (str_from_expanded_name (devices.first)); + return build_url (idx, str_from_expanded_name (devices.first)); } else if (column == m_second_column) { - return tl::to_qstring (str_from_expanded_name (devices.second)); + return build_url (idx, str_from_expanded_name (devices.second)); } else { - return tl::to_qstring (str_from_expanded_names (devices, mp_indexer->is_single ())); + return build_url (idx, str_from_expanded_names (devices, mp_indexer->is_single ())); } } -#endif } QString NetlistBrowserModel::make_link_to (const std::pair &pins, const std::pair & /*circuits*/, int column) const { -#if 0 - if ((! pins.first || column == m_second_column) && (! pins.second || column == m_first_column)) { - return QString (); - } else { - void *id = make_id_circuit_pin (mp_indexer->circuit_index (circuits), mp_indexer->pin_index (pins, circuits)); - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "pin", str_from_expanded_name (pins.first)); - } else if (column == m_second_column) { - return build_url (id, "pin", str_from_expanded_name (pins.second)); - } else { - return build_url (id, "pin", str_from_expanded_names (pins, mp_indexer->is_single ())); - } - } -#else + QModelIndex idx; + if ((! pins.first || column == m_second_column) && (! pins.second || column == m_first_column)) { return QString (); } else { if (mp_indexer->is_single () || column == m_first_column) { - return tl::to_qstring (str_from_expanded_name (pins.first)); + return build_url (idx, str_from_expanded_name (pins.first)); } else if (column == m_second_column) { - return tl::to_qstring (str_from_expanded_name (pins.second)); + return build_url (idx, str_from_expanded_name (pins.second)); } else { - return tl::to_qstring (str_from_expanded_names (pins, mp_indexer->is_single ())); + return build_url (idx, str_from_expanded_names (pins, mp_indexer->is_single ())); } } -#endif } QString NetlistBrowserModel::make_link_to (const std::pair &circuits, int column) const { -#if 0 if ((! circuits.first || column == m_second_column) && (! circuits.second || column == m_first_column)) { return QString (); } else { - void *id = make_id_circuit (mp_indexer->circuit_index (circuits)); + + QModelIndex idx = index_from_circuit (circuits); + if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "circuit", str_from_name (circuits.first)); + return build_url (idx, str_from_name (circuits.first)); } else if (column == m_second_column) { - return build_url (id, "circuit", str_from_name (circuits.second)); + return build_url (idx, str_from_name (circuits.second)); } else { - return build_url (id, "circuit", str_from_names (circuits, mp_indexer->is_single ())); + return build_url (idx, str_from_names (circuits, mp_indexer->is_single ())); } + } -#else - if ((! circuits.first || column == m_second_column) && (! circuits.second || column == m_first_column)) { - return QString (); - } else { - if (mp_indexer->is_single () || column == m_first_column) { - return tl::to_qstring (str_from_name (circuits.first)); - } else if (column == m_second_column) { - return tl::to_qstring (str_from_name (circuits.second)); - } else { - return tl::to_qstring (str_from_names (circuits, mp_indexer->is_single ())); - } - } -#endif } QString NetlistBrowserModel::make_link_to (const std::pair &subcircuits, int column) const { -#if 0 - if ((! subcircuits.first || column == m_second_column) && (! subcircuits.second || column == m_first_column)) { - return QString (); - } else { + QModelIndex idx; - IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (subcircuits); - void *id = no_id; - // NOTE: the subcircuits may not be a valid subcircuit pair. In this case, circuits is (0, 0) and - // no link is generated - if (circuits.first || circuits.second) { - id = make_id_circuit_subcircuit (mp_indexer->circuit_index (circuits), mp_indexer->subcircuit_index (subcircuits)); - } - - if (mp_indexer->is_single () || column == m_first_column) { - return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.first)); - } else if (column == m_second_column) { - return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.second)); - } else { - return build_url (id, "subcircuit", str_from_expanded_names (subcircuits, mp_indexer->is_single ())); - } - - } -#else if ((! subcircuits.first || column == m_second_column) && (! subcircuits.second || column == m_first_column)) { return QString (); } else { if (mp_indexer->is_single () || column == m_first_column) { - return tl::to_qstring (str_from_expanded_name (subcircuits.first)); + return build_url (idx, str_from_expanded_name (subcircuits.first)); } else if (column == m_second_column) { - return tl::to_qstring (str_from_expanded_name (subcircuits.second)); + return build_url (idx, str_from_expanded_name (subcircuits.second)); } else { - return tl::to_qstring (str_from_expanded_names (subcircuits, mp_indexer->is_single ())); + return build_url (idx, str_from_expanded_names (subcircuits, mp_indexer->is_single ())); } } -#endif } bool @@ -2883,12 +2831,12 @@ NetlistBrowserModel::colors_changed () } QModelIndex -NetlistBrowserModel::index_from_net (const std::pair &nets) +NetlistBrowserModel::index_from_net (const std::pair &nets) const { IndexedNetlistModel::circuit_pair circuits (nets.first ? nets.first->circuit () : 0, nets.second ? nets.second->circuit () : 0); - CircuitItemData *ci = root ()->circuit_item (this, circuits); + CircuitItemData *ci = root ()->circuit_item (const_cast (this), circuits); if (ci) { - CircuitNetItemData *ni = ci->circuit_net_item (this, nets); + CircuitNetItemData *ni = ci->circuit_net_item (const_cast (this), nets); if (ni) { return createIndex (int (ni->index ()), 0, (void *) ni); } @@ -2898,15 +2846,15 @@ NetlistBrowserModel::index_from_net (const std::pairsecond_net_for (net))); } QModelIndex -NetlistBrowserModel::index_from_circuit (const std::pair &circuits) +NetlistBrowserModel::index_from_circuit (const std::pair &circuits) const { - CircuitItemData *ci = root ()->circuit_item (this, circuits); + CircuitItemData *ci = root ()->circuit_item (const_cast (this), circuits); if (ci) { return createIndex (int (ci->index ()), 0, (void *) ci); } @@ -2915,13 +2863,13 @@ NetlistBrowserModel::index_from_circuit (const std::pairsecond_circuit_for (net))); } std::pair -NetlistBrowserModel::circuit_from_index (const QModelIndex &index) +NetlistBrowserModel::circuit_from_index (const QModelIndex &index) const { NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); if (! d) { @@ -2932,7 +2880,7 @@ NetlistBrowserModel::circuit_from_index (const QModelIndex &index) } std::pair -NetlistBrowserModel::net_from_index (const QModelIndex &index) +NetlistBrowserModel::net_from_index (const QModelIndex &index) const { NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); if (! d) { @@ -2943,7 +2891,7 @@ NetlistBrowserModel::net_from_index (const QModelIndex &index) } std::pair -NetlistBrowserModel::device_from_index (const QModelIndex &index) +NetlistBrowserModel::device_from_index (const QModelIndex &index) const { NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); if (! d) { @@ -2954,7 +2902,7 @@ NetlistBrowserModel::device_from_index (const QModelIndex &index) } std::pair -NetlistBrowserModel::subcircuit_from_index (const QModelIndex &index) +NetlistBrowserModel::subcircuit_from_index (const QModelIndex &index) const { NetlistModelItemData *d = (NetlistModelItemData *) (index.internalPointer ()); if (! d) { diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.h b/src/laybasic/laybasic/layNetlistBrowserModel.h index 44117f258..aa8e591d0 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.h +++ b/src/laybasic/laybasic/layNetlistBrowserModel.h @@ -229,16 +229,16 @@ public: return mp_indexer.get (); } - std::pair net_from_index (const QModelIndex &index); - QModelIndex index_from_net (const std::pair &net); - QModelIndex index_from_net (const db::Net *net); - std::pair circuit_from_index (const QModelIndex &index); - QModelIndex index_from_circuit (const std::pair &circuit); - QModelIndex index_from_circuit (const db::Circuit *circuit); + std::pair net_from_index (const QModelIndex &index) 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; + QModelIndex index_from_circuit (const std::pair &circuit) const; + QModelIndex index_from_circuit (const db::Circuit *circuit) const; - std::pair subcircuit_from_index (const QModelIndex &index); + std::pair subcircuit_from_index (const QModelIndex &index) const; - std::pair device_from_index (const QModelIndex &index); + std::pair device_from_index (const QModelIndex &index) const; void set_item_visibility (QTreeView *view, bool show_all, bool with_warnings); @@ -253,6 +253,8 @@ 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); + private slots: void colors_changed (); @@ -265,6 +267,7 @@ private: QString search_text (const QModelIndex &index) const; db::NetlistCrossReference::Status status (const QModelIndex &index) const; QIcon icon (const QModelIndex &index) const; + QString build_url (const QModelIndex &index, const std::string &title) const; std::pair netlists () const { @@ -285,7 +288,7 @@ private: int m_second_column; std::auto_ptr mp_root; - RootItemData *root (); + RootItemData *root () const; }; } // namespace lay diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index c29cdbde6..1146e3827 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -307,21 +307,10 @@ NetlistBrowserPage::layer_list_changed (int) void NetlistBrowserPage::anchor_clicked (const QString &a) { - QUrl url (a); - - QString ids; -#if QT_VERSION >= 0x050000 - ids = QUrlQuery (url.query ()).queryItemValue (QString::fromUtf8 ("id")); -#else - ids = url.queryItemValue (QString::fromUtf8 ("id")); -#endif - - if (ids.isEmpty ()) { - return; + NetlistBrowserModel *netlist_model = dynamic_cast (directory_tree->model ()); + if (netlist_model) { + navigate_to (netlist_model->index_from_url (a), true); } - - void *id = reinterpret_cast (ids.toULongLong ()); - navigate_to (id, true); } void @@ -356,8 +345,7 @@ NetlistBrowserPage::current_index_changed (const QModelIndex &index) return; } - void *id = index.internalPointer (); - add_to_history (id, true); + add_to_history (index, true); std::pair circuits = netlist_model->circuit_from_index (index); QModelIndex circuit_index = tree_model->index_from_circuits (circuits); @@ -519,16 +507,8 @@ NetlistBrowserPage::select_color_for_net () } void -NetlistBrowserPage::navigate_to (void *id, bool fwd) +NetlistBrowserPage::navigate_to (const QModelIndex &index, bool fwd) { -#if 0 // @@@ - NetlistBrowserTreeModel *tree_model = dynamic_cast (hierarchy_tree->model ()); - NetlistBrowserModel *netlist_model = dynamic_cast (directory_tree->model ()); - if (! tree_model || ! netlist_model) { - return; - } - - QModelIndex index = netlist_model->index_from_id (id, 0); if (! index.isValid ()) { return; } @@ -538,36 +518,43 @@ NetlistBrowserPage::navigate_to (void *id, bool fwd) directory_tree->setCurrentIndex (index); + NetlistBrowserTreeModel *tree_model = dynamic_cast (hierarchy_tree->model ()); + NetlistBrowserModel *netlist_model = dynamic_cast (directory_tree->model ()); + if (! tree_model || ! netlist_model) { + return; + } + + // @@@ with path! std::pair circuits = netlist_model->circuit_from_index (index); QModelIndex circuit_index = tree_model->index_from_circuits (circuits); hierarchy_tree->setCurrentIndex (circuit_index); } catch (...) { } + m_signals_enabled = true; - add_to_history (id, fwd); + add_to_history (index, fwd); selection_changed (); -#endif } void -NetlistBrowserPage::add_to_history (void *id, bool fwd) +NetlistBrowserPage::add_to_history (const QModelIndex &index, bool fwd) { if (! fwd) { if (m_history_ptr > 1) { --m_history_ptr; - m_history [m_history_ptr - 1] = id; + m_history [m_history_ptr - 1] = index; } } else if (m_history_ptr >= m_history.size ()) { - m_history.push_back (id); + m_history.push_back (index); m_history_ptr = m_history.size (); } else { - if (m_history [m_history_ptr] != id) { + if (m_history [m_history_ptr] != index) { m_history.erase (m_history.begin () + m_history_ptr + 1, m_history.end ()); } - m_history [m_history_ptr] = id; + m_history [m_history_ptr] = index; ++m_history_ptr; } @@ -733,7 +720,7 @@ NetlistBrowserPage::find_button_pressed () QModelIndex next = find_next (directory_tree, directory_tree->model (), re, directory_tree->currentIndex ()); if (next.isValid ()) { - navigate_to (next.internalPointer ()); + navigate_to (next); } } diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.h b/src/laybasic/laybasic/layNetlistBrowserPage.h index 4aef9bae8..6c4ef1d73 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.h +++ b/src/laybasic/laybasic/layNetlistBrowserPage.h @@ -228,7 +228,7 @@ private: unsigned int m_cv_index; lay::Dispatcher *mp_plugin_root; tl::weak_ptr mp_database; - std::vector m_history; + std::vector m_history; size_t m_history_ptr; bool m_signals_enabled; std::vector mp_markers; @@ -244,8 +244,8 @@ private: db::ContextCache m_cell_context_cache; void setup_trees (); - void add_to_history (void *id, bool fwd); - void navigate_to (void *id, bool forward = true); + void add_to_history (const QModelIndex &index, bool fwd); + 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); diff --git a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc index 7b39e9446..07130eb5d 100644 --- a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc +++ b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc @@ -108,9 +108,9 @@ TEST (1) // Subcircuits EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_subcircuits), Qt::UserRole).toString ()), "INV2|$1"); EXPECT_EQ (model->parent (model->index (0, 0, sn_subcircuits)) == model->parent (model->index (0, 3, sn_subcircuits)), true); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "INV2"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "INV2"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$1"); - EXPECT_EQ (tl::to_string (model->data (model->index (9, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "INV2"); + EXPECT_EQ (tl::to_string (model->data (model->index (9, 0, sn_subcircuits), Qt::DisplayRole).toString ()), "INV2"); EXPECT_EQ (tl::to_string (model->data (model->index (9, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$10"); // Devices @@ -135,10 +135,10 @@ TEST (1) EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2NOutIndex), Qt::UserRole).toString ()), "D|PMOS|$2"); EXPECT_EQ (model->parent (model->index (0, 0, inv2NOutIndex)) == model->parent (model->index (0, 3, inv2NOutIndex)), true); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2NOutIndex), Qt::DisplayRole).toString ()), "D / PMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2NOutIndex), Qt::DisplayRole).toString ()), "$2"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2NOutIndex), Qt::DisplayRole).toString ()), "$2"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2NOutIndex), Qt::DisplayRole).toString ()), "D / NMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2NOutIndex), Qt::DisplayRole).toString ()), "$4"); - EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, inv2NOutIndex), Qt::DisplayRole).toString ()), "OUT"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2NOutIndex), Qt::DisplayRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, inv2NOutIndex), Qt::DisplayRole).toString ()), "OUT"); EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, inv2NOutIndex), Qt::DisplayRole).toString ()), ""); EXPECT_EQ (model->parent (model->index (2, 0, inv2NOutIndex)) == model->parent (model->index (2, 3, inv2NOutIndex)), true); @@ -174,10 +174,10 @@ TEST (1) EXPECT_EQ (model->rowCount (ringoFbIndex), 2); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbIndex), Qt::UserRole).toString ()), "IN|INV2|$2"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbIndex), Qt::DisplayRole).toString ()), "IN / INV2"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoFbIndex), Qt::DisplayRole).toString ()), "$2"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, ringoFbIndex), Qt::DisplayRole).toString ()), "$1 / INV2"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, ringoFbIndex), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbIndex), Qt::DisplayRole).toString ()), "IN / INV2"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoFbIndex), Qt::DisplayRole).toString ()), "$2"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, ringoFbIndex), Qt::DisplayRole).toString ()), "$1 / INV2"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, ringoFbIndex), Qt::DisplayRole).toString ()), "$1"); QModelIndex ringoFbSubcircuit2Index = model->index (0, 0, ringoFbIndex); EXPECT_EQ (model->parent (ringoFbSubcircuit2Index) == ringoFbIndex, true); @@ -185,16 +185,16 @@ TEST (1) EXPECT_EQ (model->rowCount (ringoFbSubcircuit2Index), 5); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbSubcircuit2Index), Qt::UserRole).toString ()), "IN|FB"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "IN"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "FB"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "IN (already seen)"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "FB"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$1 (already seen)"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), ""); - EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "OUT"); - EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$4"); - EXPECT_EQ (tl::to_string (model->data (model->index (3, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$3"); - EXPECT_EQ (tl::to_string (model->data (model->index (3, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "VSS"); - EXPECT_EQ (tl::to_string (model->data (model->index (4, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$4"); - EXPECT_EQ (tl::to_string (model->data (model->index (4, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "VDD"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "OUT"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (3, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$3"); + EXPECT_EQ (tl::to_string (model->data (model->index (3, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "VSS"); + EXPECT_EQ (tl::to_string (model->data (model->index (4, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (4, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "VDD"); QModelIndex ringoFbSubcircuit2InPinIndex = model->index (1, 0, ringoFbSubcircuit2Index); EXPECT_EQ (model->parent (ringoFbSubcircuit2InPinIndex) == ringoFbSubcircuit2Index, true); @@ -209,7 +209,7 @@ TEST (1) EXPECT_EQ (model->rowCount (ringoSubcircuit1Index), 5); 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, 0, ringoSubcircuit1Index), Qt::DisplayRole).toString ()), "OUT"); EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, ringoSubcircuit1Index), Qt::DisplayRole).toString ()), ""); QModelIndex ringoSubcircuit1OutPinIndex = model->index (2, 0, ringoSubcircuit1Index); @@ -287,7 +287,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"); std::pair nets = model->net_from_index (model->index (0, 0, inv2Pin0Index)); EXPECT_EQ (nets.first != 0, true); if (nets.first != 0) { @@ -297,7 +297,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"); // first of nets in INV2 circuit EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::UserRole).toString ()), "$1|1"); @@ -314,8 +314,8 @@ TEST (2) // INV2, net 1 has one pin and one terminal at BULK EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Net0Index), Qt::UserRole).toString ()), "B|B|PMOS|PMOS|$1|$1"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Net0Index), Qt::DisplayRole).toString ()), "B / PMOS [L=0.25, W=3.5]"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2Net0Index), Qt::DisplayRole).toString ()), "$1"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2Net0Index), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2Net0Index), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2Net0Index), Qt::DisplayRole).toString ()), "$1"); // This terminal connects to a device with four other terminals .. QModelIndex inv2Net0TerminalIndex = model->index (0, 0, inv2Net0Index); @@ -325,14 +325,14 @@ TEST (2) // .. whose second terminal is gate EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0TerminalIndex), Qt::UserRole).toString ()), "G|G|IN|2"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "G"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "IN"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "2"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "IN"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "2"); // The Pin EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0Index), Qt::UserRole).toString ()), ""); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0Index), Qt::DisplayRole).toString ()), ""); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2Net0Index), Qt::DisplayRole).toString ()), "$0"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, inv2Net0Index), Qt::DisplayRole).toString ()), "$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2Net0Index), Qt::DisplayRole).toString ()), "$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, inv2Net0Index), Qt::DisplayRole).toString ()), "$0"); // This pin does not have children QModelIndex inv2Net0PinIndex = model->index (1, 0, inv2Net0Index); @@ -396,7 +396,7 @@ TEST (2) // The pin EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0Index), Qt::UserRole).toString ()), ""); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0Index), Qt::DisplayRole).toString ()), ""); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2PairNet0Index), Qt::DisplayRole).toString ()), "$3"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2PairNet0Index), Qt::DisplayRole).toString ()), "$3"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2PairNet0Index), Qt::DisplayRole).toString ()), ""); // This pin does not have children @@ -407,8 +407,8 @@ TEST (2) // The first subcircuit EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2PairNet0Index), Qt::UserRole).toString ()), "OUT|INV2|$1"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2PairNet0Index), Qt::DisplayRole).toString ()), "OUT ⇔ - / INV2 ⇔ -"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2PairNet0Index), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2PairNet0Index), Qt::DisplayRole).toString ()), "OUT ⇔ - / INV2 ⇔ -"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2PairNet0Index), Qt::DisplayRole).toString ()), "$1"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, inv2PairNet0Index), Qt::DisplayRole).toString ()), ""); // This subcircuit has 6 other pins @@ -417,8 +417,8 @@ TEST (2) EXPECT_EQ (model->rowCount (inv2PairNet0SubCircuit0Index), 6); EXPECT_EQ (model->parent (inv2PairNet0SubCircuit0Index) == inv2PairNet0Index, true); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0SubCircuit0Index), Qt::UserRole).toString ()), "$1"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0SubCircuit0Index), Qt::DisplayRole).toString ()), "$0"); - 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, 0, inv2PairNet0SubCircuit0Index), Qt::UserRole).toString ()), "$7"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0SubCircuit0Index), Qt::DisplayRole).toString ()), "$0 ⇔ -"); + 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 ()), ""); } From f00f5c76b814f6d6b842241e025cfb67bfa1e966 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 12 Jul 2020 01:22:22 +0200 Subject: [PATCH 19/32] WIP: netlist browser tree, highlights etc. --- .../laybasic/layNetlistBrowserModel.cc | 367 ++++++++++++++---- .../laybasic/layNetlistBrowserModel.h | 57 ++- .../laybasic/layNetlistBrowserPage.cc | 229 +++++------ src/laybasic/laybasic/layNetlistBrowserPage.h | 6 +- .../unit_tests/layNetlistBrowserModelTests.cc | 67 +++- 5 files changed, 503 insertions(+), 223 deletions(-) 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"); +} From 98f808d585527d118f6f8aeca60b60ec7aa8667d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 12 Jul 2020 09:28:42 +0200 Subject: [PATCH 20/32] WIP: connections of subcircuits are separate node now, pins and terminals show up as nets. --- .../laybasic/layNetlistBrowserModel.cc | 275 ++++++++++-------- 1 file changed, 151 insertions(+), 124 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index dccfddbb2..f1c7ec0bb 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -828,7 +828,7 @@ class CircuitItemData : public NetlistModelItemData { public: - CircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::circuit_pair &cp, const IndexedNetlistModel::subcircuit_pair &sp = IndexedNetlistModel::subcircuit_pair (0, 0)); + CircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::circuit_pair &cp); virtual void do_ensure_children (NetlistBrowserModel *model); virtual QIcon icon (NetlistBrowserModel *model); @@ -842,17 +842,33 @@ public: 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; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitItemForSubCircuitData + : public CircuitItemData +{ +public: + CircuitItemForSubCircuitData (NetlistModelItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp); + + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + virtual std::pair subcircuits_of_this () + { + return m_sp; + } + +private: IndexedNetlistModel::subcircuit_pair m_sp; }; @@ -906,6 +922,11 @@ public: return pp (); } + virtual std::pair nets_of_this () + { + return nets_from_circuit_pins (circuits (), pins_of_this ()); + } + private: IndexedNetlistModel::pin_pair m_pp; bool m_pin_seen; @@ -1087,36 +1108,6 @@ private: // ---------------------------------------------------------------------------------- -class CircuitNetSubCircuitPinOthersItemData - : public NetlistModelItemData -{ -public: - CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp, bool is_self); - - virtual void do_ensure_children (NetlistBrowserModel *); - virtual QIcon icon (NetlistBrowserModel *model); - virtual QString text (int column, NetlistBrowserModel *model); - virtual QString search_text (); - virtual std::string tooltip (NetlistBrowserModel * /*model*/); - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/); - - const IndexedNetlistModel::net_subcircuit_pin_pair &pp () - { - return m_pp; - } - - virtual std::pair pins_of_this () - { - return pins_from_pinrefs (m_pp); - } - -private: - IndexedNetlistModel::net_subcircuit_pin_pair m_pp; - bool m_net_seen; -}; - -// ---------------------------------------------------------------------------------- - class CircuitNetPinItemData : public NetlistModelItemData { @@ -1159,14 +1150,38 @@ public: return m_sp; } - CircuitItemData *circuit_item () + CircuitItemForSubCircuitData *circuit_item () { return mp_circuit_node; } private: IndexedNetlistModel::subcircuit_pair m_sp; - CircuitItemData *mp_circuit_node; + CircuitItemForSubCircuitData *mp_circuit_node; +}; + +// ---------------------------------------------------------------------------------- + +class CircuitSubCircuitPinsItemData + : public NetlistModelItemData +{ +public: + CircuitSubCircuitPinsItemData (NetlistModelItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp); + + virtual void do_ensure_children (NetlistBrowserModel *model); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + const IndexedNetlistModel::subcircuit_pair &sp () + { + return m_sp; + } + +private: + IndexedNetlistModel::subcircuit_pair m_sp; }; // ---------------------------------------------------------------------------------- @@ -1194,6 +1209,11 @@ public: return pins_from_netrefs (m_pp); } + virtual std::pair nets_of_this () + { + return nets_from_pinrefs (m_pp); + } + private: IndexedNetlistModel::net_subcircuit_pin_pair m_pp; }; @@ -1242,10 +1262,9 @@ public: virtual std::string tooltip (NetlistBrowserModel *model); virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/); - const IndexedNetlistModel::device_pair &dp () + virtual std::pair nets_of_this () { - CircuitDeviceItemData *p = static_cast (parent ()); - return p->dp (); + return nets_from_device_terminals (devices (), m_tp); } private: @@ -1510,8 +1529,8 @@ RootItemData::circuit_item (NetlistBrowserModel *model, const IndexedNetlistMode // ---------------------------------------------------------------------------------- -CircuitItemData::CircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::circuit_pair &cp, const IndexedNetlistModel::subcircuit_pair &sp) - : NetlistModelItemData (parent), m_cp (cp), m_sp (sp) +CircuitItemData::CircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::circuit_pair &cp) + : NetlistModelItemData (parent), m_cp (cp) { } void @@ -1616,6 +1635,40 @@ CircuitItemData::circuit_subcircuit_item (NetlistBrowserModel *model, const Inde // ---------------------------------------------------------------------------------- +CircuitItemForSubCircuitData::CircuitItemForSubCircuitData (NetlistModelItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp) + : CircuitItemData (parent, circuit_refs_from_subcircuits (sp)), m_sp (sp) +{ } + +QString +CircuitItemForSubCircuitData::text (int column, NetlistBrowserModel *model) +{ + if (column == model->object_column ()) { + return tr ("Circuit"); + } else { + return QString (); + } +} + +QString +CircuitItemForSubCircuitData::search_text () +{ + return QString (); +} + +std::string +CircuitItemForSubCircuitData::tooltip (NetlistBrowserModel * /*model*/) +{ + return std::string (); +} + +db::NetlistCrossReference::Status +CircuitItemForSubCircuitData::status (NetlistBrowserModel * /*model*/) +{ + return db::NetlistCrossReference::None; +} + +// ---------------------------------------------------------------------------------- + CircuitItemNodeData::CircuitItemNodeData (NetlistModelItemData *parent, CircuitItemNodeData::type t) : NetlistModelItemData (parent), m_type (t) { } @@ -2158,77 +2211,6 @@ CircuitNetSubCircuitPinItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- -CircuitNetSubCircuitPinOthersItemData::CircuitNetSubCircuitPinOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp, bool net_seen) - : NetlistModelItemData (parent), m_pp (pp), m_net_seen (net_seen) -{ } - -void -CircuitNetSubCircuitPinOthersItemData::do_ensure_children (NetlistBrowserModel *) -{ - if (! m_net_seen) { - IndexedNetlistModel::net_pair nets = nets_from_pinrefs (pp ()); - if (nets.first || nets.second) { - push_back (new CircuitNetItemData (this, nets)); - } - } -} - -QIcon -CircuitNetSubCircuitPinOthersItemData::icon (NetlistBrowserModel *model) -{ - return model->icon_for_connection (nets_from_pinrefs (pp ())); -} - -QString -CircuitNetSubCircuitPinOthersItemData::text (int column, NetlistBrowserModel *model) -{ - // circuit/net/device terminal/more: header column = pin name, second column = net link - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pp ()); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - - if (column == model->object_column ()) { - return model->make_link_to (pins (), circuit_refs) + (m_net_seen ? tr (" (already seen)") : QString ()); - } else if (column == model->first_column () || column == model->second_column ()) { - return model->make_link_to (nets_from_pinrefs (pp ()), column); - } - - return QString (); -} - -QString -CircuitNetSubCircuitPinOthersItemData::search_text () -{ - return tl::to_qstring (combine_search_strings (search_string_from_names (pins ()), search_string_from_expanded_names (nets_from_pinrefs (pp ())))); -} - -std::string -CircuitNetSubCircuitPinOthersItemData::tooltip (NetlistBrowserModel *model) -{ - std::string hint; - - if (! model->is_valid_net_pair (nets_from_pinrefs (pp ()))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - hint = rewire_subcircuit_pins_status_hint (); - } - - return hint; -} - -db::NetlistCrossReference::Status -CircuitNetSubCircuitPinOthersItemData::status (NetlistBrowserModel *model) -{ - if (! model->is_valid_net_pair (nets_from_pinrefs (pp ()))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - return db::NetlistCrossReference::None; -} - -// ---------------------------------------------------------------------------------- - CircuitNetPinItemData::CircuitNetPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pin_pair &pp) : NetlistModelItemData (parent), m_pp (pp) { } @@ -2279,21 +2261,67 @@ CircuitNetPinItemData::status (NetlistBrowserModel * /*model*/) // ---------------------------------------------------------------------------------- -CircuitSubCircuitItemData::CircuitSubCircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp) - : NetlistModelItemData (parent), m_sp (sp), mp_circuit_node (0) +CircuitSubCircuitPinsItemData::CircuitSubCircuitPinsItemData (NetlistModelItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp) + : NetlistModelItemData (parent), m_sp (sp) { } void -CircuitSubCircuitItemData::do_ensure_children (NetlistBrowserModel *model) +CircuitSubCircuitPinsItemData::do_ensure_children (NetlistBrowserModel *model) { size_t n = model->indexer ()->subcircuit_pin_count (sp ()); for (size_t i = 0; i < n; ++i) { IndexedNetlistModel::net_subcircuit_pin_pair pp = model->indexer ()->subcircuit_pinref_from_index (sp (), i); push_back (new CircuitSubCircuitPinItemData (this, pp)); } +} + +QIcon +CircuitSubCircuitPinsItemData::icon (NetlistBrowserModel * /*model*/) +{ + return icon_for_pin (); +} + +QString +CircuitSubCircuitPinsItemData::text (int column, NetlistBrowserModel *model) +{ + if (column == model->object_column ()) { + return tr ("Connections"); + } else { + return QString (); + } +} + +QString +CircuitSubCircuitPinsItemData::search_text () +{ + return QString (); +} + +std::string +CircuitSubCircuitPinsItemData::tooltip (NetlistBrowserModel * /*model*/) +{ + return std::string (); +} + +db::NetlistCrossReference::Status +CircuitSubCircuitPinsItemData::status (NetlistBrowserModel * /*model*/) +{ + return db::NetlistCrossReference::None; +} + +// ---------------------------------------------------------------------------------- + +CircuitSubCircuitItemData::CircuitSubCircuitItemData (NetlistModelItemData *parent, const IndexedNetlistModel::subcircuit_pair &sp) + : NetlistModelItemData (parent), m_sp (sp), mp_circuit_node (0) +{ } + +void +CircuitSubCircuitItemData::do_ensure_children (NetlistBrowserModel * /*model*/) +{ + push_back (new CircuitSubCircuitPinsItemData (this, m_sp)); // plus one item for the circuit reference - mp_circuit_node = new CircuitItemData (this, circuit_refs_from_subcircuits (m_sp), m_sp); + mp_circuit_node = new CircuitItemForSubCircuitData (this, m_sp); push_back (mp_circuit_node); } @@ -2484,15 +2512,14 @@ CircuitDeviceTerminalItemData::CircuitDeviceTerminalItemData (NetlistModelItemDa void CircuitDeviceTerminalItemData::do_ensure_children (NetlistBrowserModel *) { - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (devices (), m_tp); push_back (new CircuitNetItemData (this, nets)); } QIcon CircuitDeviceTerminalItemData::icon (NetlistBrowserModel *model) { - const IndexedNetlistModel::device_pair &dp = static_cast (parent ())->dp (); - return model->icon_for_connection (nets_from_device_terminals (dp, m_tp)); + return model->icon_for_connection (nets_from_device_terminals (devices (), m_tp)); } QString @@ -2505,7 +2532,7 @@ CircuitDeviceTerminalItemData::text (int column, NetlistBrowserModel *model) } else if (column == model->first_column () || column == model->second_column ()) { - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (devices (), m_tp); return model->make_link_to (nets, column); } @@ -2516,7 +2543,7 @@ CircuitDeviceTerminalItemData::text (int column, NetlistBrowserModel *model) QString CircuitDeviceTerminalItemData::search_text () { - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); + IndexedNetlistModel::net_pair nets = nets_from_device_terminals (devices (), m_tp); return tl::to_qstring (combine_search_strings (search_string_from_names (m_tp), search_string_from_expanded_names (nets))); } @@ -2529,7 +2556,7 @@ CircuitDeviceTerminalItemData::tooltip (NetlistBrowserModel * /*model*/) db::NetlistCrossReference::Status CircuitDeviceTerminalItemData::status (NetlistBrowserModel *model) { - if (! model->is_valid_net_pair (nets_from_device_terminals (dp (), m_tp))) { + if (! model->is_valid_net_pair (nets_from_device_terminals (devices (), m_tp))) { // This indicates a wrong connection: the nets are associated in a way which is a not // corresponding to a mapped net pair. Report Mismatch here. return db::NetlistCrossReference::NoMatch; From 8bb7342147bcd618d3650c10ec2fcd4ff77aa820 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 12 Jul 2020 10:15:21 +0200 Subject: [PATCH 21/32] WIP: less nodes. --- .../laybasic/layNetlistBrowserModel.cc | 363 +++++------------- 1 file changed, 94 insertions(+), 269 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index f1c7ec0bb..142674903 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -899,71 +899,6 @@ private: // ---------------------------------------------------------------------------------- -class CircuitPinItemData - : public NetlistModelItemData -{ -public: - CircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp); - - virtual void do_ensure_children (NetlistBrowserModel * /*model*/); - virtual QIcon icon (NetlistBrowserModel *model); - virtual QString text (int column, NetlistBrowserModel *model); - virtual QString search_text (); - virtual std::string tooltip (NetlistBrowserModel *model); - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - - const IndexedNetlistModel::pin_pair &pp () - { - return m_pp; - } - - virtual std::pair pins_of_this () - { - return pp (); - } - - virtual std::pair nets_of_this () - { - return nets_from_circuit_pins (circuits (), pins_of_this ()); - } - -private: - IndexedNetlistModel::pin_pair m_pp; - bool m_pin_seen; -}; - -// ---------------------------------------------------------------------------------- - -class CircuitPinNetItemData - : public NetlistModelItemData -{ -public: - CircuitPinNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np); - - virtual void do_ensure_children (NetlistBrowserModel *model); - virtual QIcon icon (NetlistBrowserModel *model); - virtual QString text (int column, NetlistBrowserModel *model); - virtual QString search_text (); - virtual std::string tooltip (NetlistBrowserModel *model); - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); - - const IndexedNetlistModel::pin_pair &pp () - { - CircuitPinItemData *p = static_cast (parent ()); - return p->pp (); - } - - virtual std::pair nets_of_this () - { - return m_np; - } - -private: - IndexedNetlistModel::net_pair m_np; -}; - -// ---------------------------------------------------------------------------------- - class CircuitNetItemData : public NetlistModelItemData { @@ -987,8 +922,14 @@ public: return m_np; } + bool seen () const + { + return m_seen; + } + private: IndexedNetlistModel::net_pair m_np; + bool m_seen; }; // ---------------------------------------------------------------------------------- @@ -1035,28 +976,18 @@ private: // ---------------------------------------------------------------------------------- class CircuitNetDeviceTerminalOthersItemData - : public NetlistModelItemData + : public CircuitNetItemData { public: - CircuitNetDeviceTerminalOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp, bool is_self); + CircuitNetDeviceTerminalOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp); - virtual void do_ensure_children (NetlistBrowserModel *); virtual QIcon icon (NetlistBrowserModel *model); virtual QString text (int column, NetlistBrowserModel *model); virtual QString search_text (); - virtual std::string tooltip (NetlistBrowserModel *model); - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/); - - IndexedNetlistModel::device_pair dp () - { - CircuitNetDeviceTerminalItemData *p = static_cast (parent ()); - return p->dp (); - } private: std::pair m_tp; IndexedNetlistModel::net_pair m_np; - bool m_net_seen; }; // ---------------------------------------------------------------------------------- @@ -1162,6 +1093,55 @@ private: // ---------------------------------------------------------------------------------- +class CircuitPinItemData + : public CircuitNetItemData +{ +public: + CircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp); + + virtual QIcon icon (NetlistBrowserModel *model); + + virtual std::pair pins_of_this () + { + return m_pp; + } + +private: + IndexedNetlistModel::pin_pair m_pp; +}; + +// ---------------------------------------------------------------------------------- + +// @@@ TODO: remove? +class CircuitPinNetItemData + : public NetlistModelItemData +{ +public: + CircuitPinNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np); + + virtual void do_ensure_children (NetlistBrowserModel *model); + virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); + virtual std::string tooltip (NetlistBrowserModel *model); + virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); + + IndexedNetlistModel::pin_pair pp () + { + return pins (); + } + + virtual std::pair nets_of_this () + { + return m_np; + } + +private: + IndexedNetlistModel::net_pair m_np; +}; + +// ---------------------------------------------------------------------------------- + class CircuitSubCircuitPinsItemData : public NetlistModelItemData { @@ -1187,17 +1167,14 @@ private: // ---------------------------------------------------------------------------------- class CircuitSubCircuitPinItemData - : public NetlistModelItemData + : public CircuitNetItemData { public: CircuitSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp); - virtual void do_ensure_children (NetlistBrowserModel *); virtual QIcon icon (NetlistBrowserModel *model); virtual QString text (int column, NetlistBrowserModel *model); virtual QString search_text (); - virtual std::string tooltip (NetlistBrowserModel *model); - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model); IndexedNetlistModel::subcircuit_pair sp () { @@ -1209,11 +1186,6 @@ public: return pins_from_netrefs (m_pp); } - virtual std::pair nets_of_this () - { - return nets_from_pinrefs (m_pp); - } - private: IndexedNetlistModel::net_subcircuit_pin_pair m_pp; }; @@ -1250,22 +1222,14 @@ private: // ---------------------------------------------------------------------------------- class CircuitDeviceTerminalItemData - : public NetlistModelItemData + : public CircuitNetItemData { public: CircuitDeviceTerminalItemData (NetlistModelItemData *parent, const std::pair &tp); - virtual void do_ensure_children (NetlistBrowserModel *); virtual QIcon icon (NetlistBrowserModel *model); virtual QString text (int column, NetlistBrowserModel *model); virtual QString search_text (); - virtual std::string tooltip (NetlistBrowserModel *model); - virtual db::NetlistCrossReference::Status status (NetlistBrowserModel * /*model*/); - - virtual std::pair nets_of_this () - { - return nets_from_device_terminals (devices (), m_tp); - } private: std::pair m_tp; @@ -1817,63 +1781,17 @@ CircuitItemNodeData::circuit_subcircuit_item (NetlistBrowserModel *model, const // ---------------------------------------------------------------------------------- CircuitPinItemData::CircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp) - : NetlistModelItemData (parent), m_pp (pp), m_pin_seen (parent && parent->derived_from_pins (pp)) + : CircuitNetItemData (parent, nets_from_circuit_pins (parent->circuits (), pp)), + m_pp (pp) { } -void -CircuitPinItemData::do_ensure_children (NetlistBrowserModel * /*model*/) -{ - if (! m_pin_seen) { - push_back (new CircuitNetItemData (this, nets_from_circuit_pins (circuits (), pp ()))); - } -} - QIcon CircuitPinItemData::icon (NetlistBrowserModel * /*model*/) { return icon_for_pin (); } -QString -CircuitPinItemData::text (int column, NetlistBrowserModel *model) -{ - // pin: - // + single mode: xname | | - // + dual mode: xname(a)/xname(b) | xname(a) | xname(b) - if (column == model->object_column ()) { - 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)); - } - - return QString (); -} - -QString -CircuitPinItemData::search_text () -{ - return tl::to_qstring (search_string_from_expanded_names (pp ())); -} - -std::string -CircuitPinItemData::tooltip (NetlistBrowserModel *model) -{ - size_t index = model->indexer ()->pin_index (pp (), circuits ()); - return model->indexer ()->pin_status_hint (circuits (), index); -} - -db::NetlistCrossReference::Status -CircuitPinItemData::status (NetlistBrowserModel *model) -{ - size_t index = model->indexer ()->pin_index (pp (), circuits ()); - return model->indexer ()->pin_from_index (circuits (), index).second; -} - // ---------------------------------------------------------------------------------- // @@@ remove? @@ -1927,12 +1845,17 @@ CircuitPinNetItemData::status (NetlistBrowserModel * /*model*/) // ---------------------------------------------------------------------------------- CircuitNetItemData::CircuitNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np) - : NetlistModelItemData (parent), m_np (np) + : NetlistModelItemData (parent), m_np (np), m_seen (parent && parent->derived_from_nets (np)) { } void CircuitNetItemData::do_ensure_children (NetlistBrowserModel *model) { + // no subnodes if already seen + if (m_seen) { + return; + } + size_t n; n = model->indexer ()->net_terminal_count (np ()); @@ -1962,7 +1885,11 @@ CircuitNetItemData::text (int column, NetlistBrowserModel *model) { // circuit/net: header column = node count, second column net name if (column == model->object_column ()) { - return escaped (str_from_expanded_names (m_np, model->indexer ()->is_single ())); + std::string suffix; + if (seen ()) { + suffix = tl::to_string (tr (" (already seen)")); + } + return escaped (str_from_expanded_names (m_np, model->indexer ()->is_single ()) + suffix); } else if (column == model->first_column () && m_np.first) { return escaped (m_np.first->expanded_name () + " (" + tl::to_string (m_np.first->pin_count () + m_np.first->terminal_count () + m_np.first->subcircuit_pin_count ()) + ")"); } else if (column == model->second_column () && m_np.second) { @@ -2010,7 +1937,7 @@ CircuitNetDeviceTerminalItemData::do_ensure_children (NetlistBrowserModel *model std::pair device_classes = device_classes_from_devices (dp ()); std::pair termdefs = terminal_defs_from_device_classes (model->indexer (), device_classes, dp (), i); IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), termdefs); - push_back (new CircuitNetDeviceTerminalOthersItemData (this, nets, termdefs, derived_from_nets (nets))); + push_back (new CircuitNetDeviceTerminalOthersItemData (this, nets, termdefs)); } } @@ -2069,25 +1996,14 @@ CircuitNetDeviceTerminalItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- -CircuitNetDeviceTerminalOthersItemData::CircuitNetDeviceTerminalOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp, bool net_seen) - : NetlistModelItemData (parent), m_tp (tp), m_np (np), m_net_seen (net_seen) +CircuitNetDeviceTerminalOthersItemData::CircuitNetDeviceTerminalOthersItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np, const std::pair &tp) + : CircuitNetItemData (parent, nets_from_device_terminals (parent->devices (), tp)), m_tp (tp), m_np (np) { } -void -CircuitNetDeviceTerminalOthersItemData::do_ensure_children (NetlistBrowserModel *) -{ - if (! m_net_seen) { - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); - if (nets.first || nets.second) { - push_back (new CircuitNetItemData (this, nets)); - } - } -} - QIcon CircuitNetDeviceTerminalOthersItemData::icon (NetlistBrowserModel *model) { - return model->icon_for_connection (nets_from_device_terminals (dp (), m_tp)); + return model->icon_for_connection (nets_from_device_terminals (devices (), m_tp)); } QString @@ -2095,41 +2011,16 @@ CircuitNetDeviceTerminalOthersItemData::text (int column, NetlistBrowserModel *m { // circuit/net/device terminal/more: header column = terminal name, second column = net link if (column == model->object_column ()) { - - return escaped (str_from_names (m_tp, model->indexer ()->is_single ())) + (m_net_seen ? tr (" (already seen)") : QString ()); - - } else if (column == model->first_column () || column == model->second_column ()) { - - return model->make_link_to (m_np, column); - + return escaped (str_from_names (m_tp, model->indexer ()->is_single ()) + (seen () ? tl::to_string (tr (" (already seen)")) : std::string ())); + } else { + return CircuitNetItemData::text (column, model); } - - return QString (); } QString CircuitNetDeviceTerminalOthersItemData::search_text () { - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (dp (), m_tp); - return tl::to_qstring (combine_search_strings (search_string_from_names (m_tp), search_string_from_expanded_names (nets))); -} - -std::string -CircuitNetDeviceTerminalOthersItemData::tooltip (NetlistBrowserModel * /*model*/) -{ - return std::string (); -} - -db::NetlistCrossReference::Status -CircuitNetDeviceTerminalOthersItemData::status (NetlistBrowserModel *model) -{ - if (! model->is_valid_net_pair (nets_from_device_terminals (dp (), m_tp))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - return db::NetlistCrossReference::None; + return tl::to_qstring (combine_search_strings (search_string_from_names (m_tp), search_string_from_expanded_names (nets_of_this ()))); } // ---------------------------------------------------------------------------------- @@ -2371,18 +2262,9 @@ CircuitSubCircuitItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- CircuitSubCircuitPinItemData::CircuitSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &pp) - : NetlistModelItemData (parent), m_pp (pp) + : CircuitNetItemData (parent, nets_from_pinrefs (pp)), m_pp (pp) { } -void -CircuitSubCircuitPinItemData::do_ensure_children (NetlistBrowserModel *) -{ - IndexedNetlistModel::net_pair nets = nets_from_pinrefs (m_pp); - if (nets.first || nets.second) { - push_back (new CircuitNetItemData (this, nets)); - } -} - QIcon CircuitSubCircuitPinItemData::icon (NetlistBrowserModel * /*model*/) { @@ -2393,12 +2275,10 @@ QString CircuitSubCircuitPinItemData::text (int column, NetlistBrowserModel *model) { if (column == model->object_column ()) { - return model->make_link_to (pins (), circuit_refs_from_subcircuits (sp ())); - } else if (column == model->first_column () || column == model->second_column ()) { - return model->make_link_to (nets_from_pinrefs (m_pp), column); + return model->make_link_to (pins (), circuit_refs_from_subcircuits (sp ())) + (seen () ? tr (" (already seen)") : QString ()); + } else { + return CircuitNetItemData::text (column, model); } - - return QString (); } QString @@ -2407,31 +2287,6 @@ CircuitSubCircuitPinItemData::search_text () return tl::to_qstring (combine_search_strings (search_string_from_names (pins ()), search_string_from_expanded_names (nets_from_pinrefs (m_pp)))); } -std::string -CircuitSubCircuitPinItemData::tooltip (NetlistBrowserModel *model) -{ - std::string hint; - - // Check whether the pins may be attached to an invalid net pair - if (! model->is_valid_net_pair (nets_from_pinrefs (m_pp))) { - hint = rewire_subcircuit_pins_status_hint (); - } - - return hint; -} - -db::NetlistCrossReference::Status -CircuitSubCircuitPinItemData::status (NetlistBrowserModel *model) -{ - if (! model->is_valid_net_pair (nets_from_pinrefs (m_pp))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - return db::NetlistCrossReference::None; -} - // ---------------------------------------------------------------------------------- CircuitDeviceItemData::CircuitDeviceItemData (NetlistModelItemData *parent, const IndexedNetlistModel::device_pair &dp) @@ -2506,63 +2361,33 @@ CircuitDeviceItemData::status (NetlistBrowserModel *model) // ---------------------------------------------------------------------------------- CircuitDeviceTerminalItemData::CircuitDeviceTerminalItemData (NetlistModelItemData *parent, const std::pair &tp) - : NetlistModelItemData (parent), m_tp (tp) + : CircuitNetItemData (parent, nets_from_device_terminals (parent->devices (), tp)), m_tp (tp) { } -void -CircuitDeviceTerminalItemData::do_ensure_children (NetlistBrowserModel *) -{ - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (devices (), m_tp); - push_back (new CircuitNetItemData (this, nets)); -} - QIcon CircuitDeviceTerminalItemData::icon (NetlistBrowserModel *model) { - return model->icon_for_connection (nets_from_device_terminals (devices (), m_tp)); + return model->icon_for_connection (nets_of_this ()); } QString CircuitDeviceTerminalItemData::text (int column, NetlistBrowserModel *model) { - // circuit/device/terminal: header column = terminal name, second column link to net if (column == model->object_column ()) { - - return escaped (str_from_names (m_tp, model->indexer ()->is_single ())); - - } else if (column == model->first_column () || column == model->second_column ()) { - - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (devices (), m_tp); - return model->make_link_to (nets, column); - + std::string suffix; + if (seen ()) { + suffix = tl::to_string (tr (" (already seen)")); + } + return escaped (str_from_names (m_tp, model->indexer ()->is_single ()) + suffix); + } else { + return CircuitNetItemData::text (column, model); } - - return QString (); } QString CircuitDeviceTerminalItemData::search_text () { - IndexedNetlistModel::net_pair nets = nets_from_device_terminals (devices (), m_tp); - return tl::to_qstring (combine_search_strings (search_string_from_names (m_tp), search_string_from_expanded_names (nets))); -} - -std::string -CircuitDeviceTerminalItemData::tooltip (NetlistBrowserModel * /*model*/) -{ - return std::string (); -} - -db::NetlistCrossReference::Status -CircuitDeviceTerminalItemData::status (NetlistBrowserModel *model) -{ - if (! model->is_valid_net_pair (nets_from_device_terminals (devices (), m_tp))) { - // This indicates a wrong connection: the nets are associated in a way which is a not - // corresponding to a mapped net pair. Report Mismatch here. - return db::NetlistCrossReference::NoMatch; - } - - return db::NetlistCrossReference::None; + return tl::to_qstring (combine_search_strings (search_string_from_names (m_tp), search_string_from_expanded_names (nets_of_this ()))); } // ---------------------------------------------------------------------------------- From 27d1f2fac1e0c7e679cdac276bd434bfb5d46fbf Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 12 Jul 2020 10:32:46 +0200 Subject: [PATCH 22/32] WIP: same sorting of subcircuit connections and circuit pins. --- .../laybasic/layNetlistBrowserModel.cc | 85 ------------------- .../laybasic/layNetlistCrossReferenceModel.cc | 70 +++++++++++++-- 2 files changed, 63 insertions(+), 92 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 142674903..335141342 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -798,11 +798,6 @@ static std::string search_string_from_names (const std::pair nets_of_this () - { - return m_np; - } - -private: - IndexedNetlistModel::net_pair m_np; -}; - -// ---------------------------------------------------------------------------------- - class CircuitSubCircuitPinsItemData : public NetlistModelItemData { @@ -1794,56 +1759,6 @@ CircuitPinItemData::icon (NetlistBrowserModel * /*model*/) // ---------------------------------------------------------------------------------- -// @@@ remove? -CircuitPinNetItemData::CircuitPinNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np) - : NetlistModelItemData (parent), m_np (np) -{ } - -void -CircuitPinNetItemData::do_ensure_children (NetlistBrowserModel * /*model*/) -{ - // nothing (leaf node) -} - -QIcon -CircuitPinNetItemData::icon (NetlistBrowserModel *model) -{ - return model->icon_for_connection (m_np); -} - -QString -CircuitPinNetItemData::text (int column, NetlistBrowserModel *model) -{ - // circuit/pin/net: header column = name, second column link to net - if (column == model->object_column ()) { - return escaped (str_from_expanded_names (m_np, model->indexer ()->is_single ())); - } else if (column == model->first_column () || column == model->second_column ()) { - return model->make_link_to (m_np, column); - } - - return QString (); -} - -QString -CircuitPinNetItemData::search_text () -{ - return tl::to_qstring (search_string_from_expanded_names (nets_from_circuit_pins (circuits (), pp ()))); -} - -std::string -CircuitPinNetItemData::tooltip (NetlistBrowserModel * /*model*/) -{ - return std::string (); -} - -db::NetlistCrossReference::Status -CircuitPinNetItemData::status (NetlistBrowserModel * /*model*/) -{ - return db::NetlistCrossReference::None; -} - -// ---------------------------------------------------------------------------------- - CircuitNetItemData::CircuitNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np) : NetlistModelItemData (parent), m_np (np), m_seen (parent && parent->derived_from_nets (np)) { } diff --git a/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc b/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc index fc82a79a6..bf816b302 100644 --- a/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc +++ b/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc @@ -310,17 +310,73 @@ const db::Circuit *NetlistCrossReferenceModel::second_circuit_for (const db::Cir namespace { - struct CompareNetRefsByPins + // TODO: borrowed from dbNetlistCrossReference.cc + + static int string_value_compare (const std::string &a, const std::string &b) { - bool operator () (const std::pair &a, - const std::pair &b) + return a == b ? 0 : (a < b ? -1 : 1); + } + + template + struct by_expanded_name_value_compare + { + int operator() (const Obj &a, const Obj &b) const { - size_t pin_id1 = a.first ? a.first->pin_id () : (a.second ? a.second->pin_id () : std::numeric_limits::max ()); - size_t pin_id2 = b.first ? b.first->pin_id () : (b.second ? b.second->pin_id () : std::numeric_limits::max ()); - return pin_id1 < pin_id2; + return string_value_compare (a.expanded_name (), b.expanded_name ()); } }; + template struct net_object_compare; + + template <> + struct net_object_compare + { + int operator() (const db::NetSubcircuitPinRef &a, const db::NetSubcircuitPinRef &b) const + { + int ct = by_expanded_name_value_compare () (*a.subcircuit (), *b.subcircuit ()); + if (ct == 0) { + return by_expanded_name_value_compare () (*a.pin (), *b.pin ()); + } else { + return ct; + } + } + }; + + template + struct two_pointer_compare + { + int operator() (const Obj *a, const Obj *b) const + { + if ((a == 0) != (b == 0)) { + return (a == 0) > (b == 0) ? -1 : 1; + } + if (a != 0) { + return ValueCompare () (*a, *b); + } else { + return 0; + } + } + }; + + template + struct two_pair_compare + { + bool operator() (const std::pair &a, const std::pair &b) + { + int ct = two_pointer_compare () (a.first, b.first); + if (ct != 0) { + return ct < 0; + } + return two_pointer_compare () (a.second, b.second) < 0; + } + }; + + struct SortNetSubCircuitPins + : public two_pair_compare > + { + // .. nothing yet .. + }; + } void NetlistCrossReferenceModel::ensure_subcircuit_data_built () const @@ -370,7 +426,7 @@ void NetlistCrossReferenceModel::ensure_subcircuit_data_built () const } } - std::sort (sc_data.nets_per_pins.begin (), sc_data.nets_per_pins.end (), CompareNetRefsByPins ()); + std::sort (sc_data.nets_per_pins.begin (), sc_data.nets_per_pins.end (), SortNetSubCircuitPins ()); } From dcdf9a8ec150cdd1cccc11bc7565b90eea021d1b Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 12 Jul 2020 21:06:03 +0200 Subject: [PATCH 23/32] WIP: paths for tree model too --- .../laybasic/layNetlistBrowserModel.h | 3 ++ .../laybasic/layNetlistBrowserPage.cc | 10 ++--- .../laybasic/layNetlistBrowserTreeModel.cc | 40 +++++++++++++++++++ .../laybasic/layNetlistBrowserTreeModel.h | 2 + 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.h b/src/laybasic/laybasic/layNetlistBrowserModel.h index 16496e471..1fd624ce8 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.h +++ b/src/laybasic/laybasic/layNetlistBrowserModel.h @@ -183,6 +183,9 @@ private: */ struct LAYBASIC_PUBLIC NetlistObjectPath { + typedef std::list > path_type; + typedef path_type::const_iterator path_iterator; + NetlistObjectPath () { } bool operator== (const NetlistObjectPath &other) const diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index d0cb92b98..9f9de9fcb 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -323,6 +323,7 @@ NetlistBrowserPage::current_tree_index_changed (const QModelIndex &index) return; } + // TODO: this could give a path ... std::pair circuits = tree_model->circuits_from_index (index); QModelIndex circuit_index = netlist_model->index_from_circuit (circuits); @@ -346,8 +347,8 @@ NetlistBrowserPage::current_index_changed (const QModelIndex &index) add_to_history (index, true); - std::pair circuits = netlist_model->circuit_from_index (index); - QModelIndex circuit_index = tree_model->index_from_circuits (circuits); + NetlistObjectPath path = netlist_model->netpath_from_index (index); + QModelIndex circuit_index = tree_model->index_from_netpath (path); m_signals_enabled = false; hierarchy_tree->setCurrentIndex (circuit_index); @@ -516,9 +517,8 @@ NetlistBrowserPage::navigate_to (const QModelIndex &index, bool fwd) return; } - // @@@ with path! - std::pair circuits = netlist_model->circuit_from_index (index); - QModelIndex circuit_index = tree_model->index_from_circuits (circuits); + lay::NetlistObjectPath path = netlist_model->netpath_from_index (index); + QModelIndex circuit_index = tree_model->index_from_netpath (path); hierarchy_tree->setCurrentIndex (circuit_index); } catch (...) { diff --git a/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc b/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc index 24cfb3c34..db47fad4b 100644 --- a/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc @@ -24,6 +24,7 @@ #include "layNetlistBrowserTreeModel.h" #include "layIndexedNetlistModel.h" #include "layNetlistCrossReferenceModel.h" +#include "layNetlistBrowserModel.h" #include #include @@ -257,6 +258,45 @@ NetlistBrowserTreeModel::build_circuits_to_index (size_t nprod, const std::pair< } } +static bool is_compatible (const std::pair &a, const std::pair &b) +{ + if (a.first && b.first && a.first == b.first) { + return true; + } else if (a.second && b.second && a.second == b.second) { + return true; + } else { + return false; + } +} + +QModelIndex +NetlistBrowserTreeModel::index_from_netpath (const NetlistObjectPath &path) const +{ + QModelIndex idx; + + idx = index_from_circuits (path.root); + + for (NetlistObjectPath::path_iterator p = path.path.begin (); p != path.path.end () && idx.isValid (); ++p) { + + std::pair sc (p->first ? p->first->circuit_ref () : 0, p->second ? p->second->circuit_ref (): 0); + std::pair circuit = circuits_from_index (idx); + + size_t count = mp_indexer->child_circuit_count (circuit); + for (size_t n = count; n > 0; ) { + --n; + std::pair cc = mp_indexer->child_circuit_from_index (circuit, n).first; + if (is_compatible (sc, cc)) { + circuit = cc; + idx = index (n, 0, idx); + break; + } + } + + } + + return idx; +} + QModelIndex NetlistBrowserTreeModel::index_from_circuits (const std::pair &circuits) const { diff --git a/src/laybasic/laybasic/layNetlistBrowserTreeModel.h b/src/laybasic/laybasic/layNetlistBrowserTreeModel.h index 3ecff81f1..c4fe0696d 100644 --- a/src/laybasic/laybasic/layNetlistBrowserTreeModel.h +++ b/src/laybasic/laybasic/layNetlistBrowserTreeModel.h @@ -42,6 +42,7 @@ namespace lay { class IndexedNetlistModel; +struct NetlistObjectPath; // ---------------------------------------------------------------------------------- // NetlistBrowserTreeModel definition @@ -77,6 +78,7 @@ public: std::pair circuits_from_index (const QModelIndex &index) const; QModelIndex index_from_circuits (const std::pair &circuits) const; + QModelIndex index_from_netpath (const NetlistObjectPath &path) const; private: NetlistBrowserTreeModel (const NetlistBrowserTreeModel &); From f54c03f4caff4286b949c270b5fba51d71d136d7 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 12 Jul 2020 21:33:02 +0200 Subject: [PATCH 24/32] WIP: fixed some segfaults. --- .../laybasic/layNetlistBrowserModel.cc | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 335141342..852fb70b1 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -1021,6 +1021,12 @@ public: return subcircuits_from_pinrefs (m_sp); } + // NOTE: this is important as this node acts as parent for nets inside this circuit + virtual std::pair circuits_of_this () + { + return circuit_refs_from_subcircuits (subcircuits_of_this ()); + } + virtual std::pair pins_of_this () { return m_pp; @@ -1941,7 +1947,7 @@ CircuitNetDeviceTerminalOthersItemData::search_text () // ---------------------------------------------------------------------------------- CircuitNetSubCircuitPinItemData::CircuitNetSubCircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_subcircuit_pin_pair &sp) - : NetlistModelItemData (parent), m_sp (sp), m_subcircuit_seen (parent && parent->derived_from_subcircuits (subcircuits ())) + : NetlistModelItemData (parent), m_sp (sp), m_subcircuit_seen (parent && parent->derived_from_subcircuits (subcircuits_from_pinrefs (sp))) { } void @@ -1951,10 +1957,8 @@ CircuitNetSubCircuitPinItemData::do_ensure_children (NetlistBrowserModel *model) 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); + 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) { @@ -1974,9 +1978,6 @@ QString CircuitNetSubCircuitPinItemData::text (int column, NetlistBrowserModel *model) { // circuit/net/pin: header column = pin name, second column empty (for now) - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - if (column == model->object_column ()) { QString suffix; @@ -1984,10 +1985,10 @@ CircuitNetSubCircuitPinItemData::text (int column, NetlistBrowserModel *model) suffix = tr (" (already seen)"); } - return model->make_link_to (pp (), circuit_refs) + tl::to_qstring (field_sep) + model->make_link_to (circuit_refs) + suffix; + return model->make_link_to (pp (), circuits ()) + tl::to_qstring (field_sep) + model->make_link_to (circuits ()) + suffix; } else if (column == model->first_column () || column == model->second_column ()) { - return model->make_link_to (subcircuits, column); + return model->make_link_to (subcircuits (), column); } return QString (); @@ -1996,23 +1997,19 @@ CircuitNetSubCircuitPinItemData::text (int column, NetlistBrowserModel *model) QString CircuitNetSubCircuitPinItemData::search_text () { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits); - return tl::to_qstring (combine_search_strings (combine_search_strings (search_string_from_names (pp ()), search_string_from_names (circuit_refs)), search_string_from_expanded_names (subcircuits))); + return tl::to_qstring (combine_search_strings (combine_search_strings (search_string_from_names (pp ()), search_string_from_names (circuits ())), search_string_from_expanded_names (subcircuits ()))); } std::string CircuitNetSubCircuitPinItemData::tooltip (NetlistBrowserModel *model) { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - return model->indexer ()->subcircuit_status_hint (circuits (), model->indexer ()->subcircuit_index (subcircuits)); + return model->indexer ()->subcircuit_status_hint (parent ()->circuits (), model->indexer ()->subcircuit_index (subcircuits ())); } db::NetlistCrossReference::Status CircuitNetSubCircuitPinItemData::status (NetlistBrowserModel *model) { - IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (sp ()); - return model->indexer ()->subcircuit_from_index (circuits (), model->indexer ()->subcircuit_index (subcircuits)).second; + return model->indexer ()->subcircuit_from_index (parent ()->circuits (), model->indexer ()->subcircuit_index (subcircuits ())).second; } // ---------------------------------------------------------------------------------- From 2762daf14f0a172150547368ce20baa04ed343f5 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 12 Jul 2020 22:32:01 +0200 Subject: [PATCH 25/32] WIP: fixed tests, fixed an assertion with null nets --- .../laybasic/layNetlistBrowserModel.cc | 63 +++++++-- .../unit_tests/layNetlistBrowserModelTests.cc | 132 ++++++++---------- 2 files changed, 109 insertions(+), 86 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 852fb70b1..689ad41cb 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -1101,6 +1101,8 @@ public: CircuitPinItemData (NetlistModelItemData *parent, const IndexedNetlistModel::pin_pair &pp); virtual QIcon icon (NetlistBrowserModel *model); + virtual QString text (int column, NetlistBrowserModel *model); + virtual QString search_text (); virtual std::pair pins_of_this () { @@ -1277,12 +1279,14 @@ NetlistModelItemData::circuits () } bool -NetlistModelItemData::derived_from_circuits (const std::pair &sp) +NetlistModelItemData::derived_from_circuits (const std::pair &cp) { - if (circuits_of_this () == sp) { + if (! cp.first && ! cp.second) { + return false; + } else if (circuits_of_this () == cp) { return true; } else if (mp_parent) { - return mp_parent->derived_from_circuits (sp); + return mp_parent->derived_from_circuits (cp); } else { return false; } @@ -1308,7 +1312,9 @@ NetlistModelItemData::devices () bool NetlistModelItemData::derived_from_devices (const std::pair &sp) { - if (devices_of_this () == sp) { + if (! sp.first && ! sp.second) { + return false; + } else if (devices_of_this () == sp) { return true; } else if (mp_parent) { return mp_parent->derived_from_devices (sp); @@ -1337,7 +1343,9 @@ NetlistModelItemData::pins () bool NetlistModelItemData::derived_from_pins (const std::pair &sp) { - if (pins_of_this () == sp) { + if (! sp.first && ! sp.second) { + return false; + } else if (pins_of_this () == sp) { return true; } else if (mp_parent) { return mp_parent->derived_from_pins (sp); @@ -1366,7 +1374,9 @@ NetlistModelItemData::subcircuits () bool NetlistModelItemData::derived_from_subcircuits (const std::pair &sp) { - if (subcircuits_of_this () == sp) { + if (! sp.first && ! sp.second) { + return false; + } else if (subcircuits_of_this () == sp) { return true; } else if (mp_parent) { return mp_parent->derived_from_subcircuits (sp); @@ -1395,7 +1405,9 @@ NetlistModelItemData::nets () bool NetlistModelItemData::derived_from_nets (const std::pair &np) { - if (nets_of_this () == np) { + if (! np.first && ! np.second) { + return false; + } else if (nets_of_this () == np) { return true; } else if (mp_parent) { return mp_parent->derived_from_nets (np); @@ -1755,6 +1767,7 @@ CircuitPinItemData::CircuitPinItemData (NetlistModelItemData *parent, const Inde : CircuitNetItemData (parent, nets_from_circuit_pins (parent->circuits (), pp)), m_pp (pp) { + // .. nothing yet .. } QIcon @@ -1763,6 +1776,26 @@ CircuitPinItemData::icon (NetlistBrowserModel * /*model*/) return icon_for_pin (); } +QString +CircuitPinItemData::text (int column, NetlistBrowserModel *model) +{ + if (column == model->object_column ()) { + std::string suffix; + if (seen ()) { + suffix = tl::to_string (tr (" (already seen)")); + } + return escaped (str_from_expanded_names (m_pp, model->indexer ()->is_single ()) + suffix); + } else { + return CircuitNetItemData::text (column, model); + } +} + +QString +CircuitPinItemData::search_text () +{ + return tl::to_qstring (combine_search_strings (search_string_from_expanded_names (m_pp), search_string_from_expanded_names (nets ()))); +} + // ---------------------------------------------------------------------------------- CircuitNetItemData::CircuitNetItemData (NetlistModelItemData *parent, const IndexedNetlistModel::net_pair &np) @@ -1829,15 +1862,23 @@ CircuitNetItemData::search_text () std::string CircuitNetItemData::tooltip (NetlistBrowserModel *model) { - size_t index = model->indexer ()->net_index (m_np); - return model->indexer ()->net_status_hint (circuits (), index); + if (m_np.first || m_np.second) { + size_t index = model->indexer ()->net_index (m_np); + return model->indexer ()->net_status_hint (circuits (), index); + } else { + return std::string (); + } } db::NetlistCrossReference::Status CircuitNetItemData::status (NetlistBrowserModel *model) { - size_t index = model->indexer ()->net_index (m_np); - return model->indexer ()->net_from_index (circuits (), index).second; + if (m_np.first || m_np.second) { + size_t index = model->indexer ()->net_index (m_np); + return model->indexer ()->net_from_index (circuits (), index).second; + } else { + return db::NetlistCrossReference::None; + } } // ---------------------------------------------------------------------------------- diff --git a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc index ad5d94aa4..19d53cee8 100644 --- a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc +++ b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc @@ -51,7 +51,7 @@ TEST (1) QModelIndex sn_nets = model->index (1, 0, inv2Index); QModelIndex sn_devices = model->index (2, 0, inv2Index); // Pins - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::UserRole).toString ()), "IN"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::UserRole).toString ()), "IN|NIN"); EXPECT_EQ (model->parent (model->index (0, 0, sn_pins)) == model->parent (model->index (0, 3, sn_pins)), true); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::DisplayRole).toString ()), "IN"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, sn_pins), Qt::DisplayRole).toString ()), "$1"); @@ -114,17 +114,12 @@ TEST (1) EXPECT_EQ (tl::to_string (model->data (model->index (9, 2, sn_subcircuits), Qt::DisplayRole).toString ()), "$10"); // Devices - // OUT pin of INV2 has a single child node which is the "NOUT" net + // OUT pin of INV2 is identical with the "NOUT" net QModelIndex inv2PinOutIndex = model->index (2, 0, model->index (0, 0, inv2Index)); EXPECT_EQ (model->parent (inv2PinOutIndex) == model->index (0, 0, inv2Index), true); EXPECT_EQ (model->hasChildren (inv2PinOutIndex), true); - EXPECT_EQ (model->rowCount (inv2PinOutIndex), 1); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PinOutIndex), Qt::DisplayRole).toString ()), "NOUT"); - - QModelIndex inv2PinOutIndexNet = model->index (0, 0, inv2PinOutIndex); - EXPECT_EQ (model->parent (inv2PinOutIndexNet) == inv2PinOutIndex, true); - EXPECT_EQ (model->hasChildren (inv2PinOutIndexNet), true); - EXPECT_EQ (model->rowCount (inv2PinOutIndexNet), 3); + EXPECT_EQ (model->rowCount (inv2PinOutIndex), 3); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PinOutIndex), Qt::DisplayRole).toString ()), "D / PMOS [L=0.25, W=0.95, AS=0.26125, AD=0.49875, PS=1.5, PD=2.95]"); // NOUT net has 1 pin, 2 devices, 0 subcircuits QModelIndex inv2NOutIndex = model->index (1, 0, model->index (1, 0, inv2Index)); @@ -164,8 +159,8 @@ TEST (1) QModelIndex inv2NOutDeviceGateIndex = model->index (1, 0, inv2NOutDeviceIndex); EXPECT_EQ (model->parent (inv2NOutDeviceGateIndex) == inv2NOutDeviceIndex, true); - EXPECT_EQ (model->hasChildren (inv2NOutDeviceGateIndex), true); // @@@ -> children: nets - EXPECT_EQ (model->rowCount (inv2NOutDeviceGateIndex), 1); + EXPECT_EQ (model->hasChildren (inv2NOutDeviceGateIndex), true); + EXPECT_EQ (model->rowCount (inv2NOutDeviceGateIndex), 5); // FB net has 0 pin, 0 devices, 2 subcircuits QModelIndex ringoFbIndex = model->index (0, 0, sn_nets); @@ -175,50 +170,58 @@ TEST (1) EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbIndex), Qt::UserRole).toString ()), "IN|INV2|$2"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbIndex), Qt::DisplayRole).toString ()), "IN / INV2"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoFbIndex), Qt::DisplayRole).toString ()), "$2"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoFbIndex), Qt::DisplayRole).toString ()), "$2"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, ringoFbIndex), Qt::DisplayRole).toString ()), "$1 / INV2"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, ringoFbIndex), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, ringoFbIndex), Qt::DisplayRole).toString ()), "$1"); QModelIndex ringoFbSubcircuit2Index = model->index (0, 0, ringoFbIndex); EXPECT_EQ (model->parent (ringoFbSubcircuit2Index) == ringoFbIndex, true); EXPECT_EQ (model->hasChildren (ringoFbSubcircuit2Index), true); - EXPECT_EQ (model->rowCount (ringoFbSubcircuit2Index), 5); + EXPECT_EQ (model->rowCount (ringoFbSubcircuit2Index), 1); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbSubcircuit2Index), Qt::UserRole).toString ()), "IN|FB"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "IN (already seen)"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "FB"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$1 (already seen)"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), ""); - EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "OUT"); - EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$4"); - EXPECT_EQ (tl::to_string (model->data (model->index (3, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$3"); - EXPECT_EQ (tl::to_string (model->data (model->index (3, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "VSS"); - EXPECT_EQ (tl::to_string (model->data (model->index (4, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "$4"); - EXPECT_EQ (tl::to_string (model->data (model->index (4, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "VDD"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbSubcircuit2Index), Qt::UserRole).toString ()), "NIN"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "NIN"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, ringoFbSubcircuit2Index), Qt::DisplayRole).toString ()), "NIN (3)"); - QModelIndex ringoFbSubcircuit2InPinIndex = model->index (1, 0, ringoFbSubcircuit2Index); - EXPECT_EQ (model->parent (ringoFbSubcircuit2InPinIndex) == ringoFbSubcircuit2Index, true); - EXPECT_EQ (model->hasChildren (ringoFbSubcircuit2InPinIndex), false); - EXPECT_EQ (model->rowCount (ringoFbSubcircuit2InPinIndex), 0); + QModelIndex ringoFbSubcircuit2InsideNetIndex = model->index (0, 0, ringoFbSubcircuit2Index); + EXPECT_EQ (model->parent (ringoFbSubcircuit2InsideNetIndex) == ringoFbSubcircuit2Index, true); + EXPECT_EQ (model->hasChildren (ringoFbSubcircuit2InsideNetIndex), true); + EXPECT_EQ (model->rowCount (ringoFbSubcircuit2InsideNetIndex), 3); // Subcircuit 1 of RINGO has 5 pins 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), 6); + EXPECT_EQ (model->rowCount (ringoSubcircuit1Index), 2); - 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 ringoSubcircuit1PinsIndex = model->index (0, 0, ringoSubcircuit1Index); + EXPECT_EQ (model->rowCount (ringoSubcircuit1PinsIndex), 5); - QModelIndex ringoSubcircuit1OutPinIndex = model->index (2, 0, ringoSubcircuit1Index); - EXPECT_EQ (model->parent (ringoSubcircuit1OutPinIndex) == ringoSubcircuit1Index, true); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoSubcircuit1PinsIndex), Qt::UserRole).toString ()), "IN|$5"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, ringoSubcircuit1PinsIndex), Qt::UserRole).toString ()), "FB"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, ringoSubcircuit1PinsIndex), Qt::UserRole).toString ()), "OUT"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, ringoSubcircuit1PinsIndex), Qt::DisplayRole).toString ()), "OUT"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, ringoSubcircuit1PinsIndex), Qt::DisplayRole).toString ()), ""); + + QModelIndex ringoSubcircuit1NodeIndex = model->index (1, 0, ringoSubcircuit1Index); + EXPECT_EQ (model->rowCount (ringoSubcircuit1NodeIndex), 3); + + QModelIndex ringoSubcircuit1InsidePinsIndex = model->index (0, 0, ringoSubcircuit1NodeIndex); + EXPECT_EQ (model->rowCount (ringoSubcircuit1InsidePinsIndex), 5); + + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, ringoSubcircuit1InsidePinsIndex), Qt::UserRole).toString ()), "IN|NIN"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, ringoSubcircuit1InsidePinsIndex), Qt::UserRole).toString ()), "$1|$2"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, ringoSubcircuit1InsidePinsIndex), Qt::UserRole).toString ()), "OUT|NOUT"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 0, ringoSubcircuit1InsidePinsIndex), Qt::DisplayRole).toString ()), "OUT"); + EXPECT_EQ (tl::to_string (model->data (model->index (2, 2, ringoSubcircuit1InsidePinsIndex), Qt::DisplayRole).toString ()), "NOUT (3)"); + + QModelIndex ringoSubcircuit1OutPinIndex = model->index (2, 0, ringoSubcircuit1PinsIndex); + EXPECT_EQ (model->parent (ringoSubcircuit1OutPinIndex) == ringoSubcircuit1PinsIndex, true); EXPECT_EQ (model->hasChildren (ringoSubcircuit1OutPinIndex), false); EXPECT_EQ (model->rowCount (ringoSubcircuit1OutPinIndex), 0); - // Device 1 of INV2 has 3 pins + // Device 1 of INV2 has 3 terminals QModelIndex inv2Device1Index = model->index (0, 0, sn_devices); EXPECT_EQ (model->parent (inv2Device1Index) == sn_devices, true); @@ -231,7 +234,10 @@ TEST (1) QModelIndex inv2Device1GateIndex = model->index (1, 0, inv2Device1Index); EXPECT_EQ (model->parent (inv2Device1GateIndex) == inv2Device1Index, true); EXPECT_EQ (model->hasChildren (inv2Device1GateIndex), true); - EXPECT_EQ (model->rowCount (inv2Device1GateIndex), 1); + EXPECT_EQ (model->rowCount (inv2Device1GateIndex), 3); + + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Device1GateIndex), Qt::UserRole).toString ()), "G|PMOS|$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Device1GateIndex), Qt::DisplayRole).toString ()), "G / PMOS [L=0.25, W=0.95, AS=0.49875, AD=0.26125, PS=2.95, PD=1.5] (already seen)"); } TEST (2) @@ -274,22 +280,22 @@ TEST (2) EXPECT_EQ (model->rowCount (sn_devices), 2); // first of pins in INV2 circuit - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::UserRole).toString ()), "$0|$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::UserRole).toString ()), "$0|$0|$1|1"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::DisplayRole).toString ()), "$0"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_pins), Qt::DisplayRole).toString ()), "$0"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, sn_pins), Qt::DisplayRole).toString ()), "$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_pins), Qt::DisplayRole).toString ()), "$1 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, sn_pins), Qt::DisplayRole).toString ()), "1 (2)"); // INV2, pin 0 node QModelIndex inv2Pin0Index = model->index (0, 0, sn_pins); EXPECT_EQ (model->hasChildren (inv2Pin0Index), true); - EXPECT_EQ (model->rowCount (inv2Pin0Index), 1); + EXPECT_EQ (model->rowCount (inv2Pin0Index), 2); EXPECT_EQ (model->parent (inv2Pin0Index) == sn_pins, true); // 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 (2)"); - std::pair nets = model->net_from_index (model->index (0, 0, inv2Pin0Index)); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::UserRole).toString ()), "$0|$0|$1|1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::DisplayRole).toString ()), "$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_pins), Qt::DisplayRole).toString ()), "$1 (2)"); + std::pair nets = model->net_from_index (model->index (0, 0, sn_pins)); EXPECT_EQ (nets.first != 0, true); if (nets.first != 0) { EXPECT_EQ (nets.first->expanded_name (), "$1"); @@ -298,7 +304,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 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, sn_pins), 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"); @@ -326,8 +332,8 @@ TEST (2) // .. whose second terminal is gate EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0TerminalIndex), Qt::UserRole).toString ()), "G|G|IN|2"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "G"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "IN"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "2"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "IN (3)"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "2 (3)"); // The Pin EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0Index), Qt::UserRole).toString ()), ""); @@ -367,20 +373,7 @@ TEST (2) EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::UserRole).toString ()), "$4"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_pins), Qt::DisplayRole).toString ()), "- ⇔ $4"); EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, sn_pins), Qt::DisplayRole).toString ()), ""); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, sn_pins), Qt::DisplayRole).toString ()), "$4"); - - // INV2, pin 0 node - QModelIndex inv2PairPin0Index = model->index (0, 0, sn_pins); - EXPECT_EQ (model->hasChildren (inv2PairPin0Index), true); - EXPECT_EQ (model->rowCount (inv2PairPin0Index), 1); - EXPECT_EQ (model->parent (inv2PairPin0Index) == sn_pins, true); - - // INV2, pin 0 has one net node - // The pin isnt't connected to any net, left side because there is no match, right side because the pin isn't connected - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairPin0Index), Qt::UserRole).toString ()), ""); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairPin0Index), Qt::DisplayRole).toString ()), "-"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2PairPin0Index), Qt::DisplayRole).toString ()), ""); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, inv2PairPin0Index), Qt::DisplayRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 3, sn_pins), Qt::DisplayRole).toString ()), ""); // first of nets in INV2 circuit EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, sn_nets), Qt::UserRole).toString ()), "$4"); @@ -409,19 +402,8 @@ TEST (2) // The first subcircuit EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2PairNet0Index), Qt::UserRole).toString ()), "OUT|INV2|$1"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2PairNet0Index), Qt::DisplayRole).toString ()), "OUT ⇔ - / INV2 ⇔ -"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2PairNet0Index), Qt::DisplayRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2PairNet0Index), Qt::DisplayRole).toString ()), "$1"); EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, inv2PairNet0Index), Qt::DisplayRole).toString ()), ""); - - // This subcircuit has 6 other pins - QModelIndex inv2PairNet0SubCircuit0Index = model->index (1, 0, inv2PairNet0Index); - EXPECT_EQ (model->hasChildren (inv2PairNet0SubCircuit0Index), true); - EXPECT_EQ (model->rowCount (inv2PairNet0SubCircuit0Index), 6); - EXPECT_EQ (model->parent (inv2PairNet0SubCircuit0Index) == inv2PairNet0Index, true); - - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0SubCircuit0Index), Qt::UserRole).toString ()), "$7"); - EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0SubCircuit0Index), Qt::DisplayRole).toString ()), "$0 ⇔ -"); - 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) From a10d56e6b60f04dffeff9a63962e7fd60e8e8853 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 13 Jul 2020 22:11:10 +0200 Subject: [PATCH 26/32] WIP: netlist browser - net object paths, single + pairs, tests --- .../laybasic/layNetlistBrowserModel.cc | 69 +++++++++- .../laybasic/layNetlistBrowserModel.h | 68 +++++++++- .../laybasic/layNetlistBrowserPage.cc | 8 +- src/laybasic/laybasic/layNetlistBrowserPage.h | 4 +- .../laybasic/layNetlistBrowserTreeModel.cc | 4 +- .../laybasic/layNetlistBrowserTreeModel.h | 4 +- .../unit_tests/layNetlistBrowserModelTests.cc | 126 +++++++++++++++++- 7 files changed, 259 insertions(+), 24 deletions(-) diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index 689ad41cb..5e4934951 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -36,6 +36,67 @@ namespace lay { +// ---------------------------------------------------------------------------------- +// NetlistObjectPath implementation + +NetlistObjectsPath +NetlistObjectsPath::from_first (const NetlistObjectPath &p) +{ + NetlistObjectsPath pp; + pp.root.first = p.root; + for (NetlistObjectPath::path_iterator i = p.path.begin (); i != p.path.end (); ++i) { + pp.path.push_back (std::make_pair (*i, (const db::SubCircuit *) 0)); + } + pp.device.first = p.device; + pp.net.first = p.net; + return pp; +} + +NetlistObjectsPath +NetlistObjectsPath::from_second (const NetlistObjectPath &p) +{ + NetlistObjectsPath pp; + pp.root.second = p.root; + for (NetlistObjectPath::path_iterator i = p.path.begin (); i != p.path.end (); ++i) { + pp.path.push_back (std::make_pair ((const db::SubCircuit *) 0, *i)); + } + pp.device.second = p.device; + pp.net.second = p.net; + return pp; +} + +NetlistObjectPath +NetlistObjectsPath::first () const +{ + NetlistObjectPath p; + p.root = root.first; + for (NetlistObjectsPath::path_iterator i = path.begin (); i != path.end (); ++i) { + if (! i->first) { + return NetlistObjectPath (); + } + p.path.push_back (i->first); + } + p.device = device.first; + p.net = net.first; + return p; +} + +NetlistObjectPath +NetlistObjectsPath::second () const +{ + NetlistObjectPath p; + p.root = root.second; + for (NetlistObjectsPath::path_iterator i = path.begin (); i != path.end (); ++i) { + if (! i->second) { + return NetlistObjectPath (); + } + p.path.push_back (i->second); + } + p.device = device.second; + p.net = net.second; + return p; +} + // ---------------------------------------------------------------------------------- // NetColorizer implementation @@ -2435,10 +2496,10 @@ NetlistBrowserModel::data (const QModelIndex &index, int role) const return QVariant (); } -NetlistObjectPath -NetlistBrowserModel::netpath_from_index (const QModelIndex &index) const +NetlistObjectsPath +NetlistBrowserModel::path_from_index (const QModelIndex &index) const { - NetlistObjectPath np; + NetlistObjectsPath np; np.net = net_from_index (index, false); np.device = device_from_index (index, false); @@ -2463,7 +2524,7 @@ NetlistBrowserModel::netpath_from_index (const QModelIndex &index) const } QModelIndex -NetlistBrowserModel::index_from_netpath (const NetlistObjectPath &path) +NetlistBrowserModel::index_from_path (const NetlistObjectsPath &path) { QModelIndex index = index_from_circuit (path.root); diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.h b/src/laybasic/laybasic/layNetlistBrowserModel.h index 1fd624ce8..3d80362e7 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.h +++ b/src/laybasic/laybasic/layNetlistBrowserModel.h @@ -179,14 +179,22 @@ private: }; /** - * @brief An object describing the instantiation path of a net + * @brief An object describing the instantiation path of a net, a device or a (sub)circuit pair + * + * This object applies to pairs of these objects. A class providing a path for a single + * object is NetlistObjectPath */ struct LAYBASIC_PUBLIC NetlistObjectPath { - typedef std::list > path_type; + typedef std::list path_type; typedef path_type::const_iterator path_iterator; - NetlistObjectPath () { } + NetlistObjectPath () : root (0), net (0), device (0) { } + + bool is_null () const + { + return ! root; + } bool operator== (const NetlistObjectPath &other) const { @@ -198,6 +206,46 @@ struct LAYBASIC_PUBLIC NetlistObjectPath return ! operator== (other); } + const db::Circuit *root; + std::list path; + const db::Net *net; + const db::Device *device; +}; + +/** + * @brief An object describing the instantiation path of a net, a device or a (sub)circuit pair + * + * This object applies to pairs of these objects. A class providing a path for a single + * object is NetlistObjectPath + */ +struct LAYBASIC_PUBLIC NetlistObjectsPath +{ + typedef std::list > path_type; + typedef path_type::const_iterator path_iterator; + + NetlistObjectsPath () { } + + bool is_null () const + { + return ! root.first && ! root.second; + } + + static NetlistObjectsPath from_first(const NetlistObjectPath &p); + static NetlistObjectsPath from_second (const NetlistObjectPath &p); + + NetlistObjectPath first () const; + NetlistObjectPath second () const; + + bool operator== (const NetlistObjectsPath &other) const + { + return root == other.root && path == other.path && net == other.net && device == other.device; + } + + bool operator!= (const NetlistObjectsPath &other) const + { + return ! operator== (other); + } + std::pair root; std::list > path; std::pair net; @@ -292,8 +340,18 @@ public: QIcon icon_for_connection (const std::pair &net) const; QModelIndex index_from_url (const QString &url) const; - NetlistObjectPath netpath_from_index (const QModelIndex &index) const; - QModelIndex index_from_netpath (const NetlistObjectPath &path); + + NetlistObjectsPath path_from_index (const QModelIndex &index) const; + NetlistObjectPath spath_from_index (const QModelIndex &index) const + { + return path_from_index (index).first (); + } + + QModelIndex index_from_path (const NetlistObjectsPath &path); + QModelIndex index_from_path (const NetlistObjectPath &path) + { + return index_from_path (NetlistObjectsPath::from_first (path)); + } private slots: void colors_changed (); diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index 9f9de9fcb..32a2c8bd0 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -347,7 +347,7 @@ NetlistBrowserPage::current_index_changed (const QModelIndex &index) add_to_history (index, true); - NetlistObjectPath path = netlist_model->netpath_from_index (index); + NetlistObjectsPath path = netlist_model->path_from_index (index); QModelIndex circuit_index = tree_model->index_from_netpath (path); m_signals_enabled = false; @@ -460,7 +460,7 @@ NetlistBrowserPage::selection_changed () tl_assert (model != 0); QModelIndex current = directory_tree->selectionModel ()->currentIndex (); - highlight (model->netpath_from_index (current)); + highlight (model->path_from_index (current)); } void @@ -517,7 +517,7 @@ NetlistBrowserPage::navigate_to (const QModelIndex &index, bool fwd) return; } - lay::NetlistObjectPath path = netlist_model->netpath_from_index (index); + lay::NetlistObjectsPath path = netlist_model->path_from_index (index); QModelIndex circuit_index = tree_model->index_from_netpath (path); hierarchy_tree->setCurrentIndex (circuit_index); @@ -874,7 +874,7 @@ NetlistBrowserPage::setup_trees () } void -NetlistBrowserPage::highlight (const NetlistObjectPath &path) +NetlistBrowserPage::highlight (const NetlistObjectsPath &path) { if (path != m_current_path) { diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.h b/src/laybasic/laybasic/layNetlistBrowserPage.h index 37aff1312..5c0b61f60 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.h +++ b/src/laybasic/laybasic/layNetlistBrowserPage.h @@ -235,7 +235,7 @@ private: bool m_enable_updates; bool m_update_needed; // @@@ TODO: make multiple ... - lay::NetlistObjectPath m_current_path; + lay::NetlistObjectsPath m_current_path; // @@@ TODO: remove std::vector m_current_nets; std::vector m_current_devices; @@ -251,7 +251,7 @@ private: void navigate_to (const QModelIndex &index, bool forward = true); void adjust_view (); void clear_markers (); - void highlight (const lay::NetlistObjectPath &path); + void highlight (const lay::NetlistObjectsPath &path); std::vector selected_nets (); std::vector selected_devices (); std::vector selected_subcircuits (); diff --git a/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc b/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc index db47fad4b..f77138f8f 100644 --- a/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserTreeModel.cc @@ -270,13 +270,13 @@ static bool is_compatible (const std::pair sc (p->first ? p->first->circuit_ref () : 0, p->second ? p->second->circuit_ref (): 0); std::pair circuit = circuits_from_index (idx); diff --git a/src/laybasic/laybasic/layNetlistBrowserTreeModel.h b/src/laybasic/laybasic/layNetlistBrowserTreeModel.h index c4fe0696d..d0f182bfc 100644 --- a/src/laybasic/laybasic/layNetlistBrowserTreeModel.h +++ b/src/laybasic/laybasic/layNetlistBrowserTreeModel.h @@ -42,7 +42,7 @@ namespace lay { class IndexedNetlistModel; -struct NetlistObjectPath; +struct NetlistObjectsPath; // ---------------------------------------------------------------------------------- // NetlistBrowserTreeModel definition @@ -78,7 +78,7 @@ public: std::pair circuits_from_index (const QModelIndex &index) const; QModelIndex index_from_circuits (const std::pair &circuits) const; - QModelIndex index_from_netpath (const NetlistObjectPath &path) const; + QModelIndex index_from_netpath (const NetlistObjectsPath &path) const; private: NetlistBrowserTreeModel (const NetlistBrowserTreeModel &); diff --git a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc index 19d53cee8..3b951e718 100644 --- a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc +++ b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc @@ -417,8 +417,8 @@ TEST (3) 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); + lay::NetlistObjectsPath path; + EXPECT_EQ (model->index_from_path (path).isValid (), false); path.root.first = root; @@ -427,7 +427,7 @@ TEST (3) path.net.first = net; - QModelIndex index = model->index_from_netpath (path); + QModelIndex index = model->index_from_path (path); EXPECT_EQ (index.isValid (), true); EXPECT_EQ (tl::to_string (model->data (index, Qt::UserRole).toString ()), "FB"); @@ -444,7 +444,7 @@ TEST (4) db::Circuit *root = l2n.netlist ()->circuit_by_name ("RINGO"); EXPECT_EQ (root != 0, true); - lay::NetlistObjectPath path; + lay::NetlistObjectsPath path; path.root.first = root; db::SubCircuit *sc1 = root->begin_subcircuits ().operator-> (); @@ -456,8 +456,124 @@ TEST (4) path.net.first = net; - QModelIndex index = model->index_from_netpath (path); + QModelIndex index = model->index_from_path (path); EXPECT_EQ (index.isValid (), true); EXPECT_EQ (tl::to_string (model->data (index, Qt::UserRole).toString ()), "NOUT"); } + +// Netlist object path: single vs. pairs - first +TEST (5) +{ + db::LayoutVsSchematic lvs; + lvs.load (tl::testsrc () + "/testdata/lay/lvsdb_browser.lvsdb"); + + lay::NetColorizer colorizer; + std::auto_ptr model (new lay::NetlistBrowserModel (0, &lvs, &colorizer)); + QModelIndex idx; + + db::Circuit *root = lvs.netlist ()->circuit_by_name ("INV2PAIR"); + EXPECT_EQ (root != 0, true); + db::Circuit *sc = lvs.netlist ()->circuit_by_name ("INV2"); + EXPECT_EQ (sc != 0, true); + + lay::NetlistObjectPath path; + EXPECT_EQ (path.is_null (), true); + path.root = root; + EXPECT_EQ (path.is_null (), false); + + idx = model->index_from_path (path); + EXPECT_EQ (idx.isValid (), true); + EXPECT_EQ (tl::to_string (model->data (idx, Qt::UserRole).toString ()), "INV2PAIR|INV2PAIR"); + EXPECT_EQ (path == model->path_from_index (idx).first (), true); + + path.net = root->net_by_cluster_id (5); + idx = model->index_from_path (lay::NetlistObjectsPath::from_first (path)); + EXPECT_EQ (idx.isValid (), true); + EXPECT_EQ (tl::to_string (model->data (idx, Qt::UserRole).toString ()), "$5|4"); + EXPECT_EQ (path == model->path_from_index (idx).first (), true); + + path.path.push_back (root->subcircuit_by_id (1)); + EXPECT_EQ (path.path.back () != 0, true); + EXPECT_EQ (path.path.back ()->expanded_name (), "$1"); + EXPECT_EQ (path.path.back ()->circuit_ref ()->name (), "INV2"); + + path.net = 0; + idx = model->index_from_path (lay::NetlistObjectsPath::from_first (path)); + EXPECT_EQ (idx.isValid (), true); + // A pure subcircuit path addresses the "Circuit" representative node of the subcircuit + EXPECT_EQ (tl::to_string (model->data (idx, Qt::DisplayRole).toString ()), "Circuit"); + EXPECT_EQ (tl::to_string (model->data (model->parent (idx), Qt::UserRole).toString ()), "INV2|$1"); + EXPECT_EQ (path == model->path_from_index (idx).first (), true); + + path.net = sc->net_by_cluster_id (2); + idx = model->index_from_path (lay::NetlistObjectsPath::from_first (path)); + EXPECT_EQ (idx.isValid (), true); + EXPECT_EQ (tl::to_string (model->data (idx, Qt::UserRole).toString ()), "IN|2"); + EXPECT_EQ (path == model->path_from_index (idx).first (), true); + + path.net = 0; + path.device = sc->device_by_id (1); + idx = model->index_from_path (lay::NetlistObjectsPath::from_first (path)); + EXPECT_EQ (idx.isValid (), true); + EXPECT_EQ (tl::to_string (model->data (idx, Qt::UserRole).toString ()), "$1|$1|PMOS|PMOS"); + EXPECT_EQ (path == model->path_from_index (idx).first (), true); +} + +// Netlist object path: single vs. pairs - second +TEST (6) +{ + db::LayoutVsSchematic lvs; + lvs.load (tl::testsrc () + "/testdata/lay/lvsdb_browser.lvsdb"); + + lay::NetColorizer colorizer; + std::auto_ptr model (new lay::NetlistBrowserModel (0, &lvs, &colorizer)); + QModelIndex idx; + + db::Circuit *root = lvs.reference_netlist ()->circuit_by_name ("INV2PAIR"); + EXPECT_EQ (root != 0, true); + db::Circuit *sc = lvs.reference_netlist ()->circuit_by_name ("INV2"); + EXPECT_EQ (sc != 0, true); + + lay::NetlistObjectPath path; + EXPECT_EQ (path.is_null (), true); + path.root = root; + EXPECT_EQ (path.is_null (), false); + + idx = model->index_from_path (lay::NetlistObjectsPath::from_second (path)); + EXPECT_EQ (idx.isValid (), true); + EXPECT_EQ (tl::to_string (model->data (idx, Qt::UserRole).toString ()), "INV2PAIR|INV2PAIR"); + EXPECT_EQ (path == model->path_from_index (idx).second (), true); + + path.net = root->net_by_name ("4"); + idx = model->index_from_path (lay::NetlistObjectsPath::from_second (path)); + EXPECT_EQ (idx.isValid (), true); + EXPECT_EQ (tl::to_string (model->data (idx, Qt::UserRole).toString ()), "$5|4"); + EXPECT_EQ (path == model->path_from_index (idx).second (), true); + + path.path.push_back (root->subcircuit_by_name ("$2")); + EXPECT_EQ (path.path.back () != 0, true); + EXPECT_EQ (path.path.back ()->expanded_name (), "$2"); + EXPECT_EQ (path.path.back ()->circuit_ref ()->name (), "INV2"); + + path.net = 0; + idx = model->index_from_path (lay::NetlistObjectsPath::from_second (path)); + EXPECT_EQ (idx.isValid (), true); + // A pure subcircuit path addresses the "Circuit" representative node of the subcircuit + EXPECT_EQ (tl::to_string (model->data (idx, Qt::DisplayRole).toString ()), "Circuit"); + EXPECT_EQ (tl::to_string (model->data (model->parent (idx), Qt::UserRole).toString ()), "INV2|$2"); + EXPECT_EQ (path == model->path_from_index (idx).second (), true); + + path.net = sc->net_by_name ("2"); + idx = model->index_from_path (lay::NetlistObjectsPath::from_second (path)); + EXPECT_EQ (idx.isValid (), true); + EXPECT_EQ (tl::to_string (model->data (idx, Qt::UserRole).toString ()), "IN|2"); + EXPECT_EQ (path == model->path_from_index (idx).second (), true); + + path.net = 0; + path.device = sc->device_by_id (1); + idx = model->index_from_path (lay::NetlistObjectsPath::from_second (path)); + EXPECT_EQ (idx.isValid (), true); + EXPECT_EQ (tl::to_string (model->data (idx, Qt::UserRole).toString ()), "$1|$1|PMOS|PMOS"); + EXPECT_EQ (path == model->path_from_index (idx).second (), true); +} From be5f03b1f45723fe94c03ba36c94fafeabd99c61 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 14 Jul 2020 23:06:26 +0200 Subject: [PATCH 27/32] Netlist browser: Paths for probing, cell contexts for highlighting, probe_net with initial circuit (not just top one) --- src/db/db/dbLayoutToNetlist.cc | 18 +++++-- src/db/db/dbLayoutToNetlist.h | 4 +- src/db/db/gsiDeclDbLayoutToNetlist.cc | 9 ++-- .../laybasic/layNetlistBrowserDialog.cc | 51 ++++++++++++------- .../laybasic/layNetlistBrowserPage.cc | 34 +++++++++++-- src/laybasic/laybasic/layNetlistBrowserPage.h | 16 ++++++ 6 files changed, 98 insertions(+), 34 deletions(-) diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 90d229f1f..9232b78ea 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -1041,9 +1041,9 @@ LayoutToNetlist::build_nets (const std::vector *nets, const db: } } -db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point, std::vector *sc_path_out) +db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point, std::vector *sc_path_out, db::Circuit *initial_circuit) { - return probe_net (of_region, db::CplxTrans (internal_layout ()->dbu ()).inverted () * point, sc_path_out); + return probe_net (of_region, db::CplxTrans (internal_layout ()->dbu ()).inverted () * point, sc_path_out, initial_circuit); } size_t LayoutToNetlist::search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster &test_cluster, std::vector &rev_inst_path) @@ -1077,7 +1077,7 @@ size_t LayoutToNetlist::search_net (const db::ICplxTrans &trans, const db::Cell return 0; } -db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Point &point, std::vector *sc_path_out) +db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Point &point, std::vector *sc_path_out, db::Circuit *initial_circuit) { if (! m_netlist_extracted) { throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet"))); @@ -1089,6 +1089,14 @@ db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Poin unsigned int layer = layer_of (of_region); + const db::Cell *top_cell = internal_top_cell (); + if (initial_circuit && internal_layout ()->is_valid_cell_index (initial_circuit->cell_index ())) { + top_cell = &internal_layout ()->cell (initial_circuit->cell_index ()); + } + if (! top_cell) { + return 0; + } + // Prepare a test cluster db::Box box (point - db::Vector (1, 1), point + db::Vector (1, 1)); db::GenericRepository sr; @@ -1097,7 +1105,7 @@ db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Poin std::vector inst_path; - size_t cluster_id = search_net (db::ICplxTrans (), internal_top_cell (), test_cluster, inst_path); + size_t cluster_id = search_net (db::ICplxTrans (), top_cell, test_cluster, inst_path); if (cluster_id > 0) { // search_net delivers the path in reverse order @@ -1105,7 +1113,7 @@ db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Poin std::vector cell_indexes; cell_indexes.reserve (inst_path.size () + 1); - cell_indexes.push_back (internal_top_cell ()->cell_index ()); + cell_indexes.push_back (top_cell->cell_index ()); for (std::vector::const_iterator i = inst_path.begin (); i != inst_path.end (); ++i) { cell_indexes.push_back (i->inst_ptr.cell_index ()); } diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index 8b42b99f2..4d103e66e 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -713,7 +713,7 @@ public: * The subcircuit path leading to the topmost net is stored in *sc_path_out if this * pointer is non-null. */ - db::Net *probe_net (const db::Region &of_region, const db::DPoint &point, std::vector *sc_path_out = 0); + db::Net *probe_net (const db::Region &of_region, const db::DPoint &point, std::vector *sc_path_out = 0, Circuit *initial_circuit = 0); /** * @brief Finds the net by probing a specific location on the given layer @@ -721,7 +721,7 @@ public: * This variant accepts a database-unit location. The location is given in the * coordinate space of the initial cell. */ - db::Net *probe_net (const db::Region &of_region, const db::Point &point, std::vector *sc_path_out = 0); + db::Net *probe_net (const db::Region &of_region, const db::Point &point, std::vector *sc_path_out = 0, Circuit *initial_circuit = 0); /** * @brief Runs an antenna check on the extracted clusters diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index 703699536..76dacfb14 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -543,7 +543,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", gsi::method_ext ("build_nets", &build_nets, gsi::arg ("nets"), gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::LayoutToNetlist::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"), "@brief Like \\build_all_nets, but with the ability to select some nets." ) + - gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &, std::vector *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector *) 0, "nil"), + gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &, std::vector *, db::Circuit *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector *) 0, "nil"), gsi::arg ("initial_circuit", (db::Circuit *) 0, "nil"), "@brief Finds the net by probing a specific location on the given layer\n" "\n" "This method will find a net looking at the given layer at the specific position.\n" @@ -551,9 +551,12 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "in the specified location. The function will report the topmost net from far above the\n" "hierarchy of circuits as possible.\n" "\n" + "If \\initial_circuit is given, the probing will start from this circuit and from the " + "cell this circuit represents. By default, the probing will start from the top circuit.\n" + "\n" "If no net is found at all, 0 is returned.\n" "\n" - "It is recommended to use \\probe on the netlist right after extraction.\n" + "It is recommended to use \\probe_net on the netlist right after extraction.\n" "Optimization functions such as \\Netlist#purge will remove parts of the net which means\n" "shape to net probing may no longer work for these nets.\n" "\n" @@ -565,7 +568,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "\n" "The \\sc_path_out parameter has been added in version 0.27.\n" ) + - gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::Point &, std::vector *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector *) 0, "nil"), + gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::Point &, std::vector *, db::Circuit *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector *) 0, "nil"), gsi::arg ("initial_circuit", (db::Circuit *) 0, "nil"), "@brief Finds the net by probing a specific location on the given layer\n" "See the description of the other \\probe_net variant.\n" "This variant accepts a database-unit location. The location is given in the\n" diff --git a/src/laybasic/laybasic/layNetlistBrowserDialog.cc b/src/laybasic/laybasic/layNetlistBrowserDialog.cc index 78644cfc3..e225cbf4e 100644 --- a/src/laybasic/laybasic/layNetlistBrowserDialog.cc +++ b/src/laybasic/laybasic/layNetlistBrowserDialog.cc @@ -307,41 +307,54 @@ NetlistBrowserDialog::probe_net (const db::DPoint &p, bool trace_path) } db::Net *net = 0; + db::Circuit *root = 0; std::vector sc_path; db::LayoutToNetlist *l2ndb = view ()->get_l2ndb (m_l2n_index); if (l2ndb) { - // determines the corresponding layer inside the database and probe the net from this region and the - // start point. + root = l2ndb->netlist ()->circuit_by_name (cv->layout ().cell_name (cv.cell_index ())); + if (root) { - std::vector regions; + // determines the corresponding layer inside the database and probe the net from this region and the + // start point. - const db::Connectivity &conn = l2ndb->connectivity (); - for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) { - db::LayerProperties lp = l2ndb->internal_layout ()->get_properties (*layer); - if (! lp.is_null ()) { - db::Region *region = l2ndb->layer_by_index (*layer); - if (lp == cv->layout ().get_properties (start_layer)) { - // a matching original layer is looked up with higher prio - regions.insert (regions.begin (), region); - } else { - regions.push_back (region); + std::vector regions; + + const db::Connectivity &conn = l2ndb->connectivity (); + for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) { + db::LayerProperties lp = l2ndb->internal_layout ()->get_properties (*layer); + if (! lp.is_null ()) { + db::Region *region = l2ndb->layer_by_index (*layer); + if (lp == cv->layout ().get_properties (start_layer)) { + // a matching original layer is looked up with higher prio + regions.insert (regions.begin (), region); + } else { + regions.push_back (region); + } } } - } - // probe the net + // probe the net + + for (std::vector::const_iterator r = regions.begin (); r != regions.end () && !net; ++r) { + sc_path.clear (); + net = l2ndb->probe_net (**r, start_point, &sc_path, root); + } - for (std::vector::const_iterator r = regions.begin (); r != regions.end () && !net; ++r) { - sc_path.clear (); - net = l2ndb->probe_net (**r, start_point, &sc_path); } } // select the net if one was found - browser_page->select_net (net); + lay::NetlistObjectPath path; + if (net) { + path.root = root; + path.net = net; + path.path = lay::NetlistObjectPath::path_type (sc_path.begin (), sc_path.end ()); + } + + browser_page->select_path (path); // emits the probe event probe_event (net, sc_path); diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index 32a2c8bd0..1bd2019e1 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -369,6 +369,18 @@ NetlistBrowserPage::select_net (const db::Net *net) } } +void +NetlistBrowserPage::select_path (const lay::NetlistObjectsPath &path) +{ + if (path.is_null ()) { + directory_tree->clearSelection (); + } else { + NetlistBrowserModel *model = dynamic_cast (directory_tree->model ()); + tl_assert (model != 0); + directory_tree->setCurrentIndex (model->index_from_path (path)); + } +} + std::vector NetlistBrowserPage::selected_nets () { @@ -946,13 +958,20 @@ NetlistBrowserPage::adjust_view () return; } + const db::Layout &original_layout = mp_view->cellview (m_cv_index)->layout (); + const db::Circuit *top_circuit = mp_database->netlist ()->circuit_by_name (original_layout.cell_name (mp_view->cellview (m_cv_index).cell_index ())); + + const db::Circuit *circuit = m_current_path.root.first; + if (! circuit) { + return; + } + const db::Layout *layout = mp_database->internal_layout (); - const db::Cell *cell = mp_database->internal_top_cell (); + const db::Cell *cell = (top_circuit && layout->is_valid_cell_index (top_circuit->cell_index ()) ? &layout->cell (top_circuit->cell_index ()) : mp_database->internal_top_cell ()); if (! layout || ! cell) { return; } - const db::Circuit *circuit = m_current_path.root.first; db::DCplxTrans trans; if (circuit) { @@ -1232,16 +1251,21 @@ NetlistBrowserPage::update_highlights () } const db::Layout &original_layout = mp_view->cellview (m_cv_index)->layout (); + const db::Circuit *top_circuit = mp_database->netlist ()->circuit_by_name (original_layout.cell_name (mp_view->cellview (m_cv_index).cell_index ())); + + const db::Circuit *circuit = m_current_path.root.first; + if (! circuit) { + return; + } const db::Layout *layout = mp_database->internal_layout (); - const db::Cell *cell = mp_database->internal_top_cell (); + const db::Cell *cell = (top_circuit && layout->is_valid_cell_index (top_circuit->cell_index ()) ? &layout->cell (top_circuit->cell_index ()) : mp_database->internal_top_cell ()); if (! layout || ! cell) { return; } - // compute the transformation supplied by the path + // computes the transformation supplied by the path - const db::Circuit *circuit = m_current_path.root.first; db::DCplxTrans trans; if (circuit) { diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.h b/src/laybasic/laybasic/layNetlistBrowserPage.h index 5c0b61f60..03c695824 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.h +++ b/src/laybasic/laybasic/layNetlistBrowserPage.h @@ -106,6 +106,22 @@ public: */ void select_net (const db::Net *net); + /** + * @brief Selects a netlist object (a circuit, a subcircuit, a net or a device) + */ + void select_path (const lay::NetlistObjectPath &path) + { + select_path (lay::NetlistObjectsPath::from_first (path)); + } + + /** + * @brief Selects a netlist object (a circuit, a subcircuit, a net or a device) + * + * This variant allows specifying a paired path using either an object from the first, + * the second netlist of both. + */ + void select_path (const lay::NetlistObjectsPath &path); + /** * @brief Set the window type and window dimensions */ From f8c2afaad81dcf5f1afff487cb7264277af1507d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 15 Jul 2020 00:10:42 +0200 Subject: [PATCH 28/32] Using NetlistObjectPath for probe_event. --- src/db/db/gsiDeclDbLayoutToNetlist.cc | 4 +- .../gsiDeclLayNetlistBrowserDialog.cc | 121 +++++++++++++++++- .../laybasic/layNetlistBrowserDialog.cc | 15 ++- .../laybasic/layNetlistBrowserDialog.h | 9 +- src/laybasic/laybasic/layNetlistBrowserPage.h | 8 ++ 5 files changed, 148 insertions(+), 9 deletions(-) diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index 76dacfb14..cedc464ab 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -566,7 +566,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "This variant accepts a micrometer-unit location. The location is given in the\n" "coordinate space of the initial cell.\n" "\n" - "The \\sc_path_out parameter has been added in version 0.27.\n" + "The \\sc_path_out and \\initial_circuit parameters have been added in version 0.27.\n" ) + gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::Point &, std::vector *, db::Circuit *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector *) 0, "nil"), gsi::arg ("initial_circuit", (db::Circuit *) 0, "nil"), "@brief Finds the net by probing a specific location on the given layer\n" @@ -574,7 +574,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "This variant accepts a database-unit location. The location is given in the\n" "coordinate space of the initial cell.\n" "\n" - "The \\sc_path_out parameter has been added in version 0.27.\n" + "The \\sc_path_out and \\initial_circuit parameters have been added in version 0.27.\n" ) + gsi::method ("write|write_l2n", &db::LayoutToNetlist::save, gsi::arg ("path"), gsi::arg ("short_format", false), "@brief Writes the extracted netlist to a file.\n" diff --git a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc index dfd7b08af..016afa8d8 100644 --- a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc +++ b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc @@ -42,6 +42,109 @@ template <> struct type_traits : public type_traitsroot = r; +} + +static db::Circuit *root (const lay::NetlistObjectPath *path) +{ + return const_cast (path->root); +} + +static void set_device (lay::NetlistObjectPath *path, db::Device *r) +{ + path->device = r; +} + +static db::Device *device (const lay::NetlistObjectPath *path) +{ + return const_cast (path->device); +} + +static void set_net (lay::NetlistObjectPath *path, db::Net *r) +{ + path->net = r; +} + +static db::Net *net (const lay::NetlistObjectPath *path) +{ + return const_cast (path->net); +} + +static std::vector path (const lay::NetlistObjectPath *p) +{ + std::vector pp; + pp.reserve (p->path.size ()); + for (lay::NetlistObjectPath::path_iterator i = p->path.begin (); i != p->path.end (); ++i) { + pp.push_back (const_cast (*i)); + } + return pp; +} + +static void set_path (lay::NetlistObjectPath *p, const std::vector &path) +{ + p->path = lay::NetlistObjectPath::path_type (path.begin (), path.end ()); +} + +Class decl_NetlistObjectPath ("lay", "NetlistObjectPath", + gsi::method_ext ("root=", &set_root, gsi::arg ("root"), + "@brief Sets the root circuit of the path.\n" + "The root circuit is the circuit from which the path starts.\n" + ) + + gsi::method_ext ("root", &root, + "@brief Gets the root circuit of the path.\n" + ) + + gsi::method_ext ("path=", &set_path, gsi::arg ("path"), + "@brief Sets the path.\n" + "The path is a list of subcircuits leading from the root to the final object. " + "The final (net, device) object is located in the circuit called by the last subcircuit " + "of the subcircuit chain. If the subcircuit list is empty, the final object is located inside " + "the root object." + ) + + gsi::method_ext ("path", &path, + "@brief Gets the path.\n" + ) + + gsi::method_ext ("net=", &set_net, gsi::arg ("net"), + "@brief Sets the net the path points to.\n" + "If the path describes the location of a net, this member will indicate it.\n" + "The other way to describe a final object is \\device=. If neither a device nor " + "net is given, the path describes a circuit and how it is referenced from the root." + ) + + gsi::method_ext ("net", &net, + "@brief Gets the net the path points to.\n" + ) + + gsi::method_ext ("device=", &set_device, gsi::arg ("device"), + "@brief Sets the device the path points to.\n" + "If the path describes the location of a device, this member will indicate it.\n" + "The other way to describe a final object is \\net=. If neither a device nor " + "net is given, the path describes a circuit and how it is referenced from the root." + ) + + gsi::method_ext ("device", &device, + "@brief Gets the device the path points to.\n" + ) + + gsi::method ("is_null", &lay::NetlistObjectPath::is_null, + "@brief Returns a value indicating whether the path is an empty one.\n" + ), + "@brief An object describing the instantiation of an object.\n" + "This class describes the instantiation of a net or a device or a circuit in terms of " + "a root circuit and a subcircuit chain leading to the indicated object.\n" + "\n" + "See \\net= or \\device= for the indicated object, \\path= for the subcircuit chain.\n" + "\n" + "This class has been introduced in version 0.27.\n" +); + +static lay::NetlistObjectPath current_path_first (lay::NetlistBrowserDialog *dialog) +{ + return dialog->current_path ().first (); +} + +static lay::NetlistObjectPath current_path_second (lay::NetlistBrowserDialog *dialog) +{ + return dialog->current_path ().second (); +} + Class decl_NetlistBrowserDialog ("lay", "NetlistBrowserDialog", gsi::event ("on_current_db_changed", &lay::NetlistBrowserDialog::current_db_changed_event, "@brief This event is triggered when the current database is changed.\n" @@ -51,24 +154,32 @@ Class decl_NetlistBrowserDialog ("lay", "NetlistBrows "@brief This event is triggered when the selection changed.\n" "The selection can be obtained with \\selected_nets, \\selected_devices, \\selected_subcircuits and \\selected_circuits." ) + - gsi::event ("on_probe", &lay::NetlistBrowserDialog::probe_event, gsi::arg ("net"), gsi::arg ("subcircuit_path"), + gsi::event ("on_probe", &lay::NetlistBrowserDialog::probe_event, gsi::arg ("first_path"), gsi::arg ("second_path"), "@brief This event is triggered when a net is probed.\n" - "'subcircuit_path' will contain the subcircuit objects leading to the probed net from the netlist databases' top circuit. " + "The first path will indicate the location of the probed net in terms of " + "\\subcircuit_path will contain the subcircuit objects leading to the probed net from the circuit given by \\root_circuit. " "This path may not be complete - it may contain null entries if a cell instance can't be associated with a subcircuit." ) + gsi::method ("db", &lay::NetlistBrowserDialog::db, "@brief Gets the database the browser is connected to.\n" ) + + gsi::method_ext ("current_path_first", ¤t_path_first, + "@brief Gets the path of the current object on the first (layout in case of LVS database) side.\n" + ) + + gsi::method_ext ("current_path_second", ¤t_path_second, + "@brief Gets the path of the current object on the second (schematic in case of LVS database) side.\n" + ) + + // @@@ gsi::method ("selected_nets", &lay::NetlistBrowserDialog::selected_nets, "@brief Gets the nets currently selected in the netlist database browser.\n" ) + - gsi::method ("selected_nets", &lay::NetlistBrowserDialog::selected_devices, + gsi::method ("selected_devices", &lay::NetlistBrowserDialog::selected_devices, "@brief Gets the devices currently selected in the netlist database browser.\n" ) + - gsi::method ("selected_nets", &lay::NetlistBrowserDialog::selected_subcircuits, + gsi::method ("selected_subcircuits", &lay::NetlistBrowserDialog::selected_subcircuits, "@brief Gets the subcircuits currently selected in the netlist database browser.\n" ) + - gsi::method ("selected_nets", &lay::NetlistBrowserDialog::selected_circuits, + gsi::method ("selected_circuits", &lay::NetlistBrowserDialog::selected_circuits, "@brief Gets the circuits currently selected in the netlist database browser.\n" ), "@brief Represents the netlist browser dialog.\n" diff --git a/src/laybasic/laybasic/layNetlistBrowserDialog.cc b/src/laybasic/laybasic/layNetlistBrowserDialog.cc index e225cbf4e..85cc4b4c3 100644 --- a/src/laybasic/laybasic/layNetlistBrowserDialog.cc +++ b/src/laybasic/laybasic/layNetlistBrowserDialog.cc @@ -135,6 +135,17 @@ NetlistBrowserDialog::db () return browser_page->db (); } +const lay::NetlistObjectsPath & +NetlistBrowserDialog::current_path () const +{ + if (browser_page) { + return browser_page->current_path (); + } else { + static lay::NetlistObjectsPath empty; + return empty; + } +} + const std::vector & NetlistBrowserDialog::selected_nets () const { @@ -357,7 +368,9 @@ NetlistBrowserDialog::probe_net (const db::DPoint &p, bool trace_path) browser_page->select_path (path); // emits the probe event - probe_event (net, sc_path); + // NOTE: browser_page->current_path () will hold the paired path with the schematic side being + // expanded. + probe_event (browser_page->current_path ().first (), browser_page->current_path ().second ()); } void diff --git a/src/laybasic/laybasic/layNetlistBrowserDialog.h b/src/laybasic/laybasic/layNetlistBrowserDialog.h index 221408999..2c3d84bcb 100644 --- a/src/laybasic/laybasic/layNetlistBrowserDialog.h +++ b/src/laybasic/laybasic/layNetlistBrowserDialog.h @@ -54,14 +54,21 @@ public: /** * @brief This event is emitted when a shape is probed + * The first path is that of the layout, the second that of the schematic in case of a + * LVS database. */ - tl::event > probe_event; + tl::event probe_event; /** * @brief Gets the current database */ db::LayoutToNetlist *db (); + /** + * @brief Gets the current object's path + */ + const lay::NetlistObjectsPath ¤t_path () const; + /** * @brief Gets the selected nets */ diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.h b/src/laybasic/laybasic/layNetlistBrowserPage.h index 03c695824..88a48acca 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.h +++ b/src/laybasic/laybasic/layNetlistBrowserPage.h @@ -168,6 +168,14 @@ public: */ void update_highlights (); + /** + * @brief Gets the current object's path + */ + const lay::NetlistObjectsPath ¤t_path () const + { + return m_current_path; + } + /** * @brief Gets the selected nets */ From c8a4d25b517d618a22951fd2c64f00599c25437a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 15 Jul 2020 00:35:38 +0200 Subject: [PATCH 29/32] WIP: enabling selection_changed event --- .../laybasic/gsiDeclLayNetlistBrowserDialog.cc | 10 +++++----- src/laybasic/laybasic/layNetlistBrowserPage.cc | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc index 016afa8d8..fc1ce6ba3 100644 --- a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc +++ b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc @@ -123,7 +123,7 @@ Class decl_NetlistObjectPath ("lay", "NetlistObjectPath" gsi::method_ext ("device", &device, "@brief Gets the device the path points to.\n" ) + - gsi::method ("is_null", &lay::NetlistObjectPath::is_null, + gsi::method ("is_null?", &lay::NetlistObjectPath::is_null, "@brief Returns a value indicating whether the path is an empty one.\n" ), "@brief An object describing the instantiation of an object.\n" @@ -152,13 +152,13 @@ Class decl_NetlistBrowserDialog ("lay", "NetlistBrows ) + gsi::event ("on_selection_changed", &lay::NetlistBrowserDialog::selection_changed_event, "@brief This event is triggered when the selection changed.\n" - "The selection can be obtained with \\selected_nets, \\selected_devices, \\selected_subcircuits and \\selected_circuits." + "The selection can be obtained with \\current_path_first, \\current_path_second, \\selected_nets, \\selected_devices, \\selected_subcircuits and \\selected_circuits." ) + gsi::event ("on_probe", &lay::NetlistBrowserDialog::probe_event, gsi::arg ("first_path"), gsi::arg ("second_path"), "@brief This event is triggered when a net is probed.\n" - "The first path will indicate the location of the probed net in terms of " - "\\subcircuit_path will contain the subcircuit objects leading to the probed net from the circuit given by \\root_circuit. " - "This path may not be complete - it may contain null entries if a cell instance can't be associated with a subcircuit." + "The first path will indicate the location of the probed net in terms of two paths: one describing the instantiation of the " + "net in layout space and one in schematic space. Both objects are \\NetlistObjectPath objects which hold the root circuit, the " + "chain of subcircuits leading to the circuit containing the net and the net itself." ) + gsi::method ("db", &lay::NetlistBrowserDialog::db, "@brief Gets the database the browser is connected to.\n" diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index 1bd2019e1..15fabc830 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -473,6 +473,8 @@ NetlistBrowserPage::selection_changed () QModelIndex current = directory_tree->selectionModel ()->currentIndex (); highlight (model->path_from_index (current)); + + selection_changed_event (); } void @@ -896,8 +898,6 @@ NetlistBrowserPage::highlight (const NetlistObjectsPath &path) adjust_view (); update_highlights (); - selection_changed (); - } } From 3dff7549f2389a89c59bb689660e65a866ad88e7 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 16 Jul 2020 01:49:18 +0200 Subject: [PATCH 30/32] Implemented #588: Netlist browser enhancements 1. The netlist browser now got events for selection and probe events 2. The netlist browser was overhauled to support "infinite depth" views 3. Ambiguities are not shown as errors now 4. New classes for support netlist object selections and the netlist browser. Multiple selections for netlist browser. --- .../gsiDeclLayNetlistBrowserDialog.cc | 51 +++++-- .../laybasic/layNetlistBrowserDialog.cc | 41 +---- .../laybasic/layNetlistBrowserDialog.h | 17 +-- .../laybasic/layNetlistBrowserPage.cc | 144 ++++++++++-------- src/laybasic/laybasic/layNetlistBrowserPage.h | 37 +---- 5 files changed, 126 insertions(+), 164 deletions(-) diff --git a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc index fc1ce6ba3..f662339e2 100644 --- a/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc +++ b/src/laybasic/laybasic/gsiDeclLayNetlistBrowserDialog.cc @@ -126,7 +126,7 @@ Class decl_NetlistObjectPath ("lay", "NetlistObjectPath" gsi::method ("is_null?", &lay::NetlistObjectPath::is_null, "@brief Returns a value indicating whether the path is an empty one.\n" ), - "@brief An object describing the instantiation of an object.\n" + "@brief An object describing the instantiation of a netlist object.\n" "This class describes the instantiation of a net or a device or a circuit in terms of " "a root circuit and a subcircuit chain leading to the indicated object.\n" "\n" @@ -135,6 +135,39 @@ Class decl_NetlistObjectPath ("lay", "NetlistObjectPath" "This class has been introduced in version 0.27.\n" ); +static lay::NetlistObjectPath first (const lay::NetlistObjectsPath *pp) +{ + return pp->first (); +} + +static lay::NetlistObjectPath second (const lay::NetlistObjectsPath *pp) +{ + return pp->second (); +} + +Class decl_NetlistObjectsPath ("lay", "NetlistObjectsPath", + gsi::method_ext ("first", &first, + "@brief Gets the first object's path.\n" + "In cases of paired netlists (LVS database), the first path points to the layout netlist object.\n" + "For the single netlist, the first path is the only path supplied." + ) + + gsi::method_ext ("second", &second, + "@brief Gets the second object's path.\n" + "In cases of paired netlists (LVS database), the first path points to the schematic netlist object.\n" + "For the single netlist, the scecond path is always a null path." + ), + "@brief An object describing the instantiation of a single netlist object or a pair of those.\n" + "This class is basically a pair of netlist object paths (see \\NetlistObjectPath). When derived from a single netlist view, " + "only the first path is valid and will point to the selected object (a net, a device or a circuit). The second path is null.\n" + "\n" + "If the path is derived from a paired netlist view (a LVS report view), the first path corresponds to the object in the layout netlist, " + "the second one to the object in the schematic netlist.\n" + "If the selected object isn't a matched one, either the first or second path may be a null or a partial path without a final net or device object " + "or a partial path.\n" + "\n" + "This class has been introduced in version 0.27.\n" +); + static lay::NetlistObjectPath current_path_first (lay::NetlistBrowserDialog *dialog) { return dialog->current_path ().first (); @@ -169,18 +202,12 @@ Class decl_NetlistBrowserDialog ("lay", "NetlistBrows gsi::method_ext ("current_path_second", ¤t_path_second, "@brief Gets the path of the current object on the second (schematic in case of LVS database) side.\n" ) + - // @@@ - gsi::method ("selected_nets", &lay::NetlistBrowserDialog::selected_nets, - "@brief Gets the nets currently selected in the netlist database browser.\n" + gsi::method ("current_path", &lay::NetlistBrowserDialog::current_path, + "@brief Gets the path of the current object as a path pair (combines layout and schematic object paths in case of a LVS database view).\n" ) + - gsi::method ("selected_devices", &lay::NetlistBrowserDialog::selected_devices, - "@brief Gets the devices currently selected in the netlist database browser.\n" - ) + - gsi::method ("selected_subcircuits", &lay::NetlistBrowserDialog::selected_subcircuits, - "@brief Gets the subcircuits currently selected in the netlist database browser.\n" - ) + - gsi::method ("selected_circuits", &lay::NetlistBrowserDialog::selected_circuits, - "@brief Gets the circuits currently selected in the netlist database browser.\n" + gsi::method ("selected_paths", &lay::NetlistBrowserDialog::selected_paths, + "@brief Gets the nets currently selected objects (paths) in the netlist database browser.\n" + "The result is an array of path pairs. See \\NetlistObjectsPath for details about these pairs." ), "@brief Represents the netlist browser dialog.\n" "This dialog is a part of the \\LayoutView class and can be obtained through \\LayoutView#netlist_browser.\n" diff --git a/src/laybasic/laybasic/layNetlistBrowserDialog.cc b/src/laybasic/laybasic/layNetlistBrowserDialog.cc index 85cc4b4c3..b44db19bc 100644 --- a/src/laybasic/laybasic/layNetlistBrowserDialog.cc +++ b/src/laybasic/laybasic/layNetlistBrowserDialog.cc @@ -146,46 +146,13 @@ NetlistBrowserDialog::current_path () const } } -const std::vector & -NetlistBrowserDialog::selected_nets () const +const std::vector & +NetlistBrowserDialog::selected_paths () const { if (browser_page) { - return browser_page->current_nets (); + return browser_page->selected_paths (); } else { - static std::vector empty; - return empty; - } -} - -const std::vector & -NetlistBrowserDialog::selected_devices () const -{ - if (browser_page) { - return browser_page->current_devices (); - } else { - static std::vector empty; - return empty; - } -} - -const std::vector & -NetlistBrowserDialog::selected_subcircuits () const -{ - if (browser_page) { - return browser_page->current_subcircuits (); - } else { - static std::vector empty; - return empty; - } -} - -const std::vector & -NetlistBrowserDialog::selected_circuits () const -{ - if (browser_page) { - return browser_page->current_circuits (); - } else { - static std::vector empty; + static std::vector empty; return empty; } } diff --git a/src/laybasic/laybasic/layNetlistBrowserDialog.h b/src/laybasic/laybasic/layNetlistBrowserDialog.h index 2c3d84bcb..1c350fc78 100644 --- a/src/laybasic/laybasic/layNetlistBrowserDialog.h +++ b/src/laybasic/laybasic/layNetlistBrowserDialog.h @@ -72,22 +72,7 @@ public: /** * @brief Gets the selected nets */ - const std::vector &selected_nets () const; - - /** - * @brief Gets the selected devices - */ - const std::vector &selected_devices () const; - - /** - * @brief Gets the selected subcircuits - */ - const std::vector &selected_subcircuits () const; - - /** - * @brief Gets the selected circuits - */ - const std::vector &selected_circuits () const; + const std::vector &selected_paths () const; /** * @brief An event indicating that the selection has changed diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index 15fabc830..cf055fe0c 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -471,8 +471,18 @@ NetlistBrowserPage::selection_changed () NetlistBrowserModel *model = dynamic_cast (directory_tree->model ()); tl_assert (model != 0); + QModelIndexList selected = directory_tree->selectionModel ()->selectedIndexes (); + + std::vector selected_paths; + selected_paths.reserve (selected.size ()); + for (QModelIndexList::const_iterator i = selected.begin (); i != selected.end (); ++i) { + if (i->column () == 0) { + selected_paths.push_back (model->path_from_index (*i)); + } + } + QModelIndex current = directory_tree->selectionModel ()->currentIndex (); - highlight (model->path_from_index (current)); + highlight (model->path_from_index (current), selected_paths); selection_changed_event (); } @@ -792,11 +802,6 @@ NetlistBrowserPage::set_db (db::LayoutToNetlist *l2ndb) clear_markers (); - m_current_nets.clear (); - m_current_devices.clear (); - m_current_subcircuits.clear (); - m_current_circuits.clear (); - m_cell_context_cache = db::ContextCache (mp_database.get () ? mp_database->internal_layout () : 0); setup_trees (); @@ -888,11 +893,12 @@ NetlistBrowserPage::setup_trees () } void -NetlistBrowserPage::highlight (const NetlistObjectsPath &path) +NetlistBrowserPage::highlight (const NetlistObjectsPath ¤t_path, const std::vector &selected_paths) { - if (path != m_current_path) { + if (current_path != m_current_path && selected_paths != m_selected_paths) { - m_current_path = path; + m_current_path = current_path; + m_selected_paths = selected_paths; clear_markers (); adjust_view (); @@ -961,24 +967,26 @@ NetlistBrowserPage::adjust_view () const db::Layout &original_layout = mp_view->cellview (m_cv_index)->layout (); const db::Circuit *top_circuit = mp_database->netlist ()->circuit_by_name (original_layout.cell_name (mp_view->cellview (m_cv_index).cell_index ())); - const db::Circuit *circuit = m_current_path.root.first; - if (! circuit) { - return; - } - const db::Layout *layout = mp_database->internal_layout (); const db::Cell *cell = (top_circuit && layout->is_valid_cell_index (top_circuit->cell_index ()) ? &layout->cell (top_circuit->cell_index ()) : mp_database->internal_top_cell ()); if (! layout || ! cell) { return; } - db::DCplxTrans trans; + db::DBox bbox; - if (circuit) { + for (std::vector::const_iterator path = m_selected_paths.begin (); path != m_selected_paths.end (); ++path) { + + const db::Circuit *circuit = path->root.first; + if (! circuit) { + continue; + } + + db::DCplxTrans trans; 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) { + for (std::list >::const_iterator p = path->path.begin (); p != path->path.end () && circuit; ++p) { if (p->first) { circuit = p->first->circuit_ref (); trans = trans * p->first->trans (); @@ -987,16 +995,14 @@ NetlistBrowserPage::adjust_view () } } - } - - db::DBox bbox; - - if (circuit) { + if (! circuit) { + continue; + } db::Box ebox; - const db::Device *device = m_current_path.device.first; - const db::Net *net = m_current_path.net.first; + const db::Device *device = path->device.first; + const db::Net *net = path->net.first; if (device) { @@ -1018,7 +1024,7 @@ NetlistBrowserPage::adjust_view () 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 (); + layer_bbox += shapes->bbox ().transformed (shapes.trans ()); ++shapes; } @@ -1030,7 +1036,7 @@ NetlistBrowserPage::adjust_view () ebox += bbox_for_circuit (layout, circuit); } - bbox = trans * db::CplxTrans (layout->dbu ()) * ebox; + bbox += trans * db::CplxTrans (layout->dbu ()) * ebox; } @@ -1253,38 +1259,12 @@ NetlistBrowserPage::update_highlights () const db::Layout &original_layout = mp_view->cellview (m_cv_index)->layout (); const db::Circuit *top_circuit = mp_database->netlist ()->circuit_by_name (original_layout.cell_name (mp_view->cellview (m_cv_index).cell_index ())); - const db::Circuit *circuit = m_current_path.root.first; - if (! circuit) { - return; - } - const db::Layout *layout = mp_database->internal_layout (); const db::Cell *cell = (top_circuit && layout->is_valid_cell_index (top_circuit->cell_index ()) ? &layout->cell (top_circuit->cell_index ()) : mp_database->internal_top_cell ()); if (! layout || ! cell) { return; } - // computes the transformation supplied by the path - - 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; for (lay::LayerPropertiesConstIterator lp = mp_view->begin_layers (); ! lp.at_end (); ++lp) { if (! lp->has_children () && lp->cellview_index () == int (m_cv_index) && lp->layer_index () >= 0 && (unsigned int) lp->layer_index () < original_layout.layers ()) { @@ -1292,22 +1272,55 @@ NetlistBrowserPage::update_highlights () } } - std::vector tv = mp_view->cv_transform_variants (m_cv_index); - - // correct DBU differences between the storage layout and the original layout - for (std::vector::iterator t = tv.begin (); t != tv.end (); ++t) { - *t = *t * trans * db::DCplxTrans (layout->dbu () / original_layout.dbu ()); - } - size_t n_markers = 0; bool not_all_shapes_are_shown = false; - 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); + for (std::vector::const_iterator path = m_selected_paths.begin (); path != m_selected_paths.end (); ++path) { + + const db::Circuit *circuit = path->root.first; + if (! circuit) { + continue; + } + + // computes the transformation supplied by the path + + db::DCplxTrans trans = trans_for (circuit, *layout, *cell, m_cell_context_cache, db::DCplxTrans ()); + + for (std::list >::const_iterator p = path->path.begin (); p != path->path.end () && circuit; ++p) { + if (p->first) { + circuit = p->first->circuit_ref (); + trans = trans * p->first->trans (); + } else { + circuit = 0; + } + } + + if (! circuit) { + continue; + } + + // a map of display properties vs. layer properties + + // correct DBU differences between the storage layout and the original layout + std::vector tv = mp_view->cv_transform_variants (m_cv_index); + for (std::vector::iterator t = tv.begin (); t != tv.end (); ++t) { + *t = *t * trans * db::DCplxTrans (layout->dbu () / original_layout.dbu ()); + } + + if (path->net.first) { + if (produce_highlights_for_net (path->net.first, n_markers, display_by_lp, tv)) { + not_all_shapes_are_shown = true; + } + } else if (path->device.first) { + if (produce_highlights_for_device (path->device.first, n_markers, tv)) { + not_all_shapes_are_shown = true; + } + } else if (circuit) { + if (produce_highlights_for_circuit (circuit, n_markers, tv)) { + not_all_shapes_are_shown = true; + } + } + } if (not_all_shapes_are_shown) { @@ -1318,7 +1331,6 @@ NetlistBrowserPage::update_highlights () } else { info_label->hide (); } - } void diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.h b/src/laybasic/laybasic/layNetlistBrowserPage.h index 88a48acca..11fb8418d 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.h +++ b/src/laybasic/laybasic/layNetlistBrowserPage.h @@ -179,33 +179,9 @@ public: /** * @brief Gets the selected nets */ - const std::vector ¤t_nets () const + const std::vector &selected_paths () const { - return m_current_nets; - } - - /** - * @brief Gets the selected devices - */ - const std::vector ¤t_devices () const - { - return m_current_devices; - } - - /** - * @brief Gets the selected subcircuits - */ - const std::vector ¤t_subcircuits () const - { - return m_current_subcircuits; - } - - /** - * @brief Gets the selected circuits - */ - const std::vector ¤t_circuits () const - { - return m_current_circuits; + return m_selected_paths; } /** @@ -258,13 +234,8 @@ private: std::vector mp_markers; bool m_enable_updates; bool m_update_needed; - // @@@ TODO: make multiple ... lay::NetlistObjectsPath m_current_path; - // @@@ TODO: remove - std::vector m_current_nets; - std::vector m_current_devices; - std::vector m_current_subcircuits; - std::vector m_current_circuits; + std::vector m_selected_paths; lay::NetInfoDialog *mp_info_dialog; tl::DeferredMethod dm_update_highlights; tl::DeferredMethod dm_rerun_macro; @@ -275,7 +246,7 @@ private: void navigate_to (const QModelIndex &index, bool forward = true); void adjust_view (); void clear_markers (); - void highlight (const lay::NetlistObjectsPath &path); + void highlight (const NetlistObjectsPath ¤t_path, const std::vector &selected_paths); std::vector selected_nets (); std::vector selected_devices (); std::vector selected_subcircuits (); From 4d4c7aee785a4168aad7ce7ef183f5da4aca322a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 17 Jul 2020 23:59:37 +0200 Subject: [PATCH 31/32] Fixed a unit test. --- src/db/unit_tests/dbNetlistCompareTests.cc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index b98d25af7..60eec5eb9 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -2167,17 +2167,14 @@ TEST(14_Subcircuit2NandMismatchNoSwap) " pin $4:$4 [Match]\n" " net IN1:INT [Mismatch]\n" " pin $0:(null)\n" - " subcircuit_pin (null):$2[$2]\n" - " subcircuit_pin $1[$0]:(null)\n" + " subcircuit_pin $1[$0]:$2[$2]\n" " subcircuit_pin $2[$0]:$1[$0]\n" " net IN2:IN2 [Mismatch]\n" " pin $1:$1\n" - " subcircuit_pin (null):$2[$0]\n" - " subcircuit_pin $1[$1]:(null)\n" + " subcircuit_pin $1[$1]:$2[$0]\n" " net INT:IN1 [Mismatch]\n" " pin (null):$0\n" - " subcircuit_pin (null):$2[$1]\n" - " subcircuit_pin $1[$2]:(null)\n" + " subcircuit_pin $1[$2]:$2[$1]\n" " subcircuit_pin $2[$1]:$1[$1]\n" " net OUT:OUT [Match]\n" " pin $2:$2\n" From 1d74cf19dc86f72ae7fd80dba79f9332c4f0024e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 18 Jul 2020 00:02:45 +0200 Subject: [PATCH 32/32] Added missing file --- .../algo/device_extract_l1_with_inv_nodes.gds | Bin 0 -> 2698 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 testdata/algo/device_extract_l1_with_inv_nodes.gds diff --git a/testdata/algo/device_extract_l1_with_inv_nodes.gds b/testdata/algo/device_extract_l1_with_inv_nodes.gds new file mode 100644 index 0000000000000000000000000000000000000000..db58f6700a5c0963f740c3671ecd2ca3a6b48dfd GIT binary patch literal 2698 zcma);K}Zx~6vyAp&VDnyu4c9bhD1q0fmoCoWr^BWiecey5+dlaOAsUxQ6ZFINf6Y@ zI!KTmyaj=vr-%qo9fKk~bPX0fx#Uj&H{U#GW^u-Z^|!q5{pY>!d+&R*q{uXHP>W&O zze!O8<;kG4;qT;_>dHVLQ9hOK?tOZC@XP!1nZnYs`PZW*YDvfIvPzYPdxwfdmP4fK zO)^O}m_*dpm~!3CyRKV3%p@{?5Sh<}VrP=IJJ4HUebvPJDn6jQ0R9Rn_UdYq9+`}? z9&tNaA5iQx8mEVED>SQ`?gCil_?lvmkIy=euW59$4j-RluZge1``=ta{3kfS73dxy z_93CznUVZMdc^+et%Iz?`4@y@5A+#bzmy+e9poxHyHfaHp?o8gT=(x9lPGmSN3|)j zKOCh7hDJ`1l_knHNw4I%H>$V22YI#Mel=UxF(RvKpD{&*CtxQpVxCarBhT@7C?^!! zp>dP@)!P-(S2W`Up6t^`V`H}@%uL3eH%_Mw`x;{sWhPO#S3dZX(l z6nm;8qL+H<`?iiAQHZ;a((%3dBNRI`PLC7a`K(W(cvOcq@_1Sk?FBE%bFN zrS-W}S}zoPU6GbeN;21R>TW4L%g=8fzzz6UN50Q{Px;m4&psI zJTP?mDm*dGoF+XLy(xw)`A_CxWG#Cwel0&AzqY>|zjm}Ie(hv*qDFE#zZS3SKOVm} zJQcq-_AOY$nC0IOGM&A7Ryz+WpY=Ro{?9zv=!ahq?gMBe*7&)AVpl!-?EUzmc>@0< ztk-1y#FExC#a^S2+^3C~@S8<^(4NM9d>&BjYBmx-q(|I4tk<-s5&stJHN`G^zn_tR x(5d5P_&da%TD;)**mizg1>N_T`gAsNUU0