mirror of https://github.com/KLayout/klayout.git
WIP: netlist browser - net object paths, single + pairs, tests
This commit is contained in:
parent
2762daf14f
commit
a10d56e6b6
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<std::pair<const db::SubCircuit *, const db::SubCircuit *> > path_type;
|
||||
typedef std::list<const db::SubCircuit *> 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<const db::SubCircuit *> 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<std::pair<const db::SubCircuit *, const db::SubCircuit *> > 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<const db::Circuit *, const db::Circuit *> root;
|
||||
std::list<std::pair<const db::SubCircuit *, const db::SubCircuit *> > path;
|
||||
std::pair<const db::Net *, const db::Net *> net;
|
||||
|
|
@ -292,8 +340,18 @@ public:
|
|||
QIcon icon_for_connection (const std::pair<const db::Net *, const db::Net *> &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 ();
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
||||
|
|
|
|||
|
|
@ -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<const db::Net *> m_current_nets;
|
||||
std::vector<const db::Device *> 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<const db::Net *> selected_nets ();
|
||||
std::vector<const db::Device *> selected_devices ();
|
||||
std::vector<const db::SubCircuit *> selected_subcircuits ();
|
||||
|
|
|
|||
|
|
@ -270,13 +270,13 @@ static bool is_compatible (const std::pair<const db::Circuit *, const db::Circui
|
|||
}
|
||||
|
||||
QModelIndex
|
||||
NetlistBrowserTreeModel::index_from_netpath (const NetlistObjectPath &path) const
|
||||
NetlistBrowserTreeModel::index_from_netpath (const NetlistObjectsPath &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) {
|
||||
for (NetlistObjectsPath::path_iterator p = path.path.begin (); p != path.path.end () && idx.isValid (); ++p) {
|
||||
|
||||
std::pair<const db::Circuit *, const db::Circuit *> sc (p->first ? p->first->circuit_ref () : 0, p->second ? p->second->circuit_ref (): 0);
|
||||
std::pair<const db::Circuit *, const db::Circuit *> circuit = circuits_from_index (idx);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace lay
|
|||
{
|
||||
|
||||
class IndexedNetlistModel;
|
||||
struct NetlistObjectPath;
|
||||
struct NetlistObjectsPath;
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// NetlistBrowserTreeModel definition
|
||||
|
|
@ -78,7 +78,7 @@ public:
|
|||
|
||||
std::pair<const db::Circuit *, const db::Circuit *> circuits_from_index (const QModelIndex &index) const;
|
||||
QModelIndex index_from_circuits (const std::pair<const db::Circuit *, const db::Circuit *> &circuits) const;
|
||||
QModelIndex index_from_netpath (const NetlistObjectPath &path) const;
|
||||
QModelIndex index_from_netpath (const NetlistObjectsPath &path) const;
|
||||
|
||||
private:
|
||||
NetlistBrowserTreeModel (const NetlistBrowserTreeModel &);
|
||||
|
|
|
|||
|
|
@ -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<lay::NetlistBrowserModel> 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<lay::NetlistBrowserModel> 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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue