Providing a way to generate netlist browser paths

You can generate paths from net, device, circuit or subcircuit
objects. To generate a path for an object from the first netlist
of a pair (layout netlist in LVS case), use

  NetlistObjectsPath#from_first

e.g.

  path = RBA::NetlistObjectsPath::from_first(net)

For an object from the second netlist (schematic in the LVS case)
use "from_second".
This commit is contained in:
Matthias Koefferlein 2026-03-23 20:36:37 +01:00
parent c211925d2a
commit 1588e74873
2 changed files with 172 additions and 7 deletions

View File

@ -136,6 +136,83 @@ static lay::NetlistObjectPath second (const lay::NetlistObjectsPath *pp)
return pp->second ();
}
namespace {
struct First
{
lay::NetlistObjectsPath operator() (const lay::NetlistObjectPath &p)
{
return lay::NetlistObjectsPath::from_first (p);
}
};
struct Second
{
lay::NetlistObjectsPath operator() (const lay::NetlistObjectPath &p)
{
return lay::NetlistObjectsPath::from_second (p);
}
};
}
template <class Which>
static lay::NetlistObjectsPath from (const lay::NetlistObjectPath &p)
{
return Which () (p);
}
template <class Which>
static lay::NetlistObjectsPath from_net (const db::Net *net)
{
if (! net) {
return lay::NetlistObjectsPath ();
}
lay::NetlistObjectPath p;
p.root = net->circuit ();
p.net = net;
return Which () (p);
}
template <class Which>
static lay::NetlistObjectsPath from_device (const db::Device *device)
{
if (! device) {
return lay::NetlistObjectsPath ();
}
lay::NetlistObjectPath p;
p.root = device->circuit ();
p.device = device;
return Which () (p);
}
template <class Which>
static lay::NetlistObjectsPath from_circuit (const db::Circuit *circuit)
{
if (! circuit) {
return lay::NetlistObjectsPath ();
}
lay::NetlistObjectPath p;
p.root = circuit;
return Which () (p);
}
template <class Which>
static lay::NetlistObjectsPath from_subcircuit (const db::SubCircuit *subcircuit)
{
if (! subcircuit) {
return lay::NetlistObjectsPath ();
}
lay::NetlistObjectPath p;
p.root = subcircuit->circuit ();
p.path.push_back (subcircuit);
return Which () (p);
}
Class<lay::NetlistObjectsPath> decl_NetlistObjectsPath ("lay", "NetlistObjectsPath",
gsi::method_ext ("first", &first,
"@brief Gets the first object's path.\n"
@ -146,6 +223,67 @@ Class<lay::NetlistObjectsPath> decl_NetlistObjectsPath ("lay", "NetlistObjectsPa
"@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 second path is always a null path."
) +
gsi::method ("from_first", &from<First>, gsi::arg ("p"),
"@brief Creates a path from given first coordinates.\n"
"Use this constructor to create a paired path from a first set of coordinates (net, circuit, device).\n"
"For single-sided databases (i.e. extracted netlist or schematic only), use the first coordinates. "
"For two-sided database (i.e. LVS cross references), use the first coordinates when you refer to "
"layout netlist objects.\n"
"\n"
"In this version, the minimum requirement for the path is to have a root.\n"
"\n"
"This constructor has been added in version 0.30.8."
) +
gsi::method ("from_first", &from_net<First>, gsi::arg ("net"),
"@brief Creates a path from a given net in the first netlist space.\n"
"\n"
"This constructor has been added in version 0.30.8."
) +
gsi::method ("from_first", &from_device<First>, gsi::arg ("device"),
"@brief Creates a path from a given device in the first netlist space.\n"
"\n"
"This constructor has been added in version 0.30.8."
) +
gsi::method ("from_first", &from_circuit<First>, gsi::arg ("circuit"),
"@brief Creates a path from a given circuit in the first netlist space.\n"
"\n"
"This constructor has been added in version 0.30.8."
) +
gsi::method ("from_first", &from_subcircuit<First>, gsi::arg ("subcircuit"),
"@brief Creates a path from a given subcircuit in the first netlist space.\n"
"\n"
"This constructor has been added in version 0.30.8."
) +
gsi::method ("from_second", &from<Second>, gsi::arg ("p"),
"@brief Creates a path from given second coordinates.\n"
"Use this constructor to create a paired path from a second set of coordinates (net, circuit, device).\n"
"For two-sided database (i.e. LVS cross references), use the second coordinates when you refer to "
"schematic netlist objects.\n"
"\n"
"In this version, the minimum requirement for the path is to have a root.\n"
"\n"
"This constructor has been added in version 0.30.8."
) +
gsi::method ("from_second", &from_net<Second>, gsi::arg ("net"),
"@brief Creates a path from a given net in the second netlist space.\n"
"\n"
"This constructor has been added in version 0.30.8."
) +
gsi::method ("from_second", &from_device<Second>, gsi::arg ("device"),
"@brief Creates a path from a given device in the second netlist space.\n"
"\n"
"This constructor has been added in version 0.30.8."
) +
gsi::method ("from_second", &from_circuit<Second>, gsi::arg ("circuit"),
"@brief Creates a path from a given circuit in the second netlist space.\n"
"\n"
"This constructor has been added in version 0.30.8."
) +
gsi::method ("from_second", &from_subcircuit<Second>, gsi::arg ("subcircuit"),
"@brief Creates a path from a given subcircuit in the second netlist space.\n"
"\n"
"This constructor has been added in version 0.30.8."
),
"@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, "
@ -156,7 +294,16 @@ Class<lay::NetlistObjectsPath> decl_NetlistObjectsPath ("lay", "NetlistObjectsPa
"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"
"To create a paired path from an existing object (net, device, circuit, subcircuit), use \\from_first and \\from_second.\n"
"Use \\from_first, if the object belongs to the first netlist of the database ('netlist', layout netlist in the LVS context).\n"
"Use \\from_second, if the object belongs to the second netlist of the database ('reference', schematic netlist in the LVS context).\n"
"\n"
"It is also possible to create a paired path from a full path object (including root, a subcircuit path and a target object), either "
"for the first or second side. Use \\from_first and \\from_second with a \\NetlistObjectPath argument in that case.\n"
"A minimum requirement in that case is to set the root (the origin of the path). If no subcircuit path is "
"given (see \\NetlistObjectPath#path), a suitable path leading from the target object (net or device) to the root will be constructed.\n"
"\n"
"This class has been introduced in version 0.27 and has been extended in version 0.30.8.\n"
);
static lay::NetlistObjectPath current_path_first (lay::NetlistBrowserDialog *dialog)
@ -226,6 +373,8 @@ Class<lay::NetlistBrowserDialog> decl_NetlistBrowserDialog ("lay", "NetlistBrows
"Changing the selection will update the highlights and navigate to the location depending on the "
"settings. An \\on_selection_changed signal is not emitted.\n"
"\n"
"To get a suitable path, see the \\NetlistObjectsPath#from_first and \\NetlistObjectsPath#from_second generators.\n"
"\n"
"This setter has been introduced in version 0.30.8.\n"
) +
gsi::method ("selected_paths", &lay::NetlistBrowserDialog::selected_paths,

View File

@ -514,17 +514,33 @@ NetlistBrowserPage::select_path (const lay::NetlistObjectsPath &path)
model = dynamic_cast<NetlistBrowserModel *> (nl_directory_tree->model ());
if (model) {
nl_directory_tree->setCurrentIndex (model->index_from_path (path));
if (lvsdb && lvsdb->cross_ref () && ! path.root.first) {
lay::NetlistObjectsPath nl_path = lay::NetlistObjectsPath::from_first (path.second ());
// Note: translation helps generating a layout-netlist index to
// naviate to the layout netlist in case of schematic probing for example (only
// works if all path components can be translated)
if (lay::NetlistObjectsPath::translate (nl_path, *lvsdb->cross_ref ())) {
nl_directory_tree->setCurrentIndex (model->index_from_path (nl_path));
}
} else {
nl_directory_tree->setCurrentIndex (model->index_from_path (path));
}
}
model = dynamic_cast<NetlistBrowserModel *> (sch_directory_tree->model ());
if (model && lvsdb && lvsdb->cross_ref ()) {
lay::NetlistObjectsPath sch_path = path;
// Note: translation helps generating a schematic-netlist index to
// naviate to the schematic netlist in case of probing for example (only
// works if all path components can be translated)
if (lay::NetlistObjectsPath::translate (sch_path, *lvsdb->cross_ref ())) {
if (! path.root.first) {
// No first path given: use second one for schematic directly.
lay::NetlistObjectsPath sch_path = lay::NetlistObjectsPath::from_first (path.second ());
sch_directory_tree->setCurrentIndex (model->index_from_path (sch_path));
} else {
lay::NetlistObjectsPath sch_path = path;
// Note: translation helps generating a schematic-netlist index to
// naviate to the schematic netlist in case of probing for example (only
// works if all path components can be translated)
if (lay::NetlistObjectsPath::translate (sch_path, *lvsdb->cross_ref ())) {
sch_directory_tree->setCurrentIndex (model->index_from_path (sch_path));
}
}
}