Merge branch 'master' of gitlab.com:SymbioticEDA/nextpnr into q3k/lock-the-things

This commit is contained in:
Sergiusz Bazanski 2018-07-13 19:10:20 +01:00
commit b8ca1a5582
27 changed files with 411 additions and 527 deletions

View File

@ -1,322 +0,0 @@
#include "pyconsole.h"
#include "pyinterpreter.h"
#include "ColumnFormatter.h"
#include <iostream>
#include <QKeyEvent>
#include <QFont>
#include "Utils.h"
const QString PythonConsole::PROMPT = ">>> ";
const QString PythonConsole::MULTILINE_PROMPT = "... ";
const QColor PythonConsole::NORMAL_COLOR = QColor::fromRgbF( 0, 0, 0 );
const QColor PythonConsole::ERROR_COLOR = QColor::fromRgbF( 1.0, 0, 0 );
const QColor PythonConsole::OUTPUT_COLOR = QColor::fromRgbF( 0, 0, 1.0 );
PythonConsole::PythonConsole( QWidget* parent ):
QTextEdit( parent )
{
QFont font("unexistent");
font.setStyleHint(QFont::Monospace);
setFont(font);
m_parseHelper.subscribe( this );
}
void PythonConsole::keyPressEvent( QKeyEvent* e )
{
switch ( e->key() )
{
case Qt::Key_Return:
handleReturnKeyPress( );
return;
case Qt::Key_Tab:
autocomplete( );
return;
case Qt::Key_Backspace:
if ( ! canBackspace( ) )
return;
break;
case Qt::Key_Up:
previousHistory( );
return;
case Qt::Key_Down:
nextHistory( );
return;
case Qt::Key_Left:
if ( ! canGoLeft( ) )
return;
}
if (!cursorIsOnInputLine()) return;
if (textCursor().columnNumber() < PythonConsole::PROMPT.size()) return;
QTextEdit::keyPressEvent( e );
}
void PythonConsole::handleReturnKeyPress( )
{
if ( ! cursorIsOnInputLine( ) )
{
return;
}
QString line = getLine( );
m_parseHelper.process( line.toStdString( ) );
if ( m_parseHelper.buffered( ) )
{
append("");
displayPrompt( );
}
if ( line.size( ) )
{
m_historyBuffer.push_back( line.toStdString( ) );
m_historyIt = m_historyBuffer.end();
}
moveCursorToEnd( );
}
void PythonConsole::parseEvent( const ParseMessage& message )
{
// handle invalid user input
if ( message.errorCode )
{
setTextColor( ERROR_COLOR );
append(message.message.c_str());
setTextColor( NORMAL_COLOR );
append("");
displayPrompt( );
return;
}
// interpret valid user input
int errorCode = 0;
std::string res;
if ( message.message.size() )
res = pyinterpreter_execute( message.message, &errorCode );
if ( errorCode )
{
setTextColor( ERROR_COLOR );
}
else
{
setTextColor( OUTPUT_COLOR );
}
if ( res.size( ) )
{
append(res.c_str());
}
setTextColor( NORMAL_COLOR );
// set up the next line on the console
append("");
displayPrompt( );
}
QString PythonConsole::getLine( )
{
QTextCursor cursor = textCursor();
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, PythonConsole::PROMPT.size( ) );
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
QString line = cursor.selectedText( );
cursor.clearSelection( );
return line;
}
bool PythonConsole::cursorIsOnInputLine( )
{
int cursorBlock = textCursor( ).blockNumber( );
QTextCursor bottomCursor = textCursor( );
bottomCursor.movePosition( QTextCursor::End );
int bottomBlock = bottomCursor.blockNumber( );
return ( cursorBlock == bottomBlock );
}
bool PythonConsole::inputLineIsEmpty( )
{
QTextCursor bottomCursor = textCursor( );
bottomCursor.movePosition( QTextCursor::End );
int col = bottomCursor.columnNumber( );
return ( col == PythonConsole::PROMPT.size( ) );
}
bool PythonConsole::canBackspace( )
{
if ( ! cursorIsOnInputLine( ) )
{
return false;
}
if ( inputLineIsEmpty( ) )
{
return false;
}
return true;
}
bool PythonConsole::canGoLeft( )
{
if ( cursorIsOnInputLine( ) )
{
QTextCursor bottomCursor = textCursor( );
int col = bottomCursor.columnNumber( );
return (col > PythonConsole::PROMPT.size( ));
}
return true;
}
void PythonConsole::displayPrompt( )
{
QTextCursor cursor = textCursor();
cursor.movePosition( QTextCursor::End );
if ( m_parseHelper.buffered( ) )
{
cursor.insertText( PythonConsole::MULTILINE_PROMPT );
}
else
{
cursor.insertText( PythonConsole::PROMPT );
}
cursor.movePosition( QTextCursor::EndOfLine );
}
void PythonConsole::displayString(QString text)
{
QTextCursor cursor = textCursor();
cursor.movePosition( QTextCursor::End );
cursor.insertText( text );
cursor.movePosition( QTextCursor::EndOfLine );
}
void PythonConsole::autocomplete( )
{
if ( ! cursorIsOnInputLine( ) )
return;
QString line = getLine( );
const std::list<std::string>& suggestions =
pyinterpreter_suggest( line.toStdString( ) );
if (suggestions.size() == 1)
{
line = suggestions.back().c_str();
}
else
{
// try to complete to longest common prefix
std::string prefix =
LongestCommonPrefix(suggestions.begin(), suggestions.end());
if (prefix.size() > (size_t)line.size())
{
line = prefix.c_str();
}
else
{
ColumnFormatter fmt;
fmt.setItems(suggestions.begin(), suggestions.end());
fmt.format(width() / 10);
setTextColor( OUTPUT_COLOR );
const std::list<std::string>& formatted = fmt.formattedOutput();
for (std::list<std::string>::const_iterator it = formatted.begin();
it != formatted.end(); ++it)
{
append(it->c_str());
}
setTextColor( NORMAL_COLOR );
}
}
// set up the next line on the console
append("");
displayPrompt( );
moveCursorToEnd( );
QTextCursor cursor = textCursor();
cursor.insertText( line );
moveCursorToEnd( );
}
void PythonConsole::previousHistory( )
{
if ( ! cursorIsOnInputLine( ) )
return;
if ( ! m_historyBuffer.size( ) )
return;
QTextCursor cursor = textCursor();
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, PythonConsole::PROMPT.size( ) );
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
cursor.removeSelectedText( );
if ( m_historyIt != m_historyBuffer.begin( ) )
{
--m_historyIt;
}
cursor.insertText( m_historyIt->c_str() );
}
void PythonConsole::nextHistory( )
{
if ( ! cursorIsOnInputLine( ) )
return;
if ( ! m_historyBuffer.size( ) )
return;
if ( m_historyIt == m_historyBuffer.end( ) )
{
return;
}
QTextCursor cursor = textCursor();
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, PythonConsole::PROMPT.size( ) );
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
cursor.removeSelectedText( );
++m_historyIt;
if ( m_historyIt == m_historyBuffer.end( ) )
{
return;
}
cursor.insertText( m_historyIt->c_str() );
}
void PythonConsole::moveCursorToEnd( )
{
QTextCursor cursor = textCursor();
cursor.movePosition( QTextCursor::End );
setTextCursor( cursor );
}
void PythonConsole::insertFromMimeData(const QMimeData *src)
{
if (src->hasText()) {
QStringList list = src->text().split("\n",QString::KeepEmptyParts);
bool lastends = src->text().endsWith("\n");
for (int i=0;i<list.size();i++)
{
QString line = list.at(i);
displayString(line);
if (!lastends && (i==list.size()-1)) break;
m_parseHelper.process( line.toStdString( ) );
if ( m_parseHelper.buffered( ) )
{
append("");
displayPrompt( );
}
if ( line.size( ) )
{
m_historyBuffer.push_back( line.toStdString( ) );
m_historyIt = m_historyBuffer.end();
}
moveCursorToEnd( );
}
}
}

