mirror of https://github.com/KLayout/klayout.git
Netlist browser: some bug fixes in search, probe net feature.
This commit is contained in:
parent
4e15b3df92
commit
60216ee3f6
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ()));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue