Functional netlist hierarchy tree.

This commit is contained in:
Matthias Koefferlein 2019-06-06 01:36:07 +02:00
parent 577edea08b
commit 7c220c63e1
18 changed files with 364 additions and 101 deletions

View File

@ -41,6 +41,42 @@ namespace db
class Netlist;
/**
* @brief An iterator wrapper for the child and parent circuit iterator
*/
template <class Iter, class Value>
struct DB_PUBLIC_TEMPLATE dereferencing_iterator
: public Iter
{
public:
typedef Value *pointer;
typedef Value &reference;
typedef typename Iter::difference_type difference_type;
dereferencing_iterator () { }
dereferencing_iterator (const dereferencing_iterator &d) : Iter (d) { }
dereferencing_iterator (const Iter &d) : Iter (d) { }
dereferencing_iterator &operator= (const dereferencing_iterator &d)
{
Iter::operator= (d);
return *this;
}
dereferencing_iterator operator+ (difference_type offset) const
{
return dereferencing_iterator (Iter::operator+ (offset));
}
dereferencing_iterator &operator+= (difference_type offset)
{
Iter::operator+= (offset);
return *this;
}
pointer operator-> () const { return Iter::operator* (); }
reference operator* () const { return *Iter::operator* (); }
};
/**
* @brief A circuit
*
@ -65,10 +101,10 @@ public:
typedef subcircuit_list::iterator subcircuit_iterator;
typedef tl::weak_collection<SubCircuit>::const_iterator const_refs_iterator;
typedef tl::weak_collection<SubCircuit>::iterator refs_iterator;
typedef tl::vector<Circuit *>::const_iterator child_circuit_iterator;
typedef tl::vector<const Circuit *>::const_iterator const_child_circuit_iterator;
typedef tl::vector<Circuit *>::const_iterator parent_circuit_iterator;
typedef tl::vector<const Circuit *>::const_iterator const_parent_circuit_iterator;
typedef dereferencing_iterator<tl::vector<Circuit *>::const_iterator, Circuit> child_circuit_iterator;
typedef dereferencing_iterator<tl::vector<const Circuit *>::const_iterator, const Circuit> const_child_circuit_iterator;
typedef dereferencing_iterator<tl::vector<Circuit *>::const_iterator, Circuit> parent_circuit_iterator;
typedef dereferencing_iterator<tl::vector<const Circuit *>::const_iterator, const Circuit> const_parent_circuit_iterator;
/**
* @brief Constructor

View File

@ -184,7 +184,7 @@ void std_writer_impl<Keys>::write (const db::Netlist *nl, const db::LayoutToNetl
*mp_stream << indent << "# Circuits are the hierarchical building blocks of the netlist." << endl;
}
for (db::Netlist::const_bottom_up_circuit_iterator i = nl->begin_bottom_up (); i != nl->end_bottom_up (); ++i) {
const db::Circuit *x = *i;
const db::Circuit *x = i.operator-> ();
*mp_stream << indent << Keys::circuit_key << "(" << tl::to_word_or_quoted_string (x->name ()) << endl;
write (nl, l2n, *x, indent, net2id_per_circuit);
*mp_stream << indent << ")" << endl;

View File

@ -435,7 +435,7 @@ void Netlist::make_top_level_pins ()
size_t ntop = top_circuit_count ();
for (top_down_circuit_iterator c = begin_top_down (); c != end_top_down () && ntop > 0; ++c, --ntop) {
Circuit *circuit = *c;
Circuit *circuit = c.operator-> ();
if (circuit->pin_count () == 0) {
@ -460,7 +460,7 @@ void Netlist::purge ()
for (bottom_up_circuit_iterator c = begin_bottom_up (); c != end_bottom_up (); ++c) {
Circuit *circuit = *c;
Circuit *circuit = c.operator-> ();
circuit->purge_nets ();
if (circuit->begin_nets () == circuit->end_nets ()) {

View File

@ -55,10 +55,10 @@ public:
typedef tl::shared_collection<DeviceAbstract> device_abstract_list;
typedef device_abstract_list::const_iterator const_abstract_model_iterator;
typedef device_abstract_list::iterator device_abstract_iterator;
typedef tl::vector<Circuit *>::const_iterator top_down_circuit_iterator;
typedef tl::vector<const Circuit *>::const_iterator const_top_down_circuit_iterator;
typedef tl::vector<Circuit *>::const_reverse_iterator bottom_up_circuit_iterator;
typedef tl::vector<const Circuit *>::const_reverse_iterator const_bottom_up_circuit_iterator;
typedef dereferencing_iterator<tl::vector<Circuit *>::iterator, Circuit> top_down_circuit_iterator;
typedef dereferencing_iterator<tl::vector<const Circuit *>::const_iterator, const Circuit> const_top_down_circuit_iterator;
typedef dereferencing_iterator<tl::vector<Circuit *>::reverse_iterator, Circuit> bottom_up_circuit_iterator;
typedef dereferencing_iterator<tl::vector<const Circuit *>::const_reverse_iterator, const Circuit> const_bottom_up_circuit_iterator;
/**
* @brief Constructor

View File

@ -1733,7 +1733,7 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
for (db::Netlist::const_bottom_up_circuit_iterator c = a->begin_bottom_up (); c != a->end_bottom_up (); ++c) {
size_t ccat = circuit_categorizer.cat_for_circuit (*c);
size_t ccat = circuit_categorizer.cat_for_circuit (c.operator-> ());
std::map<size_t, std::pair<const db::Circuit *, const db::Circuit *> >::const_iterator i = cat2circuits.find (ccat);
tl_assert (i != cat2circuits.end ());

View File

@ -370,7 +370,7 @@ void NetlistSpiceWriter::do_write (const std::string &description)
for (db::Netlist::const_top_down_circuit_iterator c = mp_netlist->begin_top_down (); c != mp_netlist->end_top_down (); ++c) {
const db::Circuit &circuit = **c;
const db::Circuit &circuit = *c;
// assign internal node numbers to the nets
m_net_to_spice_id.clear ();

View File

@ -191,7 +191,7 @@ static std::string children2string (const db::Circuit *c)
if (!res.empty ()) {
res += ",";
}
res += (*r)->name ();
res += r->name ();
}
return res;
}
@ -203,7 +203,7 @@ static std::string parents2string (const db::Circuit *c)
if (!res.empty ()) {
res += ",";
}
res += (*r)->name ();
res += r->name ();
}
return res;
}
@ -215,7 +215,7 @@ static std::string td2string (const db::Netlist *nl)
if (!res.empty ()) {
res += ",";
}
res += (*r)->name ();
res += r->name ();
}
return res;
}
@ -227,7 +227,7 @@ static std::string bu2string (const db::Netlist *nl)
if (!res.empty ()) {
res += ",";
}
res += (*r)->name ();
res += r->name ();
}
return res;
}

View File

@ -204,49 +204,95 @@
</widget>
</item>
<item>
<widget class="QTreeView" name="directory_tree">
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>4</height>
</size>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="headerShowSortIndicator" stdset="0">
<bool>false</bool>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTreeView" name="hierarchy_tree">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="headerDefaultSectionSize">
<number>100</number>
</attribute>
</widget>
<widget class="QTreeView" name="directory_tree">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="headerShowSortIndicator" stdset="0">
<bool>false</bool>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item>
@ -338,6 +384,12 @@
</customwidget>
</customwidgets>
<tabstops>
<tabstop>backward</tabstop>
<tabstop>forward</tabstop>
<tabstop>info_button</tabstop>
<tabstop>find_text</tabstop>
<tabstop>find_button</tabstop>
<tabstop>hierarchy_tree</tabstop>
<tabstop>directory_tree</tabstop>
</tabstops>
<resources>

View File

@ -272,15 +272,15 @@ SingleIndexedNetlistModel::parent_of (const subcircuit_pair &subcircuits) const
std::pair<IndexedNetlistModel::circuit_pair, IndexedNetlistModel::Status>
SingleIndexedNetlistModel::top_circuit_from_index (size_t index) const
{
const db::Circuit *c = mp_netlist->begin_top_down () [index];
return std::make_pair (std::make_pair (c, (const db::Circuit *) 0), db::NetlistCrossReference::None);
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> ()), db::NetlistCrossReference::None);
}
std::pair<IndexedNetlistModel::circuit_pair, IndexedNetlistModel::Status>
SingleIndexedNetlistModel::child_circuit_from_index (const circuit_pair &circuits, size_t index) const
{
const db::Circuit *c = circuits.first->begin_children () [index];
return std::make_pair (std::make_pair (c, (const db::Circuit *) 0), db::NetlistCrossReference::None);
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> ()), db::NetlistCrossReference::None);
}
std::pair<IndexedNetlistModel::circuit_pair, IndexedNetlistModel::Status>
@ -303,6 +303,12 @@ SingleIndexedNetlistModel::second_net_for (const db::Net * /*first*/) const
return 0;
}
const db::Circuit *
SingleIndexedNetlistModel::second_circuit_for (const db::Circuit * /*first*/) const
{
return 0;
}
IndexedNetlistModel::net_subcircuit_pin_pair
SingleIndexedNetlistModel::net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const
{

View File

@ -90,6 +90,7 @@ public:
virtual std::pair<circuit_pair, Status> circuit_from_index (size_t index) const = 0;
virtual std::pair<net_pair, Status> net_from_index (const circuit_pair &circuits, size_t index) const = 0;
virtual const db::Net *second_net_for (const db::Net *first) const = 0;
virtual const db::Circuit *second_circuit_for (const db::Circuit *first) const = 0;
virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const = 0;
virtual net_terminal_pair net_terminalref_from_index (const net_pair &nets, size_t index) const = 0;
virtual net_pin_pair net_pinref_from_index (const net_pair &nets, size_t index) const = 0;
@ -147,7 +148,8 @@ public:
virtual std::pair<circuit_pair, Status> circuit_from_index (size_t index) const;
virtual std::pair<circuit_pair, Status> child_circuit_from_index (const circuit_pair &circuits, size_t index) const;
virtual std::pair<net_pair, Status> net_from_index (const circuit_pair &circuits, size_t index) const;
virtual const db::Net *second_net_for (const db::Net * /*first*/) const;
virtual const db::Net *second_net_for (const db::Net *first) const;
virtual const db::Circuit *second_circuit_for (const db::Circuit *first) const;
virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const;
virtual net_terminal_pair net_terminalref_from_index (const net_pair &nets, size_t index) const;
virtual net_pin_pair net_pinref_from_index (const net_pair &nets, size_t index) const;
@ -167,6 +169,7 @@ private:
const db::Netlist *mp_netlist;
mutable std::map<netlist_pair, std::vector<circuit_pair> > m_circuit_by_index;
mutable std::map<circuit_pair, std::vector<circuit_pair> > m_child_circuit_by_circuit_and_index;
mutable std::map<circuit_pair, std::vector<net_pair> > m_net_by_circuit_and_index;
mutable std::map<net_pair, std::vector<net_subcircuit_pin_pair> > m_subcircuit_pinref_by_net_and_index;
mutable std::map<net_pair, std::vector<net_terminal_pair> > m_terminalref_by_net_and_index;

View File

@ -1911,6 +1911,25 @@ NetlistBrowserModel::index_from_net (const db::Net *net) const
return index_from_net (std::make_pair (net, mp_indexer->second_net_for (net)));
}
QModelIndex
NetlistBrowserModel::index_from_circuit (const std::pair<const db::Circuit *, const db::Circuit *> &circuits) const
{
void *id = make_id_circuit (mp_indexer->circuit_index (circuits));
return index_from_id (id, 0);
}
QModelIndex
NetlistBrowserModel::index_from_circuit (const db::Circuit *net) const
{
return index_from_circuit (std::make_pair (net, mp_indexer->second_circuit_for (net)));
}
std::pair<const db::Circuit *, const db::Circuit *>
NetlistBrowserModel::circuit_from_index (const QModelIndex &index) const
{
return circuits_from_id (index.internalPointer ());
}
std::pair<const db::Net *, const db::Net *>
NetlistBrowserModel::net_from_index (const QModelIndex &index) const
{

View File

@ -135,6 +135,9 @@ public:
std::pair<const db::Net *, const db::Net *> net_from_index (const QModelIndex &index) const;
QModelIndex index_from_net (const std::pair<const db::Net *, const db::Net *> &net) const;
QModelIndex index_from_net (const db::Net *net) const;
std::pair<const db::Circuit *, const db::Circuit *> circuit_from_index (const QModelIndex &index) const;
QModelIndex index_from_circuit (const std::pair<const db::Circuit *, const db::Circuit *> &circuit) const;
QModelIndex index_from_circuit (const db::Circuit *circuit) const;
std::pair<const db::SubCircuit *, const db::SubCircuit *> subcircuit_from_index (const QModelIndex &index) const;

View File

@ -23,6 +23,7 @@
#include "layNetlistBrowserPage.h"
#include "layNetlistBrowserModel.h"
#include "layNetlistBrowserTreeModel.h"
#include "layItemDelegates.h"
#include "layCellView.h"
#include "layLayoutView.h"
@ -153,6 +154,14 @@ NetlistBrowserPage::NetlistBrowserPage (QWidget * /*parent*/)
directory_tree->setItemDelegateForColumn (i, delegate);
}
for (int i = 0; i < 2; ++i) {
delegate = new lay::HTMLItemDelegate (this);
delegate->set_text_margin (2);
delegate->set_anchors_clickable (true);
connect (delegate, SIGNAL (anchor_clicked (const QString &)), this, SLOT (anchor_clicked (const QString &)));
hierarchy_tree->setItemDelegateForColumn (i, delegate);
}
QMenu *find_edit_menu = new QMenu (find_text);
find_edit_menu->addAction (actionUseRegularExpressions);
find_edit_menu->addAction (actionCaseSensitive);
@ -284,14 +293,48 @@ NetlistBrowserPage::anchor_clicked (const QString &a)
navigate_to (id, true);
}
void
NetlistBrowserPage::current_tree_index_changed (const QModelIndex &index)
{
if (index.isValid () && m_signals_enabled) {
NetlistBrowserTreeModel *tree_model = dynamic_cast<NetlistBrowserTreeModel *> (hierarchy_tree->model ());
NetlistBrowserModel *netlist_model = dynamic_cast<NetlistBrowserModel *> (directory_tree->model ());
if (! tree_model || ! netlist_model) {
return;
}
std::pair<const db::Circuit *, const db::Circuit *> circuits = tree_model->circuits_from_index (index);
QModelIndex circuit_index = netlist_model->index_from_circuit (circuits);
m_signals_enabled = false;
directory_tree->setCurrentIndex (circuit_index);
m_signals_enabled = true;
}
}
void
NetlistBrowserPage::current_index_changed (const QModelIndex &index)
{
if (index.isValid () && m_signals_enabled) {
NetlistBrowserTreeModel *tree_model = dynamic_cast<NetlistBrowserTreeModel *> (hierarchy_tree->model ());
NetlistBrowserModel *netlist_model = dynamic_cast<NetlistBrowserModel *> (directory_tree->model ());
if (! tree_model || ! netlist_model) {
return;
}
void *id = index.internalPointer ();
add_to_history (id, true);
std::pair<const db::Circuit *, const db::Circuit *> circuits = netlist_model->circuit_from_index (index);
QModelIndex circuit_index = tree_model->index_from_circuits (circuits);
m_signals_enabled = false;
hierarchy_tree->setCurrentIndex (circuit_index);
m_signals_enabled = true;
}
}
@ -424,19 +467,26 @@ NetlistBrowserPage::select_color_for_net ()
void
NetlistBrowserPage::navigate_to (void *id, bool fwd)
{
NetlistBrowserModel *model = dynamic_cast<NetlistBrowserModel *> (directory_tree->model ());
if (! model) {
NetlistBrowserTreeModel *tree_model = dynamic_cast<NetlistBrowserTreeModel *> (hierarchy_tree->model ());
NetlistBrowserModel *netlist_model = dynamic_cast<NetlistBrowserModel *> (directory_tree->model ());
if (! tree_model || ! netlist_model) {
return;
}
QModelIndex index = model->index_from_id (id, 0);
QModelIndex index = netlist_model->index_from_id (id, 0);
if (! index.isValid ()) {
return;
}
m_signals_enabled = false;
try {
directory_tree->setCurrentIndex (index);
std::pair<const db::Circuit *, const db::Circuit *> circuits = netlist_model->circuit_from_index (index);
QModelIndex circuit_index = tree_model->index_from_circuits (circuits);
hierarchy_tree->setCurrentIndex (circuit_index);
} catch (...) {
}
m_signals_enabled = true;
@ -636,43 +686,78 @@ NetlistBrowserPage::set_db (db::LayoutToNetlist *l2ndb)
if (! mp_database.get ()) {
delete directory_tree->model ();
directory_tree->setModel (0);
delete hierarchy_tree->model ();
hierarchy_tree->setModel (0);
return;
}
m_cell_context_cache = db::ContextCache (mp_database->internal_layout ());
// NOTE: with the tree as the parent, the tree will take over ownership of the model
NetlistBrowserModel *new_model = 0;
if (lvsdb) {
new_model = new NetlistBrowserModel (directory_tree, lvsdb, &m_colorizer);
} else {
new_model = new NetlistBrowserModel (directory_tree, l2ndb, &m_colorizer);
}
int columns = directory_tree->model () ? directory_tree->model ()->columnCount (QModelIndex ()) : 0;
int new_columns = new_model->columnCount (QModelIndex ());
delete directory_tree->model ();
directory_tree->setModel (new_model);
connect (directory_tree->selectionModel (), SIGNAL (currentChanged (const QModelIndex &, const QModelIndex &)), this, SLOT (current_index_changed (const QModelIndex &)));
connect (directory_tree->selectionModel (), SIGNAL (selectionChanged (const QItemSelection &, const QItemSelection &)), this, SLOT (selection_changed ()));
directory_tree->header ()->show ();
directory_tree->header ()->setStretchLastSection (true);
directory_tree->header ()->setMinimumSectionSize (25);
if (columns < new_columns) {
// makes sure new columns are properly size-adjusted
for (int i = std::max (0, columns - 1); i < new_columns; ++i) {
directory_tree->header ()->resizeSection (i, i == 1 ? directory_tree->header ()->minimumSectionSize () : directory_tree->header ()->defaultSectionSize ());
{
// NOTE: with the tree as the parent, the tree will take over ownership of the model
NetlistBrowserModel *new_model = 0;
if (lvsdb) {
new_model = new NetlistBrowserModel (directory_tree, lvsdb, &m_colorizer);
} else {
new_model = new NetlistBrowserModel (directory_tree, l2ndb, &m_colorizer);
}
int columns = directory_tree->model () ? directory_tree->model ()->columnCount (QModelIndex ()) : 0;
int new_columns = new_model->columnCount (QModelIndex ());
delete directory_tree->model ();
directory_tree->setModel (new_model);
connect (directory_tree->selectionModel (), SIGNAL (currentChanged (const QModelIndex &, const QModelIndex &)), this, SLOT (current_index_changed (const QModelIndex &)));
connect (directory_tree->selectionModel (), SIGNAL (selectionChanged (const QItemSelection &, const QItemSelection &)), this, SLOT (selection_changed ()));
directory_tree->header ()->show ();
directory_tree->header ()->setStretchLastSection (true);
directory_tree->header ()->setMinimumSectionSize (25);
if (columns < new_columns) {
// makes sure new columns are properly size-adjusted
for (int i = std::max (0, columns - 1); i < new_columns; ++i) {
directory_tree->header ()->resizeSection (i, i == 1 ? directory_tree->header ()->minimumSectionSize () : directory_tree->header ()->defaultSectionSize ());
}
}
// hide the status column if not needed
directory_tree->header ()->setSectionHidden (1, new_model->status_column () < 0);
// establish visibility according to "show all"
new_model->set_item_visibility (directory_tree, m_show_all, false /*show warnings only with 'show all'*/);
}
// hide the status column if not needed
directory_tree->header ()->setSectionHidden (1, new_model->status_column () < 0);
{
// NOTE: with the tree as the parent, the tree will take over ownership of the model
NetlistBrowserTreeModel *new_hierarchy_model = 0;
if (lvsdb) {
new_hierarchy_model = new NetlistBrowserTreeModel (hierarchy_tree, lvsdb);
} else {
new_hierarchy_model = new NetlistBrowserTreeModel (hierarchy_tree, l2ndb);
}
// establish visibility according to "show all"
new_model->set_item_visibility (directory_tree, m_show_all, false /*show warnings only with 'show all'*/);
int columns = hierarchy_tree->model () ? hierarchy_tree->model ()->columnCount (QModelIndex ()) : 0;
int new_columns = new_hierarchy_model->columnCount (QModelIndex ());
delete hierarchy_tree->model ();
hierarchy_tree->setModel (new_hierarchy_model);
connect (hierarchy_tree->selectionModel (), SIGNAL (currentChanged (const QModelIndex &, const QModelIndex &)), this, SLOT (current_tree_index_changed (const QModelIndex &)));
hierarchy_tree->header ()->show ();
hierarchy_tree->header ()->setStretchLastSection (true);
hierarchy_tree->header ()->setMinimumSectionSize (25);
if (columns < new_columns) {
// makes sure new columns are properly size-adjusted
for (int i = std::max (0, columns - 1); i < new_columns; ++i) {
hierarchy_tree->header ()->resizeSection (i, i == 1 ? hierarchy_tree->header ()->minimumSectionSize () : hierarchy_tree->header ()->defaultSectionSize ());
}
}
// hide the status column if not needed
hierarchy_tree->header ()->setSectionHidden (1, new_hierarchy_model->status_column () < 0);
}
find_text->setText (QString ());
}

View File

@ -169,6 +169,7 @@ private slots:
void navigate_back ();
void navigate_forward ();
void current_index_changed (const QModelIndex &index);
void current_tree_index_changed (const QModelIndex &index);
void selection_changed ();
void browse_color_for_net ();
void select_color_for_net ();

View File

@ -202,7 +202,7 @@ NetlistBrowserTreeModel::search_text (const QModelIndex &index) const
}
std::pair<std::pair<const db::Circuit *, const db::Circuit *>, db::NetlistCrossReference::Status>
NetlistBrowserTreeModel::cp_status_from_index (const QModelIndex &index, size_t &nprod, size_t &nlast) const
NetlistBrowserTreeModel::cp_status_from_index (const QModelIndex &index, size_t &nprod, size_t &nlast, size_t &nnlast) const
{
typedef std::pair<std::pair<const db::Circuit *, const db::Circuit *>, db::NetlistCrossReference::Status> cp_status;
@ -210,6 +210,7 @@ NetlistBrowserTreeModel::cp_status_from_index (const QModelIndex &index, size_t
tl_assert (id != 0);
nprod = 1;
nnlast = 1;
nlast = mp_indexer->top_circuit_count () + 1;
size_t i = pop (id, nlast);
@ -217,6 +218,7 @@ NetlistBrowserTreeModel::cp_status_from_index (const QModelIndex &index, size_t
cp_status cps = mp_indexer->top_circuit_from_index (i - 1);
while (id != 0) {
nnlast = nlast;
nlast = mp_indexer->child_circuit_count (cps.first) + 1;
i = pop (id, nlast);
nprod *= nlast;
@ -229,15 +231,58 @@ NetlistBrowserTreeModel::cp_status_from_index (const QModelIndex &index, size_t
std::pair<const db::Circuit *, const db::Circuit *>
NetlistBrowserTreeModel::circuits_from_index (const QModelIndex &index) const
{
size_t nprod = 0, nlast = 0;
return cp_status_from_index (index, nprod, nlast).first;
size_t nprod = 0, nlast = 0, nnlast = 0;
return cp_status_from_index (index, nprod, nlast, nnlast).first;
}
void
NetlistBrowserTreeModel::build_circuits_to_index (size_t nprod, const std::pair<const db::Circuit *, const db::Circuit *> &circuits, IndexedNetlistModel *model, const QModelIndex &index, std::map<std::pair<const db::Circuit *, const db::Circuit *>, QModelIndex> &map) const
{
if (map.find (circuits) != map.end ()) {
return;
}
map.insert (std::make_pair (circuits, index));
size_t count = mp_indexer->child_circuit_count (circuits);
size_t child_nprod = nprod * (count + 1);
for (size_t n = count; n > 0; ) {
std::pair<std::pair<const db::Circuit *, const db::Circuit *>, IndexedNetlistModel::Status> cp = mp_indexer->child_circuit_from_index (circuits, n - 1);
QModelIndex child_index = createIndex (int (n - 1), 0, reinterpret_cast<void *> (size_t (index.internalPointer ()) + nprod * n));
build_circuits_to_index (child_nprod, cp.first, model, child_index, map);
--n;
}
}
QModelIndex
NetlistBrowserTreeModel::index_from_circuits (const std::pair<const db::Circuit *, const db::Circuit *> &circuits) const
{
if (m_circuits_to_index.empty ()) {
size_t count = mp_indexer->top_circuit_count ();
for (size_t n = count; n > 0; ) {
std::pair<std::pair<const db::Circuit *, const db::Circuit *>, IndexedNetlistModel::Status> cp = mp_indexer->top_circuit_from_index (n - 1);
build_circuits_to_index (count + 1, cp.first, mp_indexer.get (), createIndex (int (n - 1), 0, reinterpret_cast<void *> (n)), m_circuits_to_index);
--n;
}
}
std::map<std::pair<const db::Circuit *, const db::Circuit *>, QModelIndex>::const_iterator m = m_circuits_to_index.find (circuits);
if (m != m_circuits_to_index.end ()) {
return m->second;
} else {
return QModelIndex ();
}
}
db::NetlistCrossReference::Status
NetlistBrowserTreeModel::status (const QModelIndex &index) const
{
size_t nprod = 0, nlast = 0;
return cp_status_from_index (index, nprod, nlast).second;
size_t nprod = 0, nlast = 0, nnlast = 0;
return cp_status_from_index (index, nprod, nlast, nnlast).second;
}
Qt::ItemFlags
@ -276,8 +321,8 @@ NetlistBrowserTreeModel::index (int row, int column, const QModelIndex &parent)
} else {
size_t nprod = 0, nlast = 0;
cp_status_from_index (parent, nprod, nlast);
size_t nprod = 0, nlast = 0, nnlast = 0;
cp_status_from_index (parent, nprod, nlast, nnlast);
void *id = parent.internalPointer ();
return createIndex (row, column, reinterpret_cast<void *> (reinterpret_cast<size_t> (id) + size_t (row + 1) * nprod));
@ -290,8 +335,8 @@ NetlistBrowserTreeModel::parent (const QModelIndex &index) const
{
if (index.isValid ()) {
size_t nprod = 0, nlast = 0;
cp_status_from_index (index, nprod, nlast);
size_t nprod = 0, nlast = 0, nnlast = 0;
cp_status_from_index (index, nprod, nlast, nnlast);
tl_assert (nlast != 0);
@ -302,7 +347,11 @@ NetlistBrowserTreeModel::parent (const QModelIndex &index) const
void *id = index.internalPointer ();
size_t ids = reinterpret_cast<size_t> (id);
tl_assert (ids >= nprod);
return createIndex (int (ids / nprod - 1), index.column (), reinterpret_cast<void *> (ids % nprod));
ids %= nprod;
nprod /= nnlast;
return createIndex (int (ids / nprod - 1), index.column (), reinterpret_cast<void *> (ids));
}

View File

@ -76,6 +76,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;
private:
NetlistBrowserTreeModel (const NetlistBrowserTreeModel &);
@ -84,11 +85,13 @@ private:
QString text (const QModelIndex &index) const;
QString search_text (const QModelIndex &index) const;
db::NetlistCrossReference::Status status (const QModelIndex &index) const;
std::pair<std::pair<const db::Circuit *, const db::Circuit *>, db::NetlistCrossReference::Status> cp_status_from_index (const QModelIndex &index, size_t &nprod, size_t &nlast) const;
std::pair<std::pair<const db::Circuit *, const db::Circuit *>, db::NetlistCrossReference::Status> cp_status_from_index (const QModelIndex &index, size_t &nprod, size_t &nlast, size_t &nnlast) const;
void build_circuits_to_index (size_t nprod, const std::pair<const db::Circuit *, const db::Circuit *> &circuits, IndexedNetlistModel *model, const QModelIndex &index, std::map<std::pair<const db::Circuit *, const db::Circuit *>, QModelIndex> &map) const;
db::LayoutToNetlist *mp_l2ndb;
db::LayoutVsSchematic *mp_lvsdb;
std::auto_ptr<IndexedNetlistModel> mp_indexer;
mutable std::map<std::pair<const db::Circuit *, const db::Circuit *>, QModelIndex> m_circuits_to_index;
int m_object_column;
int m_status_column;
};

View File

@ -299,6 +299,11 @@ const db::Net *NetlistCrossReferenceModel::second_net_for (const db::Net *first)
return mp_cross_ref->other_net_for (first);
}
const db::Circuit *NetlistCrossReferenceModel::second_circuit_for (const db::Circuit *first) const
{
return mp_cross_ref->other_circuit_for (first);
}
IndexedNetlistModel::net_subcircuit_pin_pair NetlistCrossReferenceModel::net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const
{
const db::NetlistCrossReference::PerNetData *data = mp_cross_ref->per_net_data_for (nets);

View File

@ -63,6 +63,7 @@ public:
virtual std::pair<circuit_pair, Status> child_circuit_from_index (const circuit_pair &circuits, size_t index) const;
virtual std::pair<net_pair, Status> net_from_index (const circuit_pair &circuits, size_t index) const;
virtual const db::Net *second_net_for (const db::Net *first) const;
virtual const db::Circuit *second_circuit_for (const db::Circuit *first) const;
virtual net_subcircuit_pin_pair net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const;
virtual net_terminal_pair net_terminalref_from_index (const net_pair &nets, size_t index) const;
virtual net_pin_pair net_pinref_from_index (const net_pair &nets, size_t index) const;