View File

@ -1,80 +0,0 @@
/**
python-console
Copyright (C) 2018 Alex Tsui
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef PYCONSOLE_H
#define PYCONSOLE_H
#include <QColor>
#include <QTextEdit>
#include <QMimeData>
#include "ParseHelper.h"
#include "ParseListener.h"
class QWidget;
class QKeyEvent;
class PythonConsole : public QTextEdit, ParseListener
{
Q_OBJECT
public:
PythonConsole(QWidget *parent = 0);
void displayPrompt();
void displayString(QString text);
protected:
// override QTextEdit
virtual void keyPressEvent(QKeyEvent *e);
virtual void handleReturnKeyPress();
virtual void insertFromMimeData(const QMimeData *src);
/**
Handle a compilable chunk of Python user input.
*/
virtual void parseEvent(const ParseMessage &message);
QString getLine();
bool cursorIsOnInputLine();
bool inputLineIsEmpty();
bool canBackspace();
bool canGoLeft();
void autocomplete();
void previousHistory();
void nextHistory();
void moveCursorToEnd();
static const QString PROMPT;
static const QString MULTILINE_PROMPT;
static const QColor NORMAL_COLOR;
static const QColor ERROR_COLOR;
static const QColor OUTPUT_COLOR;
ParseHelper m_parseHelper;
std::list<std::string> m_historyBuffer;
std::list<std::string>::const_iterator m_historyIt;
};
#endif // PYCONSOLE_H

View File

@ -730,6 +730,7 @@ struct Arch : BaseCtx
// -------------------------------------------------
bool pack();
bool place();
bool route();

View File

@ -22,7 +22,7 @@
#error Include "archdefs.h" via "nextpnr.h" only.
#endif
#include <boost/functional/hash_fwd.hpp>
#include <boost/functional/hash.hpp>
NEXTPNR_NAMESPACE_BEGIN

View File

@ -43,7 +43,6 @@
#include "bitstream.h"
#include "design_utils.h"
#include "jsonparse.h"
#include "pack.h"
#include "timing.h"
USING_NEXTPNR_NAMESPACE
@ -147,7 +146,7 @@ int main(int argc, char *argv[])
if (!parse_json_file(f, filename, ctx.get()))
log_error("Loading design failed.\n");
if (!pack_design(ctx.get()) && !ctx->force)
if (!ctx->pack() && !ctx->force)
log_error("Packing design failed.\n");
if (vm.count("freq"))
ctx->target_freq = vm["freq"].as<double>() * 1e6;

View File

