mirror of https://github.com/KLayout/klayout.git
Netlist browser: Paths for probing, cell contexts for highlighting, probe_net with initial circuit (not just top one)
This commit is contained in:
parent
a10d56e6b6
commit
be5f03b1f4
|
|
@ -1041,9 +1041,9 @@ LayoutToNetlist::build_nets (const std::vector<const db::Net *> *nets, const db:
|
|||
}
|
||||
}
|
||||
|
||||
db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point, std::vector<db::SubCircuit *> *sc_path_out)
|
||||
db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point, std::vector<db::SubCircuit *> *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<db::NetShape> &test_cluster, std::vector<db::InstElement> &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<db::SubCircuit *> *sc_path_out)
|
||||
db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Point &point, std::vector<db::SubCircuit *> *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<db::InstElement> 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<db::cell_index_type> 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<db::InstElement>::const_iterator i = inst_path.begin (); i != inst_path.end (); ++i) {
|
||||
cell_indexes.push_back (i->inst_ptr.cell_index ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SubCircuit *> *sc_path_out = 0);
|
||||
db::Net *probe_net (const db::Region &of_region, const db::DPoint &point, std::vector<SubCircuit *> *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<SubCircuit *> *sc_path_out = 0);
|
||||
db::Net *probe_net (const db::Region &of_region, const db::Point &point, std::vector<SubCircuit *> *sc_path_out = 0, Circuit *initial_circuit = 0);
|
||||
|
||||
/**
|
||||
* @brief Runs an antenna check on the extracted clusters
|
||||
|
|
|
|||
|
|
@ -543,7 +543,7 @@ Class<db::LayoutToNetlist> 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::SubCircuit *> *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector<db::SubCircuit *> *) 0, "nil"),
|
||||
gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &, std::vector<db::SubCircuit *> *, db::Circuit *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector<db::SubCircuit *> *) 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<db::LayoutToNetlist> 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<db::LayoutToNetlist> 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::SubCircuit *> *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector<db::SubCircuit *> *) 0, "nil"),
|
||||
gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::Point &, std::vector<db::SubCircuit *> *, db::Circuit *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector<db::SubCircuit *> *) 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"
|
||||
|
|
|
|||
|
|
@ -307,41 +307,54 @@ NetlistBrowserDialog::probe_net (const db::DPoint &p, bool trace_path)
|
|||
}
|
||||
|
||||
db::Net *net = 0;
|
||||
db::Circuit *root = 0;
|
||||
std::vector<db::SubCircuit *> 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<db::Region *> 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<db::Region *> 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<db::Region *>::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<db::Region *>::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);
|
||||
|
|
|
|||
|
|
@ -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<NetlistBrowserModel *> (directory_tree->model ());
|
||||
tl_assert (model != 0);
|
||||
directory_tree->setCurrentIndex (model->index_from_path (path));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<const db::Net *>
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue