diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index 0a33ee2b..2c561230 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -18,6 +18,10 @@ */ #include "mainwindow.h" +#include "bitstream.h" +#include "log.h" + +#include static void initMainResource() { Q_INIT_RESOURCE(nextpnr); } @@ -44,7 +48,29 @@ void MainWindow::newContext(Context *ctx) setWindowTitle(title.c_str()); } -void MainWindow::createMenu() {} +void MainWindow::createMenu() { + // Add arch specific actions + actionLoadBase = new QAction("Open Base Config", this); + actionLoadBase->setIcon(QIcon(":/icons/resources/open_base.png")); + actionLoadBase->setStatusTip("Open Base Config file"); + actionLoadBase->setEnabled(false); + connect(actionLoadBase, &QAction::triggered, this, &MainWindow::open_base); + + actionSaveConfig = new QAction("Save Bitstream", this); + actionSaveConfig->setIcon(QIcon(":/icons/resources/save_config.png")); + actionSaveConfig->setStatusTip("Save Bitstream config file"); + actionSaveConfig->setEnabled(false); + connect(actionSaveConfig, &QAction::triggered, this, &MainWindow::save_config); + + // Add actions in menus + mainActionBar->addSeparator(); + mainActionBar->addAction(actionLoadBase); + mainActionBar->addAction(actionSaveConfig); + + menuDesign->addSeparator(); + menuDesign->addAction(actionLoadBase); + menuDesign->addAction(actionSaveConfig); +} void MainWindow::new_proj() {} @@ -52,4 +78,38 @@ void MainWindow::open_proj() {} bool MainWindow::save_proj() { return false; } +void MainWindow::load_base_config(std::string filename) +{ + disableActions(); + currentBaseConfig = filename; + actionSaveConfig->setEnabled(true); +} + +void MainWindow::open_base() +{ + QString fileName = QFileDialog::getOpenFileName(this, QString("Open Base Config"), QString(), QString("*.config")); + if (!fileName.isEmpty()) { + load_base_config(fileName.toStdString()); + } +} + +void MainWindow::save_config() +{ + QString fileName = QFileDialog::getSaveFileName(this, QString("Save Bitstream"), QString(), QString("*.config")); + if (!fileName.isEmpty()) { + std::string fn = fileName.toStdString(); + disableActions(); + write_bitstream(ctx.get(), currentBaseConfig, fileName.toStdString()); + log("Saving Bitstream successful.\n"); + } +} + +void MainWindow::onDisableActions() +{ + actionLoadBase->setEnabled(false); + actionSaveConfig->setEnabled(false); +} + +void MainWindow::onRouteFinished() { actionLoadBase->setEnabled(true); } + NEXTPNR_NAMESPACE_END diff --git a/gui/ecp5/mainwindow.h b/gui/ecp5/mainwindow.h index 8421b52a..788eafc9 100644 --- a/gui/ecp5/mainwindow.h +++ b/gui/ecp5/mainwindow.h @@ -34,15 +34,26 @@ class MainWindow : public BaseMainWindow public: void createMenu(); + void load_base_config(std::string filename); + + protected: + void onDisableActions() override; + void onRouteFinished() override; protected Q_SLOTS: virtual void new_proj(); virtual void open_proj(); virtual bool save_proj(); void newContext(Context *ctx); + void open_base(); + void save_config(); + private: + QAction *actionLoadBase; + QAction *actionSaveConfig; -private: ArchArgs chipArgs; + + std::string currentBaseConfig; }; NEXTPNR_NAMESPACE_END diff --git a/gui/ecp5/nextpnr.qrc b/gui/ecp5/nextpnr.qrc index 03585ec0..09f96d74 100644 --- a/gui/ecp5/nextpnr.qrc +++ b/gui/ecp5/nextpnr.qrc @@ -1,2 +1,6 @@ + + resources/open_base.png + resources/save_config.png + diff --git a/gui/ecp5/resources/open_base.png b/gui/ecp5/resources/open_base.png new file mode 100644 index 00000000..d58d226c Binary files /dev/null and b/gui/ecp5/resources/open_base.png differ diff --git a/gui/ecp5/resources/save_config.png b/gui/ecp5/resources/save_config.png new file mode 100644 index 00000000..2ade7128 Binary files /dev/null and b/gui/ecp5/resources/save_config.png differ