@ -17,7 +17,6 @@
*
*/
#include "pack.h"
#include <algorithm>
#include <iterator>
#include <unordered_set>
@ -84,8 +83,9 @@ void pack_io(Context *ctx)
}
// Main pack function
bool pack_design(Context *ctx)
bool Arch::pack()
{
Context *ctx = getCtx();
try {
log_break();
pack_io(ctx);

View File

@ -181,6 +181,7 @@ void Arch::bindBel(BelId bel, IdString cell, PlaceStrength strength)
bels.at(bel).bound_cell = cell;
cells.at(cell)->bel = bel;
cells.at(cell)->belStrength = strength;
refreshUiBel(bel);
}
void Arch::unbindBel(BelId bel)
@ -188,6 +189,7 @@ void Arch::unbindBel(BelId bel)
cells.at(bels.at(bel).bound_cell)->bel = BelId();
cells.at(bels.at(bel).bound_cell)->belStrength = STRENGTH_NONE;
bels.at(bel).bound_cell = IdString();
refreshUiBel(bel);
}
bool Arch::checkBelAvail(BelId bel) const { return bels.at(bel).bound_cell == IdString(); }
@ -236,6 +238,7 @@ void Arch::bindWire(WireId wire, IdString net, PlaceStrength strength)
wires.at(wire).bound_net = net;
nets.at(net)->wires[wire].pip = PipId();
nets.at(net)->wires[wire].strength = strength;
refreshUiWire(wire);
}
void Arch::unbindWire(WireId wire)
@ -243,11 +246,14 @@ void Arch::unbindWire(WireId wire)
auto &net_wires = nets[wires.at(wire).bound_net]->wires;
auto pip = net_wires.at(wire).pip;
if (pip != PipId())
if (pip != PipId()) {
pips.at(pip).bound_net = IdString();
refreshUiPip(pip);
}
net_wires.erase(wire);
wires.at(wire).bound_net = IdString();
refreshUiWire(wire);
}
bool Arch::checkWireAvail(WireId wire) const { return wires.at(wire).bound_net == IdString(); }
@ -282,6 +288,8 @@ void Arch::bindPip(PipId pip, IdString net, PlaceStrength strength)
wires.at(wire).bound_net = net;
nets.at(net)->wires[wire].pip = pip;
nets.at(net)->wires[wire].strength = strength;
refreshUiPip(pip);
refreshUiWire(wire);
}
void Arch::unbindPip(PipId pip)
@ -290,6 +298,8 @@ void Arch::unbindPip(PipId pip)
nets.at(wires.at(wire).bound_net)->wires.erase(wire);
pips.at(pip).bound_net = IdString();
wires.at(wire).bound_net = IdString();
refreshUiPip(pip);
refreshUiWire(wire);
}
bool Arch::checkPipAvail(PipId pip) const { return pips.at(pip).bound_net == IdString(); }

View File

@ -183,6 +183,7 @@ struct Arch : BaseCtx
float getDelayNS(delay_t v) const { return v; }
uint32_t getDelayChecksum(delay_t v) const { return 0; }
bool pack() { return true; }
bool place();
bool route();

View File

@ -12,7 +12,6 @@ if (BUILD_PYTHON)
../3rdparty/python-console/modified/pyredirector.cc
../3rdparty/python-console/modified/pyinterpreter.cc
../3rdparty/python-console/modified/pyconsole.cc
)
endif()

View File

