#include "mainwindow.h" #include #include #include #include "emb.h" #include "pybindings.h" #include "ui_mainwindow.h" #include #include enum class ElementType { BEL, WIRE, PIP }; class ElementTreeItem : public QTreeWidgetItem { public: ElementTreeItem(ElementType t, QString str) : QTreeWidgetItem((QTreeWidget *)nullptr, QStringList(str)), type(t) { } virtual ~ElementTreeItem(){}; ElementType getType() { return type; }; private: ElementType type; }; class BelTreeItem : public ElementTreeItem { public: BelTreeItem(IdString d, ElementType type, QString str) : ElementTreeItem(type, str) { this->data = d; } virtual ~BelTreeItem(){}; IdString getData() { return this->data; }; private: IdString data; }; class WireTreeItem : public ElementTreeItem { public: WireTreeItem(IdString d, ElementType type, QString str) : ElementTreeItem(type, str) { this->data = d; } virtual ~WireTreeItem(){}; IdString getData() { return this->data; }; private: IdString data; }; class PipTreeItem : public ElementTreeItem { public: PipTreeItem(IdString d, ElementType type, QString str) : ElementTreeItem(type, str) { this->data = d; } virtual ~PipTreeItem(){}; IdString getData() { return this->data; }; private: IdString data; }; MainWindow::MainWindow(Design *_design, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), design(_design) { ui->setupUi(this); ui->treeWidget->setColumnCount(1); ui->treeWidget->setHeaderLabel(QString("Items")); ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, &MainWindow::prepareMenu); QTreeWidgetItem *bel_root = new QTreeWidgetItem(ui->treeWidget); bel_root->setText(0, QString("Bels")); ui->treeWidget->insertTopLevelItem(0, bel_root); QList bel_items; for (auto bel : design->chip.getBels()) { auto name = design->chip.getBelName(bel); bel_items.append( new BelTreeItem(name, ElementType::BEL, QString(name.c_str()))); } bel_root->addChildren(bel_items); QTreeWidgetItem *wire_root = new QTreeWidgetItem(ui->treeWidget); QList wire_items; wire_root->setText(0, QString("Wires")); ui->treeWidget->insertTopLevelItem(0, wire_root); for (auto wire : design->chip.getWires()) { auto name = design->chip.getWireName(wire); wire_items.append(new WireTreeItem(name, ElementType::WIRE, QString(name.c_str()))); } wire_root->addChildren(wire_items); QTreeWidgetItem *pip_root = new QTreeWidgetItem(ui->treeWidget); QList pip_items; pip_root->setText(0, QString("Pips")); ui->treeWidget->insertTopLevelItem(0, pip_root); for (auto pip : design->chip.getPips()) { auto name = design->chip.getPipName(pip); pip_items.append( new PipTreeItem(name, ElementType::PIP, QString(name.c_str()))); } pip_root->addChildren(pip_items); PyImport_ImportModule("emb"); write = [this](std::string s) { ui->plainTextEdit->moveCursor(QTextCursor::End); ui->plainTextEdit->insertPlainText(s.c_str()); ui->plainTextEdit->moveCursor(QTextCursor::End); }; emb::set_stdout(write); std::string title = "nextpnr-ice40 - " + design->chip.getChipName(); setWindowTitle(title.c_str()); variantManager = new QtVariantPropertyManager(); variantFactory = new QtVariantEditorFactory(); propertyEditor = new QtTreePropertyBrowser(); propertyEditor->setFactoryForManager(variantManager, variantFactory); propertyEditor->setPropertiesWithoutValueMarked(true); propertyEditor->setRootIsDecorated(false); propertyEditor->show(); ui->splitter_2->addWidget(propertyEditor); connect(ui->treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), SLOT(onItemClicked(QTreeWidgetItem *, int))); } MainWindow::~MainWindow() { delete variantManager; delete variantFactory; delete propertyEditor; delete ui; } void MainWindow::addProperty(QtVariantProperty *property, const QString &id) { propertyToId[property] = id; idToProperty[id] = property; QtBrowserItem *item = propertyEditor->addProperty(property); } void MainWindow::onItemClicked(QTreeWidgetItem *item, int pos) { if (!item->parent()) return; ElementType type = static_cast(item)->getType(); QMap::ConstIterator itProp = propertyToId.constBegin(); while (itProp != propertyToId.constEnd()) { delete itProp.key(); itProp++; } propertyToId.clear(); idToProperty.clear(); if (type == ElementType::BEL) { IdString c = static_cast(item)->getData(); QtVariantProperty *topItem = variantManager->addProperty(QVariant::String, QString("Name")); topItem->setValue(QString(c.c_str())); addProperty(topItem, QString("Name")); } else if (type == ElementType::WIRE) { IdString c = static_cast(item)->getData(); QtVariantProperty *topItem = variantManager->addProperty(QVariant::String, QString("Name")); topItem->setValue(QString(c.c_str())); addProperty(topItem, QString("Name")); } else if (type == ElementType::PIP) { IdString c = static_cast(item)->getData(); QtVariantProperty *topItem = variantManager->addProperty(QVariant::String, QString("Name")); topItem->setValue(QString(c.c_str())); addProperty(topItem, QString("Name")); } } void MainWindow::prepareMenu(const QPoint &pos) { QTreeWidget *tree = ui->treeWidget; itemContextMenu = tree->itemAt(pos); QAction *selectAction = new QAction("&Select", this); selectAction->setStatusTip("Select item on view"); connect(selectAction, SIGNAL(triggered()), this, SLOT(selectObject())); QMenu menu(this); menu.addAction(selectAction); QPoint pt(pos); menu.exec(tree->mapToGlobal(pos)); } void MainWindow::selectObject() { ui->plainTextEdit->moveCursor(QTextCursor::End); ui->plainTextEdit->insertPlainText( std::string("selected " + itemContextMenu->text(0).toStdString() + "\n") .c_str()); ui->plainTextEdit->moveCursor(QTextCursor::End); } void handle_system_exit() { exit(-1); } int MainWindow::executePython(std::string command) { PyObject *m, *d, *v; m = PyImport_AddModule("__main__"); if (m == NULL) return -1; d = PyModule_GetDict(m); v = PyRun_StringFlags(command.c_str(), (command.empty() ? Py_file_input : Py_single_input), d, d, NULL); if (v == NULL) { PyObject *exception, *v, *tb; if (PyErr_ExceptionMatches(PyExc_SystemExit)) { handle_system_exit(); } PyErr_Fetch(&exception, &v, &tb); if (exception == NULL) return 0; PyErr_NormalizeException(&exception, &v, &tb); if (tb == NULL) { tb = Py_None; Py_INCREF(tb); } PyException_SetTraceback(v, tb); if (exception == NULL) return 0; PyErr_Clear(); PyObject *objectsRepresentation = PyObject_Str(v); std::string errorStr = PyUnicode_AsUTF8(objectsRepresentation) + std::string("\n"); ui->plainTextEdit->moveCursor(QTextCursor::End); ui->plainTextEdit->insertPlainText(errorStr.c_str()); ui->plainTextEdit->moveCursor(QTextCursor::End); Py_DECREF(objectsRepresentation); Py_XDECREF(exception); Py_XDECREF(v); Py_XDECREF(tb); return -1; } Py_DECREF(v); return 0; } void MainWindow::on_lineEdit_returnPressed() { std::string input = ui->lineEdit->text().toStdString(); ui->plainTextEdit->moveCursor(QTextCursor::End); ui->plainTextEdit->insertPlainText( std::string(">>> " + input + "\n").c_str()); ui->plainTextEdit->moveCursor(QTextCursor::End); ui->plainTextEdit->update(); ui->lineEdit->clear(); int error = executePython(input); }