Merge branch 'master' of gitlab.com:SymbioticEDA/nextpnr into q3k/lock-2-electric-boogaloo
This commit is contained in:
commit
f3c6c76fff
@ -74,6 +74,7 @@ public:
|
|||||||
QtProperty *indexToProperty(const QModelIndex &index) const;
|
QtProperty *indexToProperty(const QModelIndex &index) const;
|
||||||
QTreeWidgetItem *indexToItem(const QModelIndex &index) const;
|
QTreeWidgetItem *indexToItem(const QModelIndex &index) const;
|
||||||
QtBrowserItem *indexToBrowserItem(const QModelIndex &index) const;
|
QtBrowserItem *indexToBrowserItem(const QModelIndex &index) const;
|
||||||
|
QtBrowserItem *itemToBrowserItem(QTreeWidgetItem *item) const { return m_itemToIndex.value(item); };
|
||||||
bool lastColumn(int column) const;
|
bool lastColumn(int column) const;
|
||||||
void disableItem(QTreeWidgetItem *item) const;
|
void disableItem(QTreeWidgetItem *item) const;
|
||||||
void enableItem(QTreeWidgetItem *item) const;
|
void enableItem(QTreeWidgetItem *item) const;
|
||||||
@ -1068,6 +1069,16 @@ void QtTreePropertyBrowser::editItem(QtBrowserItem *item)
|
|||||||
d_ptr->editItem(item);
|
d_ptr->editItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QTreeWidget *QtTreePropertyBrowser::treeWidget() const
|
||||||
|
{
|
||||||
|
return d_ptr->treeWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
QtBrowserItem *QtTreePropertyBrowser::itemToBrowserItem(QTreeWidgetItem *item)
|
||||||
|
{
|
||||||
|
return d_ptr->itemToBrowserItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040400
|
#if QT_VERSION >= 0x040400
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
#endif
|
#endif
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class QTreeWidget;
|
||||||
class QTreeWidgetItem;
|
class QTreeWidgetItem;
|
||||||
class QtTreePropertyBrowserPrivate;
|
class QtTreePropertyBrowserPrivate;
|
||||||
|
|
||||||
@ -107,6 +108,9 @@ public:
|
|||||||
|
|
||||||
void editItem(QtBrowserItem *item);
|
void editItem(QtBrowserItem *item);
|
||||||
|
|
||||||
|
//ADDED:miodrag
|
||||||
|
QTreeWidget *treeWidget() const;
|
||||||
|
QtBrowserItem *itemToBrowserItem(QTreeWidgetItem *item);
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|
||||||
void collapsed(QtBrowserItem *item);
|
void collapsed(QtBrowserItem *item);
|
||||||
|
@ -9,5 +9,6 @@
|
|||||||
<file>resources/resultset_previous.png</file>
|
<file>resources/resultset_previous.png</file>
|
||||||
<file>resources/resultset_next.png</file>
|
<file>resources/resultset_next.png</file>
|
||||||
<file>resources/resultset_last.png</file>
|
<file>resources/resultset_last.png</file>
|
||||||
|
<file>resources/splash.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
@ -61,15 +62,10 @@ BaseMainWindow::BaseMainWindow(std::unique_ptr<Context> context, QWidget *parent
|
|||||||
|
|
||||||
setCentralWidget(centralWidget);
|
setCentralWidget(centralWidget);
|
||||||
|
|
||||||
DesignWidget *designview = new DesignWidget();
|
designview = new DesignWidget();
|
||||||
designview->setMinimumWidth(300);
|
designview->setMinimumWidth(300);
|
||||||
splitter_h->addWidget(designview);
|
splitter_h->addWidget(designview);
|
||||||
|
|
||||||
connect(this, SIGNAL(contextChanged(Context *)), designview, SLOT(newContext(Context *)));
|
|
||||||
connect(this, SIGNAL(updateTreeView()), designview, SLOT(updateTree()));
|
|
||||||
|
|
||||||
connect(designview, SIGNAL(info(std::string)), this, SLOT(writeInfo(std::string)));
|
|
||||||
|
|
||||||
tabWidget = new QTabWidget();
|
tabWidget = new QTabWidget();
|
||||||
|
|
||||||
console = new PythonTab();
|
console = new PythonTab();
|
||||||
@ -81,14 +77,40 @@ BaseMainWindow::BaseMainWindow(std::unique_ptr<Context> context, QWidget *parent
|
|||||||
centralTabWidget->addTab(fpgaView, "Graphics");
|
centralTabWidget->addTab(fpgaView, "Graphics");
|
||||||
|
|
||||||
connect(this, SIGNAL(contextChanged(Context *)), fpgaView, SLOT(newContext(Context *)));
|
connect(this, SIGNAL(contextChanged(Context *)), fpgaView, SLOT(newContext(Context *)));
|
||||||
connect(designview, SIGNAL(selected(std::vector<DecalXY>)), fpgaView, SLOT(onSelectedArchItem(std::vector<DecalXY>)));
|
connect(designview, SIGNAL(selected(std::vector<DecalXY>)), fpgaView,
|
||||||
|
SLOT(onSelectedArchItem(std::vector<DecalXY>)));
|
||||||
|
|
||||||
|
connect(designview, SIGNAL(highlight(std::vector<DecalXY>, int)), fpgaView,
|
||||||
|
SLOT(onHighlightGroupChanged(std::vector<DecalXY>, int)));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(contextChanged(Context *)), designview, SLOT(newContext(Context *)));
|
||||||
|
connect(this, SIGNAL(updateTreeView()), designview, SLOT(updateTree()));
|
||||||
|
|
||||||
|
connect(designview, SIGNAL(info(std::string)), this, SLOT(writeInfo(std::string)));
|
||||||
|
|
||||||
splitter_v->addWidget(centralTabWidget);
|
splitter_v->addWidget(centralTabWidget);
|
||||||
splitter_v->addWidget(tabWidget);
|
splitter_v->addWidget(tabWidget);
|
||||||
|
displaySplash();
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseMainWindow::~BaseMainWindow() {}
|
BaseMainWindow::~BaseMainWindow() {}
|
||||||
|
|
||||||
|
void BaseMainWindow::displaySplash()
|
||||||
|
{
|
||||||
|
splash = new QSplashScreen();
|
||||||
|
splash->setPixmap(QPixmap(":/icons/resources/splash.png"));
|
||||||
|
splash->show();
|
||||||
|
connect(designview, SIGNAL(finishContextLoad()), splash, SLOT(close()));
|
||||||
|
connect(designview, SIGNAL(contextLoadStatus(std::string)), this, SLOT(displaySplashMessage(std::string)));
|
||||||
|
QCoreApplication::instance()->processEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseMainWindow::displaySplashMessage(std::string msg)
|
||||||
|
{
|
||||||
|
splash->showMessage(msg.c_str(), Qt::AlignCenter | Qt::AlignBottom, Qt::white);
|
||||||
|
QCoreApplication::instance()->processEvents();
|
||||||
|
}
|
||||||
|
|
||||||
void BaseMainWindow::writeInfo(std::string text) { console->info(text); }
|
void BaseMainWindow::writeInfo(std::string text) { console->info(text); }
|
||||||
|
|
||||||
void BaseMainWindow::createMenusAndBars()
|
void BaseMainWindow::createMenusAndBars()
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
#include <QProgressBar>
|
#include <QProgressBar>
|
||||||
|
#include <QSplashScreen>
|
||||||
#include <QStatusBar>
|
#include <QStatusBar>
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
#include <QToolBar>
|
#include <QToolBar>
|
||||||
@ -36,6 +37,7 @@ Q_DECLARE_METATYPE(NEXTPNR_NAMESPACE_PREFIX DecalXY)
|
|||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class PythonTab;
|
class PythonTab;
|
||||||
|
class DesignWidget;
|
||||||
|
|
||||||
class BaseMainWindow : public QMainWindow
|
class BaseMainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
@ -48,9 +50,11 @@ class BaseMainWindow : public QMainWindow
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void createMenusAndBars();
|
void createMenusAndBars();
|
||||||
|
void displaySplash();
|
||||||
|
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
void writeInfo(std::string text);
|
void writeInfo(std::string text);
|
||||||
|
void displaySplashMessage(std::string msg);
|
||||||
|
|
||||||
virtual void new_proj() = 0;
|
virtual void new_proj() = 0;
|
||||||
virtual void open_proj() = 0;
|
virtual void open_proj() = 0;
|
||||||
@ -72,6 +76,8 @@ class BaseMainWindow : public QMainWindow
|
|||||||
QAction *actionNew;
|
QAction *actionNew;
|
||||||
QAction *actionOpen;
|
QAction *actionOpen;
|
||||||
QProgressBar *progressBar;
|
QProgressBar *progressBar;
|
||||||
|
QSplashScreen *splash;
|
||||||
|
DesignWidget *designview;
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -29,16 +29,6 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
enum class ElementType
|
|
||||||
{
|
|
||||||
NONE,
|
|
||||||
BEL,
|
|
||||||
WIRE,
|
|
||||||
PIP,
|
|
||||||
NET,
|
|
||||||
CELL
|
|
||||||
};
|
|
||||||
|
|
||||||
class ElementTreeItem : public QTreeWidgetItem
|
class ElementTreeItem : public QTreeWidgetItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -87,8 +77,8 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), net
|
|||||||
propertyEditor = new QtTreePropertyBrowser(this);
|
propertyEditor = new QtTreePropertyBrowser(this);
|
||||||
propertyEditor->setFactoryForManager(variantManager, variantFactory);
|
propertyEditor->setFactoryForManager(variantManager, variantFactory);
|
||||||
propertyEditor->setPropertiesWithoutValueMarked(true);
|
propertyEditor->setPropertiesWithoutValueMarked(true);
|
||||||
|
|
||||||
propertyEditor->show();
|
propertyEditor->show();
|
||||||
|
propertyEditor->treeWidget()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
QLineEdit *lineEdit = new QLineEdit();
|
QLineEdit *lineEdit = new QLineEdit();
|
||||||
lineEdit->setClearButtonEnabled(true);
|
lineEdit->setClearButtonEnabled(true);
|
||||||
@ -98,18 +88,42 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), net
|
|||||||
actionFirst = new QAction("", this);
|
actionFirst = new QAction("", this);
|
||||||
actionFirst->setIcon(QIcon(":/icons/resources/resultset_first.png"));
|
actionFirst->setIcon(QIcon(":/icons/resources/resultset_first.png"));
|
||||||
actionFirst->setEnabled(false);
|
actionFirst->setEnabled(false);
|
||||||
|
connect(actionFirst, &QAction::triggered, this, [this] {
|
||||||
|
history_ignore = true;
|
||||||
|
history_index = 0;
|
||||||
|
treeWidget->setCurrentItem(history.at(history_index));
|
||||||
|
updateButtons();
|
||||||
|
});
|
||||||
|
|
||||||
actionPrev = new QAction("", this);
|
actionPrev = new QAction("", this);
|
||||||
actionPrev->setIcon(QIcon(":/icons/resources/resultset_previous.png"));
|
actionPrev->setIcon(QIcon(":/icons/resources/resultset_previous.png"));
|
||||||
actionPrev->setEnabled(false);
|
actionPrev->setEnabled(false);
|
||||||
|
connect(actionPrev, &QAction::triggered, this, [this] {
|
||||||
|
history_ignore = true;
|
||||||
|
history_index--;
|
||||||
|
treeWidget->setCurrentItem(history.at(history_index));
|
||||||
|
updateButtons();
|
||||||
|
});
|
||||||
|
|
||||||
actionNext = new QAction("", this);
|
actionNext = new QAction("", this);
|
||||||
actionNext->setIcon(QIcon(":/icons/resources/resultset_next.png"));
|
actionNext->setIcon(QIcon(":/icons/resources/resultset_next.png"));
|
||||||
actionNext->setEnabled(false);
|
actionNext->setEnabled(false);
|
||||||
|
connect(actionNext, &QAction::triggered, this, [this] {
|
||||||
|
history_ignore = true;
|
||||||
|
history_index++;
|
||||||
|
treeWidget->setCurrentItem(history.at(history_index));
|
||||||
|
updateButtons();
|
||||||
|
});
|
||||||
|
|
||||||
actionLast = new QAction("", this);
|
actionLast = new QAction("", this);
|
||||||
actionLast->setIcon(QIcon(":/icons/resources/resultset_last.png"));
|
actionLast->setIcon(QIcon(":/icons/resources/resultset_last.png"));
|
||||||
actionLast->setEnabled(false);
|
actionLast->setEnabled(false);
|
||||||
|
connect(actionLast, &QAction::triggered, this, [this] {
|
||||||
|
history_ignore = true;
|
||||||
|
history_index = int(history.size() - 1);
|
||||||
|
treeWidget->setCurrentItem(history.at(history_index));
|
||||||
|
updateButtons();
|
||||||
|
});
|
||||||
|
|
||||||
QToolBar *toolbar = new QToolBar();
|
QToolBar *toolbar = new QToolBar();
|
||||||
toolbar->addAction(actionFirst);
|
toolbar->addAction(actionFirst);
|
||||||
@ -153,16 +167,61 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), net
|
|||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
// Connection
|
// Connection
|
||||||
connect(treeWidget, &QTreeWidget::customContextMenuRequested, this, &DesignWidget::prepareMenu);
|
connect(propertyEditor->treeWidget(), &QTreeWidget::customContextMenuRequested, this,
|
||||||
|
&DesignWidget::prepareMenuProperty);
|
||||||
|
connect(propertyEditor->treeWidget(), &QTreeWidget::itemDoubleClicked, this, &DesignWidget::onItemDoubleClicked);
|
||||||
|
|
||||||
connect(treeWidget, SIGNAL(itemSelectionChanged()), SLOT(onItemSelectionChanged()));
|
connect(treeWidget, SIGNAL(itemSelectionChanged()), SLOT(onItemSelectionChanged()));
|
||||||
|
connect(treeWidget, &QTreeWidget::customContextMenuRequested, this, &DesignWidget::prepareMenuTree);
|
||||||
|
|
||||||
|
history_index = -1;
|
||||||
|
history_ignore = false;
|
||||||
|
|
||||||
|
highlightColors[0] = QColor("#6495ed");
|
||||||
|
highlightColors[1] = QColor("#7fffd4");
|
||||||
|
highlightColors[2] = QColor("#98fb98");
|
||||||
|
highlightColors[3] = QColor("#ffd700");
|
||||||
|
highlightColors[4] = QColor("#cd5c5c");
|
||||||
|
highlightColors[5] = QColor("#fa8072");
|
||||||
|
highlightColors[6] = QColor("#ff69b4");
|
||||||
|
highlightColors[7] = QColor("#da70d6");
|
||||||
}
|
}
|
||||||
|
|
||||||
DesignWidget::~DesignWidget() {}
|
DesignWidget::~DesignWidget() {}
|
||||||
|
|
||||||
|
void DesignWidget::updateButtons()
|
||||||
|
{
|
||||||
|
int count = int(history.size());
|
||||||
|
actionFirst->setEnabled(history_index > 0);
|
||||||
|
actionPrev->setEnabled(history_index > 0);
|
||||||
|
actionNext->setEnabled(history_index < (count - 1));
|
||||||
|
actionLast->setEnabled(history_index < (count - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesignWidget::addToHistory(QTreeWidgetItem *item)
|
||||||
|
{
|
||||||
|
if (!history_ignore) {
|
||||||
|
int count = int(history.size());
|
||||||
|
for (int i = count - 1; i > history_index; i--)
|
||||||
|
history.pop_back();
|
||||||
|
history.push_back(item);
|
||||||
|
history_index++;
|
||||||
|
}
|
||||||
|
history_ignore = false;
|
||||||
|
updateButtons();
|
||||||
|
}
|
||||||
|
|
||||||
void DesignWidget::newContext(Context *ctx)
|
void DesignWidget::newContext(Context *ctx)
|
||||||
{
|
{
|
||||||
treeWidget->clear();
|
treeWidget->clear();
|
||||||
|
history_ignore = false;
|
||||||
|
history_index = -1;
|
||||||
|
history.clear();
|
||||||
|
updateButtons();
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
nameToItem[i].clear();
|
||||||
|
|
||||||
this->ctx = ctx;
|
this->ctx = ctx;
|
||||||
|
|
||||||
// Add bels to tree
|
// Add bels to tree
|
||||||
@ -171,6 +230,7 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
bel_root->setText(0, "Bels");
|
bel_root->setText(0, "Bels");
|
||||||
treeWidget->insertTopLevelItem(0, bel_root);
|
treeWidget->insertTopLevelItem(0, bel_root);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
|
Q_EMIT contextLoadStatus("Configuring bels...");
|
||||||
for (auto bel : ctx->getBels()) {
|
for (auto bel : ctx->getBels()) {
|
||||||
auto id = ctx->getBelName(bel);
|
auto id = ctx->getBelName(bel);
|
||||||
QStringList items = QString(id.c_str(ctx)).split("/");
|
QStringList items = QString(id.c_str(ctx)).split("/");
|
||||||
@ -182,7 +242,7 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
name += items.at(i);
|
name += items.at(i);
|
||||||
if (!bel_items.contains(name)) {
|
if (!bel_items.contains(name)) {
|
||||||
if (i == items.size() - 1)
|
if (i == items.size() - 1)
|
||||||
bel_items.insert(name, new IdStringTreeItem(id, ElementType::BEL, items.at(i), parent));
|
nameToItem[0].insert(name, new IdStringTreeItem(id, ElementType::BEL, items.at(i), parent));
|
||||||
else
|
else
|
||||||
bel_items.insert(name, new ElementTreeItem(ElementType::NONE, items.at(i), parent));
|
bel_items.insert(name, new ElementTreeItem(ElementType::NONE, items.at(i), parent));
|
||||||
}
|
}
|
||||||
@ -193,6 +253,9 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
for (auto bel : bel_items.toStdMap()) {
|
for (auto bel : bel_items.toStdMap()) {
|
||||||
bel_root->addChild(bel.second);
|
bel_root->addChild(bel.second);
|
||||||
}
|
}
|
||||||
|
for (auto bel : nameToItem[0].toStdMap()) {
|
||||||
|
bel_root->addChild(bel.second);
|
||||||
|
}
|
||||||
|
|
||||||
// Add wires to tree
|
// Add wires to tree
|
||||||
QTreeWidgetItem *wire_root = new QTreeWidgetItem(treeWidget);
|
QTreeWidgetItem *wire_root = new QTreeWidgetItem(treeWidget);
|
||||||
@ -200,6 +263,7 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
wire_root->setText(0, "Wires");
|
wire_root->setText(0, "Wires");
|
||||||
treeWidget->insertTopLevelItem(0, wire_root);
|
treeWidget->insertTopLevelItem(0, wire_root);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
|
Q_EMIT contextLoadStatus("Configuring wires...");
|
||||||
for (auto wire : ctx->getWires()) {
|
for (auto wire : ctx->getWires()) {
|
||||||
auto id = ctx->getWireName(wire);
|
auto id = ctx->getWireName(wire);
|
||||||
QStringList items = QString(id.c_str(ctx)).split("/");
|
QStringList items = QString(id.c_str(ctx)).split("/");
|
||||||
@ -211,7 +275,7 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
name += items.at(i);
|
name += items.at(i);
|
||||||
if (!wire_items.contains(name)) {
|
if (!wire_items.contains(name)) {
|
||||||
if (i == items.size() - 1)
|
if (i == items.size() - 1)
|
||||||
wire_items.insert(name, new IdStringTreeItem(id, ElementType::WIRE, items.at(i), parent));
|
nameToItem[1].insert(name, new IdStringTreeItem(id, ElementType::WIRE, items.at(i), parent));
|
||||||
else
|
else
|
||||||
wire_items.insert(name, new ElementTreeItem(ElementType::NONE, items.at(i), parent));
|
wire_items.insert(name, new ElementTreeItem(ElementType::NONE, items.at(i), parent));
|
||||||
}
|
}
|
||||||
@ -222,13 +286,16 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
for (auto wire : wire_items.toStdMap()) {
|
for (auto wire : wire_items.toStdMap()) {
|
||||||
wire_root->addChild(wire.second);
|
wire_root->addChild(wire.second);
|
||||||
}
|
}
|
||||||
|
for (auto wire : nameToItem[1].toStdMap()) {
|
||||||
|
wire_root->addChild(wire.second);
|
||||||
|
}
|
||||||
// Add pips to tree
|
// Add pips to tree
|
||||||
QTreeWidgetItem *pip_root = new QTreeWidgetItem(treeWidget);
|
QTreeWidgetItem *pip_root = new QTreeWidgetItem(treeWidget);
|
||||||
QMap<QString, QTreeWidgetItem *> pip_items;
|
QMap<QString, QTreeWidgetItem *> pip_items;
|
||||||
pip_root->setText(0, "Pips");
|
pip_root->setText(0, "Pips");
|
||||||
treeWidget->insertTopLevelItem(0, pip_root);
|
treeWidget->insertTopLevelItem(0, pip_root);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
|
Q_EMIT contextLoadStatus("Configuring pips...");
|
||||||
for (auto pip : ctx->getPips()) {
|
for (auto pip : ctx->getPips()) {
|
||||||
auto id = ctx->getPipName(pip);
|
auto id = ctx->getPipName(pip);
|
||||||
QStringList items = QString(id.c_str(ctx)).split("/");
|
QStringList items = QString(id.c_str(ctx)).split("/");
|
||||||
@ -240,7 +307,7 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
name += items.at(i);
|
name += items.at(i);
|
||||||
if (!pip_items.contains(name)) {
|
if (!pip_items.contains(name)) {
|
||||||
if (i == items.size() - 1)
|
if (i == items.size() - 1)
|
||||||
pip_items.insert(name, new IdStringTreeItem(id, ElementType::PIP, items.at(i), parent));
|
nameToItem[2].insert(name, new IdStringTreeItem(id, ElementType::PIP, items.at(i), parent));
|
||||||
else
|
else
|
||||||
pip_items.insert(name, new ElementTreeItem(ElementType::NONE, items.at(i), parent));
|
pip_items.insert(name, new ElementTreeItem(ElementType::NONE, items.at(i), parent));
|
||||||
}
|
}
|
||||||
@ -251,6 +318,9 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
for (auto pip : pip_items.toStdMap()) {
|
for (auto pip : pip_items.toStdMap()) {
|
||||||
pip_root->addChild(pip.second);
|
pip_root->addChild(pip.second);
|
||||||
}
|
}
|
||||||
|
for (auto pip : nameToItem[2].toStdMap()) {
|
||||||
|
pip_root->addChild(pip.second);
|
||||||
|
}
|
||||||
|
|
||||||
// Add nets to tree
|
// Add nets to tree
|
||||||
nets_root = new QTreeWidgetItem(treeWidget);
|
nets_root = new QTreeWidgetItem(treeWidget);
|
||||||
@ -261,6 +331,8 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
cells_root = new QTreeWidgetItem(treeWidget);
|
cells_root = new QTreeWidgetItem(treeWidget);
|
||||||
cells_root->setText(0, "Cells");
|
cells_root->setText(0, "Cells");
|
||||||
treeWidget->insertTopLevelItem(0, cells_root);
|
treeWidget->insertTopLevelItem(0, cells_root);
|
||||||
|
|
||||||
|
Q_EMIT finishContextLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignWidget::updateTree()
|
void DesignWidget::updateTree()
|
||||||
@ -268,45 +340,48 @@ void DesignWidget::updateTree()
|
|||||||
clearProperties();
|
clearProperties();
|
||||||
delete nets_root;
|
delete nets_root;
|
||||||
delete cells_root;
|
delete cells_root;
|
||||||
|
nameToItem[3].clear();
|
||||||
|
nameToItem[4].clear();
|
||||||
|
|
||||||
// Add nets to tree
|
// Add nets to tree
|
||||||
nets_root = new QTreeWidgetItem(treeWidget);
|
nets_root = new QTreeWidgetItem(treeWidget);
|
||||||
QMap<QString, QTreeWidgetItem *> nets_items;
|
|
||||||
nets_root->setText(0, "Nets");
|
nets_root->setText(0, "Nets");
|
||||||
treeWidget->insertTopLevelItem(0, nets_root);
|
treeWidget->insertTopLevelItem(0, nets_root);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
for (auto &item : ctx->nets) {
|
for (auto &item : ctx->nets) {
|
||||||
auto id = item.first;
|
auto id = item.first;
|
||||||
QString name = QString(id.c_str(ctx));
|
QString name = QString(id.c_str(ctx));
|
||||||
nets_items.insert(name, new IdStringTreeItem(id, ElementType::NET, name, nullptr));
|
IdStringTreeItem *newItem = new IdStringTreeItem(id, ElementType::NET, name, nullptr);
|
||||||
|
nameToItem[3].insert(name, newItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto item : nets_items.toStdMap()) {
|
for (auto item : nameToItem[3].toStdMap()) {
|
||||||
nets_root->addChild(item.second);
|
nets_root->addChild(item.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add cells to tree
|
// Add cells to tree
|
||||||
cells_root = new QTreeWidgetItem(treeWidget);
|
cells_root = new QTreeWidgetItem(treeWidget);
|
||||||
QMap<QString, QTreeWidgetItem *> cells_items;
|
|
||||||
cells_root->setText(0, "Cells");
|
cells_root->setText(0, "Cells");
|
||||||
treeWidget->insertTopLevelItem(0, cells_root);
|
treeWidget->insertTopLevelItem(0, cells_root);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
for (auto &item : ctx->cells) {
|
for (auto &item : ctx->cells) {
|
||||||
auto id = item.first;
|
auto id = item.first;
|
||||||
QString name = QString(id.c_str(ctx));
|
QString name = QString(id.c_str(ctx));
|
||||||
cells_items.insert(name, new IdStringTreeItem(id, ElementType::CELL, name, nullptr));
|
IdStringTreeItem *newItem = new IdStringTreeItem(id, ElementType::CELL, name, nullptr);
|
||||||
|
nameToItem[4].insert(name, newItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto item : cells_items.toStdMap()) {
|
for (auto item : nameToItem[4].toStdMap()) {
|
||||||
cells_root->addChild(item.second);
|
cells_root->addChild(item.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
QtProperty *DesignWidget::addTopLevelProperty(const QString &id)
|
||||||
void DesignWidget::addProperty(QtProperty *property, const QString &id)
|
|
||||||
{
|
{
|
||||||
propertyToId[property] = id;
|
QtProperty *topItem = groupManager->addProperty(id);
|
||||||
idToProperty[id] = property;
|
propertyToId[topItem] = id;
|
||||||
propertyEditor->addProperty(property);
|
idToProperty[id] = topItem;
|
||||||
|
propertyEditor->addProperty(topItem);
|
||||||
|
return topItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignWidget::clearProperties()
|
void DesignWidget::clearProperties()
|
||||||
@ -320,9 +395,72 @@ void DesignWidget::clearProperties()
|
|||||||
idToProperty.clear();
|
idToProperty.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString DesignWidget::getElementTypeName(ElementType type)
|
||||||
|
{
|
||||||
|
if (type == ElementType::NONE)
|
||||||
|
return "";
|
||||||
|
if (type == ElementType::BEL)
|
||||||
|
return "BEL";
|
||||||
|
if (type == ElementType::WIRE)
|
||||||
|
return "WIRE";
|
||||||
|
if (type == ElementType::PIP)
|
||||||
|
return "PIP";
|
||||||
|
if (type == ElementType::NET)
|
||||||
|
return "NET";
|
||||||
|
if (type == ElementType::CELL)
|
||||||
|
return "CELL";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
int DesignWidget::getElementIndex(ElementType type)
|
||||||
|
{
|
||||||
|
if (type == ElementType::BEL)
|
||||||
|
return 0;
|
||||||
|
if (type == ElementType::WIRE)
|
||||||
|
return 1;
|
||||||
|
if (type == ElementType::PIP)
|
||||||
|
return 2;
|
||||||
|
if (type == ElementType::NET)
|
||||||
|
return 3;
|
||||||
|
if (type == ElementType::CELL)
|
||||||
|
return 4;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementType DesignWidget::getElementTypeByName(QString type)
|
||||||
|
{
|
||||||
|
if (type == "BEL")
|
||||||
|
return ElementType::BEL;
|
||||||
|
if (type == "WIRE")
|
||||||
|
return ElementType::WIRE;
|
||||||
|
if (type == "PIP")
|
||||||
|
return ElementType::PIP;
|
||||||
|
if (type == "NET")
|
||||||
|
return ElementType::NET;
|
||||||
|
if (type == "CELL")
|
||||||
|
return ElementType::CELL;
|
||||||
|
return ElementType::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesignWidget::addProperty(QtProperty *topItem, int propertyType, const QString &name, QVariant value,
|
||||||
|
const ElementType &type)
|
||||||
|
{
|
||||||
|
QtVariantProperty *item = readOnlyManager->addProperty(propertyType, name);
|
||||||
|
item->setValue(value);
|
||||||
|
item->setPropertyId(getElementTypeName(type));
|
||||||
|
topItem->addSubProperty(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
QtProperty *DesignWidget::addSubGroup(QtProperty *topItem, const QString &name)
|
||||||
|
{
|
||||||
|
QtProperty *item = groupManager->addProperty(name);
|
||||||
|
topItem->addSubProperty(item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
void DesignWidget::onItemSelectionChanged()
|
void DesignWidget::onItemSelectionChanged()
|
||||||
{
|
{
|
||||||
if (treeWidget->selectedItems().size()== 0) return;
|
if (treeWidget->selectedItems().size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
QTreeWidgetItem *clickItem = treeWidget->selectedItems().at(0);
|
QTreeWidgetItem *clickItem = treeWidget->selectedItems().at(0);
|
||||||
|
|
||||||
@ -336,6 +474,8 @@ void DesignWidget::onItemSelectionChanged()
|
|||||||
|
|
||||||
std::vector<DecalXY> decals;
|
std::vector<DecalXY> decals;
|
||||||
|
|
||||||
|
addToHistory(clickItem);
|
||||||
|
|
||||||
clearProperties();
|
clearProperties();
|
||||||
if (type == ElementType::BEL) {
|
if (type == ElementType::BEL) {
|
||||||
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
||||||
@ -344,28 +484,14 @@ void DesignWidget::onItemSelectionChanged()
|
|||||||
decals.push_back(ctx->getBelDecal(bel));
|
decals.push_back(ctx->getBelDecal(bel));
|
||||||
Q_EMIT selected(decals);
|
Q_EMIT selected(decals);
|
||||||
|
|
||||||
QtProperty *topItem = groupManager->addProperty("Bel");
|
QtProperty *topItem = addTopLevelProperty("Bel");
|
||||||
addProperty(topItem, "Bel");
|
|
||||||
|
|
||||||
QtVariantProperty *nameItem = readOnlyManager->addProperty(QVariant::String, "Name");
|
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
|
||||||
nameItem->setValue(c.c_str(ctx));
|
addProperty(topItem, QVariant::String, "Type", ctx->belTypeToId(ctx->getBelType(bel)).c_str(ctx));
|
||||||
topItem->addSubProperty(nameItem);
|
addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel));
|
||||||
|
addProperty(topItem, QVariant::String, "Bound Cell", ctx->getBoundBelCell(bel).c_str(ctx), ElementType::CELL);
|
||||||
QtVariantProperty *typeItem = readOnlyManager->addProperty(QVariant::String, "Type");
|
addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->getConflictingBelCell(bel).c_str(ctx),
|
||||||
typeItem->setValue(ctx->belTypeToId(ctx->getBelType(bel)).c_str(ctx));
|
ElementType::CELL);
|
||||||
topItem->addSubProperty(typeItem);
|
|
||||||
|
|
||||||
QtVariantProperty *availItem = readOnlyManager->addProperty(QVariant::Bool, "Available");
|
|
||||||
availItem->setValue(ctx->checkBelAvail(bel));
|
|
||||||
topItem->addSubProperty(availItem);
|
|
||||||
|
|
||||||
QtVariantProperty *cellItem = readOnlyManager->addProperty(QVariant::String, "Bound Cell");
|
|
||||||
cellItem->setValue(ctx->getBoundBelCell(bel).c_str(ctx));
|
|
||||||
topItem->addSubProperty(cellItem);
|
|
||||||
|
|
||||||
QtVariantProperty *conflictItem = readOnlyManager->addProperty(QVariant::String, "Conflicting Cell");
|
|
||||||
conflictItem->setValue(ctx->getConflictingBelCell(bel).c_str(ctx));
|
|
||||||
topItem->addSubProperty(conflictItem);
|
|
||||||
|
|
||||||
} else if (type == ElementType::WIRE) {
|
} else if (type == ElementType::WIRE) {
|
||||||
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
||||||
@ -374,76 +500,56 @@ void DesignWidget::onItemSelectionChanged()
|
|||||||
decals.push_back(ctx->getWireDecal(wire));
|
decals.push_back(ctx->getWireDecal(wire));
|
||||||
Q_EMIT selected(decals);
|
Q_EMIT selected(decals);
|
||||||
|
|
||||||
QtProperty *topItem = groupManager->addProperty("Wire");
|
QtProperty *topItem = addTopLevelProperty("Wire");
|
||||||
addProperty(topItem, "Wire");
|
|
||||||
|
|
||||||
QtVariantProperty *nameItem = readOnlyManager->addProperty(QVariant::String, "Name");
|
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
|
||||||
nameItem->setValue(c.c_str(ctx));
|
addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire));
|
||||||
topItem->addSubProperty(nameItem);
|
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundWireNet(wire).c_str(ctx), ElementType::NET);
|
||||||
|
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingWireNet(wire).c_str(ctx),
|
||||||
QtVariantProperty *availItem = readOnlyManager->addProperty(QVariant::Bool, "Available");
|
ElementType::NET);
|
||||||
availItem->setValue(ctx->checkWireAvail(wire));
|
|
||||||
topItem->addSubProperty(availItem);
|
|
||||||
|
|
||||||
QtVariantProperty *cellItem = readOnlyManager->addProperty(QVariant::String, "Bound Net");
|
|
||||||
cellItem->setValue(ctx->getBoundWireNet(wire).c_str(ctx));
|
|
||||||
topItem->addSubProperty(cellItem);
|
|
||||||
|
|
||||||
QtVariantProperty *conflictItem = readOnlyManager->addProperty(QVariant::String, "Conflicting Net");
|
|
||||||
conflictItem->setValue(ctx->getConflictingWireNet(wire).c_str(ctx));
|
|
||||||
topItem->addSubProperty(conflictItem);
|
|
||||||
|
|
||||||
|
QtProperty *belpinItem = addSubGroup(topItem, "BelPin Uphill");
|
||||||
BelPin uphill = ctx->getBelPinUphill(wire);
|
BelPin uphill = ctx->getBelPinUphill(wire);
|
||||||
QtProperty *belpinItem = groupManager->addProperty("BelPin Uphill");
|
|
||||||
topItem->addSubProperty(belpinItem);
|
|
||||||
|
|
||||||
QtVariantProperty *belUphillItem = readOnlyManager->addProperty(QVariant::String, "Bel");
|
|
||||||
if (uphill.bel != BelId())
|
if (uphill.bel != BelId())
|
||||||
belUphillItem->setValue(ctx->getBelName(uphill.bel).c_str(ctx));
|
addProperty(belpinItem, QVariant::String, "Bel", ctx->getBelName(uphill.bel).c_str(ctx), ElementType::BEL);
|
||||||
else
|
else
|
||||||
belUphillItem->setValue("");
|
addProperty(belpinItem, QVariant::String, "Bel", "", ElementType::BEL);
|
||||||
belpinItem->addSubProperty(belUphillItem);
|
|
||||||
|
|
||||||
QtVariantProperty *portUphillItem = readOnlyManager->addProperty(QVariant::String, "PortPin");
|
addProperty(belpinItem, QVariant::String, "PortPin", ctx->portPinToId(uphill.pin).c_str(ctx), ElementType::BEL);
|
||||||
portUphillItem->setValue(ctx->portPinToId(uphill.pin).c_str(ctx));
|
|
||||||
belpinItem->addSubProperty(portUphillItem);
|
|
||||||
|
|
||||||
QtProperty *downhillItem = groupManager->addProperty("BelPins Downhill");
|
QtProperty *downhillItem = addSubGroup(topItem, "BelPin Downhill");
|
||||||
topItem->addSubProperty(downhillItem);
|
|
||||||
for (const auto &item : ctx->getBelPinsDownhill(wire)) {
|
for (const auto &item : ctx->getBelPinsDownhill(wire)) {
|
||||||
QString belname = "";
|
QString belname = "";
|
||||||
if (item.bel != BelId())
|
if (item.bel != BelId())
|
||||||
belname = ctx->getBelName(item.bel).c_str(ctx);
|
belname = ctx->getBelName(item.bel).c_str(ctx);
|
||||||
QString pinname = ctx->portPinToId(item.pin).c_str(ctx);
|
QString pinname = ctx->portPinToId(item.pin).c_str(ctx);
|
||||||
|
|
||||||
QtProperty *dhItem = groupManager->addProperty(belname + "-" + pinname);
|
QtProperty *dhItem = addSubGroup(downhillItem, belname + "-" + pinname);
|
||||||
downhillItem->addSubProperty(dhItem);
|
addProperty(dhItem, QVariant::String, "Bel", belname, ElementType::BEL);
|
||||||
|
addProperty(dhItem, QVariant::String, "PortPin", pinname);
|
||||||
QtVariantProperty *belItem = readOnlyManager->addProperty(QVariant::String, "Bel");
|
|
||||||
belItem->setValue(belname);
|
|
||||||
dhItem->addSubProperty(belItem);
|
|
||||||
|
|
||||||
QtVariantProperty *portItem = readOnlyManager->addProperty(QVariant::String, "PortPin");
|
|
||||||
portItem->setValue(pinname);
|
|
||||||
dhItem->addSubProperty(portItem);
|
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
QtProperty *pipsDownItem = groupManager->addProperty("Pips Downhill");
|
int counter = 0;
|
||||||
topItem->addSubProperty(pipsDownItem);
|
QtProperty *pipsDownItem = addSubGroup(downhillItem, "Pips Downhill");
|
||||||
for (const auto &item : ctx->getPipsDownhill(wire)) {
|
for (const auto &item : ctx->getPipsDownhill(wire)) {
|
||||||
QtVariantProperty *pipItem = readOnlyManager->addProperty(QVariant::String, "");
|
addProperty(pipsDownItem, QVariant::String, "", ctx->getPipName(item).c_str(ctx), ElementType::PIP);
|
||||||
pipItem->setValue(ctx->getPipName(item).c_str(ctx));
|
counter++;
|
||||||
pipsDownItem->addSubProperty(pipItem);
|
if (counter == 50) {
|
||||||
|
addProperty(pipsDownItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QtProperty *pipsUpItem = groupManager->addProperty("Pips Uphill");
|
counter = 0;
|
||||||
topItem->addSubProperty(pipsUpItem);
|
QtProperty *pipsUpItem = addSubGroup(downhillItem, "Pips Uphill");
|
||||||
for (const auto &item : ctx->getPipsUphill(wire)) {
|
for (const auto &item : ctx->getPipsUphill(wire)) {
|
||||||
QtVariantProperty *pipItem = readOnlyManager->addProperty(QVariant::String, "");
|
addProperty(pipsUpItem, QVariant::String, "", ctx->getPipName(item).c_str(ctx), ElementType::PIP);
|
||||||
pipItem->setValue(ctx->getPipName(item).c_str(ctx));
|
counter++;
|
||||||
pipsUpItem->addSubProperty(pipItem);
|
if (counter == 50) {
|
||||||
|
addProperty(pipsUpItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
} else if (type == ElementType::PIP) {
|
} else if (type == ElementType::PIP) {
|
||||||
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
||||||
PipId pip = ctx->getPipByName(c);
|
PipId pip = ctx->getPipByName(c);
|
||||||
@ -451,199 +557,108 @@ void DesignWidget::onItemSelectionChanged()
|
|||||||
decals.push_back(ctx->getPipDecal(pip));
|
decals.push_back(ctx->getPipDecal(pip));
|
||||||
Q_EMIT selected(decals);
|
Q_EMIT selected(decals);
|
||||||
|
|
||||||
QtProperty *topItem = groupManager->addProperty("Pip");
|
QtProperty *topItem = addTopLevelProperty("Pip");
|
||||||
addProperty(topItem, "Pip");
|
|
||||||
|
|
||||||
QtVariantProperty *nameItem = readOnlyManager->addProperty(QVariant::String, "Name");
|
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
|
||||||
nameItem->setValue(c.c_str(ctx));
|
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip));
|
||||||
topItem->addSubProperty(nameItem);
|
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundPipNet(pip).c_str(ctx), ElementType::NET);
|
||||||
|
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingPipNet(pip).c_str(ctx),
|
||||||
QtVariantProperty *availItem = readOnlyManager->addProperty(QVariant::Bool, "Available");
|
ElementType::NET);
|
||||||
availItem->setValue(ctx->checkPipAvail(pip));
|
addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx),
|
||||||
topItem->addSubProperty(availItem);
|
ElementType::WIRE);
|
||||||
|
addProperty(topItem, QVariant::String, "Dest Wire", ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx),
|
||||||
QtVariantProperty *cellItem = readOnlyManager->addProperty(QVariant::String, "Bound Net");
|
ElementType::WIRE);
|
||||||
cellItem->setValue(ctx->getBoundPipNet(pip).c_str(ctx));
|
|
||||||
topItem->addSubProperty(cellItem);
|
|
||||||
|
|
||||||
QtVariantProperty *conflictItem = readOnlyManager->addProperty(QVariant::String, "Conflicting Net");
|
|
||||||
conflictItem->setValue(ctx->getConflictingPipNet(pip).c_str(ctx));
|
|
||||||
topItem->addSubProperty(conflictItem);
|
|
||||||
|
|
||||||
QtVariantProperty *srcWireItem = readOnlyManager->addProperty(QVariant::String, "Src Wire");
|
|
||||||
srcWireItem->setValue(ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx));
|
|
||||||
topItem->addSubProperty(srcWireItem);
|
|
||||||
|
|
||||||
QtVariantProperty *destWireItem = readOnlyManager->addProperty(QVariant::String, "Dest Wire");
|
|
||||||
destWireItem->setValue(ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx));
|
|
||||||
topItem->addSubProperty(destWireItem);
|
|
||||||
|
|
||||||
DelayInfo delay = ctx->getPipDelay(pip);
|
DelayInfo delay = ctx->getPipDelay(pip);
|
||||||
QtProperty *delayItem = groupManager->addProperty("Delay");
|
|
||||||
topItem->addSubProperty(delayItem);
|
|
||||||
|
|
||||||
QtVariantProperty *raiseDelayItem = readOnlyManager->addProperty(QVariant::Double, "Raise");
|
|
||||||
raiseDelayItem->setValue(delay.raiseDelay());
|
|
||||||
delayItem->addSubProperty(raiseDelayItem);
|
|
||||||
|
|
||||||
QtVariantProperty *fallDelayItem = readOnlyManager->addProperty(QVariant::Double, "Fall");
|
|
||||||
fallDelayItem->setValue(delay.fallDelay());
|
|
||||||
delayItem->addSubProperty(fallDelayItem);
|
|
||||||
|
|
||||||
QtVariantProperty *avgDelayItem = readOnlyManager->addProperty(QVariant::Double, "Average");
|
|
||||||
avgDelayItem->setValue(delay.avgDelay());
|
|
||||||
delayItem->addSubProperty(avgDelayItem);
|
|
||||||
|
|
||||||
|
QtProperty *delayItem = addSubGroup(topItem, "Delay");
|
||||||
|
addProperty(delayItem, QVariant::Double, "Raise", delay.raiseDelay());
|
||||||
|
addProperty(delayItem, QVariant::Double, "Fall", delay.fallDelay());
|
||||||
|
addProperty(delayItem, QVariant::Double, "Average", delay.avgDelay());
|
||||||
} else if (type == ElementType::NET) {
|
} else if (type == ElementType::NET) {
|
||||||
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
||||||
NetInfo *net = ctx->nets.at(c).get();
|
NetInfo *net = ctx->nets.at(c).get();
|
||||||
|
|
||||||
QtProperty *topItem = groupManager->addProperty("Net");
|
QtProperty *topItem = addTopLevelProperty("Net");
|
||||||
addProperty(topItem, "Net");
|
|
||||||
|
|
||||||
QtVariantProperty *nameItem = readOnlyManager->addProperty(QVariant::String, "Name");
|
addProperty(topItem, QVariant::String, "Name", net->name.c_str(ctx));
|
||||||
nameItem->setValue(net->name.c_str(ctx));
|
|
||||||
topItem->addSubProperty(nameItem);
|
|
||||||
|
|
||||||
QtProperty *driverItem = groupManager->addProperty("Driver");
|
QtProperty *driverItem = addSubGroup(topItem, "Driver");
|
||||||
topItem->addSubProperty(driverItem);
|
addProperty(driverItem, QVariant::String, "Port", net->driver.port.c_str(ctx));
|
||||||
|
addProperty(driverItem, QVariant::Double, "Budget", net->driver.budget);
|
||||||
QtVariantProperty *portItem = readOnlyManager->addProperty(QVariant::String, "Port");
|
|
||||||
portItem->setValue(net->driver.port.c_str(ctx));
|
|
||||||
driverItem->addSubProperty(portItem);
|
|
||||||
|
|
||||||
QtVariantProperty *budgetItem = readOnlyManager->addProperty(QVariant::Double, "Budget");
|
|
||||||
budgetItem->setValue(net->driver.budget);
|
|
||||||
driverItem->addSubProperty(budgetItem);
|
|
||||||
|
|
||||||
QtVariantProperty *cellNameItem = readOnlyManager->addProperty(QVariant::String, "Cell");
|
|
||||||
if (net->driver.cell)
|
if (net->driver.cell)
|
||||||
cellNameItem->setValue(net->driver.cell->name.c_str(ctx));
|
addProperty(driverItem, QVariant::String, "Cell", net->driver.cell->name.c_str(ctx), ElementType::CELL);
|
||||||
else
|
else
|
||||||
cellNameItem->setValue("");
|
addProperty(driverItem, QVariant::String, "Cell", "", ElementType::CELL);
|
||||||
driverItem->addSubProperty(cellNameItem);
|
|
||||||
|
|
||||||
QtProperty *usersItem = groupManager->addProperty("Users");
|
QtProperty *usersItem = addSubGroup(topItem, "Users");
|
||||||
topItem->addSubProperty(usersItem);
|
|
||||||
for (auto &item : net->users) {
|
for (auto &item : net->users) {
|
||||||
QtProperty *portItem = groupManager->addProperty(item.port.c_str(ctx));
|
QtProperty *portItem = addSubGroup(usersItem, item.port.c_str(ctx));
|
||||||
usersItem->addSubProperty(portItem);
|
|
||||||
|
|
||||||
QtVariantProperty *nameItem = readOnlyManager->addProperty(QVariant::String, "Port");
|
addProperty(portItem, QVariant::String, "Port", item.port.c_str(ctx));
|
||||||
nameItem->setValue(item.port.c_str(ctx));
|
addProperty(portItem, QVariant::Double, "Budget", item.budget);
|
||||||
portItem->addSubProperty(nameItem);
|
|
||||||
|
|
||||||
QtVariantProperty *budgetItem = readOnlyManager->addProperty(QVariant::Double, "Budget");
|
|
||||||
budgetItem->setValue(item.budget);
|
|
||||||
portItem->addSubProperty(budgetItem);
|
|
||||||
|
|
||||||
QtVariantProperty *userItem = readOnlyManager->addProperty(QVariant::String, "Cell");
|
|
||||||
if (item.cell)
|
if (item.cell)
|
||||||
userItem->setValue(item.cell->name.c_str(ctx));
|
addProperty(portItem, QVariant::String, "Cell", item.cell->name.c_str(ctx), ElementType::CELL);
|
||||||
else
|
else
|
||||||
userItem->setValue("");
|
addProperty(portItem, QVariant::String, "Cell", "", ElementType::CELL);
|
||||||
portItem->addSubProperty(userItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QtProperty *attrsItem = groupManager->addProperty("Attributes");
|
QtProperty *attrsItem = addSubGroup(topItem, "Attributes");
|
||||||
topItem->addSubProperty(attrsItem);
|
|
||||||
for (auto &item : net->attrs) {
|
for (auto &item : net->attrs) {
|
||||||
QtVariantProperty *attrItem = readOnlyManager->addProperty(QVariant::String, item.first.c_str(ctx));
|
addProperty(attrsItem, QVariant::String, item.first.c_str(ctx), item.second.c_str());
|
||||||
attrItem->setValue(item.second.c_str());
|
|
||||||
attrsItem->addSubProperty(attrItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QtProperty *wiresItem = groupManager->addProperty("Wires");
|
QtProperty *wiresItem = addSubGroup(topItem, "Wires");
|
||||||
topItem->addSubProperty(wiresItem);
|
|
||||||
for (auto &item : net->wires) {
|
for (auto &item : net->wires) {
|
||||||
auto name = ctx->getWireName(item.first).c_str(ctx);
|
auto name = ctx->getWireName(item.first).c_str(ctx);
|
||||||
|
|
||||||
QtProperty *wireItem = groupManager->addProperty(name);
|
QtProperty *wireItem = addSubGroup(wiresItem, name);
|
||||||
|
addProperty(wireItem, QVariant::String, "Name", name);
|
||||||
QtVariantProperty *nameItem = readOnlyManager->addProperty(QVariant::String, "Name");
|
|
||||||
nameItem->setValue(name);
|
|
||||||
wireItem->addSubProperty(nameItem);
|
|
||||||
|
|
||||||
QtVariantProperty *pipItem = readOnlyManager->addProperty(QVariant::String, "Pip");
|
|
||||||
|
|
||||||
if (item.second.pip != PipId())
|
if (item.second.pip != PipId())
|
||||||
pipItem->setValue(ctx->getPipName(item.second.pip).c_str(ctx));
|
addProperty(wireItem, QVariant::String, "Pip", ctx->getPipName(item.second.pip).c_str(ctx),
|
||||||
|
ElementType::PIP);
|
||||||
else
|
else
|
||||||
pipItem->setValue("");
|
addProperty(wireItem, QVariant::String, "Pip", "", ElementType::PIP);
|
||||||
wireItem->addSubProperty(pipItem);
|
|
||||||
|
|
||||||
QtVariantProperty *strengthItem = readOnlyManager->addProperty(QVariant::Int, "Strength");
|
addProperty(wireItem, QVariant::Int, "Strength", (int)item.second.strength);
|
||||||
strengthItem->setValue((int)item.second.strength);
|
|
||||||
wireItem->addSubProperty(strengthItem);
|
|
||||||
|
|
||||||
wiresItem->addSubProperty(wireItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (type == ElementType::CELL) {
|
} else if (type == ElementType::CELL) {
|
||||||
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
||||||
CellInfo *cell = ctx->cells.at(c).get();
|
CellInfo *cell = ctx->cells.at(c).get();
|
||||||
|
|
||||||
QtProperty *topItem = groupManager->addProperty("Cell");
|
QtProperty *topItem = addTopLevelProperty("Cell");
|
||||||
addProperty(topItem, "Cell");
|
|
||||||
|
|
||||||
QtVariantProperty *cellNameItem = readOnlyManager->addProperty(QVariant::String, "Name");
|
addProperty(topItem, QVariant::String, "Name", cell->name.c_str(ctx));
|
||||||
cellNameItem->setValue(cell->name.c_str(ctx));
|
addProperty(topItem, QVariant::String, "Type", cell->type.c_str(ctx));
|
||||||
topItem->addSubProperty(cellNameItem);
|
|
||||||
|
|
||||||
QtVariantProperty *cellTypeItem = readOnlyManager->addProperty(QVariant::String, "Type");
|
|
||||||
cellTypeItem->setValue(cell->type.c_str(ctx));
|
|
||||||
topItem->addSubProperty(cellTypeItem);
|
|
||||||
|
|
||||||
QtVariantProperty *cellBelItem = readOnlyManager->addProperty(QVariant::String, "Bel");
|
|
||||||
if (cell->bel != BelId())
|
if (cell->bel != BelId())
|
||||||
cellBelItem->setValue(ctx->getBelName(cell->bel).c_str(ctx));
|
addProperty(topItem, QVariant::String, "Bel", ctx->getBelName(cell->bel).c_str(ctx), ElementType::BEL);
|
||||||
else
|
else
|
||||||
cellBelItem->setValue("");
|
addProperty(topItem, QVariant::String, "Bel", "", ElementType::BEL);
|
||||||
topItem->addSubProperty(cellBelItem);
|
addProperty(topItem, QVariant::Int, "Bel strength", int(cell->belStrength));
|
||||||
|
|
||||||
QtVariantProperty *cellBelStrItem = readOnlyManager->addProperty(QVariant::Int, "Bel strength");
|
QtProperty *cellPortsItem = addSubGroup(topItem, "Ports");
|
||||||
cellBelStrItem->setValue(int(cell->belStrength));
|
|
||||||
topItem->addSubProperty(cellBelStrItem);
|
|
||||||
|
|
||||||
QtProperty *cellPortsItem = groupManager->addProperty("Ports");
|
|
||||||
topItem->addSubProperty(cellPortsItem);
|
|
||||||
for (auto &item : cell->ports) {
|
for (auto &item : cell->ports) {
|
||||||
PortInfo p = item.second;
|
PortInfo p = item.second;
|
||||||
|
|
||||||
QtProperty *portInfoItem = groupManager->addProperty(p.name.c_str(ctx));
|
QtProperty *portInfoItem = addSubGroup(cellPortsItem, p.name.c_str(ctx));
|
||||||
|
addProperty(portInfoItem, QVariant::String, "Name", p.name.c_str(ctx));
|
||||||
QtVariantProperty *portInfoNameItem = readOnlyManager->addProperty(QVariant::String, "Name");
|
addProperty(portInfoItem, QVariant::Int, "Type", int(p.type));
|
||||||
portInfoNameItem->setValue(p.name.c_str(ctx));
|
|
||||||
portInfoItem->addSubProperty(portInfoNameItem);
|
|
||||||
|
|
||||||
QtVariantProperty *portInfoTypeItem = readOnlyManager->addProperty(QVariant::Int, "Type");
|
|
||||||
portInfoTypeItem->setValue(int(p.type));
|
|
||||||
portInfoItem->addSubProperty(portInfoTypeItem);
|
|
||||||
|
|
||||||
QtVariantProperty *portInfoNetItem = readOnlyManager->addProperty(QVariant::String, "Net");
|
|
||||||
if (p.net)
|
if (p.net)
|
||||||
portInfoNetItem->setValue(p.net->name.c_str(ctx));
|
addProperty(portInfoItem, QVariant::String, "Net", p.net->name.c_str(ctx), ElementType::NET);
|
||||||
else
|
else
|
||||||
portInfoNetItem->setValue("");
|
addProperty(portInfoItem, QVariant::String, "Net", "", ElementType::NET);
|
||||||
portInfoItem->addSubProperty(portInfoNetItem);
|
|
||||||
|
|
||||||
cellPortsItem->addSubProperty(portInfoItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QtProperty *cellAttrItem = groupManager->addProperty("Attributes");
|
QtProperty *cellAttrItem = addSubGroup(topItem, "Attributes");
|
||||||
topItem->addSubProperty(cellAttrItem);
|
|
||||||
for (auto &item : cell->attrs) {
|
for (auto &item : cell->attrs) {
|
||||||
QtVariantProperty *attrItem = readOnlyManager->addProperty(QVariant::String, item.first.c_str(ctx));
|
addProperty(cellAttrItem, QVariant::String, item.first.c_str(ctx), item.second.c_str());
|
||||||
attrItem->setValue(item.second.c_str());
|
|
||||||
cellAttrItem->addSubProperty(attrItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QtProperty *cellParamsItem = groupManager->addProperty("Parameters");
|
QtProperty *cellParamsItem = addSubGroup(topItem, "Parameters");
|
||||||
topItem->addSubProperty(cellParamsItem);
|
|
||||||
for (auto &item : cell->params) {
|
for (auto &item : cell->params) {
|
||||||
QtVariantProperty *paramItem = readOnlyManager->addProperty(QVariant::String, item.first.c_str(ctx));
|
addProperty(cellParamsItem, QVariant::String, item.first.c_str(ctx), item.second.c_str());
|
||||||
paramItem->setValue(item.second.c_str());
|
|
||||||
cellParamsItem->addSubProperty(paramItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QtProperty *cellPinsItem = groupManager->addProperty("Pins");
|
QtProperty *cellPinsItem = groupManager->addProperty("Pins");
|
||||||
@ -652,38 +667,159 @@ void DesignWidget::onItemSelectionChanged()
|
|||||||
std::string cell_port = item.first.c_str(ctx);
|
std::string cell_port = item.first.c_str(ctx);
|
||||||
std::string bel_pin = item.second.c_str(ctx);
|
std::string bel_pin = item.second.c_str(ctx);
|
||||||
|
|
||||||
QtProperty *pinGroupItem = groupManager->addProperty((cell_port + " -> " + bel_pin).c_str());
|
QtProperty *pinGroupItem = addSubGroup(cellPortsItem, (cell_port + " -> " + bel_pin).c_str());
|
||||||
|
|
||||||
QtVariantProperty *cellItem = readOnlyManager->addProperty(QVariant::String, "Cell");
|
addProperty(pinGroupItem, QVariant::String, "Cell", cell_port.c_str(), ElementType::CELL);
|
||||||
cellItem->setValue(cell_port.c_str());
|
addProperty(pinGroupItem, QVariant::String, "Bel", bel_pin.c_str(), ElementType::BEL);
|
||||||
pinGroupItem->addSubProperty(cellItem);
|
|
||||||
|
|
||||||
QtVariantProperty *belItem = readOnlyManager->addProperty(QVariant::String, "Bel");
|
|
||||||
belItem->setValue(bel_pin.c_str());
|
|
||||||
pinGroupItem->addSubProperty(belItem);
|
|
||||||
|
|
||||||
cellPinsItem->addSubProperty(pinGroupItem);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignWidget::prepareMenu(const QPoint &pos)
|
std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value)
|
||||||
|
{
|
||||||
|
std::vector<DecalXY> decals;
|
||||||
|
switch (type) {
|
||||||
|
case ElementType::BEL: {
|
||||||
|
BelId bel = ctx->getBelByName(value);
|
||||||
|
if (bel != BelId()) {
|
||||||
|
decals.push_back(ctx->getBelDecal(bel));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case ElementType::WIRE: {
|
||||||
|
WireId wire = ctx->getWireByName(value);
|
||||||
|
if (wire != WireId()) {
|
||||||
|
decals.push_back(ctx->getWireDecal(wire));
|
||||||
|
Q_EMIT selected(decals);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case ElementType::PIP: {
|
||||||
|
PipId pip = ctx->getPipByName(value);
|
||||||
|
if (pip != PipId()) {
|
||||||
|
decals.push_back(ctx->getPipDecal(pip));
|
||||||
|
Q_EMIT selected(decals);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case ElementType::NET: {
|
||||||
|
} break;
|
||||||
|
case ElementType::CELL: {
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return decals;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesignWidget::updateHighlightGroup(QTreeWidgetItem *item, int group)
|
||||||
|
{
|
||||||
|
if (highlightSelected.contains(item)) {
|
||||||
|
if (highlightSelected[item] == group) {
|
||||||
|
highlightSelected.remove(item);
|
||||||
|
} else
|
||||||
|
highlightSelected[item] = group;
|
||||||
|
} else
|
||||||
|
highlightSelected.insert(item, group);
|
||||||
|
|
||||||
|
std::vector<DecalXY> decals;
|
||||||
|
|
||||||
|
for (auto it : highlightSelected.toStdMap()) {
|
||||||
|
if (it.second == group) {
|
||||||
|
ElementType type = static_cast<ElementTreeItem *>(it.first)->getType();
|
||||||
|
IdString value = static_cast<IdStringTreeItem *>(it.first)->getData();
|
||||||
|
std::vector<DecalXY> d = getDecals(type, value);
|
||||||
|
std::move(d.begin(), d.end(), std::back_inserter(decals));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_EMIT highlight(decals, group);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesignWidget::prepareMenuProperty(const QPoint &pos)
|
||||||
|
{
|
||||||
|
QTreeWidget *tree = propertyEditor->treeWidget();
|
||||||
|
|
||||||
|
itemContextMenu = tree->itemAt(pos);
|
||||||
|
if (itemContextMenu->parent() == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QtBrowserItem *browserItem = propertyEditor->itemToBrowserItem(itemContextMenu);
|
||||||
|
if (!browserItem)
|
||||||
|
return;
|
||||||
|
QtProperty *selectedProperty = browserItem->property();
|
||||||
|
ElementType type = getElementTypeByName(selectedProperty->propertyId());
|
||||||
|
if (type == ElementType::NONE)
|
||||||
|
return;
|
||||||
|
IdString value = ctx->id(selectedProperty->valueText().toStdString());
|
||||||
|
|
||||||
|
QTreeWidgetItem *item = nameToItem[getElementIndex(type)].value(value.c_str(ctx));
|
||||||
|
|
||||||
|
QMenu menu(this);
|
||||||
|
QAction *selectAction = new QAction("&Select", this);
|
||||||
|
connect(selectAction, &QAction::triggered, this, [this, type, value] { Q_EMIT selected(getDecals(type, value)); });
|
||||||
|
menu.addAction(selectAction);
|
||||||
|
|
||||||
|
QMenu *subMenu = menu.addMenu("Highlight");
|
||||||
|
QActionGroup *group = new QActionGroup(this);
|
||||||
|
group->setExclusive(true);
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
QPixmap pixmap(32, 32);
|
||||||
|
pixmap.fill(QColor(highlightColors[i]));
|
||||||
|
QAction *action = new QAction(QIcon(pixmap), ("Group " + std::to_string(i)).c_str(), this);
|
||||||
|
action->setCheckable(true);
|
||||||
|
subMenu->addAction(action);
|
||||||
|
group->addAction(action);
|
||||||
|
if (highlightSelected.contains(item) && highlightSelected[item] == i)
|
||||||
|
action->setChecked(true);
|
||||||
|
connect(action, &QAction::triggered, this, [this, i, item] { updateHighlightGroup(item, i); });
|
||||||
|
}
|
||||||
|
menu.exec(tree->mapToGlobal(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesignWidget::prepareMenuTree(const QPoint &pos)
|
||||||
{
|
{
|
||||||
QTreeWidget *tree = treeWidget;
|
QTreeWidget *tree = treeWidget;
|
||||||
|
|
||||||
itemContextMenu = tree->itemAt(pos);
|
itemContextMenu = tree->itemAt(pos);
|
||||||
|
|
||||||
QAction *selectAction = new QAction("&Select", this);
|
ElementType type = static_cast<ElementTreeItem *>(itemContextMenu)->getType();
|
||||||
selectAction->setStatusTip("Select item on view");
|
IdString value = static_cast<IdStringTreeItem *>(itemContextMenu)->getData();
|
||||||
|
|
||||||
connect(selectAction, SIGNAL(triggered()), this, SLOT(selectObject()));
|
if (type == ElementType::NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QTreeWidgetItem *item = nameToItem[getElementIndex(type)].value(value.c_str(ctx));
|
||||||
|
|
||||||
QMenu menu(this);
|
QMenu menu(this);
|
||||||
menu.addAction(selectAction);
|
QMenu *subMenu = menu.addMenu("Highlight");
|
||||||
|
QActionGroup *group = new QActionGroup(this);
|
||||||
|
group->setExclusive(true);
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
QPixmap pixmap(32, 32);
|
||||||
|
pixmap.fill(QColor(highlightColors[i]));
|
||||||
|
QAction *action = new QAction(QIcon(pixmap), ("Group " + std::to_string(i)).c_str(), this);
|
||||||
|
action->setCheckable(true);
|
||||||
|
subMenu->addAction(action);
|
||||||
|
group->addAction(action);
|
||||||
|
if (highlightSelected.contains(item) && highlightSelected[item] == i)
|
||||||
|
action->setChecked(true);
|
||||||
|
connect(action, &QAction::triggered, this, [this, i, item] { updateHighlightGroup(item, i); });
|
||||||
|
}
|
||||||
menu.exec(tree->mapToGlobal(pos));
|
menu.exec(tree->mapToGlobal(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignWidget::selectObject() { Q_EMIT info("selected " + itemContextMenu->text(0).toStdString() + "\n"); }
|
void DesignWidget::onItemDoubleClicked(QTreeWidgetItem *item, int column)
|
||||||
|
{
|
||||||
|
QtProperty *selectedProperty = propertyEditor->itemToBrowserItem(item)->property();
|
||||||
|
ElementType type = getElementTypeByName(selectedProperty->propertyId());
|
||||||
|
QString value = selectedProperty->valueText();
|
||||||
|
int index = getElementIndex(type);
|
||||||
|
switch (type) {
|
||||||
|
case ElementType::NONE:
|
||||||
|
return;
|
||||||
|
default: {
|
||||||
|
if (nameToItem[index].contains(value))
|
||||||
|
treeWidget->setCurrentItem(nameToItem[index].value(value));
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define DESIGNWIDGET_H
|
#define DESIGNWIDGET_H
|
||||||
|
|
||||||
#include <QTreeWidget>
|
#include <QTreeWidget>
|
||||||
|
#include <QVariant>
|
||||||
#include "nextpnr.h"
|
#include "nextpnr.h"
|
||||||
#include "qtgroupboxpropertybrowser.h"
|
#include "qtgroupboxpropertybrowser.h"
|
||||||
#include "qtpropertymanager.h"
|
#include "qtpropertymanager.h"
|
||||||
@ -29,6 +30,16 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
enum class ElementType
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
BEL,
|
||||||
|
WIRE,
|
||||||
|
PIP,
|
||||||
|
NET,
|
||||||
|
CELL
|
||||||
|
};
|
||||||
|
|
||||||
class DesignWidget : public QWidget
|
class DesignWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -38,17 +49,30 @@ class DesignWidget : public QWidget
|
|||||||
~DesignWidget();
|
~DesignWidget();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addProperty(QtProperty *property, const QString &id);
|
|
||||||
void clearProperties();
|
void clearProperties();
|
||||||
|
QtProperty *addTopLevelProperty(const QString &id);
|
||||||
|
QtProperty *addSubGroup(QtProperty *topItem, const QString &name);
|
||||||
|
void addProperty(QtProperty *topItem, int propertyType, const QString &name, QVariant value,
|
||||||
|
const ElementType &type = ElementType::NONE);
|
||||||
|
QString getElementTypeName(ElementType type);
|
||||||
|
ElementType getElementTypeByName(QString type);
|
||||||
|
int getElementIndex(ElementType type);
|
||||||
|
void updateButtons();
|
||||||
|
void addToHistory(QTreeWidgetItem *item);
|
||||||
|
std::vector<DecalXY> getDecals(ElementType type, IdString value);
|
||||||
|
void updateHighlightGroup(QTreeWidgetItem *item, int group);
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void info(std::string text);
|
void info(std::string text);
|
||||||
void selected(std::vector<DecalXY> decal);
|
void selected(std::vector<DecalXY> decal);
|
||||||
|
void highlight(std::vector<DecalXY> decal, int group);
|
||||||
|
void finishContextLoad();
|
||||||
|
void contextLoadStatus(std::string text);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void prepareMenu(const QPoint &pos);
|
void prepareMenuProperty(const QPoint &pos);
|
||||||
|
void prepareMenuTree(const QPoint &pos);
|
||||||
void onItemSelectionChanged();
|
void onItemSelectionChanged();
|
||||||
void selectObject();
|
void onItemDoubleClicked(QTreeWidgetItem *item, int column);
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void newContext(Context *ctx);
|
void newContext(Context *ctx);
|
||||||
void updateTree();
|
void updateTree();
|
||||||
@ -67,6 +91,12 @@ class DesignWidget : public QWidget
|
|||||||
|
|
||||||
QMap<QtProperty *, QString> propertyToId;
|
QMap<QtProperty *, QString> propertyToId;
|
||||||
QMap<QString, QtProperty *> idToProperty;
|
QMap<QString, QtProperty *> idToProperty;
|
||||||
|
|
||||||
|
QMap<QString, QTreeWidgetItem *> nameToItem[6];
|
||||||
|
std::vector<QTreeWidgetItem *> history;
|
||||||
|
int history_index;
|
||||||
|
bool history_ignore;
|
||||||
|
|
||||||
QTreeWidgetItem *nets_root;
|
QTreeWidgetItem *nets_root;
|
||||||
QTreeWidgetItem *cells_root;
|
QTreeWidgetItem *cells_root;
|
||||||
|
|
||||||
@ -74,6 +104,9 @@ class DesignWidget : public QWidget
|
|||||||
QAction *actionPrev;
|
QAction *actionPrev;
|
||||||
QAction *actionNext;
|
QAction *actionNext;
|
||||||
QAction *actionLast;
|
QAction *actionLast;
|
||||||
|
|
||||||
|
QColor highlightColors[8];
|
||||||
|
QMap<QTreeWidgetItem *, int> highlightSelected;
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -240,7 +240,8 @@ void LineShader::draw(const LineShaderData &line, const QColor &color, float thi
|
|||||||
vao_.release();
|
vao_.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
FPGAViewWidget::FPGAViewWidget(QWidget *parent) : QOpenGLWidget(parent), lineShader_(this), zoom_(500.f), ctx_(nullptr), selectedItemsChanged(false)
|
FPGAViewWidget::FPGAViewWidget(QWidget *parent)
|
||||||
|
: QOpenGLWidget(parent), lineShader_(this), zoom_(500.f), ctx_(nullptr), selectedItemsChanged_(false)
|
||||||
{
|
{
|
||||||
backgroundColor_ = QColor("#000000");
|
backgroundColor_ = QColor("#000000");
|
||||||
gridColor_ = QColor("#333");
|
gridColor_ = QColor("#333");
|
||||||
@ -250,6 +251,16 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) : QOpenGLWidget(parent), lineSha
|
|||||||
gActiveColor_ = QColor("#f0f0f0");
|
gActiveColor_ = QColor("#f0f0f0");
|
||||||
gSelectedColor_ = QColor("#ff6600");
|
gSelectedColor_ = QColor("#ff6600");
|
||||||
frameColor_ = QColor("#0066ba");
|
frameColor_ = QColor("#0066ba");
|
||||||
|
highlightColors[0] = QColor("#6495ed");
|
||||||
|
highlightColors[1] = QColor("#7fffd4");
|
||||||
|
highlightColors[2] = QColor("#98fb98");
|
||||||
|
highlightColors[3] = QColor("#ffd700");
|
||||||
|
highlightColors[4] = QColor("#cd5c5c");
|
||||||
|
highlightColors[5] = QColor("#fa8072");
|
||||||
|
highlightColors[6] = QColor("#ff69b4");
|
||||||
|
highlightColors[7] = QColor("#da70d6");
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
highlightItemsChanged_[i] = false;
|
||||||
|
|
||||||
auto fmt = format();
|
auto fmt = format();
|
||||||
fmt.setMajorVersion(3);
|
fmt.setMajorVersion(3);
|
||||||
@ -272,6 +283,7 @@ FPGAViewWidget::~FPGAViewWidget() {}
|
|||||||
void FPGAViewWidget::newContext(Context *ctx)
|
void FPGAViewWidget::newContext(Context *ctx)
|
||||||
{
|
{
|
||||||
ctx_ = ctx;
|
ctx_ = ctx;
|
||||||
|
selectedItems_.clear();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,27 +423,44 @@ void FPGAViewWidget::paintGL()
|
|||||||
drawDecal(shaders, ctx_->getGroupDecal(group));
|
drawDecal(shaders, ctx_->getGroupDecal(group));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedItemsChanged)
|
if (selectedItemsChanged_) {
|
||||||
{
|
selectedItemsChanged_ = false;
|
||||||
selectedItemsChanged = false;
|
|
||||||
selectedShader_.clear();
|
selectedShader_.clear();
|
||||||
for (auto decal : selectedItems_) {
|
for (auto decal : selectedItems_) {
|
||||||
drawDecal(selectedShader_, decal);
|
drawDecal(selectedShader_, decal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (highlightItemsChanged_[i]) {
|
||||||
|
highlightItemsChanged_[i] = false;
|
||||||
|
highlightShader_[i].clear();
|
||||||
|
for (auto decal : highlightItems_[i]) {
|
||||||
|
drawDecal(highlightShader_[i], decal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lineShader_.draw(shaders[0], gFrameColor_, thick11Px, matrix);
|
lineShader_.draw(shaders[0], gFrameColor_, thick11Px, matrix);
|
||||||
lineShader_.draw(shaders[1], gHiddenColor_, thick11Px, matrix);
|
lineShader_.draw(shaders[1], gHiddenColor_, thick11Px, matrix);
|
||||||
lineShader_.draw(shaders[2], gInactiveColor_, thick11Px, matrix);
|
lineShader_.draw(shaders[2], gInactiveColor_, thick11Px, matrix);
|
||||||
lineShader_.draw(shaders[3], gActiveColor_, thick11Px, matrix);
|
lineShader_.draw(shaders[3], gActiveColor_, thick11Px, matrix);
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
lineShader_.draw(highlightShader_[i], highlightColors[i], thick11Px, matrix);
|
||||||
lineShader_.draw(selectedShader_, gSelectedColor_, thick11Px, matrix);
|
lineShader_.draw(selectedShader_, gSelectedColor_, thick11Px, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FPGAViewWidget::onSelectedArchItem(std::vector<DecalXY> decals)
|
void FPGAViewWidget::onSelectedArchItem(std::vector<DecalXY> decals)
|
||||||
{
|
{
|
||||||
selectedItems_ = decals;
|
selectedItems_ = decals;
|
||||||
selectedItemsChanged = true;
|
selectedItemsChanged_ = true;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPGAViewWidget::onHighlightGroupChanged(std::vector<DecalXY> decals, int group)
|
||||||
|
{
|
||||||
|
highlightItems_[group] = decals;
|
||||||
|
highlightItemsChanged_[group] = true;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +245,8 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
|
|||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void newContext(Context *ctx);
|
void newContext(Context *ctx);
|
||||||
void onSelectedArchItem(std::vector<DecalXY> decals);
|
void onSelectedArchItem(std::vector<DecalXY> decals);
|
||||||
|
void onHighlightGroupChanged(std::vector<DecalXY> decals, int group);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPoint lastPos_;
|
QPoint lastPos_;
|
||||||
LineShader lineShader_;
|
LineShader lineShader_;
|
||||||
@ -272,7 +274,12 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
|
|||||||
|
|
||||||
LineShaderData selectedShader_;
|
LineShaderData selectedShader_;
|
||||||
std::vector<DecalXY> selectedItems_;
|
std::vector<DecalXY> selectedItems_;
|
||||||
bool selectedItemsChanged;
|
bool selectedItemsChanged_;
|
||||||
|
|
||||||
|
LineShaderData highlightShader_[8];
|
||||||
|
std::vector<DecalXY> highlightItems_[8];
|
||||||
|
bool highlightItemsChanged_[8];
|
||||||
|
QColor highlightColors[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -226,6 +226,7 @@ void MainWindow::new_proj()
|
|||||||
ctx = std::unique_ptr<Context>(new Context(chipArgs));
|
ctx = std::unique_ptr<Context>(new Context(chipArgs));
|
||||||
actionLoadJSON->setEnabled(true);
|
actionLoadJSON->setEnabled(true);
|
||||||
|
|
||||||
|
Q_EMIT displaySplash();
|
||||||
Q_EMIT contextChanged(ctx.get());
|
Q_EMIT contextChanged(ctx.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
gui/resources/splash.png
Normal file
BIN
gui/resources/splash.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
@ -334,6 +334,7 @@ IdString Arch::getPipName(PipId pip) const
|
|||||||
{
|
{
|
||||||
NPNR_ASSERT(pip != PipId());
|
NPNR_ASSERT(pip != PipId());
|
||||||
|
|
||||||
|
#if 1
|
||||||
int x = chip_info->pip_data[pip.index].x;
|
int x = chip_info->pip_data[pip.index].x;
|
||||||
int y = chip_info->pip_data[pip.index].y;
|
int y = chip_info->pip_data[pip.index].y;
|
||||||
|
|
||||||
@ -344,6 +345,9 @@ IdString Arch::getPipName(PipId pip) const
|
|||||||
std::replace(dst_name.begin(), dst_name.end(), '/', '.');
|
std::replace(dst_name.begin(), dst_name.end(), '/', '.');
|
||||||
|
|
||||||
return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name);
|
return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name);
|
||||||
|
#else
|
||||||
|
return id(chip_info->pip_data[pip.index].name.get());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
@ -480,9 +484,9 @@ DecalXY Arch::getWireDecal(WireId wire) const
|
|||||||
DecalXY Arch::getPipDecal(PipId pip) const
|
DecalXY Arch::getPipDecal(PipId pip) const
|
||||||
{
|
{
|
||||||
DecalXY decalxy;
|
DecalXY decalxy;
|
||||||
decalxy.decal.type = DecalId::TYPE_PIP;
|
// decalxy.decal.type = DecalId::TYPE_PIP;
|
||||||
decalxy.decal.index = pip.index;
|
// decalxy.decal.index = pip.index;
|
||||||
decalxy.decal.active = pip_to_net.at(pip.index) != IdString();
|
// decalxy.decal.active = pip_to_net.at(pip.index) != IdString();
|
||||||
return decalxy;
|
return decalxy;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -512,11 +516,8 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (decal.type == DecalId::TYPE_WIRE) {
|
if (decal.type == DecalId::TYPE_WIRE) {
|
||||||
WireId wire;
|
int n = chip_info->wire_data[decal.index].num_segments;
|
||||||
wire.index = decal.index;
|
const WireSegmentPOD *p = chip_info->wire_data[decal.index].segments.get();
|
||||||
|
|
||||||
int n = chip_info->wire_data[wire.index].num_segments;
|
|
||||||
const WireSegmentPOD *p = chip_info->wire_data[wire.index].segments.get();
|
|
||||||
|
|
||||||
GraphicElement::style_t style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
|
GraphicElement::style_t style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
|
||||||
|
|
||||||
@ -524,6 +525,12 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
|||||||
gfxTileWire(ret, p[i].x, p[i].y, GfxTileWireId(p[i].index), style);
|
gfxTileWire(ret, p[i].x, p[i].y, GfxTileWireId(p[i].index), style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (decal.type == DecalId::TYPE_PIP) {
|
||||||
|
const PipInfoPOD &p = chip_info->pip_data[decal.index];
|
||||||
|
GraphicElement::style_t style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_HIDDEN;
|
||||||
|
gfxTilePip(ret, p.x, p.y, GfxTileWireId(p.src_seg), GfxTileWireId(p.dst_seg), style);
|
||||||
|
}
|
||||||
|
|
||||||
if (decal.type == DecalId::TYPE_BEL) {
|
if (decal.type == DecalId::TYPE_BEL) {
|
||||||
BelId bel;
|
BelId bel;
|
||||||
bel.index = decal.index;
|
bel.index = decal.index;
|
||||||
|
@ -63,9 +63,11 @@ NPNR_PACKED_STRUCT(struct BelPortPOD {
|
|||||||
});
|
});
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct PipInfoPOD {
|
NPNR_PACKED_STRUCT(struct PipInfoPOD {
|
||||||
|
// RelPtr<char> name;
|
||||||
int32_t src, dst;
|
int32_t src, dst;
|
||||||
int32_t delay;
|
int32_t delay;
|
||||||
int8_t x, y;
|
int8_t x, y;
|
||||||
|
int16_t src_seg, dst_seg;
|
||||||
int16_t switch_mask;
|
int16_t switch_mask;
|
||||||
int32_t switch_index;
|
int32_t switch_index;
|
||||||
});
|
});
|
||||||
|
@ -390,9 +390,9 @@ with open(args.filename, "r") as f:
|
|||||||
wire_xy[mode[1]] = list()
|
wire_xy[mode[1]] = list()
|
||||||
wire_xy[mode[1]].append((int(line[0]), int(line[1])))
|
wire_xy[mode[1]].append((int(line[0]), int(line[1])))
|
||||||
if mode[1] not in wire_segments:
|
if mode[1] not in wire_segments:
|
||||||
wire_segments[mode[1]] = set()
|
wire_segments[mode[1]] = dict()
|
||||||
if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids:
|
if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids:
|
||||||
wire_segments[mode[1]].add((wname[0], wname[1], gfx_wire_ids["TILE_WIRE_" + wname[2].upper().replace("/", "_")]))
|
wire_segments[mode[1]][(wname[0], wname[1])] = wname[2]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if mode[0] in ("buffer", "routing"):
|
if mode[0] in ("buffer", "routing"):
|
||||||
@ -1077,6 +1077,7 @@ for wire, info in enumerate(wireinfo):
|
|||||||
bba.r("wire_segments_%d" % wire, "segments")
|
bba.r("wire_segments_%d" % wire, "segments")
|
||||||
else:
|
else:
|
||||||
bba.u32(0, "segments")
|
bba.u32(0, "segments")
|
||||||
|
|
||||||
bba.u8(info["x"], "x")
|
bba.u8(info["x"], "x")
|
||||||
bba.u8(info["y"], "y")
|
bba.u8(info["y"], "y")
|
||||||
bba.u8(wiretypes[wire_type(info["name"])], "type")
|
bba.u8(wiretypes[wire_type(info["name"])], "type")
|
||||||
@ -1085,18 +1086,35 @@ for wire, info in enumerate(wireinfo):
|
|||||||
for wire in range(num_wires):
|
for wire in range(num_wires):
|
||||||
if len(wire_segments[wire]):
|
if len(wire_segments[wire]):
|
||||||
bba.l("wire_segments_%d" % wire, "WireSegmentPOD")
|
bba.l("wire_segments_%d" % wire, "WireSegmentPOD")
|
||||||
for seg in sorted(wire_segments[wire]):
|
for xy, seg in sorted(wire_segments[wire].items()):
|
||||||
bba.u8(seg[0], "x")
|
bba.u8(xy[0], "x")
|
||||||
bba.u8(seg[1], "y")
|
bba.u8(xy[1], "y")
|
||||||
bba.u16(seg[2], "index")
|
bba.u16(gfx_wire_ids["TILE_WIRE_" + seg.upper().replace("/", "_")], "index")
|
||||||
|
|
||||||
bba.l("pip_data_%s" % dev_name, "PipInfoPOD")
|
bba.l("pip_data_%s" % dev_name, "PipInfoPOD")
|
||||||
for info in pipinfo:
|
for info in pipinfo:
|
||||||
|
src_seg = -1
|
||||||
|
src_segname = wire_names_r[info["src"]]
|
||||||
|
if (info["x"], info["y"]) in wire_segments[info["src"]]:
|
||||||
|
src_segname = wire_segments[info["src"]][(info["x"], info["y"])]
|
||||||
|
src_seg = gfx_wire_ids["TILE_WIRE_" + src_segname.upper().replace("/", "_")]
|
||||||
|
src_segname = src_segname.replace("/", ".")
|
||||||
|
|
||||||
|
dst_seg = -1
|
||||||
|
dst_segname = wire_names_r[info["dst"]]
|
||||||
|
if (info["x"], info["y"]) in wire_segments[info["dst"]]:
|
||||||
|
dst_segname = wire_segments[info["dst"]][(info["x"], info["y"])]
|
||||||
|
dst_seg = gfx_wire_ids["TILE_WIRE_" + dst_segname.upper().replace("/", "_")]
|
||||||
|
dst_segname = dst_segname.replace("/", ".")
|
||||||
|
|
||||||
|
# bba.s("X%d/Y%d/%s->%s" % (info["x"], info["y"], src_segname, dst_segname), "name")
|
||||||
bba.u32(info["src"], "src")
|
bba.u32(info["src"], "src")
|
||||||
bba.u32(info["dst"], "dst")
|
bba.u32(info["dst"], "dst")
|
||||||
bba.u32(info["delay"], "delay")
|
bba.u32(info["delay"], "delay")
|
||||||
bba.u8(info["x"], "x")
|
bba.u8(info["x"], "x")
|
||||||
bba.u8(info["y"], "y")
|
bba.u8(info["y"], "y")
|
||||||
|
bba.u16(src_seg, "src_seg")
|
||||||
|
bba.u16(dst_seg, "dst_seg")
|
||||||
bba.u16(info["switch_mask"], "switch_mask")
|
bba.u16(info["switch_mask"], "switch_mask")
|
||||||
bba.u32(info["switch_index"], "switch_index")
|
bba.u32(info["switch_index"], "switch_index")
|
||||||
|
|
||||||
|
219
ice40/gfx.cc
219
ice40/gfx.cc
@ -485,4 +485,223 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool getWireXY_main(GfxTileWireId id, float &x, float &y)
|
||||||
|
{
|
||||||
|
// Horizontal Span-4 Wires
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_SP4_H_L_36 && id <= TILE_WIRE_SP4_H_L_47) {
|
||||||
|
int idx = (id - TILE_WIRE_SP4_H_L_36) + 48;
|
||||||
|
x = main_swbox_x1 + 0.0025 * (idx + 35);
|
||||||
|
y = main_swbox_y2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_SP4_H_R_0 && id <= TILE_WIRE_SP4_H_R_47) {
|
||||||
|
int idx = id - TILE_WIRE_SP4_H_R_0;
|
||||||
|
x = main_swbox_x1 + 0.0025 * ((idx ^ 1) + 35);
|
||||||
|
y = main_swbox_y2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertical Span-4 Wires
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_SP4_V_T_36 && id <= TILE_WIRE_SP4_V_T_47) {
|
||||||
|
int idx = (id - TILE_WIRE_SP4_V_T_36) + 48;
|
||||||
|
y = 1.0 - (0.03 + 0.0025 * (270 - idx));
|
||||||
|
x = main_swbox_x1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_SP4_V_B_0 && id <= TILE_WIRE_SP4_V_B_47) {
|
||||||
|
int idx = id - TILE_WIRE_SP4_V_B_0;
|
||||||
|
y = 1.0 - (0.03 + 0.0025 * (270 - (idx ^ 1)));
|
||||||
|
x = main_swbox_x1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Horizontal Span-12 Wires
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_SP12_H_L_22 && id <= TILE_WIRE_SP12_H_L_23) {
|
||||||
|
int idx = (id - TILE_WIRE_SP12_H_L_22) + 24;
|
||||||
|
x = main_swbox_x1 + 0.0025 * (idx + 5);
|
||||||
|
y = main_swbox_y2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_SP12_H_R_0 && id <= TILE_WIRE_SP12_H_R_23) {
|
||||||
|
int idx = id - TILE_WIRE_SP12_H_R_0;
|
||||||
|
x = main_swbox_x1 + 0.0025 * ((idx ^ 1) + 5);
|
||||||
|
y = main_swbox_y2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertical Right Span-4
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_SP4_R_V_B_0 && id <= TILE_WIRE_SP4_R_V_B_47) {
|
||||||
|
int idx = id - TILE_WIRE_SP4_R_V_B_0;
|
||||||
|
y = 1.0 - (0.03 + 0.0025 * (145 - (idx ^ 1)));
|
||||||
|
x = main_swbox_x2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertical Span-12 Wires
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_SP12_V_T_22 && id <= TILE_WIRE_SP12_V_T_23) {
|
||||||
|
int idx = (id - TILE_WIRE_SP12_V_T_22) + 24;
|
||||||
|
y = 1.0 - (0.03 + 0.0025 * (300 - idx));
|
||||||
|
x = main_swbox_x1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_SP12_V_B_0 && id <= TILE_WIRE_SP12_V_B_23) {
|
||||||
|
int idx = id - TILE_WIRE_SP12_V_B_0;
|
||||||
|
y = 1.0 - (0.03 + 0.0025 * (300 - (idx ^ 1)));
|
||||||
|
x = main_swbox_x1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global2Local
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_GLB2LOCAL_0 && id <= TILE_WIRE_GLB2LOCAL_3) {
|
||||||
|
int idx = id - TILE_WIRE_GLB2LOCAL_0;
|
||||||
|
x = main_swbox_x1 + 0.005 * (idx + 5);
|
||||||
|
y = main_swbox_y1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalNets
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_GLB_NETWK_0 && id <= TILE_WIRE_GLB_NETWK_7) {
|
||||||
|
int idx = id - TILE_WIRE_GLB_NETWK_0;
|
||||||
|
x = main_swbox_x1;
|
||||||
|
y = main_swbox_y1 + 0.005 * (13 - idx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neighbours
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_NEIGH_OP_BNL_0 && id <= TILE_WIRE_NEIGH_OP_TOP_7) {
|
||||||
|
int idx = id - TILE_WIRE_NEIGH_OP_BNL_0;
|
||||||
|
y = main_swbox_y2 - (0.0025 * (idx + 10) + 0.01 * (idx / 8));
|
||||||
|
x = main_swbox_x1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local Tracks
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_LOCAL_G0_0 && id <= TILE_WIRE_LOCAL_G3_7) {
|
||||||
|
int idx = id - TILE_WIRE_LOCAL_G0_0;
|
||||||
|
float yoff = (local_swbox_y1 + local_swbox_y2) / 2 - 0.005 * 16 - 0.075;
|
||||||
|
x = main_swbox_x2;
|
||||||
|
y = yoff + 0.005 * idx + 0.05 * (idx / 8);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LC Outputs
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_LUTFF_0_OUT && id <= TILE_WIRE_LUTFF_7_OUT) {
|
||||||
|
int idx = id - TILE_WIRE_LUTFF_0_OUT;
|
||||||
|
y = 1.0 - (0.03 + 0.0025 * (152 + idx));
|
||||||
|
x = main_swbox_x2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LC Control
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_LUTFF_GLOBAL_CEN && id <= TILE_WIRE_LUTFF_GLOBAL_S_R) {
|
||||||
|
int idx = id - TILE_WIRE_LUTFF_GLOBAL_CEN;
|
||||||
|
x = main_swbox_x2 - 0.005 * (idx + 5);
|
||||||
|
y = main_swbox_y1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool getWireXY_local(GfxTileWireId id, float &x, float &y)
|
||||||
|
{
|
||||||
|
if (id >= TILE_WIRE_LOCAL_G0_0 && id <= TILE_WIRE_LOCAL_G3_7) {
|
||||||
|
int idx = id - TILE_WIRE_LOCAL_G0_0;
|
||||||
|
float yoff = (local_swbox_y1 + local_swbox_y2) / 2 - 0.005 * 16 - 0.075;
|
||||||
|
x = local_swbox_x1;
|
||||||
|
y = yoff + 0.005 * idx + 0.05 * (idx / 8);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id >= TILE_WIRE_LUTFF_0_IN_0 && id <= TILE_WIRE_LUTFF_7_IN_3) {
|
||||||
|
int idx = id - TILE_WIRE_LUTFF_0_IN_0;
|
||||||
|
int z = idx / 4;
|
||||||
|
int input = idx % 4;
|
||||||
|
x = local_swbox_x2;
|
||||||
|
y = (logic_cell_y1 + logic_cell_y2) / 2 - 0.0075 + (0.005 * input) + z * logic_cell_pitch;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipGfx(std::vector<GraphicElement> &g, int x, int y,
|
||||||
|
float x1, float y1, float x2, float y2,
|
||||||
|
float swx1, float swy1, float swx2, float swy2,
|
||||||
|
GraphicElement::style_t style)
|
||||||
|
{
|
||||||
|
float tx = 0.5 * (x1 + x2);
|
||||||
|
float ty = 0.5 * (y1 + y2);
|
||||||
|
|
||||||
|
GraphicElement el;
|
||||||
|
el.type = GraphicElement::G_LINE;
|
||||||
|
el.style = style;
|
||||||
|
|
||||||
|
if (fabsf(x1 - swx1) < 0.001 && fabsf(x2 - swx1) < 0.001) {
|
||||||
|
tx = x1 + 0.25 * fabsf(y1 - y2);
|
||||||
|
goto edge_pip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fabsf(x1 - swx2) < 0.001 && fabsf(x2 - swx2) < 0.001) {
|
||||||
|
tx = x1 - 0.25 * fabsf(y1 - y2);
|
||||||
|
goto edge_pip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fabsf(y1 - swy1) < 0.001 && fabsf(y2 - swy1) < 0.001) {
|
||||||
|
ty = y1 + 0.25 * fabsf(x1 - x2);
|
||||||
|
goto edge_pip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fabsf(y1 - swy1) < 0.001 && fabsf(y2 - swy1) < 0.001) {
|
||||||
|
ty = y1 + 0.25 * fabsf(x1 - x2);
|
||||||
|
goto edge_pip;
|
||||||
|
}
|
||||||
|
|
||||||
|
el.x1 = x + x1;
|
||||||
|
el.y1 = y + y1;
|
||||||
|
el.x2 = x + x2;
|
||||||
|
el.y2 = y + y2;
|
||||||
|
g.push_back(el);
|
||||||
|
return;
|
||||||
|
|
||||||
|
edge_pip:
|
||||||
|
el.x1 = x + x1;
|
||||||
|
el.y1 = y + y1;
|
||||||
|
el.x2 = x + tx;
|
||||||
|
el.y2 = y + ty;
|
||||||
|
g.push_back(el);
|
||||||
|
|
||||||
|
el.x1 = x + tx;
|
||||||
|
el.y1 = y + ty;
|
||||||
|
el.x2 = x + x2;
|
||||||
|
el.y2 = y + y2;
|
||||||
|
g.push_back(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfxTilePip(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId src, GfxTileWireId dst, GraphicElement::style_t style)
|
||||||
|
{
|
||||||
|
float x1, y1, x2, y2;
|
||||||
|
|
||||||
|
if (getWireXY_main(src, x1, y1) && getWireXY_main(dst, x2, y2))
|
||||||
|
pipGfx(g, x, y, x1, y1, x2, y2, main_swbox_x1, main_swbox_y1, main_swbox_x2, main_swbox_y2, style);
|
||||||
|
|
||||||
|
if (getWireXY_local(src, x1, y1) && getWireXY_local(dst, x2, y2))
|
||||||
|
pipGfx(g, x, y, x1, y1, x2, y2, local_swbox_x1, local_swbox_y1, local_swbox_x2, local_swbox_y2, style);
|
||||||
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -468,6 +468,7 @@ enum GfxTileWireId
|
|||||||
};
|
};
|
||||||
|
|
||||||
void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, GraphicElement::style_t style);
|
void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, GraphicElement::style_t style);
|
||||||
|
void gfxTilePip(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId src, GfxTileWireId dst, GraphicElement::style_t style);
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user