@ -66,7 +66,6 @@ BaseMainWindow::BaseMainWindow(std::unique_ptr<Context> context, QWidget *parent
DesignWidget *designview = new DesignWidget();
designview->setMinimumWidth(300);
designview->setMaximumWidth(300);
splitter_h->addWidget(designview);
connect(this, SIGNAL(contextChanged(Context *)), designview, SLOT(newContext(Context *)));
@ -77,7 +76,7 @@ BaseMainWindow::BaseMainWindow(std::unique_ptr<Context> context, QWidget *parent
tabWidget = new QTabWidget();
#ifndef NO_PYTHON
PythonTab *pythontab = new PythonTab();
tabWidget->addTab(pythontab, "Python");
tabWidget->addTab(pythontab, "Console");
connect(this, SIGNAL(contextChanged(Context *)), pythontab, SLOT(newContext(Context *)));
#endif
info = new InfoTab();

View File

@ -27,7 +27,6 @@
#include "design_utils.h"
#include "jsonparse.h"
#include "log.h"
#include "pack.h"
#include "pcf.h"
static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }

View File

@ -23,7 +23,6 @@
#include "design_utils.h"
#include "jsonparse.h"
#include "log.h"
#include "pack.h"
#include "pcf.h"
#include "timing.h"
@ -97,7 +96,7 @@ void Worker::pack()
{
Q_EMIT taskStarted();
try {
bool res = pack_design(ctx);
bool res = ctx->pack();
print_utilisation(ctx);
Q_EMIT pack_finished(res);
} catch (WorkerInterruptionRequested) {

View File

@ -2,6 +2,7 @@
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
* Copyright (C) 2018 Alex Tsui
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -17,12 +18,18 @@
*
*/
#ifndef NO_PYTHON
#include "line_editor.h"
#include <QKeyEvent>
#include <QToolTip>
#include "ColumnFormatter.h"
#include "Utils.h"
#include "pyinterpreter.h"
NEXTPNR_NAMESPACE_BEGIN
LineEditor::LineEditor(QWidget *parent) : QLineEdit(parent), index(0)
LineEditor::LineEditor(ParseHelper *helper, QWidget *parent) : QLineEdit(parent), index(0), parseHelper(helper)
{
setContextMenuPolicy(Qt::CustomContextMenu);
QAction *clearAction = new QAction("Clear &history", this);
@ -38,10 +45,12 @@ LineEditor::LineEditor(QWidget *parent) : QLineEdit(parent), index(0)
void LineEditor::keyPressEvent(QKeyEvent *ev)
{
if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) {
QToolTip::hideText();
if (lines.empty())
return;
printf("Key_Up\n");
if (ev->key() == Qt::Key_Up)
index--;
if (ev->key() == Qt::Key_Down)
@ -56,12 +65,21 @@ void LineEditor::keyPressEvent(QKeyEvent *ev)
}
setText(lines[index]);
} else if (ev->key() == Qt::Key_Escape) {
QToolTip::hideText();
clear();
return;
} else if (ev->key() == Qt::Key_Tab) {
autocomplete();
return;
}
QToolTip::hideText();
QLineEdit::keyPressEvent(ev);
}
// This makes TAB work
bool LineEditor::focusNextPrevChild(bool next) { return false; }
void LineEditor::textInserted()
{
if (lines.empty() || lines.back() != text())
@ -82,4 +100,36 @@ void LineEditor::clearHistory()
clear();
}
void LineEditor::autocomplete()
{
QString line = text();
const std::list<std::string> &suggestions = pyinterpreter_suggest(line.toStdString());
if (suggestions.size() == 1) {
line = suggestions.back().c_str();
} else {
// try to complete to longest common prefix
std::string prefix = LongestCommonPrefix(suggestions.begin(), suggestions.end());
if (prefix.size() > (size_t)line.size()) {
line = prefix.c_str();
} else {
ColumnFormatter fmt;
fmt.setItems(suggestions.begin(), suggestions.end());
fmt.format(width() / 5);
QString out = "";
for (auto &it : fmt.formattedOutput()) {
if (!out.isEmpty())
out += "\n";
out += it.c_str();
}
QToolTip::setFont(font());
if (!out.trimmed().isEmpty())
QToolTip::showText(mapToGlobal(QPoint(0, 0)), out);
}
}
// set up the next line on the console
setText(line);
}
NEXTPNR_NAMESPACE_END
#endif // NO_PYTHON

View File

@ -2,6 +2,7 @@
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
* Copyright (C) 2018 Alex Tsui
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -20,8 +21,11 @@
#ifndef LINE_EDITOR_H
#define LINE_EDITOR_H
#ifndef NO_PYTHON
#include <QLineEdit>
#include <QMenu>
#include "ParseHelper.h"
#include "nextpnr.h"
NEXTPNR_NAMESPACE_BEGIN
@ -31,7 +35,7 @@ class LineEditor : public QLineEdit
Q_OBJECT
public:
explicit LineEditor(QWidget *parent = 0);
explicit LineEditor(ParseHelper *helper, QWidget *parent = 0);
private Q_SLOTS:
void textInserted();
@ -43,13 +47,18 @@ class LineEditor : public QLineEdit
protected:
void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
bool focusNextPrevChild(bool next) Q_DECL_OVERRIDE;
void autocomplete();
private:
int index;
QStringList lines;
QMenu *contextMenu;
ParseHelper *parseHelper;
};
NEXTPNR_NAMESPACE_END
#endif // NO_PYTHON
#endif // LINE_EDITOR_H

82
gui/pyconsole.cc Normal file
View File

@ -0,0 +1,82 @@
/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
* Copyright (C) 2018 Alex Tsui
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef NO_PYTHON
#include "pyconsole.h"
#include "pyinterpreter.h"
NEXTPNR_NAMESPACE_BEGIN
const QColor PythonConsole::NORMAL_COLOR = QColor::fromRgbF(0, 0, 0);
const QColor PythonConsole::ERROR_COLOR = QColor::fromRgbF(1.0, 0, 0);
const QColor PythonConsole::OUTPUT_COLOR = QColor::fromRgbF(0, 0, 1.0);
PythonConsole::PythonConsole(QWidget *parent) : QTextEdit(parent) {}
void PythonConsole::parseEvent(const ParseMessage &message)
{
// handle invalid user input
if (message.errorCode) {
setTextColor(ERROR_COLOR);
append(message.message.c_str());
setTextColor(NORMAL_COLOR);
append("");
return;
}
// interpret valid user input
int errorCode = 0;
std::string res;
if (message.message.size())
res = pyinterpreter_execute(message.message, &errorCode);
if (errorCode) {
setTextColor(ERROR_COLOR);
} else {
setTextColor(OUTPUT_COLOR);
}
if (res.size()) {
append(res.c_str());
}
setTextColor(NORMAL_COLOR);
append("");
moveCursorToEnd();
}
void PythonConsole::displayString(QString text)
{
QTextCursor cursor = textCursor();
cursor.movePosition(QTextCursor::End);
setTextColor(NORMAL_COLOR);
cursor.insertText(text);
cursor.movePosition(QTextCursor::EndOfLine);
}
void PythonConsole::moveCursorToEnd()
{
QTextCursor cursor = textCursor();
cursor.movePosition(QTextCursor::End);
setTextCursor(cursor);
}
NEXTPNR_NAMESPACE_END
#endif // NO_PYTHON

View File

@ -1,7 +1,8 @@
/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 David Shah <david@symbioticeda.com>
* Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
* Copyright (C) 2018 Alex Tsui
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -17,15 +18,41 @@
*
*/
#ifndef PACK_H
#define PACK_H
#ifndef PYCONSOLE_H
#define PYCONSOLE_H
#ifndef NO_PYTHON
#include <QColor>
#include <QMimeData>
#include <QTextEdit>
#include "ParseHelper.h"
#include "ParseListener.h"
#include "nextpnr.h"
class QWidget;
class QKeyEvent;
NEXTPNR_NAMESPACE_BEGIN
bool pack_design(Context *ctx);
class PythonConsole : public QTextEdit, public ParseListener
{
Q_OBJECT
public:
PythonConsole(QWidget *parent = 0);
void displayString(QString text);
void moveCursorToEnd();
virtual void parseEvent(const ParseMessage &message);
protected:
static const QColor NORMAL_COLOR;
static const QColor ERROR_COLOR;
static const QColor OUTPUT_COLOR;
};
NEXTPNR_NAMESPACE_END
#endif // NO_PYTHON
#endif // ROUTE_H
#endif // PYCONSOLE_H

View File

@ -25,12 +25,20 @@
NEXTPNR_NAMESPACE_BEGIN
const QString PythonTab::PROMPT = ">>> ";
const QString PythonTab::MULTILINE_PROMPT = "... ";
PythonTab::PythonTab(QWidget *parent) : QWidget(parent), initialized(false)
{
QFont f("unexistent");
f.setStyleHint(QFont::Monospace);
// Add text area for Python output and input line
console = new PythonConsole();
console->setMinimumHeight(100);
console->setEnabled(false);
console->setReadOnly(true);
console->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
console->setFont(f);
console->setContextMenuPolicy(Qt::CustomContextMenu);
QAction *clearAction = new QAction("Clear &buffer", this);
@ -41,9 +49,21 @@ PythonTab::PythonTab(QWidget *parent) : QWidget(parent), initialized(false)
contextMenu->addAction(clearAction);
connect(console, SIGNAL(customContextMenuRequested(const QPoint)), this, SLOT(showContextMenu(const QPoint)));
lineEdit = new LineEditor(&parseHelper);
lineEdit->setMinimumHeight(30);
lineEdit->setMaximumHeight(30);
lineEdit->setFont(f);
lineEdit->setPlaceholderText(PythonTab::PROMPT);
connect(lineEdit, SIGNAL(textLineInserted(QString)), this, SLOT(editLineReturnPressed(QString)));
QGridLayout *mainLayout = new QGridLayout();
mainLayout->addWidget(console, 0, 0);
mainLayout->addWidget(lineEdit, 1, 0);
setLayout(mainLayout);
parseHelper.subscribe(console);
prompt = PythonTab::PROMPT;
}
PythonTab::~PythonTab()
@ -54,13 +74,27 @@ PythonTab::~PythonTab()
}
}
void PythonTab::editLineReturnPressed(QString text)
{
console->displayString(prompt + text + "\n");
console->moveCursorToEnd();
parseHelper.process(text.toStdString());
if (parseHelper.buffered())
prompt = PythonTab::MULTILINE_PROMPT;
else
prompt = PythonTab::PROMPT;
lineEdit->setPlaceholderText(prompt);
}
void PythonTab::newContext(Context *ctx)
{
if (initialized) {
pyinterpreter_finalize();
deinit_python();
}
console->setEnabled(true);
console->clear();
pyinterpreter_preinit();
@ -74,7 +108,6 @@ void PythonTab::newContext(Context *ctx)
QString version = QString("Python %1 on %2\n").arg(Py_GetVersion(), Py_GetPlatform());
console->displayString(version);
console->displayPrompt();
}
void PythonTab::showContextMenu(const QPoint &pt) { contextMenu->exec(mapToGlobal(pt)); }
@ -83,4 +116,4 @@ void PythonTab::clearBuffer() { console->clear(); }
NEXTPNR_NAMESPACE_END
#endif
#endif // NO_PYTHON

