mirror of https://github.com/KLayout/klayout.git
Merge pull request #2309 from KLayout/feature/issue-2306
Implemented solution for #2306
This commit is contained in:
commit
dd1a3ee7d1
|
|
@ -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)
|
||||
|
|
@ -169,6 +316,20 @@ static lay::NetlistObjectPath current_path_second (lay::NetlistBrowserDialog *di
|
|||
return dialog->current_path ().second ();
|
||||
}
|
||||
|
||||
static void set_current_path (lay::NetlistBrowserDialog *dialog, const lay::NetlistObjectsPath *path)
|
||||
{
|
||||
if (! path) {
|
||||
dialog->set_current_path (lay::NetlistObjectsPath ());
|
||||
} else {
|
||||
dialog->set_current_path (*path);
|
||||
}
|
||||
}
|
||||
|
||||
static lay::LayoutViewBase *get_view (lay::NetlistBrowserDialog *dialog)
|
||||
{
|
||||
return dialog->view ();
|
||||
}
|
||||
|
||||
Class<lay::NetlistBrowserDialog> 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"
|
||||
|
|
@ -187,6 +348,16 @@ Class<lay::NetlistBrowserDialog> decl_NetlistBrowserDialog ("lay", "NetlistBrows
|
|||
gsi::method ("db", &lay::NetlistBrowserDialog::db,
|
||||
"@brief Gets the database the browser is connected to.\n"
|
||||
) +
|
||||
gsi::method ("db_index", &lay::NetlistBrowserDialog::l2n_index,
|
||||
"@brief Gets the database index inside the view the browser is connected to.\n"
|
||||
"\n"
|
||||
"This attribute has been introduced in version 0.30.8.\n"
|
||||
) +
|
||||
gsi::method_ext ("view", &get_view,
|
||||
"@brief Gets the view the browser is connected to.\n"
|
||||
"\n"
|
||||
"This attribute has been introduced in version 0.30.8.\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"
|
||||
) +
|
||||
|
|
@ -196,6 +367,16 @@ Class<lay::NetlistBrowserDialog> decl_NetlistBrowserDialog ("lay", "NetlistBrows
|
|||
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_ext ("current_path=", &set_current_path,
|
||||
"@brief Sets the current path.\n"
|
||||
"This is the setter corresponding to the 'current_path' getter. Passing nil clears the selection.\n"
|
||||
"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,
|
||||
"@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."
|
||||
|
|
|
|||
|
|
@ -306,28 +306,28 @@ SingleIndexedNetlistModel::parent_of (const subcircuit_pair &subcircuits) const
|
|||
return std::make_pair (subcircuits.first ? subcircuits.first->circuit () : 0, (const db::Circuit *) 0);
|
||||
}
|
||||
|
||||
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::top_circuit_from_index(size_t index) const
|
||||
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::top_circuit_from_index (size_t index) const
|
||||
{
|
||||
db::Netlist::const_top_down_circuit_iterator none;
|
||||
return std::make_pair (attr_by_object_and_index (std::make_pair ((const db::Circuit *) 0, (const db::Circuit *) 0), index, mp_netlist->begin_top_down (), mp_netlist->begin_top_down () + mp_netlist->top_circuit_count (), none, none, m_child_circuit_by_circuit_and_index, sort_by_name<db::Circuit> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
}
|
||||
|
||||
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::child_circuit_from_index(const circuit_pair &circuits, size_t index) const
|
||||
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::child_circuit_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_child_circuit_iterator none;
|
||||
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_children (), circuits.first->end_children (), none, none, m_child_circuit_by_circuit_and_index, sort_by_name<db::Circuit> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
}
|
||||
|
||||
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::circuit_from_index(size_t index) const
|
||||
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::circuit_from_index (size_t index) const
|
||||
{
|
||||
db::Netlist::const_circuit_iterator none;
|
||||
return std::make_pair (attr_by_object_and_index (std::make_pair (mp_netlist, (const db::Netlist *) 0), index, mp_netlist->begin_circuits (), mp_netlist->end_circuits (), none, none, m_circuit_by_index, sort_by_name<db::Circuit> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
}
|
||||
|
||||
std::pair<IndexedNetlistModel::net_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::net_from_index(const circuit_pair &circuits, size_t index) const
|
||||
std::pair<IndexedNetlistModel::net_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::net_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_net_iterator none;
|
||||
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_nets (), circuits.first->end_nets (), none, none, m_net_by_circuit_and_index, sort_by_expanded_name<db::Net> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
return std::make_pair (attr_by_object_and_index (std::make_pair (circuits.first, (const db::Circuit *) 0), index, circuits.first->begin_nets (), circuits.first->end_nets (), none, none, m_net_by_circuit_and_index, sort_by_expanded_name<db::Net> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
}
|
||||
|
||||
const db::Net *
|
||||
|
|
@ -346,12 +346,15 @@ IndexedNetlistModel::net_subcircuit_pin_pair
|
|||
SingleIndexedNetlistModel::net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
db::Net::const_subcircuit_pin_iterator none;
|
||||
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<db::NetSubcircuitPinRef> ());
|
||||
return attr_by_object_and_index (std::make_pair (nets.first, (const db::Net *) 0), index, nets.first->begin_subcircuit_pins (), nets.first->end_subcircuit_pins (), none, none, m_subcircuit_pinref_by_net_and_index, sort_by_pin_name<db::NetSubcircuitPinRef> ());
|
||||
}
|
||||
|
||||
IndexedNetlistModel::net_subcircuit_pin_pair
|
||||
SingleIndexedNetlistModel::subcircuit_pinref_from_index (const subcircuit_pair &subcircuits, size_t index) const
|
||||
SingleIndexedNetlistModel::subcircuit_pinref_from_index (const subcircuit_pair &subcircuits_in, size_t index) const
|
||||
{
|
||||
subcircuit_pair subcircuits = subcircuits_in;
|
||||
subcircuits.second = 0;
|
||||
|
||||
if (! subcircuits.first) {
|
||||
return IndexedNetlistModel::net_subcircuit_pin_pair ((const db::NetSubcircuitPinRef *) 0, (const db::NetSubcircuitPinRef *) 0);
|
||||
}
|
||||
|
|
@ -381,62 +384,68 @@ IndexedNetlistModel::net_terminal_pair
|
|||
SingleIndexedNetlistModel::net_terminalref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
db::Net::const_terminal_iterator none;
|
||||
return attr_by_object_and_index (nets, index, nets.first->begin_terminals (), nets.first->end_terminals (), none, none, m_terminalref_by_net_and_index, sort_by_terminal_id<db::NetTerminalRef> ());
|
||||
return attr_by_object_and_index (std::make_pair (nets.first, (const db::Net *) 0), index, nets.first->begin_terminals (), nets.first->end_terminals (), none, none, m_terminalref_by_net_and_index, sort_by_terminal_id<db::NetTerminalRef> ());
|
||||
}
|
||||
|
||||
IndexedNetlistModel::net_pin_pair
|
||||
SingleIndexedNetlistModel::net_pinref_from_index (const net_pair &nets, size_t index) const
|
||||
{
|
||||
db::Net::const_pin_iterator none;
|
||||
return attr_by_object_and_index (nets, index, nets.first->begin_pins (), nets.first->end_pins (), none, none, m_pinref_by_net_and_index, sort_by_pin_name<db::NetPinRef> ());
|
||||
return attr_by_object_and_index (std::make_pair (nets.first, (const db::Net *) 0), index, nets.first->begin_pins (), nets.first->end_pins (), none, none, m_pinref_by_net_and_index, sort_by_pin_name<db::NetPinRef> ());
|
||||
}
|
||||
|
||||
std::pair<IndexedNetlistModel::device_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::device_from_index(const circuit_pair &circuits, size_t index) const
|
||||
std::pair<IndexedNetlistModel::device_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::device_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_device_iterator none;
|
||||
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_devices (), circuits.first->end_devices (), none, none, m_device_by_circuit_and_index, sort_by_expanded_name<db::Device> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
return std::make_pair (attr_by_object_and_index (std::make_pair (circuits.first, (const db::Circuit *) 0), index, circuits.first->begin_devices (), circuits.first->end_devices (), none, none, m_device_by_circuit_and_index, sort_by_expanded_name<db::Device> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
}
|
||||
|
||||
std::pair<IndexedNetlistModel::pin_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::pin_from_index(const circuit_pair &circuits, size_t index) const
|
||||
std::pair<IndexedNetlistModel::pin_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::pin_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_pin_iterator none;
|
||||
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_pins (), circuits.first->end_pins (), none, none, m_pin_by_circuit_and_index, Unsorted ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
return std::make_pair (attr_by_object_and_index (std::make_pair (circuits.first, (const db::Circuit *) 0), index, circuits.first->begin_pins (), circuits.first->end_pins (), none, none, m_pin_by_circuit_and_index, Unsorted ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
}
|
||||
|
||||
std::pair<IndexedNetlistModel::subcircuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::subcircuit_from_index(const circuit_pair &circuits, size_t index) const
|
||||
std::pair<IndexedNetlistModel::subcircuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::subcircuit_from_index (const circuit_pair &circuits, size_t index) const
|
||||
{
|
||||
db::Circuit::const_subcircuit_iterator none;
|
||||
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_subcircuits (), circuits.first->end_subcircuits (), none, none, m_subcircuit_by_circuit_and_index, sort_by_expanded_name<db::SubCircuit> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
return std::make_pair (attr_by_object_and_index (std::make_pair (circuits.first, (const db::Circuit *) 0), index, circuits.first->begin_subcircuits (), circuits.first->end_subcircuits (), none, none, m_subcircuit_by_circuit_and_index, sort_by_expanded_name<db::SubCircuit> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::circuit_index (const circuit_pair &circuits) const
|
||||
{
|
||||
db::Netlist::const_circuit_iterator none;
|
||||
return index_from_attr (circuits, mp_netlist->begin_circuits (), mp_netlist->end_circuits (), none, none, m_circuit_index_by_object, sort_by_name<db::Circuit> ());
|
||||
return index_from_attr (std::make_pair (circuits.first, (const db::Circuit *) 0), mp_netlist->begin_circuits (), mp_netlist->end_circuits (), none, none, m_circuit_index_by_object, sort_by_name<db::Circuit> ());
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::net_index (const net_pair &nets) const
|
||||
SingleIndexedNetlistModel::net_index (const net_pair &nets_in) const
|
||||
{
|
||||
db::Circuit::const_net_iterator none;
|
||||
|
||||
net_pair nets = nets_in;
|
||||
nets.second = 0;
|
||||
|
||||
circuit_pair circuits = parent_of (nets);
|
||||
return index_from_attr (nets,
|
||||
circuits.first ? circuits.first->begin_nets () : none, circuits.first ? circuits.first->end_nets () : none,
|
||||
circuits.second ? circuits.second->begin_nets () : none, circuits.second ? circuits.second->end_nets () : none,
|
||||
none, none,
|
||||
m_net_index_by_object, sort_by_expanded_name<db::Net> ());
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::device_index (const device_pair &devices) const
|
||||
SingleIndexedNetlistModel::device_index (const device_pair &devices_in) const
|
||||
{
|
||||
db::Circuit::const_device_iterator none;
|
||||
|
||||
device_pair devices = devices_in;
|
||||
devices.second = 0;
|
||||
|
||||
circuit_pair circuits = parent_of (devices);
|
||||
return index_from_attr (devices,
|
||||
circuits.first ? circuits.first->begin_devices () : none, circuits.first ? circuits.first->end_devices () : none,
|
||||
circuits.second ? circuits.second->begin_devices () : none, circuits.second ? circuits.second->end_devices () : none,
|
||||
none, none,
|
||||
m_device_index_by_object, sort_by_expanded_name<db::Device> ());
|
||||
}
|
||||
|
||||
|
|
@ -445,21 +454,24 @@ SingleIndexedNetlistModel::pin_index (const pin_pair &pins, const circuit_pair &
|
|||
{
|
||||
db::Circuit::const_pin_iterator none;
|
||||
|
||||
return index_from_attr (pins,
|
||||
return index_from_attr (std::make_pair (pins.first, (const db::Pin *) 0),
|
||||
circuits.first ? circuits.first->begin_pins () : none, circuits.first ? circuits.first->end_pins () : none,
|
||||
circuits.second ? circuits.second->begin_pins () : none, circuits.second ? circuits.second->end_pins () : none,
|
||||
none, none,
|
||||
m_pin_index_by_object, sort_by_expanded_name<db::Pin> ());
|
||||
}
|
||||
|
||||
size_t
|
||||
SingleIndexedNetlistModel::subcircuit_index (const subcircuit_pair &subcircuits) const
|
||||
SingleIndexedNetlistModel::subcircuit_index (const subcircuit_pair &subcircuits_in) const
|
||||
{
|
||||
db::Circuit::const_subcircuit_iterator none;
|
||||
|
||||
subcircuit_pair subcircuits = subcircuits_in;
|
||||
subcircuits.second = 0;
|
||||
|
||||
circuit_pair circuits = parent_of (subcircuits);
|
||||
return index_from_attr (subcircuits,
|
||||
circuits.first ? circuits.first->begin_subcircuits () : none, circuits.first ? circuits.first->end_subcircuits () : none,
|
||||
circuits.second ? circuits.second->begin_subcircuits () : none, circuits.second ? circuits.second->end_subcircuits () : none,
|
||||
none, none,
|
||||
m_subcircuit_index_by_object, sort_by_expanded_name<db::SubCircuit> ());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,6 +141,12 @@ NetlistBrowserDialog::db ()
|
|||
return mp_ui->browser_page->db ();
|
||||
}
|
||||
|
||||
int
|
||||
NetlistBrowserDialog::l2n_index ()
|
||||
{
|
||||
return m_l2n_index;
|
||||
}
|
||||
|
||||
const lay::NetlistObjectsPath &
|
||||
NetlistBrowserDialog::current_path () const
|
||||
{
|
||||
|
|
@ -152,6 +158,14 @@ NetlistBrowserDialog::current_path () const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetlistBrowserDialog::set_current_path (const lay::NetlistObjectsPath &path)
|
||||
{
|
||||
if (mp_ui->browser_page) {
|
||||
mp_ui->browser_page->select_path (path);
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<lay::NetlistObjectsPath> &
|
||||
NetlistBrowserDialog::selected_paths () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -77,11 +77,26 @@ public:
|
|||
*/
|
||||
db::LayoutToNetlist *db ();
|
||||
|
||||
/**
|
||||
* @brief Gets the index of the currently selected database in the view
|
||||
*/
|
||||
int l2n_index ();
|
||||
|
||||
/**
|
||||
* @brief Gets the current object's path
|
||||
*/
|
||||
const lay::NetlistObjectsPath ¤t_path () const;
|
||||
|
||||
/**
|
||||
* @brief Sets the current object's path
|
||||
*
|
||||
* This will make the given netlist object the current one and change the
|
||||
* selection to this one.
|
||||
*
|
||||
* Passing a null path will clear the selection.
|
||||
*/
|
||||
void set_current_path (const lay::NetlistObjectsPath &path);
|
||||
|
||||
/**
|
||||
* @brief Gets the selected nets
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3025,9 +3025,9 @@ NetlistBrowserModel::index_from_subcircuit (const std::pair<const db::SubCircuit
|
|||
}
|
||||
|
||||
QModelIndex
|
||||
NetlistBrowserModel::index_from_circuit (const db::Circuit *net) const
|
||||
NetlistBrowserModel::index_from_circuit (const db::Circuit *circuit) const
|
||||
{
|
||||
return index_from_circuit (std::make_pair (net, mp_indexer->second_circuit_for (net)));
|
||||
return index_from_circuit (std::make_pair (circuit, mp_indexer->second_circuit_for (circuit)));
|
||||
}
|
||||
|
||||
std::pair<const db::Circuit *, const db::Circuit *>
|
||||
|
|
|
|||
|
|
@ -502,9 +502,9 @@ NetlistBrowserPage::select_path (const lay::NetlistObjectsPath &path)
|
|||
{
|
||||
if (path.is_null ()) {
|
||||
|
||||
nl_directory_tree->clearSelection ();
|
||||
sch_directory_tree->clearSelection ();
|
||||
xref_directory_tree->clearSelection ();
|
||||
nl_directory_tree->setCurrentIndex (QModelIndex ());
|
||||
sch_directory_tree->setCurrentIndex (QModelIndex ());
|
||||
xref_directory_tree->setCurrentIndex (QModelIndex ());
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1315,7 +1331,7 @@ NetlistBrowserPage::clear_highlights ()
|
|||
void
|
||||
NetlistBrowserPage::highlight (const NetlistObjectsPath ¤t_path, const std::vector<NetlistObjectsPath> &selected_paths)
|
||||
{
|
||||
if (current_path != m_current_path && selected_paths != m_selected_paths) {
|
||||
if (current_path != m_current_path || selected_paths != m_selected_paths) {
|
||||
|
||||
m_current_path = current_path;
|
||||
m_selected_paths = selected_paths;
|
||||
|
|
|
|||
|
|
@ -169,6 +169,11 @@ public:
|
|||
*/
|
||||
void update_highlights ();
|
||||
|
||||
/**
|
||||
* @brief Adjusts the view depending on the current settings
|
||||
*/
|
||||
void adjust_view ();
|
||||
|
||||
/**
|
||||
* @brief Gets the current object's path
|
||||
*/
|
||||
|
|
@ -255,7 +260,6 @@ private:
|
|||
void setup_trees ();
|
||||
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 NetlistObjectsPath ¤t_path, const std::vector<NetlistObjectsPath> &selected_paths);
|
||||
void clear_highlights ();
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ RUBYTEST (extNetTracer, "extNetTracer.rb")
|
|||
RUBYTEST (imgObject, "imgObject.rb")
|
||||
RUBYTEST (layLayers, "layLayers.rb")
|
||||
RUBYTEST (layLayoutView, "layLayoutView.rb")
|
||||
RUBYTEST (layNetlistBrowser, "layNetlistBrowser.rb")
|
||||
RUBYTEST (layMainWindow, "layMainWindow.rb")
|
||||
RUBYTEST (layMarkers, "layMarkers.rb")
|
||||
RUBYTEST (layMacro, "layMacro.rb")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
# encoding: UTF-8
|
||||
|
||||
# KLayout Layout Viewer
|
||||
# Copyright (C) 2006-2026 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
|
||||
|
||||
if !$:.member?(File::dirname($0))
|
||||
$:.push(File::dirname($0))
|
||||
end
|
||||
|
||||
load("test_prologue.rb")
|
||||
|
||||
class LAYNetlistBrowser_TestClass < TestBase
|
||||
|
||||
# Basic view creation and MainWindow events
|
||||
def test_1
|
||||
|
||||
if !RBA.constants.member?(:Application)
|
||||
return
|
||||
end
|
||||
|
||||
app = RBA::Application.instance
|
||||
mw = app.main_window
|
||||
mw.close_all
|
||||
|
||||
cv = mw.load_layout(ENV["TESTSRC"] + "/testdata/lvs/ringo_mixed_hierarchy.gds", 0)
|
||||
lv = cv.view
|
||||
|
||||
nb = lv.netlist_browser
|
||||
|
||||
db = lv.lvsdb(lv.create_lvsdb("DB1"))
|
||||
db.read(ENV["TESTSRC"] + "/testdata/lvs/ringo_mixed_hierarchy.lvsdb")
|
||||
|
||||
lv.show_lvsdb(0, 0)
|
||||
|
||||
# Test path selections
|
||||
|
||||
nl = nb.db.netlist
|
||||
|
||||
# net
|
||||
n = nl.circuit_by_name("INVX1").net_by_name("OUT")
|
||||
pth = RBA::NetlistObjectsPath.from_first(n)
|
||||
nb.current_path = pth
|
||||
assert_equal(nb.current_path.first.net.to_s, "INVX1:OUT")
|
||||
assert_equal(nb.current_path.second.net.to_s, "INVX1:OUT")
|
||||
|
||||
# device
|
||||
n = nl.circuit_by_name("INVX1").device_by_id(1)
|
||||
pth = RBA::NetlistObjectsPath.from_first(n)
|
||||
nb.current_path = pth
|
||||
assert_equal(nb.current_path.first.device.expanded_name, "$1")
|
||||
assert_equal(nb.current_path.second.device.expanded_name, "$1")
|
||||
|
||||
# subcircuit
|
||||
n = nl.circuit_by_name("RINGO").subcircuit_by_id(2)
|
||||
pth = RBA::NetlistObjectsPath.from_first(n)
|
||||
nb.current_path = pth
|
||||
assert_equal(nb.current_path.first.path[-1].expanded_name, "$2")
|
||||
assert_equal(nb.current_path.second.path[-1].expanded_name, "$11")
|
||||
|
||||
# circuit
|
||||
n = nl.circuit_by_name("INVX1")
|
||||
pth = RBA::NetlistObjectsPath.from_first(n)
|
||||
nb.current_path = pth
|
||||
assert_equal(nb.current_path.first.root.name, "INVX1")
|
||||
assert_equal(nb.current_path.second.root.name, "INVX1")
|
||||
|
||||
nl = nb.db.reference
|
||||
|
||||
# net:
|
||||
n = nl.circuit_by_name("INVX1").net_by_name("OUT")
|
||||
pth = RBA::NetlistObjectsPath.from_second(n)
|
||||
nb.current_path = pth
|
||||
assert_equal(nb.current_path.first.net.to_s, "INVX1:OUT")
|
||||
assert_equal(nb.current_path.second.net.to_s, "INVX1:OUT")
|
||||
|
||||
# device
|
||||
n = nl.circuit_by_name("INVX1").device_by_name("$2")
|
||||
pth = RBA::NetlistObjectsPath.from_second(n)
|
||||
nb.current_path = pth
|
||||
assert_equal(nb.current_path.first.device.expanded_name, "$2")
|
||||
assert_equal(nb.current_path.second.device.expanded_name, "$2")
|
||||
|
||||
# subcircuit
|
||||
n = nl.circuit_by_name("RINGO").subcircuit_by_name("$3")
|
||||
pth = RBA::NetlistObjectsPath.from_second(n)
|
||||
nb.current_path = pth
|
||||
assert_equal(nb.current_path.first.path[-1].expanded_name, "$4")
|
||||
assert_equal(nb.current_path.second.path[-1].expanded_name, "$3")
|
||||
|
||||
# circuit
|
||||
n = nl.circuit_by_name("INVX1")
|
||||
pth = RBA::NetlistObjectsPath.from_second(n)
|
||||
nb.current_path = pth
|
||||
assert_equal(nb.current_path.first.root.name, "INVX1")
|
||||
assert_equal(nb.current_path.second.root.name, "INVX1")
|
||||
|
||||
mw.close_all
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
||||
Loading…
Reference in New Issue