Merge branch 'master' of gitlab.com:SymbioticEDA/nextpnr into q3k/lock-the-things
This commit is contained in:
commit
b8ca1a5582
322
3rdparty/python-console/modified/pyconsole.cc
vendored
322
3rdparty/python-console/modified/pyconsole.cc
vendored
@ -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( );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
80
3rdparty/python-console/modified/pyconsole.h
vendored
80
3rdparty/python-console/modified/pyconsole.h
vendored
@ -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
|
|
@ -730,6 +730,7 @@ struct Arch : BaseCtx
|
|||||||
|
|
||||||
// -------------------------------------------------
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
bool pack();
|
||||||
bool place();
|
bool place();
|
||||||
bool route();
|
bool route();
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#error Include "archdefs.h" via "nextpnr.h" only.
|
#error Include "archdefs.h" via "nextpnr.h" only.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/functional/hash_fwd.hpp>
|
#include <boost/functional/hash.hpp>
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
#include "bitstream.h"
|
#include "bitstream.h"
|
||||||
#include "design_utils.h"
|
#include "design_utils.h"
|
||||||
#include "jsonparse.h"
|
#include "jsonparse.h"
|
||||||
#include "pack.h"
|
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
|
|
||||||
USING_NEXTPNR_NAMESPACE
|
USING_NEXTPNR_NAMESPACE
|
||||||
@ -147,7 +146,7 @@ int main(int argc, char *argv[])
|
|||||||
if (!parse_json_file(f, filename, ctx.get()))
|
if (!parse_json_file(f, filename, ctx.get()))
|
||||||
log_error("Loading design failed.\n");
|
log_error("Loading design failed.\n");
|
||||||
|
|
||||||
if (!pack_design(ctx.get()) && !ctx->force)
|
if (!ctx->pack() && !ctx->force)
|
||||||
log_error("Packing design failed.\n");
|
log_error("Packing design failed.\n");
|
||||||
if (vm.count("freq"))
|
if (vm.count("freq"))
|
||||||
ctx->target_freq = vm["freq"].as<double>() * 1e6;
|
ctx->target_freq = vm["freq"].as<double>() * 1e6;
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pack.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
@ -84,8 +83,9 @@ void pack_io(Context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Main pack function
|
// Main pack function
|
||||||
bool pack_design(Context *ctx)
|
bool Arch::pack()
|
||||||
{
|
{
|
||||||
|
Context *ctx = getCtx();
|
||||||
try {
|
try {
|
||||||
log_break();
|
log_break();
|
||||||
pack_io(ctx);
|
pack_io(ctx);
|
||||||
|
@ -181,6 +181,7 @@ void Arch::bindBel(BelId bel, IdString cell, PlaceStrength strength)
|
|||||||
bels.at(bel).bound_cell = cell;
|
bels.at(bel).bound_cell = cell;
|
||||||
cells.at(cell)->bel = bel;
|
cells.at(cell)->bel = bel;
|
||||||
cells.at(cell)->belStrength = strength;
|
cells.at(cell)->belStrength = strength;
|
||||||
|
refreshUiBel(bel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arch::unbindBel(BelId 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)->bel = BelId();
|
||||||
cells.at(bels.at(bel).bound_cell)->belStrength = STRENGTH_NONE;
|
cells.at(bels.at(bel).bound_cell)->belStrength = STRENGTH_NONE;
|
||||||
bels.at(bel).bound_cell = IdString();
|
bels.at(bel).bound_cell = IdString();
|
||||||
|
refreshUiBel(bel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Arch::checkBelAvail(BelId bel) const { return bels.at(bel).bound_cell == IdString(); }
|
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;
|
wires.at(wire).bound_net = net;
|
||||||
nets.at(net)->wires[wire].pip = PipId();
|
nets.at(net)->wires[wire].pip = PipId();
|
||||||
nets.at(net)->wires[wire].strength = strength;
|
nets.at(net)->wires[wire].strength = strength;
|
||||||
|
refreshUiWire(wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arch::unbindWire(WireId 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 &net_wires = nets[wires.at(wire).bound_net]->wires;
|
||||||
|
|
||||||
auto pip = net_wires.at(wire).pip;
|
auto pip = net_wires.at(wire).pip;
|
||||||
if (pip != PipId())
|
if (pip != PipId()) {
|
||||||
pips.at(pip).bound_net = IdString();
|
pips.at(pip).bound_net = IdString();
|
||||||
|
refreshUiPip(pip);
|
||||||
|
}
|
||||||
|
|
||||||
net_wires.erase(wire);
|
net_wires.erase(wire);
|
||||||
wires.at(wire).bound_net = IdString();
|
wires.at(wire).bound_net = IdString();
|
||||||
|
refreshUiWire(wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Arch::checkWireAvail(WireId wire) const { return wires.at(wire).bound_net == IdString(); }
|
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;
|
wires.at(wire).bound_net = net;
|
||||||
nets.at(net)->wires[wire].pip = pip;
|
nets.at(net)->wires[wire].pip = pip;
|
||||||
nets.at(net)->wires[wire].strength = strength;
|
nets.at(net)->wires[wire].strength = strength;
|
||||||
|
refreshUiPip(pip);
|
||||||
|
refreshUiWire(wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arch::unbindPip(PipId pip)
|
void Arch::unbindPip(PipId pip)
|
||||||
@ -290,6 +298,8 @@ void Arch::unbindPip(PipId pip)
|
|||||||
nets.at(wires.at(wire).bound_net)->wires.erase(wire);
|
nets.at(wires.at(wire).bound_net)->wires.erase(wire);
|
||||||
pips.at(pip).bound_net = IdString();
|
pips.at(pip).bound_net = IdString();
|
||||||
wires.at(wire).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(); }
|
bool Arch::checkPipAvail(PipId pip) const { return pips.at(pip).bound_net == IdString(); }
|
||||||
|
@ -183,6 +183,7 @@ struct Arch : BaseCtx
|
|||||||
float getDelayNS(delay_t v) const { return v; }
|
float getDelayNS(delay_t v) const { return v; }
|
||||||
uint32_t getDelayChecksum(delay_t v) const { return 0; }
|
uint32_t getDelayChecksum(delay_t v) const { return 0; }
|
||||||
|
|
||||||
|
bool pack() { return true; }
|
||||||
bool place();
|
bool place();
|
||||||
bool route();
|
bool route();
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ if (BUILD_PYTHON)
|
|||||||
|
|
||||||
../3rdparty/python-console/modified/pyredirector.cc
|
../3rdparty/python-console/modified/pyredirector.cc
|
||||||
../3rdparty/python-console/modified/pyinterpreter.cc
|
../3rdparty/python-console/modified/pyinterpreter.cc
|
||||||
../3rdparty/python-console/modified/pyconsole.cc
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -66,7 +66,6 @@ BaseMainWindow::BaseMainWindow(std::unique_ptr<Context> context, QWidget *parent
|
|||||||
|
|
||||||
DesignWidget *designview = new DesignWidget();
|
DesignWidget *designview = new DesignWidget();
|
||||||
designview->setMinimumWidth(300);
|
designview->setMinimumWidth(300);
|
||||||
designview->setMaximumWidth(300);
|
|
||||||
splitter_h->addWidget(designview);
|
splitter_h->addWidget(designview);
|
||||||
|
|
||||||
connect(this, SIGNAL(contextChanged(Context *)), designview, SLOT(newContext(Context *)));
|
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();
|
tabWidget = new QTabWidget();
|
||||||
#ifndef NO_PYTHON
|
#ifndef NO_PYTHON
|
||||||
PythonTab *pythontab = new PythonTab();
|
PythonTab *pythontab = new PythonTab();
|
||||||
tabWidget->addTab(pythontab, "Python");
|
tabWidget->addTab(pythontab, "Console");
|
||||||
connect(this, SIGNAL(contextChanged(Context *)), pythontab, SLOT(newContext(Context *)));
|
connect(this, SIGNAL(contextChanged(Context *)), pythontab, SLOT(newContext(Context *)));
|
||||||
#endif
|
#endif
|
||||||
info = new InfoTab();
|
info = new InfoTab();
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include "design_utils.h"
|
#include "design_utils.h"
|
||||||
#include "jsonparse.h"
|
#include "jsonparse.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "pack.h"
|
|
||||||
#include "pcf.h"
|
#include "pcf.h"
|
||||||
|
|
||||||
static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }
|
static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include "design_utils.h"
|
#include "design_utils.h"
|
||||||
#include "jsonparse.h"
|
#include "jsonparse.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "pack.h"
|
|
||||||
#include "pcf.h"
|
#include "pcf.h"
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
|
|
||||||
@ -97,7 +96,7 @@ void Worker::pack()
|
|||||||
{
|
{
|
||||||
Q_EMIT taskStarted();
|
Q_EMIT taskStarted();
|
||||||
try {
|
try {
|
||||||
bool res = pack_design(ctx);
|
bool res = ctx->pack();
|
||||||
print_utilisation(ctx);
|
print_utilisation(ctx);
|
||||||
Q_EMIT pack_finished(res);
|
Q_EMIT pack_finished(res);
|
||||||
} catch (WorkerInterruptionRequested) {
|
} catch (WorkerInterruptionRequested) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
* nextpnr -- Next Generation Place and Route
|
* nextpnr -- Next Generation Place and Route
|
||||||
*
|
*
|
||||||
* Copyright (C) 2018 Miodrag Milanovic <miodrag@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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -17,12 +18,18 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef NO_PYTHON
|
||||||
|
|
||||||
#include "line_editor.h"
|
#include "line_editor.h"
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
#include <QToolTip>
|
||||||
|
#include "ColumnFormatter.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
#include "pyinterpreter.h"
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
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);
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
QAction *clearAction = new QAction("Clear &history", this);
|
QAction *clearAction = new QAction("Clear &history", this);
|
||||||
@ -38,10 +45,12 @@ LineEditor::LineEditor(QWidget *parent) : QLineEdit(parent), index(0)
|
|||||||
|
|
||||||
void LineEditor::keyPressEvent(QKeyEvent *ev)
|
void LineEditor::keyPressEvent(QKeyEvent *ev)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) {
|
if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) {
|
||||||
|
QToolTip::hideText();
|
||||||
if (lines.empty())
|
if (lines.empty())
|
||||||
return;
|
return;
|
||||||
|
printf("Key_Up\n");
|
||||||
if (ev->key() == Qt::Key_Up)
|
if (ev->key() == Qt::Key_Up)
|
||||||
index--;
|
index--;
|
||||||
if (ev->key() == Qt::Key_Down)
|
if (ev->key() == Qt::Key_Down)
|
||||||
@ -56,12 +65,21 @@ void LineEditor::keyPressEvent(QKeyEvent *ev)
|
|||||||
}
|
}
|
||||||
setText(lines[index]);
|
setText(lines[index]);
|
||||||
} else if (ev->key() == Qt::Key_Escape) {
|
} else if (ev->key() == Qt::Key_Escape) {
|
||||||
|
QToolTip::hideText();
|
||||||
clear();
|
clear();
|
||||||
return;
|
return;
|
||||||
|
} else if (ev->key() == Qt::Key_Tab) {
|
||||||
|
autocomplete();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
QToolTip::hideText();
|
||||||
|
|
||||||
QLineEdit::keyPressEvent(ev);
|
QLineEdit::keyPressEvent(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This makes TAB work
|
||||||
|
bool LineEditor::focusNextPrevChild(bool next) { return false; }
|
||||||
|
|
||||||
void LineEditor::textInserted()
|
void LineEditor::textInserted()
|
||||||
{
|
{
|
||||||
if (lines.empty() || lines.back() != text())
|
if (lines.empty() || lines.back() != text())
|
||||||
@ -82,4 +100,36 @@ void LineEditor::clearHistory()
|
|||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
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
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
* nextpnr -- Next Generation Place and Route
|
* nextpnr -- Next Generation Place and Route
|
||||||
*
|
*
|
||||||
* Copyright (C) 2018 Miodrag Milanovic <miodrag@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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -20,8 +21,11 @@
|
|||||||
#ifndef LINE_EDITOR_H
|
#ifndef LINE_EDITOR_H
|
||||||
#define LINE_EDITOR_H
|
#define LINE_EDITOR_H
|
||||||
|
|
||||||
|
#ifndef NO_PYTHON
|
||||||
|
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include "ParseHelper.h"
|
||||||
#include "nextpnr.h"
|
#include "nextpnr.h"
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
@ -31,7 +35,7 @@ class LineEditor : public QLineEdit
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LineEditor(QWidget *parent = 0);
|
explicit LineEditor(ParseHelper *helper, QWidget *parent = 0);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void textInserted();
|
void textInserted();
|
||||||
@ -43,13 +47,18 @@ class LineEditor : public QLineEdit
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
|
void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
|
||||||
|
bool focusNextPrevChild(bool next) Q_DECL_OVERRIDE;
|
||||||
|
void autocomplete();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int index;
|
int index;
|
||||||
QStringList lines;
|
QStringList lines;
|
||||||
QMenu *contextMenu;
|
QMenu *contextMenu;
|
||||||
|
ParseHelper *parseHelper;
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // NO_PYTHON
|
||||||
|
|
||||||
#endif // LINE_EDITOR_H
|
#endif // LINE_EDITOR_H
|
||||||
|
82
gui/pyconsole.cc
Normal file
82
gui/pyconsole.cc
Normal 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
|
@ -1,7 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* nextpnr -- Next Generation Place and Route
|
* 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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -17,15 +18,41 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PACK_H
|
#ifndef PYCONSOLE_H
|
||||||
#define PACK_H
|
#define PYCONSOLE_H
|
||||||
|
|
||||||
|
#ifndef NO_PYTHON
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
#include <QMimeData>
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include "ParseHelper.h"
|
||||||
|
#include "ParseListener.h"
|
||||||
#include "nextpnr.h"
|
#include "nextpnr.h"
|
||||||
|
|
||||||
|
class QWidget;
|
||||||
|
class QKeyEvent;
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
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
|
NEXTPNR_NAMESPACE_END
|
||||||
|
#endif // NO_PYTHON
|
||||||
|
|
||||||
#endif // ROUTE_H
|
#endif // PYCONSOLE_H
|
@ -25,12 +25,20 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
const QString PythonTab::PROMPT = ">>> ";
|
||||||
|
const QString PythonTab::MULTILINE_PROMPT = "... ";
|
||||||
|
|
||||||
PythonTab::PythonTab(QWidget *parent) : QWidget(parent), initialized(false)
|
PythonTab::PythonTab(QWidget *parent) : QWidget(parent), initialized(false)
|
||||||
{
|
{
|
||||||
|
QFont f("unexistent");
|
||||||
|
f.setStyleHint(QFont::Monospace);
|
||||||
|
|
||||||
// Add text area for Python output and input line
|
// Add text area for Python output and input line
|
||||||
console = new PythonConsole();
|
console = new PythonConsole();
|
||||||
console->setMinimumHeight(100);
|
console->setMinimumHeight(100);
|
||||||
console->setEnabled(false);
|
console->setReadOnly(true);
|
||||||
|
console->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
|
||||||
|
console->setFont(f);
|
||||||
|
|
||||||
console->setContextMenuPolicy(Qt::CustomContextMenu);
|
console->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
QAction *clearAction = new QAction("Clear &buffer", this);
|
QAction *clearAction = new QAction("Clear &buffer", this);
|
||||||
@ -41,9 +49,21 @@ PythonTab::PythonTab(QWidget *parent) : QWidget(parent), initialized(false)
|
|||||||
contextMenu->addAction(clearAction);
|
contextMenu->addAction(clearAction);
|
||||||
connect(console, SIGNAL(customContextMenuRequested(const QPoint)), this, SLOT(showContextMenu(const QPoint)));
|
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();
|
QGridLayout *mainLayout = new QGridLayout();
|
||||||
mainLayout->addWidget(console, 0, 0);
|
mainLayout->addWidget(console, 0, 0);
|
||||||
|
mainLayout->addWidget(lineEdit, 1, 0);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
parseHelper.subscribe(console);
|
||||||
|
|
||||||
|
prompt = PythonTab::PROMPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PythonTab::~PythonTab()
|
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)
|
void PythonTab::newContext(Context *ctx)
|
||||||
{
|
{
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
pyinterpreter_finalize();
|
pyinterpreter_finalize();
|
||||||
deinit_python();
|
deinit_python();
|
||||||
}
|
}
|
||||||
console->setEnabled(true);
|
|
||||||
console->clear();
|
console->clear();
|
||||||
|
|
||||||
pyinterpreter_preinit();
|
pyinterpreter_preinit();
|
||||||
@ -74,7 +108,6 @@ void PythonTab::newContext(Context *ctx)
|
|||||||
|
|
||||||
QString version = QString("Python %1 on %2\n").arg(Py_GetVersion(), Py_GetPlatform());
|
QString version = QString("Python %1 on %2\n").arg(Py_GetVersion(), Py_GetPlatform());
|
||||||
console->displayString(version);
|
console->displayString(version);
|
||||||
console->displayPrompt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonTab::showContextMenu(const QPoint &pt) { contextMenu->exec(mapToGlobal(pt)); }
|
void PythonTab::showContextMenu(const QPoint &pt) { contextMenu->exec(mapToGlobal(pt)); }
|
||||||
@ -83,4 +116,4 @@ void PythonTab::clearBuffer() { console->clear(); }
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
#endif
|
#endif // NO_PYTHON
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
|
#include "ParseHelper.h"
|
||||||
#include "line_editor.h"
|
#include "line_editor.h"
|
||||||
#include "nextpnr.h"
|
#include "nextpnr.h"
|
||||||
#include "pyconsole.h"
|
#include "pyconsole.h"
|
||||||
@ -42,13 +43,20 @@ class PythonTab : public QWidget
|
|||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void showContextMenu(const QPoint &pt);
|
void showContextMenu(const QPoint &pt);
|
||||||
void clearBuffer();
|
void clearBuffer();
|
||||||
|
void editLineReturnPressed(QString text);
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void newContext(Context *ctx);
|
void newContext(Context *ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PythonConsole *console;
|
PythonConsole *console;
|
||||||
|
LineEditor *lineEdit;
|
||||||
QMenu *contextMenu;
|
QMenu *contextMenu;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
ParseHelper parseHelper;
|
||||||
|
QString prompt;
|
||||||
|
|
||||||
|
static const QString PROMPT;
|
||||||
|
static const QString MULTILINE_PROMPT;
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -494,6 +494,7 @@ DecalXY Arch::getFrameDecal() const
|
|||||||
{
|
{
|
||||||
DecalXY decalxy;
|
DecalXY decalxy;
|
||||||
decalxy.decal.type = DecalId::TYPE_FRAME;
|
decalxy.decal.type = DecalId::TYPE_FRAME;
|
||||||
|
decalxy.decal.active = true;
|
||||||
return decalxy;
|
return decalxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,6 +503,7 @@ DecalXY Arch::getBelDecal(BelId bel) const
|
|||||||
DecalXY decalxy;
|
DecalXY decalxy;
|
||||||
decalxy.decal.type = DecalId::TYPE_BEL;
|
decalxy.decal.type = DecalId::TYPE_BEL;
|
||||||
decalxy.decal.index = bel.index;
|
decalxy.decal.index = bel.index;
|
||||||
|
decalxy.decal.active = bel_to_cell.at(bel.index) != IdString();
|
||||||
return decalxy;
|
return decalxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,18 +512,25 @@ DecalXY Arch::getWireDecal(WireId wire) const
|
|||||||
DecalXY decalxy;
|
DecalXY decalxy;
|
||||||
decalxy.decal.type = DecalId::TYPE_WIRE;
|
decalxy.decal.type = DecalId::TYPE_WIRE;
|
||||||
decalxy.decal.index = wire.index;
|
decalxy.decal.index = wire.index;
|
||||||
|
decalxy.decal.active = wire_to_net.at(wire.index) != IdString();
|
||||||
return decalxy;
|
return decalxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
DecalXY Arch::getPipDecal(PipId pip) const
|
DecalXY Arch::getPipDecal(PipId pip) const
|
||||||
{
|
{
|
||||||
DecalXY decalxy;
|
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;
|
return decalxy;
|
||||||
};
|
};
|
||||||
|
|
||||||
DecalXY Arch::getGroupDecal(GroupId group) const
|
DecalXY Arch::getGroupDecal(GroupId group) const
|
||||||
{
|
{
|
||||||
DecalXY decalxy;
|
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;
|
return decalxy;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -549,8 +558,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
|||||||
int n = chip_info->wire_data[wire.index].num_segments;
|
int n = chip_info->wire_data[wire.index].num_segments;
|
||||||
const WireSegmentPOD *p = chip_info->wire_data[wire.index].segments.get();
|
const WireSegmentPOD *p = chip_info->wire_data[wire.index].segments.get();
|
||||||
|
|
||||||
GraphicElement::style_t style =
|
GraphicElement::style_t style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
|
||||||
wire_to_net.at(wire.index) != IdString() ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
|
|
||||||
|
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
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);
|
||||||
@ -565,7 +573,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
|||||||
if (bel_type == TYPE_ICESTORM_LC) {
|
if (bel_type == TYPE_ICESTORM_LC) {
|
||||||
GraphicElement el;
|
GraphicElement el;
|
||||||
el.type = GraphicElement::G_BOX;
|
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.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1;
|
||||||
el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2;
|
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.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) {
|
if (bel_type == TYPE_ICESTORM_RAM) {
|
||||||
GraphicElement el;
|
for (int i = 0; i < 2; i++)
|
||||||
el.type = GraphicElement::G_BOX;
|
{
|
||||||
el.x1 = chip_info->bel_data[bel.index].x + 0.1;
|
int tx = chip_info->bel_data[bel.index].x;
|
||||||
el.x2 = chip_info->bel_data[bel.index].x + 0.9;
|
int ty = chip_info->bel_data[bel.index].y + i;
|
||||||
el.y1 = chip_info->bel_data[bel.index].y + 0.1;
|
|
||||||
el.y2 = chip_info->bel_data[bel.index].y + 1.9;
|
GraphicElement el;
|
||||||
el.z = 0;
|
el.type = GraphicElement::G_BOX;
|
||||||
ret.push_back(el);
|
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)
|
void ArchRWProxyMethods::bindBel(BelId bel, IdString cell, PlaceStrength strength)
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(bel != BelId());
|
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_->bel_to_cell[bel.index] = cell;
|
||||||
parent_->cells[cell]->bel = bel;
|
parent_->cells[cell]->bel = bel;
|
||||||
parent_->cells[cell]->belStrength = strength;
|
parent_->cells[cell]->belStrength = strength;
|
||||||
|
parent_->refreshUiBel(bel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchRWProxyMethods::unbindBel(BelId 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]]->bel = BelId();
|
||||||
parent_->cells[parent_->bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE;
|
parent_->cells[parent_->bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE;
|
||||||
parent_->bel_to_cell[bel.index] = IdString();
|
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)
|
void ArchRWProxyMethods::unbindWire(WireId wire)
|
||||||
@ -863,10 +902,12 @@ void ArchRWProxyMethods::unbindWire(WireId wire)
|
|||||||
if (pip != PipId()) {
|
if (pip != PipId()) {
|
||||||
parent_->pip_to_net[pip.index] = IdString();
|
parent_->pip_to_net[pip.index] = IdString();
|
||||||
parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index] = IdString();
|
parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index] = IdString();
|
||||||
|
parent_->refreshUiPip(pip);
|
||||||
}
|
}
|
||||||
|
|
||||||
net_wires.erase(it);
|
net_wires.erase(it);
|
||||||
parent_->wire_to_net[wire.index] = IdString();
|
parent_->wire_to_net[wire.index] = IdString();
|
||||||
|
parent_->refreshUiWire(wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchRWProxyMethods::bindPip(PipId pip, IdString net, PlaceStrength strength)
|
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_->wire_to_net[dst.index] = net;
|
||||||
parent_->nets[net]->wires[dst].pip = pip;
|
parent_->nets[net]->wires[dst].pip = pip;
|
||||||
parent_->nets[net]->wires[dst].strength = strength;
|
parent_->nets[net]->wires[dst].strength = strength;
|
||||||
|
|
||||||
|
parent_->refreshUiPip(pip);
|
||||||
|
parent_->refreshUiWire(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchRWProxyMethods::unbindPip(PipId pip)
|
void ArchRWProxyMethods::unbindPip(PipId pip)
|
||||||
@ -900,6 +944,9 @@ void ArchRWProxyMethods::unbindPip(PipId pip)
|
|||||||
|
|
||||||
parent_->pip_to_net[pip.index] = IdString();
|
parent_->pip_to_net[pip.index] = IdString();
|
||||||
parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_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)
|
CellInfo *ArchRWProxyMethods::getCell(IdString cell)
|
||||||
|
29
ice40/arch.h
29
ice40/arch.h
@ -477,21 +477,6 @@ public:
|
|||||||
|
|
||||||
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
|
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 getPips() const
|
||||||
{
|
{
|
||||||
AllPipRange range;
|
AllPipRange range;
|
||||||
@ -499,6 +484,10 @@ public:
|
|||||||
range.e.cursor = chip_info->num_pips;
|
range.e.cursor = chip_info->num_pips;
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdString getPipName(PipId pip) const;
|
||||||
|
|
||||||
|
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
|
||||||
|
|
||||||
WireId getPipSrcWire(PipId pip) const
|
WireId getPipSrcWire(PipId pip) const
|
||||||
{
|
{
|
||||||
@ -551,6 +540,15 @@ public:
|
|||||||
return range;
|
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;
|
BelId getPackagePinBel(const std::string &pin) const;
|
||||||
std::string getBelPackagePin(BelId bel) const;
|
std::string getBelPackagePin(BelId bel) const;
|
||||||
|
|
||||||
@ -575,6 +573,7 @@ public:
|
|||||||
|
|
||||||
// -------------------------------------------------
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
bool pack();
|
||||||
bool place();
|
bool place();
|
||||||
bool route();
|
bool route();
|
||||||
|
|
||||||
|
@ -58,7 +58,10 @@ void arch_wrap_python()
|
|||||||
|
|
||||||
auto arch_cls = class_<Arch, Arch *, bases<BaseCtx>, boost::noncopyable>("Arch", init<ArchArgs>());
|
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)
|
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>,
|
fn_wrapper_1a<Context, decltype(&Context::getBelType), &Context::getBelType, conv_to_str<BelType>,
|
||||||
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType");
|
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType");
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#error Include "archdefs.h" via "nextpnr.h" only.
|
#error Include "archdefs.h" via "nextpnr.h" only.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/functional/hash_fwd.hpp>
|
#include <boost/functional/hash.hpp>
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -144,6 +144,7 @@ struct DecalId
|
|||||||
TYPE_GROUP
|
TYPE_GROUP
|
||||||
} type = TYPE_NONE;
|
} type = TYPE_NONE;
|
||||||
int32_t index = -1;
|
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); }
|
||||||
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); }
|
||||||
|
@ -77,7 +77,7 @@ with open(args.gfxh) as f:
|
|||||||
state = 1
|
state = 1
|
||||||
elif state == 1 and line.startswith("};"):
|
elif state == 1 and line.startswith("};"):
|
||||||
state = 0
|
state = 0
|
||||||
elif state == 1 and line.startswith("{"):
|
elif state == 1 and (line.startswith("{") or line.strip() == ""):
|
||||||
pass
|
pass
|
||||||
elif state == 1:
|
elif state == 1:
|
||||||
idx = len(gfx_wire_ids)
|
idx = len(gfx_wire_ids)
|
||||||
|
103
ice40/gfx.cc
103
ice40/gfx.cc
@ -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) {
|
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;
|
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;
|
float y1 = y + 1.0 - (0.03 + 0.0025 * (60 - (idx ^ 1)));
|
||||||
el.x2 = x + 0.9;
|
float y2 = y + 1.0 - (0.03 + 0.0025 * (60 - idx));
|
||||||
|
|
||||||
|
el.x1 = x;
|
||||||
|
el.x2 = x + 0.01;
|
||||||
el.y1 = y1;
|
el.y1 = y1;
|
||||||
el.y2 = y1;
|
el.y2 = y1;
|
||||||
g.push_back(el);
|
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.x1 = x + main_swbox_x1 + 0.0025 * (idx + 35);
|
||||||
el.x2 = el.x1;
|
el.x2 = el.x1;
|
||||||
el.y1 = y1;
|
el.y1 = y2;
|
||||||
el.y2 = y + main_swbox_y2;
|
el.y2 = y + main_swbox_y2;
|
||||||
g.push_back(el);
|
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) {
|
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;
|
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.y1 = y + 1.00;
|
||||||
el.y2 = y + 0.1;
|
el.y2 = y + 0.99;
|
||||||
el.x1 = x1;
|
el.x1 = x1;
|
||||||
el.x2 = x1;
|
el.x2 = x1;
|
||||||
g.push_back(el);
|
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.y1 = y + 1.0 - (0.03 + 0.0025 * (270 - idx));
|
||||||
el.y2 = el.y1;
|
el.y2 = el.y1;
|
||||||
el.x1 = x1;
|
el.x1 = x2;
|
||||||
el.x2 = x + main_swbox_x1;
|
el.x2 = x + main_swbox_x1;
|
||||||
g.push_back(el);
|
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) {
|
if (id >= TILE_WIRE_SP4_V_B_0 && id <= TILE_WIRE_SP4_V_B_47) {
|
||||||
int idx = id - TILE_WIRE_SP4_V_B_0;
|
int idx = id - TILE_WIRE_SP4_V_B_0;
|
||||||
|
|
||||||
float x1 = x + 0.03 + 0.0025 * (60 - (idx ^ 1));
|
float x1 = x + 0.03 + 0.0025 * (60 - idx);
|
||||||
float x2 = 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 - 12);
|
float x3 = x + 0.03 + 0.0025 * (60 - (idx ^ 1) - 12);
|
||||||
|
|
||||||
if (idx >= 12) {
|
if (idx >= 12) {
|
||||||
el.y1 = y + 1.00;
|
el.y1 = y + 1.00;
|
||||||
@ -139,13 +166,13 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
|
|||||||
el.x2 = x3;
|
el.x2 = x3;
|
||||||
g.push_back(el);
|
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.y2 = el.y1;
|
||||||
el.x1 = x;
|
el.x1 = x;
|
||||||
el.x2 = x2;
|
el.x2 = x2;
|
||||||
g.push_back(el);
|
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.y2 = el.y1;
|
||||||
el.x1 = x2;
|
el.x1 = x2;
|
||||||
el.x2 = x + main_swbox_x1;
|
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) {
|
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;
|
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.x1 = x;
|
||||||
el.x2 = x + 0.98333;
|
el.x2 = x + 0.01;
|
||||||
el.y1 = y1;
|
el.y1 = y1;
|
||||||
el.y2 = y1;
|
el.y2 = y1;
|
||||||
g.push_back(el);
|
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.x1 = x + main_swbox_x1 + 0.0025 * (idx + 5);
|
||||||
el.x2 = el.x1;
|
el.x2 = el.x1;
|
||||||
el.y1 = y1;
|
el.y1 = y2;
|
||||||
el.y2 = y + main_swbox_y2;
|
el.y2 = y + main_swbox_y2;
|
||||||
g.push_back(el);
|
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) {
|
if (id >= TILE_WIRE_SP12_H_R_0 && id <= TILE_WIRE_SP12_H_R_23) {
|
||||||
int idx = id - TILE_WIRE_SP12_H_R_0;
|
int idx = id - TILE_WIRE_SP12_H_R_0;
|
||||||
|
|
||||||
float y1 = y + 1.0 - (0.03 + 0.0025 * (90 - (idx ^ 1)));
|
float y1 = y + 1.0 - (0.03 + 0.0025 * (90 - idx));
|
||||||
float y2 = 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 - 2));
|
float y3 = y + 1.0 - (0.03 + 0.0025 * (90 - (idx ^ 1) - 2));
|
||||||
|
|
||||||
if (idx >= 2) {
|
if (idx >= 2) {
|
||||||
el.x1 = x;
|
el.x1 = x;
|
||||||
@ -205,7 +245,7 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
|
|||||||
el.y2 = y3;
|
el.y2 = y3;
|
||||||
g.push_back(el);
|
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.x2 = el.x1;
|
||||||
el.y1 = y2;
|
el.y1 = y2;
|
||||||
el.y2 = y + main_swbox_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) {
|
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;
|
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.y1 = y1;
|
||||||
el.y2 = 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) {
|
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;
|
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.y1 = y + 1.00;
|
||||||
el.y2 = y + 0.01667;
|
el.y2 = y + 0.99;
|
||||||
el.x1 = x1;
|
el.x1 = x1;
|
||||||
el.x2 = x1;
|
el.x2 = x1;
|
||||||
g.push_back(el);
|
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.y1 = y + 1.0 - (0.03 + 0.0025 * (300 - idx));
|
||||||
el.y2 = el.y1;
|
el.y2 = el.y1;
|
||||||
el.x1 = x1;
|
el.x1 = x2;
|
||||||
el.x2 = x + main_swbox_x1;
|
el.x2 = x + main_swbox_x1;
|
||||||
g.push_back(el);
|
g.push_back(el);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
#include "jsonparse.h"
|
#include "jsonparse.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "nextpnr.h"
|
#include "nextpnr.h"
|
||||||
#include "pack.h"
|
|
||||||
#include "pcf.h"
|
#include "pcf.h"
|
||||||
#include "place_legaliser.h"
|
#include "place_legaliser.h"
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
@ -382,7 +381,7 @@ int main(int argc, char *argv[])
|
|||||||
log_error("Loading PCF failed.\n");
|
log_error("Loading PCF failed.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pack_design(ctx.get()) && !ctx->force)
|
if (!ctx->pack() && !ctx->force)
|
||||||
log_error("Packing design failed.\n");
|
log_error("Packing design failed.\n");
|
||||||
assign_budget(ctx.get());
|
assign_budget(ctx.get());
|
||||||
ctx->check();
|
ctx->check();
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pack.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
@ -577,8 +576,9 @@ static void pack_special(Context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Main pack function
|
// Main pack function
|
||||||
bool pack_design(Context *ctx)
|
bool Arch::pack()
|
||||||
{
|
{
|
||||||
|
Context *ctx = getCtx();
|
||||||
try {
|
try {
|
||||||
log_break();
|
log_break();
|
||||||
pack_constants(ctx);
|
pack_constants(ctx);
|
||||||
|
32
ice40/pack.h
32
ice40/pack.h
@ -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
|
|
Loading…
Reference in New Issue
Block a user