From 0bd73c19778c9bdbc8e6d85c120715e239a9bc0d Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 26 Jun 2018 15:47:22 +0200 Subject: [PATCH] Make GUI use recreated context --- common/nextpnr.h | 2 +- dummy/main.cc | 2 +- gui/basewindow.cc | 11 ++++-- gui/basewindow.h | 5 ++- gui/designwidget.cc | 83 ++++++++++++++++++++++++----------------- gui/designwidget.h | 5 ++- gui/dummy/mainwindow.cc | 4 +- gui/dummy/mainwindow.h | 2 +- gui/fpgaviewwidget.cc | 34 +++++++++-------- gui/fpgaviewwidget.h | 4 +- gui/ice40/mainwindow.cc | 26 +++++++++++-- gui/ice40/mainwindow.h | 4 +- gui/ice40/worker.cc | 14 +++++-- gui/ice40/worker.h | 6 ++- ice40/main.cc | 2 +- 15 files changed, 130 insertions(+), 74 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index c6c0f2ab..efe5936f 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -200,7 +200,7 @@ struct BaseCtx BaseCtx() { - assert(IdString::global_ctx == nullptr); + //assert(IdString::global_ctx == nullptr); IdString::global_ctx = this; idstring_str_to_idx = new std::unordered_map; diff --git a/dummy/main.cc b/dummy/main.cc index 47402f82..de578ca3 100644 --- a/dummy/main.cc +++ b/dummy/main.cc @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) #ifndef NO_GUI if (vm.count("gui")) { Application a(argc, argv); - MainWindow w(&ctx); + MainWindow w; w.show(); rc = a.exec(); diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 20b48dd3..dd456e07 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -36,7 +36,7 @@ static void initBasenameResource() { Q_INIT_RESOURCE(base); } NEXTPNR_NAMESPACE_BEGIN -BaseMainWindow::BaseMainWindow(Context *_ctx, QWidget *parent) : QMainWindow(parent), ctx(_ctx) +BaseMainWindow::BaseMainWindow(QWidget *parent) : QMainWindow(parent), ctx(nullptr) { initBasenameResource(); qRegisterMetaType(); @@ -63,10 +63,12 @@ BaseMainWindow::BaseMainWindow(Context *_ctx, QWidget *parent) : QMainWindow(par setCentralWidget(centralWidget); - DesignWidget *designview = new DesignWidget(ctx); + DesignWidget *designview = new DesignWidget(); designview->setMinimumWidth(300); designview->setMaximumWidth(300); splitter_h->addWidget(designview); + + connect(this, SIGNAL(contextChanged(Context*)), designview, SLOT(newContext(Context*))); connect(designview, SIGNAL(info(std::string)), this, SLOT(writeInfo(std::string))); @@ -78,7 +80,10 @@ BaseMainWindow::BaseMainWindow(Context *_ctx, QWidget *parent) : QMainWindow(par tabWidget->addTab(info, "Info"); centralTabWidget = new QTabWidget(); - centralTabWidget->addTab(new FPGAViewWidget(), "Graphics"); + FPGAViewWidget *fpgaView = new FPGAViewWidget(); + centralTabWidget->addTab(fpgaView, "Graphics"); + + connect(this, SIGNAL(contextChanged(Context*)), fpgaView, SLOT(newContext(Context*))); splitter_v->addWidget(centralTabWidget); splitter_v->addWidget(tabWidget); diff --git a/gui/basewindow.h b/gui/basewindow.h index 038b82c5..601f6acb 100644 --- a/gui/basewindow.h +++ b/gui/basewindow.h @@ -39,7 +39,7 @@ class BaseMainWindow : public QMainWindow Q_OBJECT public: - explicit BaseMainWindow(Context *ctx, QWidget *parent = 0); + explicit BaseMainWindow(QWidget *parent = 0); virtual ~BaseMainWindow(); Context *getContext() { return ctx; } @@ -53,6 +53,9 @@ class BaseMainWindow : public QMainWindow virtual void open_proj() = 0; virtual bool save_proj() = 0; + Q_SIGNALS: + void contextChanged(Context *ctx); + protected: Context *ctx; QTabWidget *tabWidget; diff --git a/gui/designwidget.cc b/gui/designwidget.cc index 326c2649..a989080e 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -82,7 +82,7 @@ class PipTreeItem : public ElementTreeItem IdString data; }; -DesignWidget::DesignWidget(Context *_ctx, QWidget *parent) : QWidget(parent), ctx(_ctx) +DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr) { treeWidget = new QTreeWidget(); @@ -92,39 +92,6 @@ DesignWidget::DesignWidget(Context *_ctx, QWidget *parent) : QWidget(parent), ct treeWidget->setHeaderLabel(QString("Items")); treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); - // Add bels to tree - QTreeWidgetItem *bel_root = new QTreeWidgetItem(treeWidget); - bel_root->setText(0, QString("Bels")); - treeWidget->insertTopLevelItem(0, bel_root); - QList bel_items; - for (auto bel : ctx->getBels()) { - auto name = ctx->getBelName(bel); - bel_items.append(new BelTreeItem(name, ElementType::BEL, QString(name.c_str(ctx)))); - } - bel_root->addChildren(bel_items); - - // Add wires to tree - QTreeWidgetItem *wire_root = new QTreeWidgetItem(treeWidget); - QList wire_items; - wire_root->setText(0, QString("Wires")); - treeWidget->insertTopLevelItem(0, wire_root); - for (auto wire : ctx->getWires()) { - auto name = ctx->getWireName(wire); - wire_items.append(new WireTreeItem(name, ElementType::WIRE, QString(name.c_str(ctx)))); - } - wire_root->addChildren(wire_items); - - // Add pips to tree - QTreeWidgetItem *pip_root = new QTreeWidgetItem(treeWidget); - QList pip_items; - pip_root->setText(0, QString("Pips")); - treeWidget->insertTopLevelItem(0, pip_root); - for (auto pip : ctx->getPips()) { - auto name = ctx->getPipName(pip); - pip_items.append(new PipTreeItem(name, ElementType::PIP, QString(name.c_str(ctx)))); - } - pip_root->addChildren(pip_items); - // Add property view variantManager = new QtVariantPropertyManager(); variantFactory = new QtVariantEditorFactory(); @@ -158,6 +125,54 @@ DesignWidget::~DesignWidget() delete propertyEditor; } +void DesignWidget::newContext(Context *ctx) +{ + treeWidget->clear(); + this->ctx = ctx; + + // Add bels to tree + QTreeWidgetItem *bel_root = new QTreeWidgetItem(treeWidget); + bel_root->setText(0, QString("Bels")); + treeWidget->insertTopLevelItem(0, bel_root); + QList bel_items; + if (ctx) + { + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + bel_items.append(new BelTreeItem(name, ElementType::BEL, QString(name.c_str(ctx)))); + } + } + bel_root->addChildren(bel_items); + + // Add wires to tree + QTreeWidgetItem *wire_root = new QTreeWidgetItem(treeWidget); + QList wire_items; + wire_root->setText(0, QString("Wires")); + treeWidget->insertTopLevelItem(0, wire_root); + if (ctx) + { + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + wire_items.append(new WireTreeItem(name, ElementType::WIRE, QString(name.c_str(ctx)))); + } + } + wire_root->addChildren(wire_items); + + // Add pips to tree + QTreeWidgetItem *pip_root = new QTreeWidgetItem(treeWidget); + QList pip_items; + pip_root->setText(0, QString("Pips")); + treeWidget->insertTopLevelItem(0, pip_root); + if (ctx) + { + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + pip_items.append(new PipTreeItem(name, ElementType::PIP, QString(name.c_str(ctx)))); + } + } + pip_root->addChildren(pip_items); +} + void DesignWidget::addProperty(QtVariantProperty *property, const QString &id) { propertyToId[property] = id; diff --git a/gui/designwidget.h b/gui/designwidget.h index 498e73d7..e3fbb19e 100644 --- a/gui/designwidget.h +++ b/gui/designwidget.h @@ -33,9 +33,8 @@ class DesignWidget : public QWidget Q_OBJECT public: - explicit DesignWidget(Context *ctx, QWidget *parent = 0); + explicit DesignWidget(QWidget *parent = 0); ~DesignWidget(); - Context *getContext() { return ctx; } private: void addProperty(QtVariantProperty *property, const QString &id); @@ -48,6 +47,8 @@ class DesignWidget : public QWidget void prepareMenu(const QPoint &pos); void onItemClicked(QTreeWidgetItem *item, int); void selectObject(); + public Q_SLOTS: + void newContext(Context *ctx); private: Context *ctx; diff --git a/gui/dummy/mainwindow.cc b/gui/dummy/mainwindow.cc index c57d0db0..e86edafd 100644 --- a/gui/dummy/mainwindow.cc +++ b/gui/dummy/mainwindow.cc @@ -23,11 +23,11 @@ static void initMainResource() { Q_INIT_RESOURCE(nextpnr); } NEXTPNR_NAMESPACE_BEGIN -MainWindow::MainWindow(Context *_ctx, QWidget *parent) : BaseMainWindow(_ctx, parent) +MainWindow::MainWindow(QWidget *parent) : BaseMainWindow(parent) { initMainResource(); - std::string title = "nextpnr-dummy - " + ctx->getChipName(); + std::string title = "nextpnr-dummy - [EMPTY]"; setWindowTitle(title.c_str()); createMenu(); diff --git a/gui/dummy/mainwindow.h b/gui/dummy/mainwindow.h index b1b9598f..fd9812cd 100644 --- a/gui/dummy/mainwindow.h +++ b/gui/dummy/mainwindow.h @@ -29,7 +29,7 @@ class MainWindow : public BaseMainWindow Q_OBJECT public: - explicit MainWindow(Context *ctx, QWidget *parent = 0); + explicit MainWindow(QWidget *parent = 0); virtual ~MainWindow(); public: diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index 34e1a761..a2691401 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -241,9 +241,8 @@ void LineShader::draw(const LineShaderData &line, const QMatrix4x4 &projection) } FPGAViewWidget::FPGAViewWidget(QWidget *parent) - : QOpenGLWidget(parent), moveX_(0), moveY_(0), zoom_(10.0f), lineShader_(this) + : QOpenGLWidget(parent), moveX_(0), moveY_(0), zoom_(10.0f), lineShader_(this), ctx_(nullptr) { - ctx_ = qobject_cast(getMainWindow())->getContext(); auto fmt = format(); fmt.setMajorVersion(3); fmt.setMinorVersion(1); @@ -260,17 +259,14 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) } } -QMainWindow *FPGAViewWidget::getMainWindow() -{ - QWidgetList widgets = qApp->topLevelWidgets(); - for (QWidgetList::iterator i = widgets.begin(); i != widgets.end(); ++i) - if ((*i)->objectName() == "BaseMainWindow") - return (QMainWindow *)(*i); - return NULL; -} - FPGAViewWidget::~FPGAViewWidget() {} +void FPGAViewWidget::newContext(Context *ctx) +{ + ctx_ = ctx; + update(); +} + QSize FPGAViewWidget::minimumSizeHint() const { return QSize(640, 480); } QSize FPGAViewWidget::sizeHint() const { return QSize(640, 480); } @@ -359,16 +355,22 @@ void FPGAViewWidget::paintGL() // Draw Bels. auto bels = LineShaderData(0.02f, QColor("#b000ba")); - for (auto bel : ctx_->getBels()) { - for (auto &el : ctx_->getBelGraphics(bel)) - drawElement(bels, el); + if (ctx_) + { + for (auto bel : ctx_->getBels()) { + for (auto &el : ctx_->getBelGraphics(bel)) + drawElement(bels, el); + } } lineShader_.draw(bels, matrix); // Draw Frame Graphics. auto frames = LineShaderData(0.02f, QColor("#0066ba")); - for (auto &el : ctx_->getFrameGraphics()) { - drawElement(frames, el); + if (ctx_) + { + for (auto &el : ctx_->getFrameGraphics()) { + drawElement(frames, el); + } } lineShader_.draw(frames, matrix); } diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index 980571fd..1d878696 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -240,8 +240,8 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; void drawElement(LineShaderData &data, const GraphicElement &el); - QMainWindow *getMainWindow(); - + public Q_SLOTS: + void newContext(Context *ctx); private: QPoint lastPos_; float moveX_; diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index 61ceb3e6..32074adc 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -36,14 +36,14 @@ static void initMainResource() { Q_INIT_RESOURCE(nextpnr); } NEXTPNR_NAMESPACE_BEGIN -MainWindow::MainWindow(Context *_ctx, QWidget *parent) : BaseMainWindow(_ctx, parent), timing_driven(false) +MainWindow::MainWindow(QWidget *parent) : BaseMainWindow(parent), timing_driven(false) { initMainResource(); - std::string title = "nextpnr-ice40 - " + ctx->getChipName(); + std::string title = "nextpnr-ice40 - [EMPTY]"; setWindowTitle(title.c_str()); - task = new TaskManager(_ctx); + task = new TaskManager(); connect(task, SIGNAL(log(std::string)), this, SLOT(writeInfo(std::string))); connect(task, SIGNAL(loadfile_finished(bool)), this, SLOT(loadfile_finished(bool))); @@ -58,6 +58,9 @@ MainWindow::MainWindow(Context *_ctx, QWidget *parent) : BaseMainWindow(_ctx, pa connect(task, SIGNAL(taskStarted()), this, SLOT(taskStarted())); connect(task, SIGNAL(taskPaused()), this, SLOT(taskPaused())); + connect(this, SIGNAL(contextChanged(Context*)), this, SLOT(newContext(Context*))); + connect(this, SIGNAL(contextChanged(Context*)), task, SIGNAL(contextChanged(Context*))); + createMenu(); } @@ -178,12 +181,27 @@ void MainWindow::createMenu() void MainWindow::new_proj() { disableActions(); + ArchArgs chipArgs; + chipArgs.type = ArchArgs::HX1K; + chipArgs.package = "tq144"; + if (ctx) + delete ctx; + ctx = new Context(chipArgs); + + Q_EMIT contextChanged(ctx); + actionLoadJSON->setEnabled(true); } +void MainWindow::newContext(Context *ctx) +{ + std::string title = "nextpnr-ice40 - " + ctx->getChipName(); + setWindowTitle(title.c_str()); +} + void MainWindow::open_proj() { - QString fileName = QFileDialog::getOpenFileName(this, QString("Open Project"), QString(), QString("*.npnr")); + QString fileName = QFileDialog::getOpenFileName(this, QString("Open Project"), QString(), QString("*.proj")); if (!fileName.isEmpty()) { tabWidget->setCurrentWidget(info); diff --git a/gui/ice40/mainwindow.h b/gui/ice40/mainwindow.h index f4037a47..ffeb0473 100644 --- a/gui/ice40/mainwindow.h +++ b/gui/ice40/mainwindow.h @@ -30,7 +30,7 @@ class MainWindow : public BaseMainWindow Q_OBJECT public: - explicit MainWindow(Context *ctx, QWidget *parent = 0); + explicit MainWindow(QWidget *parent = 0); virtual ~MainWindow(); public: @@ -59,6 +59,8 @@ class MainWindow : public BaseMainWindow void taskStarted(); void taskPaused(); + void newContext(Context *ctx); + private: void disableActions(); diff --git a/gui/ice40/worker.cc b/gui/ice40/worker.cc index f6d6d261..c49b8769 100644 --- a/gui/ice40/worker.cc +++ b/gui/ice40/worker.cc @@ -35,7 +35,7 @@ struct WorkerInterruptionRequested { }; -Worker::Worker(Context *_ctx, TaskManager *parent) : ctx(_ctx) +Worker::Worker(TaskManager *parent) : ctx(nullptr) { log_write_function = [this, parent](std::string text) { Q_EMIT log(text); @@ -56,6 +56,11 @@ Worker::Worker(Context *_ctx, TaskManager *parent) : ctx(_ctx) }; } +void Worker::newContext(Context *ctx_) +{ + ctx = ctx_; +} + void Worker::loadfile(const std::string &filename) { Q_EMIT taskStarted(); @@ -136,9 +141,9 @@ void Worker::route() } } -TaskManager::TaskManager(Context *ctx) : toTerminate(false), toPause(false) +TaskManager::TaskManager() : toTerminate(false), toPause(false) { - Worker *worker = new Worker(ctx, this); + Worker *worker = new Worker(this); worker->moveToThread(&workerThread); connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); @@ -151,6 +156,9 @@ TaskManager::TaskManager(Context *ctx) : toTerminate(false), toPause(false) connect(this, &TaskManager::place, worker, &Worker::place); connect(this, &TaskManager::route, worker, &Worker::route); + + connect(this, &TaskManager::contextChanged, worker, &Worker::newContext); + connect(worker, &Worker::log, this, &TaskManager::info); connect(worker, &Worker::loadfile_finished, this, &TaskManager::loadfile_finished); connect(worker, &Worker::loadpcf_finished, this, &TaskManager::loadpcf_finished); diff --git a/gui/ice40/worker.h b/gui/ice40/worker.h index 18f4b2c2..f4369535 100644 --- a/gui/ice40/worker.h +++ b/gui/ice40/worker.h @@ -32,8 +32,9 @@ class Worker : public QObject { Q_OBJECT public: - Worker(Context *ctx, TaskManager *parent); + explicit Worker(TaskManager *parent); public Q_SLOTS: + void newContext(Context *); void loadfile(const std::string &); void loadpcf(const std::string &); void saveasc(const std::string &); @@ -64,7 +65,7 @@ class TaskManager : public QObject QThread workerThread; public: - TaskManager(Context *ctx); + explicit TaskManager(); ~TaskManager(); bool shouldTerminate(); void clearTerminate(); @@ -75,6 +76,7 @@ class TaskManager : public QObject void pause_thread(); void continue_thread(); Q_SIGNALS: + void contextChanged(Context *ctx); void terminate(); void loadfile(const std::string &); void loadpcf(const std::string &); diff --git a/ice40/main.cc b/ice40/main.cc index 7f913bb3..d8435b73 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -399,7 +399,7 @@ int main(int argc, char *argv[]) #ifndef NO_GUI if (vm.count("gui")) { Application a(argc, argv); - MainWindow w(&ctx); + MainWindow w; w.show(); rc = a.exec();