Netlist browser: some bug fixes in search, probe net feature.

This commit is contained in:
Matthias Koefferlein 2019-05-01 00:24:43 +02:00
parent 4e15b3df92
commit 60216ee3f6
7 changed files with 283 additions and 39 deletions

View File

@ -285,6 +285,23 @@ to load a netlist or a netlist/LVS database</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="probe_pb">
<property name="toolTip">
<string>Select a new by clicking on a shape</string>
</property>
<property name="text">
<string>Probe Net</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="sticky_cbx">
<property name="text">
<string>Lock</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">

View File

@ -200,13 +200,6 @@
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="probe_button">
<property name="text">
<string>Probe</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -243,7 +236,7 @@
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
<bool>true</bool>
</attribute>
</widget>
</item>

View File

@ -154,6 +154,9 @@ void NetInfoDialog::update_info_text ()
info.cdata (tl::to_string (tr ("Net")));
info.end_element ("th");
info.start_element ("th");
info.cdata (tl::to_string (tr ("Circuit")));
info.end_element ("th");
info.start_element ("th");
info.cdata (tl::to_string (tr ("Shapes")));
info.end_element ("th");
info.start_element ("th");
@ -177,6 +180,12 @@ void NetInfoDialog::update_info_text ()
info.cdata (net->expanded_name ());
info.end_element ("td");
info.start_element ("td");
if (net->circuit ()) {
info.cdata (net->circuit ()->name ());
}
info.end_element ("td");
size_t n;
info.start_element ("td");
@ -253,23 +262,6 @@ void NetInfoDialog::update_info_text ()
info.start_element ("hr");
info.end_element ("hr");
info.start_element ("h3");
info.cdata (tl::to_string (QObject::tr ("Details:")));
info.end_element ("h3");
info.start_element ("p");
info.start_element ("b");
info.cdata (tl::to_string (QObject::tr ("Net name: ")));
info.end_element ("b");
info.cdata (net->expanded_name ());
info.start_element ("br");
info.end_element ("br");
info.start_element ("b");
info.cdata (tl::to_string (QObject::tr ("Circuit: ")));
info.end_element ("b");
info.cdata (net->circuit () ? net->circuit ()->name () : "(null)");
info.end_element ("p");
std::map<std::string, std::set<std::string> > shapes;
// map as (layernumber, group of shapes by layer):

View File

