From 2d405f966b4e69b95cd4ea9acbb5438e1fa91e69 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 21 Jun 2018 14:12:02 +0200 Subject: [PATCH 1/2] Add graphics view in tab --- gui/basewindow.cc | 6 +++++- gui/basewindow.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gui/basewindow.cc b/gui/basewindow.cc index fa9528fc..25603322 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -57,7 +57,11 @@ BaseMainWindow::BaseMainWindow(Context *_ctx, QWidget *parent) tabWidget->addTab(new PythonTab(), "Python"); info = new InfoTab(); tabWidget->addTab(info, "Info"); - splitter_v->addWidget(new FPGAViewWidget()); + + centralTabWidget = new QTabWidget(); + centralTabWidget->addTab(new FPGAViewWidget(), "Graphics"); + + splitter_v->addWidget(centralTabWidget); splitter_v->addWidget(tabWidget); } diff --git a/gui/basewindow.h b/gui/basewindow.h index 630e0f84..1d0ac468 100644 --- a/gui/basewindow.h +++ b/gui/basewindow.h @@ -34,6 +34,7 @@ class BaseMainWindow : public QMainWindow protected: Context *ctx; QTabWidget *tabWidget; + QTabWidget *centralTabWidget; InfoTab *info; QMenuBar *menuBar; From 097df1869d654b1214b925fe991aa09d2ef5b3cd Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 21 Jun 2018 15:41:40 +0200 Subject: [PATCH 2/2] Added task manager and worker thread for ice40 --- gui/basewindow.cc | 29 ++------------------- gui/basewindow.h | 9 ++++--- gui/dummy/mainwindow.cc | 9 +++++++ gui/dummy/mainwindow.h | 6 ++++- gui/ice40/mainwindow.cc | 21 +++++++++++++++ gui/ice40/mainwindow.h | 10 ++++++- gui/ice40/worker.cc | 58 +++++++++++++++++++++++++++++++++++++++++ gui/ice40/worker.h | 37 ++++++++++++++++++++++++++ 8 files changed, 147 insertions(+), 32 deletions(-) create mode 100644 gui/ice40/worker.cc create mode 100644 gui/ice40/worker.h diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 25603322..1e6b171f 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -3,28 +3,22 @@ #include #include #include -#include #include "designwidget.h" #include "fpgaviewwidget.h" #include "jsonparse.h" #include "log.h" #include "mainwindow.h" #include "pythontab.h" -//#include "pack.h" -//#include "pcf.h" -#include "place_sa.h" -#include "route.h" -//#include "bitstream.h" -#include "design_utils.h" + BaseMainWindow::BaseMainWindow(Context *_ctx, QWidget *parent) : QMainWindow(parent), ctx(_ctx) { Q_INIT_RESOURCE(nextpnr); + qRegisterMetaType(); log_files.clear(); log_streams.clear(); - log_write_function = [this](std::string text) { info->info(text); }; setObjectName(QStringLiteral("BaseMainWindow")); resize(1024, 768); @@ -121,22 +115,3 @@ void BaseMainWindow::createMenusAndBars() mainToolBar->addAction(actionOpen); mainToolBar->addAction(actionSave); } - -void BaseMainWindow::open() -{ - QString fileName = QFileDialog::getOpenFileName(this, QString(), QString(), - QString("*.json")); - if (!fileName.isEmpty()) { - tabWidget->setCurrentWidget(info); - - std::string fn = fileName.toStdString(); - std::istream *f = new std::ifstream(fn); - - parse_json_file(f, fn, ctx); - - // pack_design(ctx); - print_utilisation(ctx); - } -} - -bool BaseMainWindow::save() { return false; } diff --git a/gui/basewindow.h b/gui/basewindow.h index 1d0ac468..d6915ae9 100644 --- a/gui/basewindow.h +++ b/gui/basewindow.h @@ -14,13 +14,15 @@ // FIXME USING_NEXTPNR_NAMESPACE +Q_DECLARE_METATYPE(std::string) + class BaseMainWindow : public QMainWindow { Q_OBJECT public: explicit BaseMainWindow(Context *ctx, QWidget *parent = 0); - ~BaseMainWindow(); + virtual ~BaseMainWindow(); Context *getContext() { return ctx; } protected: @@ -28,8 +30,9 @@ class BaseMainWindow : public QMainWindow protected Q_SLOTS: void writeInfo(std::string text); - void open(); - bool save(); + + virtual void open() = 0; + virtual bool save() = 0; protected: Context *ctx; diff --git a/gui/dummy/mainwindow.cc b/gui/dummy/mainwindow.cc index a9420524..f714e30e 100644 --- a/gui/dummy/mainwindow.cc +++ b/gui/dummy/mainwindow.cc @@ -16,3 +16,12 @@ void MainWindow::createMenu() QMenu *menu_Custom = new QMenu("&Dummy", menuBar); menuBar->addAction(menu_Custom->menuAction()); } + +void MainWindow::open() +{ +} + +bool MainWindow::save() +{ + return false; +} \ No newline at end of file diff --git a/gui/dummy/mainwindow.h b/gui/dummy/mainwindow.h index e9c8ff77..ea4480fb 100644 --- a/gui/dummy/mainwindow.h +++ b/gui/dummy/mainwindow.h @@ -12,10 +12,14 @@ class MainWindow : public BaseMainWindow public: explicit MainWindow(Context *ctx, QWidget *parent = 0); - ~MainWindow(); + virtual ~MainWindow(); public: void createMenu(); + + protected Q_SLOTS: + virtual void open(); + virtual bool save(); }; #endif // MAINWINDOW_H diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index 3744cdc7..dafd92e9 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -1,5 +1,6 @@ #include "mainwindow.h" #include +#include #include #include "bitstream.h" #include "design_utils.h" @@ -17,6 +18,10 @@ MainWindow::MainWindow(Context *_ctx, QWidget *parent) setWindowTitle(title.c_str()); createMenu(); + + task = new TaskManager(_ctx); + connect(task, SIGNAL(log(std::string)), this, + SLOT(writeInfo(std::string))); } MainWindow::~MainWindow() {} @@ -26,3 +31,19 @@ void MainWindow::createMenu() QMenu *menu_Custom = new QMenu("&ICE 40", menuBar); menuBar->addAction(menu_Custom->menuAction()); } + +void MainWindow::open() +{ + QString fileName = QFileDialog::getOpenFileName(this, QString(), QString(), + QString("*.json")); + if (!fileName.isEmpty()) { + tabWidget->setCurrentWidget(info); + + std::string fn = fileName.toStdString(); + task->parsejson(fn); + } +} +bool MainWindow::save() +{ + return false; +} \ No newline at end of file diff --git a/gui/ice40/mainwindow.h b/gui/ice40/mainwindow.h index e9c8ff77..fd65f9ae 100644 --- a/gui/ice40/mainwindow.h +++ b/gui/ice40/mainwindow.h @@ -2,6 +2,7 @@ #define MAINWINDOW_H #include "../basewindow.h" +#include "worker.h" // FIXME USING_NEXTPNR_NAMESPACE @@ -12,10 +13,17 @@ class MainWindow : public BaseMainWindow public: explicit MainWindow(Context *ctx, QWidget *parent = 0); - ~MainWindow(); + virtual ~MainWindow(); public: void createMenu(); + + protected Q_SLOTS: + virtual void open(); + virtual bool save(); + + private: + TaskManager *task; }; #endif // MAINWINDOW_H diff --git a/gui/ice40/worker.cc b/gui/ice40/worker.cc new file mode 100644 index 00000000..5a8ff0e9 --- /dev/null +++ b/gui/ice40/worker.cc @@ -0,0 +1,58 @@ +#include "worker.h" +#include +#include "jsonparse.h" +#include "log.h" +#include "pack.h" +#include "pcf.h" +#include "place_sa.h" +#include "route.h" +#include "bitstream.h" +#include "design_utils.h" +#include "timing.h" + +Worker::Worker(Context *_ctx) : ctx(_ctx) +{ + log_write_function = [this](std::string text) { Q_EMIT log(text); }; +} + +void Worker::parsejson(const std::string &filename) +{ + std::string fn = filename; + std::istream *f = new std::ifstream(fn); + + parse_json_file(f, fn, ctx); + if (!pack_design(ctx)) + log_error("Packing design failed.\n"); + double freq = 50e6; + assign_budget(ctx, freq); + print_utilisation(ctx); + + if (!place_design_sa(ctx)) + log_error("Placing design failed.\n"); + if (!route_design(ctx)) + log_error("Routing design failed.\n"); + print_utilisation(ctx); + Q_EMIT log("done"); +} + + +TaskManager::TaskManager(Context *ctx) +{ + Worker *worker = new Worker(ctx); + worker->moveToThread(&workerThread); + connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); + connect(this, &TaskManager::parsejson, worker, &Worker::parsejson); + connect(worker, &Worker::log, this, &TaskManager::info); + workerThread.start(); +} + +TaskManager::~TaskManager() +{ + workerThread.quit(); + workerThread.wait(); +} + +void TaskManager::info(const std::string &result) +{ + Q_EMIT log(result); +} \ No newline at end of file diff --git a/gui/ice40/worker.h b/gui/ice40/worker.h new file mode 100644 index 00000000..5dc25d89 --- /dev/null +++ b/gui/ice40/worker.h @@ -0,0 +1,37 @@ +#ifndef WORKER_H +#define WORKER_H + +#include "nextpnr.h" +#include + +// FIXME +USING_NEXTPNR_NAMESPACE + +class Worker : public QObject +{ + Q_OBJECT +public: + Worker(Context *ctx); +public Q_SLOTS: + void parsejson(const std::string &filename); +Q_SIGNALS: + void log(const std::string &text); +private: + Context *ctx; +}; + +class TaskManager : public QObject +{ + Q_OBJECT + QThread workerThread; +public: + TaskManager(Context *ctx); + ~TaskManager(); +public Q_SLOTS: + void info(const std::string &text); +Q_SIGNALS: + void parsejson(const std::string &); + void log(const std::string &text); +}; + +#endif // WORKER_H