From be5f03b1f45723fe94c03ba36c94fafeabd99c61 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 14 Jul 2020 23:06:26 +0200 Subject: [PATCH] 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 */