@ -23,8 +23,9 @@
#include "layNetlistBrowserDialog.h"
#include "tlProgress.h"
#include "layLayoutView.h"
#include "tlExceptions.h"
#include "layLayoutView.h"
#include "layFinder.h"
#include "layFileDialog.h"
#include "layConverters.h"
#include "layQtTools.h"
@ -56,6 +57,7 @@ extern const std::string cfg_l2ndb_window_state;
NetlistBrowserDialog::NetlistBrowserDialog (lay::PluginRoot *root, lay::LayoutView *vw)
: lay::Browser (root, vw),
lay::ViewService (vw->view_object_widget ()),
Ui::NetlistBrowserDialog (),
m_window (lay::NetlistBrowserConfig::FitNet),
m_window_dim (0.0),
@ -67,7 +69,8 @@ NetlistBrowserDialog::NetlistBrowserDialog (lay::PluginRoot *root, lay::LayoutVi
m_marker_dither_pattern (-1),
m_marker_intensity (0),
m_cv_index (-1),
m_l2n_index (-1)
m_l2n_index (-1),
m_mouse_state (0)
{
Ui::NetlistBrowserDialog::setupUi (this);
@ -111,6 +114,8 @@ NetlistBrowserDialog::NetlistBrowserDialog (lay::PluginRoot *root, lay::LayoutVi
connect (layout_cb, SIGNAL (activated (int)), this, SLOT (cv_index_changed (int)));
connect (l2ndb_cb, SIGNAL (activated (int)), this, SLOT (l2ndb_index_changed (int)));
connect (configure_pb, SIGNAL (clicked ()), this, SLOT (configure_clicked ()));
connect (probe_pb, SIGNAL (clicked ()), this, SLOT (probe_button_pressed ()));
connect (sticky_cbx, SIGNAL (clicked ()), this, SLOT (sticky_mode_clicked ()));
cellviews_changed ();
}
@ -123,10 +128,188 @@ NetlistBrowserDialog::~NetlistBrowserDialog ()
void
NetlistBrowserDialog::configure_clicked ()
{
release_mouse ();
lay::ConfigurationDialog config_dialog (this, lay::PluginRoot::instance (), "NetlistBrowserPlugin");
config_dialog.exec ();
}
bool
NetlistBrowserDialog::mouse_move_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool prio)
{
if (prio && m_mouse_state != 0) {
set_cursor (lay::Cursor::cross);
}
return false;
}
void
NetlistBrowserDialog::sticky_mode_clicked ()
{
BEGIN_PROTECTED
if (! sticky_cbx->isChecked ()) {
release_mouse ();
} else {
probe_button_pressed ();
}
END_PROTECTED
}
bool
NetlistBrowserDialog::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio)
{
if (prio && (buttons & lay::LeftButton) != 0 && m_mouse_state != 0) {
// TODO: not used yet, borrowed from net tracer ... TODO: implement short locator!
if (m_mouse_state == 2) {
m_mouse_first_point = p;
m_mouse_state = 3;
view ()->message (tl::to_string (QObject::tr ("Click on the second point in the net")));
} else {
bool trace_path = (m_mouse_state == 3);
if (trace_path || ! sticky_cbx->isChecked ()) {
release_mouse ();
}
probe_net (p, trace_path);
}
}
return true;
}
void
NetlistBrowserDialog::probe_net (const db::DPoint &p, bool trace_path)
{
// prepare for the net tracing
double l = double (lay::search_range) / widget ()->mouse_event_trans ().mag ();
db::DBox start_search_box = db::DBox (p, p).enlarged (db::DVector (l, l));
// @@@ not used yet ..
db::DBox stop_search_box;
if (trace_path) {
stop_search_box = db::DBox (m_mouse_first_point, m_mouse_first_point).enlarged (db::DVector (l, l));
}
unsigned int start_layer = 0;
db::Point start_point;
unsigned int cv_index;
// locate the seed shape to figure out the cv index and layer
{
lay::ShapeFinder finder (true /*point mode*/, false /*all levels*/, db::ShapeIterator::All);
// go through all visible layers of all cellviews and find a seed shape
for (lay::LayerPropertiesConstIterator lprop = view ()->begin_layers (); ! lprop.at_end (); ++lprop) {
if (lprop->is_visual ()) {
finder.find (view (), *lprop, start_search_box);
}
}
// return, if no shape was found
lay::ShapeFinder::iterator r = finder.begin ();
if (r == finder.end ()) {
return;
}
cv_index = r->cv_index ();
start_layer = r->layer ();
}
// if the cv index is not corresponding to the one of the current netlist, ignore this event
if (int (cv_index) != m_cv_index) {
return;
}
// determine the cellview
lay::CellView cv = view ()->cellview (cv_index);
if (! cv.is_valid ()) {
return;
}
// determine the start point
{
std::vector<db::DCplxTrans> tv = view ()->cv_transform_variants (m_cv_index, start_layer);
if (tv.empty ()) {
return;
}
db::CplxTrans tt = tv.front () * db::CplxTrans (cv->layout ().dbu ()) * cv.context_trans ();
start_point = tt.inverted ().trans (start_search_box.center ());
}
const db::Net *net = 0;
db::LayoutToNetlist *l2ndb = view ()->get_l2ndb (m_l2n_index);
if (l2ndb) {
// determines the corresponding layer inside the database and probe the net from this region and the
// start point.
db::Region *region = 0;
const db::Connectivity &conn = l2ndb->connectivity ();
for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
db::LayerProperties lp = l2ndb->internal_layout ()->get_properties (*layer);
if (! lp.is_null () && lp == cv->layout ().get_properties (start_layer)) {
region = l2ndb->layer_by_index (*layer);
break;
}
}
// probe the net
if (region) {
net = l2ndb->probe_net (*region, start_point);
}
}
// select the net if one was found
browser_frame->select_net (net);
}
void
NetlistBrowserDialog::release_mouse ()
{
m_mouse_state = 0;
view ()->message ();
widget ()->ungrab_mouse (this);
}
lay::ViewService *
NetlistBrowserDialog::view_service_interface ()
{
return this;
}
void
NetlistBrowserDialog::probe_button_pressed ()
{
BEGIN_PROTECTED
m_mouse_state = 1;
view ()->message (tl::to_string (QObject::tr ("Click on a point in the net")));
widget ()->grab_mouse (this, false);
END_PROTECTED
}
void
NetlistBrowserDialog::unload_all_clicked ()
{
@ -510,8 +693,13 @@ NetlistBrowserDialog::activated ()
void
NetlistBrowserDialog::update_content ()
{
release_mouse ();
db::LayoutToNetlist *l2ndb = view ()->get_l2ndb (m_l2n_index);
probe_pb->setEnabled (l2ndb != 0);
release_mouse ();
if (! l2ndb) {
central_stack->setCurrentIndex (1);
}
@ -554,6 +742,8 @@ NetlistBrowserDialog::update_content ()
void
NetlistBrowserDialog::deactivated ()
{
release_mouse ();
if (lay::PluginRoot::instance ()) {
lay::PluginRoot::instance ()->config_set (cfg_l2ndb_window_state, lay::save_dialog_state (this).c_str ());
}

View File

@ -27,6 +27,7 @@
#include "ui_NetlistBrowserDialog.h"
#include "layBrowser.h"
#include "layNetlistBrowser.h"
#include "layViewObject.h"
#include "layColorPalette.h"
namespace lay
@ -34,6 +35,7 @@ namespace lay
class NetlistBrowserDialog
: public lay::Browser,
public lay::ViewService,
private Ui::NetlistBrowserDialog
{
Q_OBJECT
@ -49,7 +51,11 @@ private:
virtual void activated ();
virtual void deactivated ();
bool configure (const std::string &name, const std::string &value);
virtual bool configure (const std::string &name, const std::string &value);
virtual bool mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio);
virtual bool mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio);
virtual lay::ViewService *view_service_interface ();
// implementation of the lay::Plugin interface
virtual void menu_activated (const std::string &symbol);
@ -68,6 +74,8 @@ public slots:
void unload_clicked ();
void unload_all_clicked ();
void configure_clicked ();
void probe_button_pressed ();
void sticky_mode_clicked ();
private:
lay::NetlistBrowserConfig::net_window_type m_window;
@ -86,6 +94,8 @@ private:
std::string m_l2ndb_name;
int m_l2n_index;
std::string m_open_filename;
db::DPoint m_mouse_first_point;
int m_mouse_state;
QAction *m_open_action;
QAction *m_saveas_action;
QAction *m_export_action;
@ -94,8 +104,8 @@ private:
QAction *m_reload_action;
void update_content ();
void scan_layer ();
void scan_layer_flat ();
void release_mouse ();
void probe_net (const db::DPoint &p, bool trace_path);
};
}