View File

@ -25,6 +25,7 @@
#include <QLineEdit>
#include <QMenu>
#include <QPlainTextEdit>
#include "ParseHelper.h"
#include "line_editor.h"
#include "nextpnr.h"
#include "pyconsole.h"
@ -42,13 +43,20 @@ class PythonTab : public QWidget
private Q_SLOTS:
void showContextMenu(const QPoint &pt);
void clearBuffer();
void editLineReturnPressed(QString text);
public Q_SLOTS:
void newContext(Context *ctx);
private:
PythonConsole *console;
LineEditor *lineEdit;
QMenu *contextMenu;
bool initialized;
ParseHelper parseHelper;
QString prompt;
static const QString PROMPT;
static const QString MULTILINE_PROMPT;
};
NEXTPNR_NAMESPACE_END

View File

@ -494,6 +494,7 @@ DecalXY Arch::getFrameDecal() const
{
DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_FRAME;
decalxy.decal.active = true;
return decalxy;
}
@ -502,6 +503,7 @@ DecalXY Arch::getBelDecal(BelId bel) const
DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_BEL;
decalxy.decal.index = bel.index;
decalxy.decal.active = bel_to_cell.at(bel.index) != IdString();
return decalxy;
}
@ -510,18 +512,25 @@ DecalXY Arch::getWireDecal(WireId wire) const
DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_WIRE;
decalxy.decal.index = wire.index;
decalxy.decal.active = wire_to_net.at(wire.index) != IdString();
return decalxy;
}
DecalXY Arch::getPipDecal(PipId pip) const
{
DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_PIP;
decalxy.decal.index = pip.index;
decalxy.decal.active = pip_to_net.at(pip.index) != IdString();
return decalxy;
};
DecalXY Arch::getGroupDecal(GroupId group) const
{
DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_GROUP;
decalxy.decal.index = (group.type << 16) | (group.x << 8) | (group.y);
decalxy.decal.active = true;
return decalxy;
};
@ -549,8 +558,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
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 =
wire_to_net.at(wire.index) != IdString() ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
GraphicElement::style_t style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
for (int i = 0; i < n; i++)
gfxTileWire(ret, p[i].x, p[i].y, GfxTileWireId(p[i].index), style);
@ -565,7 +573,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
if (bel_type == TYPE_ICESTORM_LC) {
GraphicElement el;
el.type = GraphicElement::G_BOX;
el.style = bel_to_cell.at(bel.index) != IdString() ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
el.style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1;
el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2;
el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1 +
@ -635,14 +643,42 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
}
if (bel_type == TYPE_ICESTORM_RAM) {
for (int i = 0; i < 2; i++)
{
int tx = chip_info->bel_data[bel.index].x;
int ty = chip_info->bel_data[bel.index].y + i;
GraphicElement el;
el.type = GraphicElement::G_BOX;
el.x1 = chip_info->bel_data[bel.index].x + 0.1;
el.x2 = chip_info->bel_data[bel.index].x + 0.9;
el.y1 = chip_info->bel_data[bel.index].y + 0.1;
el.y2 = chip_info->bel_data[bel.index].y + 1.9;
el.style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1;
el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2;
el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1;
el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + 7*logic_cell_pitch;
el.z = 0;
ret.push_back(el);
// Main switchbox
GraphicElement main_sw;
main_sw.type = GraphicElement::G_BOX;
main_sw.style = GraphicElement::G_FRAME;
main_sw.x1 = tx + main_swbox_x1;
main_sw.x2 = tx + main_swbox_x2;
main_sw.y1 = ty + main_swbox_y1;
main_sw.y2 = ty + main_swbox_y2;
ret.push_back(main_sw);
// Local tracks to LUT input switchbox
GraphicElement local_sw;
local_sw.type = GraphicElement::G_BOX;
local_sw.style = GraphicElement::G_FRAME;
local_sw.x1 = tx + local_swbox_x1;
local_sw.x2 = tx + local_swbox_x2;
local_sw.y1 = ty + local_swbox_y1;
local_sw.y2 = ty + local_swbox_y2;
local_sw.z = 0;
ret.push_back(local_sw);
}
}
}
@ -822,16 +858,6 @@ BelId ArchRProxyMethods::getBelByName(IdString name) const
// -----------------------------------------------------------------------
void ArchRWProxyMethods::bindWire(WireId wire, IdString net, PlaceStrength strength)
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(parent_->wire_to_net[wire.index] == IdString());
parent_->wire_to_net[wire.index] = net;
parent_->nets[net]->wires[wire].pip = PipId();
parent_->nets[net]->wires[wire].strength = strength;
}
void ArchRWProxyMethods::bindBel(BelId bel, IdString cell, PlaceStrength strength)
{
NPNR_ASSERT(bel != BelId());
@ -839,6 +865,7 @@ void ArchRWProxyMethods::bindBel(BelId bel, IdString cell, PlaceStrength strengt
parent_->bel_to_cell[bel.index] = cell;
parent_->cells[cell]->bel = bel;
parent_->cells[cell]->belStrength = strength;
parent_->refreshUiBel(bel);
}
void ArchRWProxyMethods::unbindBel(BelId bel)
@ -848,6 +875,18 @@ void ArchRWProxyMethods::unbindBel(BelId bel)
parent_->cells[parent_->bel_to_cell[bel.index]]->bel = BelId();
parent_->cells[parent_->bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE;
parent_->bel_to_cell[bel.index] = IdString();
parent_->refreshUiBel(bel);
}
void ArchRWProxyMethods::bindWire(WireId wire, IdString net, PlaceStrength strength)
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(parent_->wire_to_net[wire.index] == IdString());
parent_->wire_to_net[wire.index] = net;
parent_->nets[net]->wires[wire].pip = PipId();
parent_->nets[net]->wires[wire].strength = strength;
parent_->refreshUiWire(wire);
}
void ArchRWProxyMethods::unbindWire(WireId wire)
@ -863,10 +902,12 @@ void ArchRWProxyMethods::unbindWire(WireId wire)
if (pip != PipId()) {
parent_->pip_to_net[pip.index] = IdString();
parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index] = IdString();
parent_->refreshUiPip(pip);
}
net_wires.erase(it);
parent_->wire_to_net[wire.index] = IdString();
parent_->refreshUiWire(wire);
}
void ArchRWProxyMethods::bindPip(PipId pip, IdString net, PlaceStrength strength)
@ -884,6 +925,9 @@ void ArchRWProxyMethods::bindPip(PipId pip, IdString net, PlaceStrength strength
parent_->wire_to_net[dst.index] = net;
parent_->nets[net]->wires[dst].pip = pip;
parent_->nets[net]->wires[dst].strength = strength;
parent_->refreshUiPip(pip);
parent_->refreshUiWire(dst);
}
void ArchRWProxyMethods::unbindPip(PipId pip)
@ -900,6 +944,9 @@ void ArchRWProxyMethods::unbindPip(PipId pip)
parent_->pip_to_net[pip.index] = IdString();
parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index] = IdString();
parent_->refreshUiPip(pip);
parent_->refreshUiWire(dst);
}
CellInfo *ArchRWProxyMethods::getCell(IdString cell)

