aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ecp5/arch.h2
-rw-r--r--ecp5/main.cc2
-rw-r--r--generic/arch.cc2
-rw-r--r--generic/main.cc5
-rw-r--r--gui/basewindow.cc4
-rw-r--r--gui/basewindow.h3
-rw-r--r--gui/ecp5/mainwindow.cc124
-rw-r--r--gui/ecp5/mainwindow.h18
-rw-r--r--gui/ecp5/nextpnr.qrc4
-rw-r--r--gui/ecp5/resources/open_base.pngbin0 -> 2022 bytes
-rw-r--r--gui/ecp5/resources/save_config.pngbin0 -> 1428 bytes
-rw-r--r--gui/generic/mainwindow.cc10
-rw-r--r--gui/generic/mainwindow.h3
-rw-r--r--gui/ice40/mainwindow.cc11
-rw-r--r--gui/ice40/mainwindow.h2
15 files changed, 165 insertions, 25 deletions
diff --git a/ecp5/arch.h b/ecp5/arch.h
index cd103b12..6daf543d 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -384,7 +384,7 @@ struct PipRange
struct ArchArgs
{
- enum
+ enum ArchArgsTypes
{
NONE,
LFE5U_25F,
diff --git a/ecp5/main.cc b/ecp5/main.cc
index dac7a635..dde3ffed 100644
--- a/ecp5/main.cc
+++ b/ecp5/main.cc
@@ -148,7 +148,7 @@ int main(int argc, char *argv[])
#ifndef NO_GUI
if (vm.count("gui")) {
Application a(argc, argv);
- MainWindow w(std::move(ctx));
+ MainWindow w(std::move(ctx),args);
w.show();
return a.exec();
diff --git a/generic/arch.cc b/generic/arch.cc
index f9133f9e..7c0828e0 100644
--- a/generic/arch.cc
+++ b/generic/arch.cc
@@ -175,7 +175,7 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy)
// ---------------------------------------------------------------
-Arch::Arch(ArchArgs) {}
+Arch::Arch(ArchArgs) : chipName("generic") {}
void IdString::initialize_arch(const BaseCtx *ctx) {}
diff --git a/generic/main.cc b/generic/main.cc
index 3b8b3fe6..8653da01 100644
--- a/generic/main.cc
+++ b/generic/main.cc
@@ -90,7 +90,8 @@ int main(int argc, char *argv[])
return 1;
}
- std::unique_ptr<Context> ctx = std::unique_ptr<Context>(new Context(ArchArgs{}));
+ ArchArgs chipArgs{};
+ std::unique_ptr<Context> ctx = std::unique_ptr<Context>(new Context(chipArgs));
if (vm.count("verbose")) {
ctx->verbose = true;
@@ -107,7 +108,7 @@ int main(int argc, char *argv[])
#ifndef NO_GUI
if (vm.count("gui")) {
Application a(argc, argv);
- MainWindow w(std::move(ctx));
+ MainWindow w(std::move(ctx), chipArgs);
w.show();
return a.exec();
diff --git a/gui/basewindow.cc b/gui/basewindow.cc
index 37141fd6..53720156 100644
--- a/gui/basewindow.cc
+++ b/gui/basewindow.cc
@@ -37,8 +37,8 @@ static void initBasenameResource() { Q_INIT_RESOURCE(base); }
NEXTPNR_NAMESPACE_BEGIN
-BaseMainWindow::BaseMainWindow(std::unique_ptr<Context> context, QWidget *parent)
- : QMainWindow(parent), ctx(std::move(context)), timing_driven(false)
+BaseMainWindow::BaseMainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent)
+ : QMainWindow(parent), chipArgs(args), ctx(std::move(context)), timing_driven(false)
{
initBasenameResource();
qRegisterMetaType<std::string>();
diff --git a/gui/basewindow.h b/gui/basewindow.h
index 5cec24c5..341cc8e2 100644
--- a/gui/basewindow.h
+++ b/gui/basewindow.h
@@ -45,7 +45,7 @@ class BaseMainWindow : public QMainWindow
Q_OBJECT
public:
- explicit BaseMainWindow(std::unique_ptr<Context> context, QWidget *parent = 0);
+ explicit BaseMainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent = 0);
virtual ~BaseMainWindow();
Context *getContext() { return ctx.get(); }
@@ -88,6 +88,7 @@ class BaseMainWindow : public QMainWindow
protected:
// state variables
+ ArchArgs chipArgs;
std::unique_ptr<Context> ctx;
TaskManager *task;
bool timing_driven;
diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc
index 935daefd..efaad364 100644
--- a/gui/ecp5/mainwindow.cc
+++ b/gui/ecp5/mainwindow.cc
@@ -18,30 +18,148 @@
*/
#include "mainwindow.h"
+#include "bitstream.h"
+#include "log.h"
+
+#include <QFileDialog>
+#include <QInputDialog>
+#include <QLineEdit>
static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }
NEXTPNR_NAMESPACE_BEGIN
-MainWindow::MainWindow(std::unique_ptr<Context> context, QWidget *parent) : BaseMainWindow(std::move(context), parent)
+MainWindow::MainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent) : BaseMainWindow(std::move(context), args, parent)
{
initMainResource();
std::string title = "nextpnr-ecp5 - [EMPTY]";
setWindowTitle(title.c_str());
+ connect(this, &BaseMainWindow::contextChanged, this, &MainWindow::newContext);
+
createMenu();
Q_EMIT contextChanged(ctx.get());
}
MainWindow::~MainWindow() {}
-void MainWindow::createMenu() {}
+void MainWindow::newContext(Context *ctx)
+{
+ std::string title = "nextpnr-generic - " + ctx->getChipName() + " ( " + chipArgs.package + " )";
+ setWindowTitle(title.c_str());
+}
+
+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);
+}
+
+static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); }
+
+static QStringList getSupportedPackages(ArchArgs::ArchArgsTypes chip)
+{
+ QStringList packages;
+ const ChipInfoPOD *chip_info;
+ if (chip == ArchArgs::LFE5U_25F) {
+ chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_25k));
+ } else if (chip == ArchArgs::LFE5U_45F) {
+ chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_45k));
+ } else if (chip == ArchArgs::LFE5U_85F) {
+ chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_85k));
+ } else {
+ log_error("Unsupported ECP5 chip type.\n");
+ }
+
+ for (int i = 0; i < chip_info->num_packages; i++) {
+ packages << chip_info->package_info[i].name.get();
+ }
+ return packages;
+}
+
+
+void MainWindow::new_proj() {
+ QMap<QString, int> arch;
+ arch.insert("Lattice ECP5 25K", ArchArgs::LFE5U_25F);
+ arch.insert("Lattice ECP5 45K", ArchArgs::LFE5U_45F);
+ arch.insert("Lattice ECP5 85K", ArchArgs::LFE5U_85F);
+ bool ok;
+ QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok);
+ if (ok && !item.isEmpty()) {
-void MainWindow::new_proj() {}
+ chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item);
+
+ QString package = QInputDialog::getItem(this, "Select package", "Package:", getSupportedPackages(chipArgs.type),
+ 0, false, &ok);
+
+ if (ok && !item.isEmpty()) {
+ currentProj = "";
+ currentJson = "";
+ disableActions();
+ chipArgs.package = package.toStdString().c_str();
+ ctx = std::unique_ptr<Context>(new Context(chipArgs));
+ actionLoadJSON->setEnabled(true);
+
+ Q_EMIT contextChanged(ctx.get());
+ }
+ }
+}
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 e97bb4e7..d1d5a5a2 100644
--- a/gui/ecp5/mainwindow.h
+++ b/gui/ecp5/mainwindow.h
@@ -29,16 +29,32 @@ class MainWindow : public BaseMainWindow
Q_OBJECT
public:
- explicit MainWindow(std::unique_ptr<Context> context, QWidget *parent = 0);
+ explicit MainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent = 0);
virtual ~MainWindow();
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;
+
+ ArchArgs chipArgs;
+
+ std::string currentProj;
+ 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 @@
<RCC>
+ <qresource prefix="/icons">
+ <file>resources/open_base.png</file>
+ <file>resources/save_config.png</file>
+ </qresource>
</RCC>
diff --git a/gui/ecp5/resources/open_base.png b/gui/ecp5/resources/open_base.png
new file mode 100644
index 00000000..d58d226c
--- /dev/null
+++ b/gui/ecp5/resources/open_base.png
Binary files differ
diff --git a/gui/ecp5/resources/save_config.png b/gui/ecp5/resources/save_config.png
new file mode 100644
index 00000000..2ade7128
--- /dev/null
+++ b/gui/ecp5/resources/save_config.png
Binary files differ
diff --git a/gui/generic/mainwindow.cc b/gui/generic/mainwindow.cc
index 70ee600d..050c0fb8 100644
--- a/gui/generic/mainwindow.cc
+++ b/gui/generic/mainwindow.cc
@@ -23,19 +23,27 @@ static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }
NEXTPNR_NAMESPACE_BEGIN
-MainWindow::MainWindow(std::unique_ptr<Context> context, QWidget *parent) : BaseMainWindow(std::move(context), parent)
+MainWindow::MainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent) : BaseMainWindow(std::move(context), args, parent)
{
initMainResource();
std::string title = "nextpnr-generic - [EMPTY]";
setWindowTitle(title.c_str());
+ connect(this, &BaseMainWindow::contextChanged, this, &MainWindow::newContext);
+
createMenu();
Q_EMIT contextChanged(ctx.get());
}
MainWindow::~MainWindow() {}
+void MainWindow::newContext(Context *ctx)
+{
+ std::string title = "nextpnr-generic - " + ctx->getChipName();
+ setWindowTitle(title.c_str());
+}
+
void MainWindow::createMenu() {}
void MainWindow::new_proj() {}
diff --git a/gui/generic/mainwindow.h b/gui/generic/mainwindow.h
index e97bb4e7..375436b6 100644
--- a/gui/generic/mainwindow.h
+++ b/gui/generic/mainwindow.h
@@ -29,7 +29,7 @@ class MainWindow : public BaseMainWindow
Q_OBJECT
public:
- explicit MainWindow(std::unique_ptr<Context> context, QWidget *parent = 0);
+ explicit MainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent = 0);
virtual ~MainWindow();
public:
@@ -39,6 +39,7 @@ class MainWindow : public BaseMainWindow
virtual void new_proj();
virtual void open_proj();
virtual bool save_proj();
+ void newContext(Context *ctx);
};
NEXTPNR_NAMESPACE_END
diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc
index 2fa2e561..40b863e9 100644
--- a/gui/ice40/mainwindow.cc
+++ b/gui/ice40/mainwindow.cc
@@ -37,7 +37,7 @@ static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }
NEXTPNR_NAMESPACE_BEGIN
MainWindow::MainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent)
- : BaseMainWindow(std::move(context), parent), chipArgs(args)
+ : BaseMainWindow(std::move(context), args, parent)
{
initMainResource();
@@ -78,18 +78,11 @@ void MainWindow::createMenu()
menuDesign->addAction(actionSaveAsc);
}
-#if defined(_MSC_VER)
-void load_chipdb();
-#endif
-
static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); }
-QStringList getSupportedPackages(ArchArgs::ArchArgsTypes chip)
+static QStringList getSupportedPackages(ArchArgs::ArchArgsTypes chip)
{
QStringList packages;
-#if defined(_MSC_VER)
- load_chipdb();
-#endif
const ChipInfoPOD *chip_info;
#ifdef ICE40_HX1K_ONLY
if (chip == ArchArgs::HX1K) {
diff --git a/gui/ice40/mainwindow.h b/gui/ice40/mainwindow.h
index 230ccc4e..829375e2 100644
--- a/gui/ice40/mainwindow.h
+++ b/gui/ice40/mainwindow.h
@@ -55,8 +55,6 @@ class MainWindow : public BaseMainWindow
QAction *actionLoadPCF;
QAction *actionSaveAsc;
- ArchArgs chipArgs;
-
std::string currentProj;
std::string currentPCF;
};