diff --git a/gui/base.qrc b/gui/base.qrc index 85d1432a..63612bf4 100644 --- a/gui/base.qrc +++ b/gui/base.qrc @@ -24,5 +24,9 @@ resources/open_json.png resources/save_json.png resources/py.png + resources/bel.png + resources/wire.png + resources/pip.png + resources/group.png diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 550a4b93..7290f73c 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -225,6 +225,38 @@ void BaseMainWindow::createMenusAndBars() actionZoomOutbound->setIcon(QIcon(":/icons/resources/shape_square.png")); connect(actionZoomOutbound, &QAction::triggered, fpgaView, &FPGAViewWidget::zoomOutbound); + actionDisplayBel = new QAction("Enable/Disable Bels", this); + actionDisplayBel->setIcon(QIcon(":/icons/resources/bel.png")); + actionDisplayBel->setCheckable(true); + actionDisplayBel->setChecked(true); + connect(actionDisplayBel, &QAction::triggered, this, &BaseMainWindow::enableDisableDecals); + + actionDisplayWire = new QAction("Enable/Disable Wires", this); + actionDisplayWire->setIcon(QIcon(":/icons/resources/wire.png")); + actionDisplayWire->setCheckable(true); + actionDisplayWire->setChecked(true); + connect(actionDisplayWire, &QAction::triggered, this, &BaseMainWindow::enableDisableDecals); + + actionDisplayPip = new QAction("Enable/Disable Pips", this); + actionDisplayPip->setIcon(QIcon(":/icons/resources/pip.png")); + actionDisplayPip->setCheckable(true); +#ifdef ARCH_ECP5 + actionDisplayPip->setChecked(false); +#else + actionDisplayPip->setChecked(true); +#endif + connect(actionDisplayPip, &QAction::triggered, this, &BaseMainWindow::enableDisableDecals); + + actionDisplayGroups = new QAction("Enable/Disable Groups", this); + actionDisplayGroups->setIcon(QIcon(":/icons/resources/group.png")); + actionDisplayGroups->setCheckable(true); + actionDisplayGroups->setChecked(true); + connect(actionDisplayGroups, &QAction::triggered, this, &BaseMainWindow::enableDisableDecals); + + // set initial state + fpgaView->enableDisableDecals(actionDisplayBel->isChecked(), actionDisplayWire->isChecked(), + actionDisplayPip->isChecked(), actionDisplayGroups->isChecked()); + // Add main menu menuBar = new QMenuBar(); menuBar->setGeometry(QRect(0, 0, 1024, 27)); @@ -281,6 +313,11 @@ void BaseMainWindow::createMenusAndBars() deviceViewToolBar->addAction(actionZoomOut); deviceViewToolBar->addAction(actionZoomSelected); deviceViewToolBar->addAction(actionZoomOutbound); + deviceViewToolBar->addSeparator(); + deviceViewToolBar->addAction(actionDisplayBel); + deviceViewToolBar->addAction(actionDisplayWire); + deviceViewToolBar->addAction(actionDisplayPip); + deviceViewToolBar->addAction(actionDisplayGroups); // Add status bar with progress bar statusBar = new QStatusBar(); @@ -293,6 +330,13 @@ void BaseMainWindow::createMenusAndBars() setStatusBar(statusBar); } +void BaseMainWindow::enableDisableDecals() +{ + fpgaView->enableDisableDecals(actionDisplayBel->isChecked(), actionDisplayWire->isChecked(), + actionDisplayPip->isChecked(), actionDisplayGroups->isChecked()); + ctx->refreshUi(); +} + void BaseMainWindow::open_json() { QString fileName = QFileDialog::getOpenFileName(this, QString("Open JSON"), QString(), QString("*.json")); diff --git a/gui/basewindow.h b/gui/basewindow.h index 305cb6c9..7562307e 100644 --- a/gui/basewindow.h +++ b/gui/basewindow.h @@ -56,6 +56,7 @@ class BaseMainWindow : public QMainWindow protected: void createMenusAndBars(); void disableActions(); + void enableDisableDecals(); virtual void onDisableActions(){}; virtual void onUpdateActions(){}; @@ -122,6 +123,11 @@ class BaseMainWindow : public QMainWindow QAction *actionPlay; QAction *actionPause; QAction *actionStop; + + QAction *actionDisplayBel; + QAction *actionDisplayWire; + QAction *actionDisplayPip; + QAction *actionDisplayGroups; }; NEXTPNR_NAMESPACE_END diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index f2929d6e..2e1bbf63 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -66,6 +66,11 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) renderRunner_->start(); renderRunner_->startTimer(1000 / 2); // render lines 2 times per second setMouseTracking(true); + + displayBel_ = false; + displayWire_ = false; + displayPip_ = false; + displayGroup_ = false; } FPGAViewWidget::~FPGAViewWidget() {} @@ -333,6 +338,14 @@ void FPGAViewWidget::paintGL() void FPGAViewWidget::pokeRenderer(void) { renderRunner_->poke(); } +void FPGAViewWidget::enableDisableDecals(bool bels, bool wires, bool pips, bool groups) +{ + displayBel_ = bels; + displayWire_ = wires; + displayPip_ = pips; + displayGroup_ = groups; +} + void FPGAViewWidget::renderLines(void) { if (ctx_ == nullptr) @@ -379,17 +392,25 @@ void FPGAViewWidget::renderLines(void) // Local copy of decals, taken as fast as possible to not block the P&R. if (decalsChanged) { - for (auto bel : ctx_->getBels()) { - belDecals.push_back({ctx_->getBelDecal(bel), bel}); + if (displayBel_) { + for (auto bel : ctx_->getBels()) { + belDecals.push_back({ctx_->getBelDecal(bel), bel}); + } } - for (auto wire : ctx_->getWires()) { - wireDecals.push_back({ctx_->getWireDecal(wire), wire}); + if (displayWire_) { + for (auto wire : ctx_->getWires()) { + wireDecals.push_back({ctx_->getWireDecal(wire), wire}); + } } - for (auto pip : ctx_->getPips()) { - pipDecals.push_back({ctx_->getPipDecal(pip), pip}); + if (displayPip_) { + for (auto pip : ctx_->getPips()) { + pipDecals.push_back({ctx_->getPipDecal(pip), pip}); + } } - for (auto group : ctx_->getGroups()) { - groupDecals.push_back({ctx_->getGroupDecal(group), group}); + if (displayGroup_) { + for (auto group : ctx_->getGroups()) { + groupDecals.push_back({ctx_->getGroupDecal(group), group}); + } } } } @@ -430,20 +451,28 @@ void FPGAViewWidget::renderLines(void) data->bbGlobal.clear(); // Draw Bels. - for (auto const &decal : belDecals) { - renderArchDecal(data->gfxByStyle, data->bbGlobal, decal.first); + if (displayBel_) { + for (auto const &decal : belDecals) { + renderArchDecal(data->gfxByStyle, data->bbGlobal, decal.first); + } } // Draw Wires. - for (auto const &decal : wireDecals) { - renderArchDecal(data->gfxByStyle, data->bbGlobal, decal.first); + if (displayWire_) { + for (auto const &decal : wireDecals) { + renderArchDecal(data->gfxByStyle, data->bbGlobal, decal.first); + } } // Draw Pips. - for (auto const &decal : pipDecals) { - renderArchDecal(data->gfxByStyle, data->bbGlobal, decal.first); + if (displayPip_) { + for (auto const &decal : pipDecals) { + renderArchDecal(data->gfxByStyle, data->bbGlobal, decal.first); + } } // Draw Groups. - for (auto const &decal : groupDecals) { - renderArchDecal(data->gfxByStyle, data->bbGlobal, decal.first); + if (displayGroup_) { + for (auto const &decal : groupDecals) { + renderArchDecal(data->gfxByStyle, data->bbGlobal, decal.first); + } } // Bounding box should be calculated by now. diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index c5ce9b18..735590ba 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -119,6 +119,7 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions void zoomOut(); void zoomSelected(); void zoomOutbound(); + void enableDisableDecals(bool bels, bool wires, bool pips, bool groups); Q_SIGNALS: void clickedBel(BelId bel, bool add); @@ -227,6 +228,11 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions QMatrix4x4 viewMove_; float zoom_; + bool displayBel_; + bool displayWire_; + bool displayPip_; + bool displayGroup_; + struct { QColor background; diff --git a/gui/resources/bel.png b/gui/resources/bel.png new file mode 100644 index 00000000..2aab6d46 Binary files /dev/null and b/gui/resources/bel.png differ diff --git a/gui/resources/group.png b/gui/resources/group.png new file mode 100644 index 00000000..2d508549 Binary files /dev/null and b/gui/resources/group.png differ diff --git a/gui/resources/pip.png b/gui/resources/pip.png new file mode 100644 index 00000000..7bd87ae8 Binary files /dev/null and b/gui/resources/pip.png differ diff --git a/gui/resources/wire.png b/gui/resources/wire.png new file mode 100644 index 00000000..5fa55d90 Binary files /dev/null and b/gui/resources/wire.png differ