View File

@ -477,21 +477,6 @@ public:
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
WireRange getWires() const
{
WireRange range;
range.b.cursor = 0;
range.e.cursor = chip_info->num_wires;
return range;
}
// -------------------------------------------------
IdString getPipName(PipId pip) const;
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
AllPipRange getPips() const
{
AllPipRange range;
@ -500,6 +485,10 @@ public:
return range;
}
IdString getPipName(PipId pip) const;
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
WireId getPipSrcWire(PipId pip) const
{
WireId wire;
@ -551,6 +540,15 @@ public:
return range;
}
WireRange getWires() const
{
WireRange range;
range.b.cursor = 0;
range.e.cursor = chip_info->num_wires;
return range;
}
BelId getPackagePinBel(const std::string &pin) const;
std::string getBelPackagePin(BelId bel) const;
@ -575,6 +573,7 @@ public:
// -------------------------------------------------
bool pack();
bool place();
bool route();

View File

@ -58,7 +58,10 @@ void arch_wrap_python()
auto arch_cls = class_<Arch, Arch *, bases<BaseCtx>, boost::noncopyable>("Arch", init<ArchArgs>());
auto ctx_cls = class_<Context, Context *, bases<Arch>, boost::noncopyable>("Context", no_init)
.def("checksum", &Context::checksum);
.def("checksum", &Context::checksum)
.def("pack", &Context::pack)
.def("place", &Context::place)
.def("route", &Context::route);
fn_wrapper_1a<Context, decltype(&Context::getBelType), &Context::getBelType, conv_to_str<BelType>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType");

