aboutsummaryrefslogtreecommitdiffstats
path: root/gui
diff options
context:
space:
mode:
authorEddie Hung <eddie.hung+gitlab@gmail.com>2018-07-24 01:19:09 +0000
committerEddie Hung <eddie.hung+gitlab@gmail.com>2018-07-24 01:19:09 +0000
commit30ec1cfbd7dd02578fa2a3e33612e863f01ea959 (patch)
treee77d130f96c8061374318f036856aa73d431017d /gui
parenteeb93d6eda613c0946867118c1ff93f2462e417f (diff)
parent771edd1fda8692930e186a8913b7588d18fda710 (diff)
downloadnextpnr-30ec1cfbd7dd02578fa2a3e33612e863f01ea959.tar.gz
nextpnr-30ec1cfbd7dd02578fa2a3e33612e863f01ea959.tar.bz2
nextpnr-30ec1cfbd7dd02578fa2a3e33612e863f01ea959.zip
Merge branch 'redist_slack' into 'redist_slack'
Update budgets during routing See merge request SymbioticEDA/nextpnr!15
Diffstat (limited to 'gui')
-rw-r--r--gui/designwidget.cc23
-rw-r--r--gui/fpgaviewwidget.cc202
-rw-r--r--gui/fpgaviewwidget.h114
-rw-r--r--gui/ice40/mainwindow.cc2
4 files changed, 243 insertions, 98 deletions
diff --git a/gui/designwidget.cc b/gui/designwidget.cc
index a59307f0..91ec5163 100644
--- a/gui/designwidget.cc
+++ b/gui/designwidget.cc
@@ -497,6 +497,14 @@ void DesignWidget::onItemSelectionChanged()
addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->getConflictingBelCell(bel).c_str(ctx),
ElementType::CELL);
+ QtProperty *belpinsItem = addSubGroup(topItem, "Ports");
+ for (const auto &item : ctx->getBelPins(bel)) {
+ QtProperty *portInfoItem = addSubGroup(belpinsItem, ctx->portPinToId(item).c_str(ctx));
+ addProperty(portInfoItem, QVariant::String, "Name", ctx->portPinToId(item).c_str(ctx));
+ addProperty(portInfoItem, QVariant::Int, "Type", int(ctx->getBelPinType(bel, item)));
+ WireId wire = ctx->getBelPinWire(bel, item);
+ addProperty(portInfoItem, QVariant::String, "Wire", ctx->getWireName(wire).c_str(ctx), ElementType::WIRE);
+ }
} else if (type == ElementType::WIRE) {
WireId wire = ctx->getWireByName(c);
QtProperty *topItem = addTopLevelProperty("Wire");
@@ -515,23 +523,14 @@ void DesignWidget::onItemSelectionChanged()
addProperty(delayItem, QVariant::Double, "Min Fall", delay.minFallDelay());
addProperty(delayItem, QVariant::Double, "Max Fall", delay.maxFallDelay());
- QtProperty *belpinItem = addSubGroup(topItem, "BelPin Uphill");
- BelPin uphill = ctx->getBelPinUphill(wire);
- if (uphill.bel != BelId())
- addProperty(belpinItem, QVariant::String, "Bel", ctx->getBelName(uphill.bel).c_str(ctx), ElementType::BEL);
- else
- addProperty(belpinItem, QVariant::String, "Bel", "", ElementType::BEL);
-
- addProperty(belpinItem, QVariant::String, "PortPin", ctx->portPinToId(uphill.pin).c_str(ctx), ElementType::BEL);
-
- QtProperty *downhillItem = addSubGroup(topItem, "BelPin Downhill");
- for (const auto &item : ctx->getBelPinsDownhill(wire)) {
+ QtProperty *belpinsItem = addSubGroup(topItem, "BelPins");
+ for (const auto &item : ctx->getWireBelPins(wire)) {
QString belname = "";
if (item.bel != BelId())
belname = ctx->getBelName(item.bel).c_str(ctx);
QString pinname = ctx->portPinToId(item.pin).c_str(ctx);
- QtProperty *dhItem = addSubGroup(downhillItem, belname + "-" + pinname);
+ QtProperty *dhItem = addSubGroup(belpinsItem, belname + "-" + pinname);
addProperty(dhItem, QVariant::String, "Bel", belname, ElementType::BEL);
addProperty(dhItem, QVariant::String, "PortPin", pinname);
}
diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc
index c926e5fa..9343419b 100644
--- a/gui/fpgaviewwidget.cc
+++ b/gui/fpgaviewwidget.cc
@@ -241,26 +241,26 @@ void LineShader::draw(const LineShaderData &line, const QColor &color, float thi
}
FPGAViewWidget::FPGAViewWidget(QWidget *parent)
- : QOpenGLWidget(parent), lineShader_(this), zoom_(500.f), ctx_(nullptr), selectedItemsChanged_(false)
+ : QOpenGLWidget(parent), lineShader_(this), zoom_(500.f), ctx_(nullptr), paintTimer_(this),
+ rendererData_(new FPGAViewWidget::RendererData), rendererArgs_(new FPGAViewWidget::RendererArgs)
{
- backgroundColor_ = QColor("#000000");
- gridColor_ = QColor("#333");
- gFrameColor_ = QColor("#d0d0d0");
- gHiddenColor_ = QColor("#606060");
- gInactiveColor_ = QColor("#303030");
- gActiveColor_ = QColor("#f0f0f0");
- gSelectedColor_ = QColor("#ff6600");
- frameColor_ = QColor("#0066ba");
- highlightColors[0] = QColor("#6495ed");
- highlightColors[1] = QColor("#7fffd4");
- highlightColors[2] = QColor("#98fb98");
- highlightColors[3] = QColor("#ffd700");
- highlightColors[4] = QColor("#cd5c5c");
- highlightColors[5] = QColor("#fa8072");
- highlightColors[6] = QColor("#ff69b4");
- highlightColors[7] = QColor("#da70d6");
- for (int i = 0; i < 8; i++)
- highlightItemsChanged_[i] = false;
+ colors_.background = QColor("#000000");
+ colors_.grid = QColor("#333");
+ colors_.frame = QColor("#d0d0d0");
+ colors_.hidden = QColor("#606060");
+ colors_.inactive = QColor("#303030");
+ colors_.active = QColor("#f0f0f0");
+ colors_.selected = QColor("#ff6600");
+ colors_.highlight[0] = QColor("#6495ed");
+ colors_.highlight[1] = QColor("#7fffd4");
+ colors_.highlight[2] = QColor("#98fb98");
+ colors_.highlight[3] = QColor("#ffd700");
+ colors_.highlight[4] = QColor("#cd5c5c");
+ colors_.highlight[5] = QColor("#fa8072");
+ colors_.highlight[6] = QColor("#ff69b4");
+ colors_.highlight[7] = QColor("#da70d6");
+
+ rendererArgs_->highlightedOrSelectedChanged = false;
auto fmt = format();
fmt.setMajorVersion(3);
@@ -268,7 +268,6 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent)
setFormat(fmt);
fmt = format();
- // printf("FPGAViewWidget running on OpenGL %d.%d\n", fmt.majorVersion(), fmt.minorVersion());
if (fmt.majorVersion() < 3) {
printf("Could not get OpenGL 3.0 context. Aborting.\n");
log_abort();
@@ -276,6 +275,13 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent)
if (fmt.minorVersion() < 1) {
printf("Could not get OpenGL 3.1 context - trying anyway...\n ");
}
+
+ connect(&paintTimer_, SIGNAL(timeout()), this, SLOT(update()));
+ paintTimer_.start(1000 / 20); // paint GL 20 times per second
+
+ renderRunner_ = std::unique_ptr<PeriodicRunner>(new PeriodicRunner(this, [this] { renderLines(); }));
+ renderRunner_->start();
+ renderRunner_->startTimer(1000 / 2); // render lines 2 times per second
}
FPGAViewWidget::~FPGAViewWidget() {}
@@ -283,8 +289,7 @@ FPGAViewWidget::~FPGAViewWidget() {}
void FPGAViewWidget::newContext(Context *ctx)
{
ctx_ = ctx;
- selectedItems_.clear();
- update();
+ pokeRenderer();
}
QSize FPGAViewWidget::minimumSizeHint() const { return QSize(640, 480); }
@@ -297,7 +302,8 @@ void FPGAViewWidget::initializeGL()
log_error("Could not compile shader.\n");
}
initializeOpenGLFunctions();
- glClearColor(backgroundColor_.red() / 255, backgroundColor_.green() / 255, backgroundColor_.blue() / 255, 0.0);
+ glClearColor(colors_.background.red() / 255, colors_.background.green() / 255, colors_.background.blue() / 255,
+ 0.0);
}
void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal)
@@ -398,67 +404,143 @@ void FPGAViewWidget::paintGL()
PolyLine(-100.0f, i, 100.0f, i).build(grid);
PolyLine(i, -100.0f, i, 100.0f).build(grid);
}
- lineShader_.draw(grid, gridColor_, thick1Px, matrix);
+ lineShader_.draw(grid, colors_.grid, thick1Px, matrix);
- LineShaderData shaders[4] = {LineShaderData(), LineShaderData(), LineShaderData(), LineShaderData()};
+ rendererDataLock_.lock();
+ lineShader_.draw(rendererData_->decals[0], colors_.frame, thick11Px, matrix);
+ lineShader_.draw(rendererData_->decals[1], colors_.hidden, thick11Px, matrix);
+ lineShader_.draw(rendererData_->decals[2], colors_.inactive, thick11Px, matrix);
+ lineShader_.draw(rendererData_->decals[3], colors_.active, thick11Px, matrix);
- if (ctx_) {
- // Draw Bels.
+ for (int i = 0; i < 8; i++)
+ lineShader_.draw(rendererData_->highlighted[i], colors_.highlight[i], thick11Px, matrix);
+
+ lineShader_.draw(rendererData_->selected, colors_.selected, thick11Px, matrix);
+ rendererDataLock_.unlock();
+}
+
+void FPGAViewWidget::pokeRenderer(void) { renderRunner_->poke(); }
+
+void FPGAViewWidget::renderLines(void)
+{
+ if (ctx_ == nullptr)
+ return;
+
+ ctx_->lock_ui();
+
+ // For now, collapse any decal changes into change of all decals.
+ // TODO(q3k): fix this
+ bool decalsChanged = false;
+ if (ctx_->allUiReload) {
+ ctx_->allUiReload = false;
+ decalsChanged = true;
+ }
+ if (ctx_->frameUiReload) {
+ ctx_->frameUiReload = false;
+ decalsChanged = true;
+ }
+ if (ctx_->belUiReload.size() > 0) {
+ ctx_->belUiReload.clear();
+ decalsChanged = true;
+ }
+ if (ctx_->wireUiReload.size() > 0) {
+ ctx_->wireUiReload.clear();
+ decalsChanged = true;
+ }
+ if (ctx_->pipUiReload.size() > 0) {
+ ctx_->pipUiReload.clear();
+ decalsChanged = true;
+ }
+ if (ctx_->groupUiReload.size() > 0) {
+ ctx_->groupUiReload.clear();
+ decalsChanged = true;
+ }
+
+ // Local copy of decals, taken as fast as possible to not block the P&R.
+ std::vector<DecalXY> belDecals;
+ std::vector<DecalXY> wireDecals;
+ std::vector<DecalXY> pipDecals;
+ std::vector<DecalXY> groupDecals;
+ if (decalsChanged) {
for (auto bel : ctx_->getBels()) {
- drawDecal(shaders, ctx_->getBelDecal(bel));
+ belDecals.push_back(ctx_->getBelDecal(bel));
}
- // Draw Wires.
for (auto wire : ctx_->getWires()) {
- drawDecal(shaders, ctx_->getWireDecal(wire));
+ wireDecals.push_back(ctx_->getWireDecal(wire));
}
- // Draw Pips.
for (auto pip : ctx_->getPips()) {
- drawDecal(shaders, ctx_->getPipDecal(pip));
+ pipDecals.push_back(ctx_->getPipDecal(pip));
}
- // Draw Groups.
for (auto group : ctx_->getGroups()) {
- drawDecal(shaders, ctx_->getGroupDecal(group));
+ groupDecals.push_back(ctx_->getGroupDecal(group));
}
+ }
+ ctx_->unlock_ui();
- if (selectedItemsChanged_) {
- selectedItemsChanged_ = false;
- selectedShader_.clear();
- for (auto decal : selectedItems_) {
- drawDecal(selectedShader_, decal);
- }
+ rendererArgsLock_.lock();
+ auto selectedItems = rendererArgs_->selectedItems;
+ auto highlightedItems = rendererArgs_->highlightedItems;
+ auto highlightedOrSelectedChanged = rendererArgs_->highlightedOrSelectedChanged;
+ rendererArgs_->highlightedOrSelectedChanged = false;
+ rendererArgsLock_.unlock();
+
+ if (decalsChanged) {
+ auto data = std::unique_ptr<FPGAViewWidget::RendererData>(new FPGAViewWidget::RendererData);
+ // Draw Bels.
+ for (auto const &decal : belDecals) {
+ drawDecal(data->decals, decal);
+ }
+ // Draw Wires.
+ for (auto const &decal : wireDecals) {
+ drawDecal(data->decals, decal);
+ }
+ // Draw Pips.
+ for (auto const &decal : pipDecals) {
+ drawDecal(data->decals, decal);
+ }
+ // Draw Groups.
+ for (auto const &decal : groupDecals) {
+ drawDecal(data->decals, decal);
+ }
+
+ // Swap over.
+ rendererDataLock_.lock();
+ rendererData_ = std::move(data);
+ rendererDataLock_.unlock();
+ }
+
+ rendererDataLock_.lock();
+ if (decalsChanged || highlightedOrSelectedChanged) {
+ rendererData_->selected.clear();
+ for (auto &decal : selectedItems) {
+ drawDecal(rendererData_->selected, decal);
}
for (int i = 0; i < 8; i++) {
- if (highlightItemsChanged_[i]) {
- highlightItemsChanged_[i] = false;
- highlightShader_[i].clear();
- for (auto decal : highlightItems_[i]) {
- drawDecal(highlightShader_[i], decal);
- }
+ rendererData_->highlighted[i].clear();
+ for (auto &decal : highlightedItems[i]) {
+ drawDecal(rendererData_->highlighted[i], decal);
}
}
}
-
- lineShader_.draw(shaders[0], gFrameColor_, thick11Px, matrix);
- lineShader_.draw(shaders[1], gHiddenColor_, thick11Px, matrix);
- lineShader_.draw(shaders[2], gInactiveColor_, thick11Px, matrix);
- lineShader_.draw(shaders[3], gActiveColor_, thick11Px, matrix);
- for (int i = 0; i < 8; i++)
- lineShader_.draw(highlightShader_[i], highlightColors[i], thick11Px, matrix);
- lineShader_.draw(selectedShader_, gSelectedColor_, thick11Px, matrix);
+ rendererDataLock_.unlock();
}
void FPGAViewWidget::onSelectedArchItem(std::vector<DecalXY> decals)
{
- selectedItems_ = decals;
- selectedItemsChanged_ = true;
- update();
+ rendererArgsLock_.lock();
+ rendererArgs_->selectedItems = decals;
+ rendererArgs_->highlightedOrSelectedChanged = true;
+ rendererArgsLock_.unlock();
+ pokeRenderer();
}
void FPGAViewWidget::onHighlightGroupChanged(std::vector<DecalXY> decals, int group)
{
- highlightItems_[group] = decals;
- highlightItemsChanged_[group] = true;
- update();
+ rendererArgsLock_.lock();
+ rendererArgs_->highlightedItems[group] = decals;
+ rendererArgs_->highlightedOrSelectedChanged = true;
+ rendererArgsLock_.unlock();
+ pokeRenderer();
}
void FPGAViewWidget::resizeGL(int width, int height) {}
diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h
index 33eb2800..b87c5d0a 100644
--- a/gui/fpgaviewwidget.h
+++ b/gui/fpgaviewwidget.h
@@ -21,12 +21,16 @@
#define MAPGLWIDGET_H
#include <QMainWindow>
+#include <QMutex>
#include <QOpenGLBuffer>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLWidget>
#include <QPainter>
+#include <QThread>
+#include <QTimer>
+#include <QWaitCondition>
#include "nextpnr.h"
@@ -206,17 +210,58 @@ class LineShader
void draw(const LineShaderData &data, const QColor &color, float thickness, const QMatrix4x4 &projection);
};
+class PeriodicRunner : public QThread
+{
+ Q_OBJECT
+ private:
+ QMutex mutex_;
+ QWaitCondition condition_;
+ bool abort_;
+ std::function<void()> target_;
+ QTimer timer_;
+
+ public:
+ explicit PeriodicRunner(QObject *parent, std::function<void()> target)
+ : QThread(parent), abort_(false), target_(target), timer_(this)
+ {
+ connect(&timer_, &QTimer::timeout, this, &PeriodicRunner::poke);
+ }
+
+ void run(void) override
+ {
+ for (;;) {
+ mutex_.lock();
+ condition_.wait(&mutex_);
+
+ if (abort_) {
+ mutex_.unlock();
+ return;
+ }
+
+ target_();
+
+ mutex_.unlock();
+ }
+ }
+
+ void startTimer(int msecs) { timer_.start(msecs); }
+
+ ~PeriodicRunner()
+ {
+ mutex_.lock();
+ abort_ = true;
+ condition_.wakeOne();
+ mutex_.unlock();
+
+ wait();
+ }
+
+ void poke(void) { condition_.wakeOne(); }
+};
+
class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
- Q_PROPERTY(QColor backgroundColor MEMBER backgroundColor_ DESIGNABLE true)
- Q_PROPERTY(QColor gridColor MEMBER gridColor_ DESIGNABLE true)
- Q_PROPERTY(QColor gFrameColor MEMBER gFrameColor_ DESIGNABLE true)
- Q_PROPERTY(QColor gHiddenColor MEMBER gHiddenColor_ DESIGNABLE true)
- Q_PROPERTY(QColor gInactiveColor MEMBER gInactiveColor_ DESIGNABLE true)
- Q_PROPERTY(QColor gActiveColor MEMBER gActiveColor_ DESIGNABLE true)
- Q_PROPERTY(QColor gSelectedColor MEMBER gSelectedColor_ DESIGNABLE true)
- Q_PROPERTY(QColor frameColor MEMBER frameColor_ DESIGNABLE true)
public:
FPGAViewWidget(QWidget *parent = 0);
@@ -246,8 +291,11 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
void newContext(Context *ctx);
void onSelectedArchItem(std::vector<DecalXY> decals);
void onHighlightGroupChanged(std::vector<DecalXY> decals, int group);
+ void pokeRenderer(void);
private:
+ void renderLines(void);
+
QPoint lastPos_;
LineShader lineShader_;
QMatrix4x4 viewMove_;
@@ -262,24 +310,40 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
const float zoomLvl2_ = 50.0f;
Context *ctx_;
+ QTimer paintTimer_;
+
+ std::unique_ptr<PeriodicRunner> renderRunner_;
- QColor backgroundColor_;
- QColor gridColor_;
- QColor gFrameColor_;
- QColor gHiddenColor_;
- QColor gInactiveColor_;
- QColor gActiveColor_;
- QColor gSelectedColor_;
- QColor frameColor_;
-
- LineShaderData selectedShader_;
- std::vector<DecalXY> selectedItems_;
- bool selectedItemsChanged_;
-
- LineShaderData highlightShader_[8];
- std::vector<DecalXY> highlightItems_[8];
- bool highlightItemsChanged_[8];
- QColor highlightColors[8];
+ struct
+ {
+ QColor background;
+ QColor grid;
+ QColor frame;
+ QColor hidden;
+ QColor inactive;
+ QColor active;
+ QColor selected;
+ QColor highlight[8];
+ } colors_;
+
+ struct RendererData
+ {
+ LineShaderData decals[4];
+ LineShaderData selected;
+ LineShaderData highlighted[8];
+ };
+
+ struct RendererArgs
+ {
+ std::vector<DecalXY> selectedItems;
+ std::vector<DecalXY> highlightedItems[8];
+ bool highlightedOrSelectedChanged;
+ };
+
+ std::unique_ptr<RendererData> rendererData_;
+ QMutex rendererDataLock_;
+ std::unique_ptr<RendererArgs> rendererArgs_;
+ QMutex rendererArgsLock_;
};
NEXTPNR_NAMESPACE_END
diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc
index 847698c5..810a98ae 100644
--- a/gui/ice40/mainwindow.cc
+++ b/gui/ice40/mainwindow.cc
@@ -222,7 +222,7 @@ void MainWindow::new_proj()
QString package = QInputDialog::getItem(this, "Select package", "Package:", getSupportedPackages(chipArgs.type),
0, false, &ok);
- if (ok && !item.isEmpty()) {
+ if (ok && !item.isEmpty()) {
currentProj = "";
currentJson = "";
currentPCF = "";