View File

@ -27,6 +27,7 @@
#include "layLayoutView.h"
#include "layMarker.h"
#include "layNetInfoDialog.h"
#include "tlProgress.h"
#include "dbLayoutToNetlist.h"
#include "dbNetlistDeviceClasses.h"
@ -1203,8 +1204,16 @@ NetlistBrowserModel::hasChildren (const QModelIndex &parent) const
}
QVariant
NetlistBrowserModel::headerData (int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const
NetlistBrowserModel::headerData (int section, Qt::Orientation /*orientation*/, int role) const
{
if (role == Qt::DisplayRole) {
if (section == 0) {
return tr ("Object");
} else if (section == 1) {
return tr ("Attribute");
}
}
return QVariant ();
}
@ -1295,6 +1304,13 @@ NetlistBrowserModel::colors_changed ()
emit dataChanged (index (0, 0, QModelIndex ()), index (rowCount (QModelIndex()) - 1, 0, QModelIndex ()));
}
QModelIndex
NetlistBrowserModel::index_from_net (const db::Net *net) const
{
void *id = make_id_circuit_net (circuit_index (net->circuit ()), net_index (net));
return index_from_id (id, 0);
}
const db::Net *
NetlistBrowserModel::net_from_index (const QModelIndex &index) const
{
@ -1818,6 +1834,18 @@ NetlistBrowserPage::current_index_changed (const QModelIndex &index)
}
}
void
NetlistBrowserPage::select_net (const db::Net *net)
{
if (! net || ! net->circuit ()) {
directory_tree->clearSelection ();
} else {
NetlistBrowserModel *model = dynamic_cast<NetlistBrowserModel *> (directory_tree->model ());
tl_assert (model != 0);
directory_tree->setCurrentIndex (model->index_from_net (net));
}
}
std::vector<const db::Net *>
NetlistBrowserPage::selected_nets ()
{
@ -1962,15 +1990,21 @@ NetlistBrowserPage::info_button_pressed ()
static QModelIndex find_next (QAbstractItemModel *model, const QRegExp &to_find, const QModelIndex &from)
{
if (! from.isValid ()) {
return from;
QModelIndex index = from;
if (! index.isValid () && model->hasChildren (index)) {
index = model->index (0, 0, index);
}
if (! index.isValid ()) {
return index;
}
QModelIndex current = index;
std::vector<QModelIndex> parent_stack;
std::vector<std::pair<int, int> > rows_stack;
QModelIndex index = from;
while (index.isValid ()) {
parent_stack.push_back (model->parent (index));
@ -1983,13 +2017,15 @@ static QModelIndex find_next (QAbstractItemModel *model, const QRegExp &to_find,
std::reverse (parent_stack.begin (), parent_stack.end ());
std::reverse (rows_stack.begin (), rows_stack.end ());
QModelIndex current = from;
tl::AbsoluteProgress progress (tl::to_string (tr ("Searching ...")));
do {
++progress;
bool has_next = false;
if (model->hasChildren (current)) {
if (model->hasChildren (current) && rows_stack.size () < 2) {
int row_count = model->rowCount (current);
if (row_count > 0) {
@ -2008,7 +2044,7 @@ static QModelIndex find_next (QAbstractItemModel *model, const QRegExp &to_find,
++rows_stack.back ().first;
if (rows_stack.back ().first == rows_stack.back ().second) {
if (rows_stack.back ().first >= rows_stack.back ().second) {
// up
current = parent_stack.back ();
@ -2033,7 +2069,7 @@ static QModelIndex find_next (QAbstractItemModel *model, const QRegExp &to_find,
}
} while (current != from);
} while (current.internalPointer () != from.internalPointer () || current.row () != from.row ());
return QModelIndex ();
}
@ -2098,6 +2134,7 @@ NetlistBrowserPage::set_l2ndb (db::LayoutToNetlist *database)
// NOTE: with the tree as the parent, the tree will take over ownership of the model
NetlistBrowserModel *new_model = new NetlistBrowserModel (directory_tree, database, &m_colorizer);
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 (net_selection_changed ()));

View File

@ -123,6 +123,7 @@ public:
QModelIndex index_from_id (void *id, int column) const;
const db::Net *net_from_index (const QModelIndex &index) const;
QModelIndex index_from_net (const db::Net *net) const;
private slots:
void colors_changed ();
@ -252,6 +253,10 @@ public:
*/
void set_l2ndb (db::LayoutToNetlist *database);
/**
* @brief Selects a net or clears the selection if net == 0
*/
void select_net (const db::Net *net);
/**
* @brief Set the window type and window dimensions