View File

@ -21,7 +21,7 @@
#error Include "archdefs.h" via "nextpnr.h" only.
#endif
#include <boost/functional/hash_fwd.hpp>
#include <boost/functional/hash.hpp>
NEXTPNR_NAMESPACE_BEGIN
@ -144,6 +144,7 @@ struct DecalId
TYPE_GROUP
} type = TYPE_NONE;
int32_t index = -1;
bool active = false;
bool operator==(const DecalId &other) const { return (type == other.type) && (index == other.index); }
bool operator!=(const DecalId &other) const { return (type != other.type) || (index != other.index); }

View File

@ -77,7 +77,7 @@ with open(args.gfxh) as f:
state = 1
elif state == 1 and line.startswith("};"):
state = 0
elif state == 1 and line.startswith("{"):
elif state == 1 and (line.startswith("{") or line.strip() == ""):
pass
elif state == 1:
idx = len(gfx_wire_ids)

View File

@ -31,17 +31,31 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
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;
float y1 = y + 1.0 - (0.03 + 0.0025 * (60 - idx));
el.x1 = x + 0.0;
el.x2 = x + 0.9;
float y1 = y + 1.0 - (0.03 + 0.0025 * (60 - (idx ^ 1)));
float y2 = y + 1.0 - (0.03 + 0.0025 * (60 - idx));
el.x1 = x;
el.x2 = x + 0.01;
el.y1 = y1;
el.y2 = y1;
g.push_back(el);
el.x1 = x + 0.01;
el.x2 = x + 0.02;
el.y1 = y1;
el.y2 = y2;
g.push_back(el);
el.x1 = x + 0.02;
el.x2 = x + 0.9;
el.y1 = y2;
el.y2 = y2;
g.push_back(el);
el.x1 = x + main_swbox_x1 + 0.0025 * (idx + 35);
el.x2 = el.x1;
el.y1 = y1;
el.y1 = y2;
el.y2 = y + main_swbox_y2;
g.push_back(el);
}
@ -91,17 +105,30 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
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;
float x1 = x + 0.03 + 0.0025 * (60 - idx);
float x1 = x + 0.03 + 0.0025 * (60 - (idx ^ 1));
float x2 = x + 0.03 + 0.0025 * (60 - idx);
el.y1 = y + 1.0;
el.y2 = y + 0.1;
el.y1 = y + 1.00;
el.y2 = y + 0.99;
el.x1 = x1;
el.x2 = x1;
g.push_back(el);
el.y1 = y + 0.99;
el.y2 = y + 0.98;
el.x1 = x1;
el.x2 = x2;
g.push_back(el);
el.y1 = y + 0.98;
el.y2 = y + 0.10;
el.x1 = x2;
el.x2 = x2;
g.push_back(el);
el.y1 = y + 1.0 - (0.03 + 0.0025 * (270 - idx));
el.y2 = el.y1;
el.x1 = x1;
el.x1 = x2;
el.x2 = x + main_swbox_x1;
g.push_back(el);
}
@ -109,9 +136,9 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
if (id >= TILE_WIRE_SP4_V_B_0 && id <= TILE_WIRE_SP4_V_B_47) {
int idx = id - TILE_WIRE_SP4_V_B_0;
float x1 = x + 0.03 + 0.0025 * (60 - (idx ^ 1));
float x2 = x + 0.03 + 0.0025 * (60 - idx);
float x3 = x + 0.03 + 0.0025 * (60 - idx - 12);
float x1 = x + 0.03 + 0.0025 * (60 - idx);
float x2 = x + 0.03 + 0.0025 * (60 - (idx ^ 1));
float x3 = x + 0.03 + 0.0025 * (60 - (idx ^ 1) - 12);
if (idx >= 12) {
el.y1 = y + 1.00;
@ -139,13 +166,13 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
el.x2 = x3;
g.push_back(el);
el.y1 = y + 1.0 - (0.03 + 0.0025 * (145 - idx));
el.y1 = y + 1.0 - (0.03 + 0.0025 * (145 - (idx ^ 1)));
el.y2 = el.y1;
el.x1 = x;
el.x2 = x2;
g.push_back(el);
el.y1 = y + 1.0 - (0.03 + 0.0025 * (270 - idx));
el.y1 = y + 1.0 - (0.03 + 0.0025 * (270 - (idx ^ 1)));
el.y2 = el.y1;
el.x1 = x2;
el.x2 = x + main_swbox_x1;
@ -157,17 +184,30 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
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;
float y1 = y + 1.0 - (0.03 + 0.0025 * (90 - idx));
float y1 = y + 1.0 - (0.03 + 0.0025 * (90 - (idx ^ 1)));
float y2 = y + 1.0 - (0.03 + 0.0025 * (90 - idx));
el.x1 = x + 0.0;
el.x2 = x + 0.98333;
el.x1 = x;
el.x2 = x + 0.01;
el.y1 = y1;
el.y2 = y1;
g.push_back(el);
el.x1 = x + 0.01;
el.x2 = x + 0.02;
el.y1 = y1;
el.y2 = y2;
g.push_back(el);
el.x1 = x + 0.02;
el.x2 = x + 0.98333;
el.y1 = y2;
el.y2 = y2;
g.push_back(el);
el.x1 = x + main_swbox_x1 + 0.0025 * (idx + 5);
el.x2 = el.x1;
el.y1 = y1;
el.y1 = y2;
el.y2 = y + main_swbox_y2;
g.push_back(el);
}
@ -175,9 +215,9 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
if (id >= TILE_WIRE_SP12_H_R_0 && id <= TILE_WIRE_SP12_H_R_23) {
int idx = id - TILE_WIRE_SP12_H_R_0;
float y1 = y + 1.0 - (0.03 + 0.0025 * (90 - (idx ^ 1)));
float y2 = y + 1.0 - (0.03 + 0.0025 * (90 - idx));
float y3 = y + 1.0 - (0.03 + 0.0025 * (90 - idx - 2));
float y1 = y + 1.0 - (0.03 + 0.0025 * (90 - idx));
float y2 = y + 1.0 - (0.03 + 0.0025 * (90 - (idx ^ 1)));
float y3 = y + 1.0 - (0.03 + 0.0025 * (90 - (idx ^ 1) - 2));
if (idx >= 2) {
el.x1 = x;
@ -205,7 +245,7 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
el.y2 = y3;
g.push_back(el);
el.x1 = x + main_swbox_x1 + 0.0025 * (idx + 5);
el.x1 = x + main_swbox_x1 + 0.0025 * ((idx ^ 1) + 5);
el.x2 = el.x1;
el.y1 = y2;
el.y2 = y + main_swbox_y2;
@ -217,7 +257,7 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
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;
float y1 = y + 1.0 - (0.03 + 0.0025 * (145 - idx));
float y1 = y + 1.0 - (0.03 + 0.0025 * (145 - (idx ^ 1)));
el.y1 = y1;
el.y2 = y1;
@ -231,17 +271,30 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
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;
float x1 = x + 0.03 + 0.0025 * (90 - idx);
float x1 = x + 0.03 + 0.0025 * (90 - (idx ^ 1));
float x2 = x + 0.03 + 0.0025 * (90 - idx);
el.y1 = y + 1.00;
el.y2 = y + 0.01667;
el.y2 = y + 0.99;
el.x1 = x1;
el.x2 = x1;
g.push_back(el);
el.y1 = y + 0.99;
el.y2 = y + 0.98;
el.x1 = x1;
el.x2 = x2;
g.push_back(el);
el.y1 = y + 0.98;
el.y2 = y + 0.01667;
el.x1 = x2;
el.x2 = x2;
g.push_back(el);
el.y1 = y + 1.0 - (0.03 + 0.0025 * (300 - idx));
el.y2 = el.y1;
el.x1 = x1;
el.x1 = x2;
el.x2 = x + main_swbox_x1;
g.push_back(el);
}

View File

@ -39,7 +39,6 @@
#include "jsonparse.h"
#include "log.h"
#include "nextpnr.h"
#include "pack.h"
#include "pcf.h"
#include "place_legaliser.h"
#include "timing.h"
@ -382,7 +381,7 @@ int main(int argc, char *argv[])
log_error("Loading PCF failed.\n");
}
if (!pack_design(ctx.get()) && !ctx->force)
if (!ctx->pack() && !ctx->force)
log_error("Packing design failed.\n");
assign_budget(ctx.get());
ctx->check();

View File

@ -18,7 +18,6 @@
*
*/
#include "pack.h"
#include <algorithm>
#include <iterator>
#include <unordered_set>
@ -577,8 +576,9 @@ static void pack_special(Context *ctx)
}
// Main pack function
bool pack_design(Context *ctx)
bool Arch::pack()
{
Context *ctx = getCtx();
try {
log_break();
pack_constants(ctx);

View File

@ -1,32 +0,0 @@
/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
* Copyright (C) 2018 David Shah <david@symbioticeda.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef PACK_H
#define PACK_H
#include "nextpnr.h"
NEXTPNR_NAMESPACE_BEGIN
bool pack_design(Context *ctx);
NEXTPNR_NAMESPACE_END
#endif // ROUTE_H