Merge branch 'master' of gitlab.com:SymbioticEDA/nextpnr
This commit is contained in:
commit
4a21436dfa
@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QtPropertyPrivate
|
class QtPropertyPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QtPropertyPrivate(QtAbstractPropertyManager *manager) : m_enabled(true), m_modified(false), m_manager(manager) {}
|
QtPropertyPrivate(QtAbstractPropertyManager *manager) : m_enabled(true), m_selectable(true), m_modified(false), m_manager(manager) {}
|
||||||
QtProperty *q_ptr;
|
QtProperty *q_ptr;
|
||||||
|
|
||||||
QSet<QtProperty *> m_parentItems;
|
QSet<QtProperty *> m_parentItems;
|
||||||
@ -66,6 +66,7 @@ public:
|
|||||||
QString m_name;
|
QString m_name;
|
||||||
QString m_id;
|
QString m_id;
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
|
bool m_selectable;
|
||||||
bool m_modified;
|
bool m_modified;
|
||||||
|
|
||||||
QtAbstractPropertyManager * const m_manager;
|
QtAbstractPropertyManager * const m_manager;
|
||||||
@ -260,6 +261,11 @@ bool QtProperty::isEnabled() const
|
|||||||
return d_ptr->m_enabled;
|
return d_ptr->m_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QtProperty::isSelectable() const
|
||||||
|
{
|
||||||
|
return d_ptr->m_selectable;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns whether the property is modified.
|
Returns whether the property is modified.
|
||||||
|
|
||||||
@ -409,6 +415,15 @@ void QtProperty::setEnabled(bool enable)
|
|||||||
propertyChanged();
|
propertyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtProperty::setSelectable(bool selectable)
|
||||||
|
{
|
||||||
|
if (d_ptr->m_selectable == selectable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
d_ptr->m_selectable = selectable;
|
||||||
|
propertyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Sets the property's modified state according to the passed \a modified value.
|
Sets the property's modified state according to the passed \a modified value.
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ public:
|
|||||||
QString propertyName() const;
|
QString propertyName() const;
|
||||||
QString propertyId() const;
|
QString propertyId() const;
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
|
bool isSelectable() const;
|
||||||
bool isModified() const;
|
bool isModified() const;
|
||||||
|
|
||||||
bool hasValue() const;
|
bool hasValue() const;
|
||||||
@ -97,6 +98,7 @@ public:
|
|||||||
void setPropertyName(const QString &text);
|
void setPropertyName(const QString &text);
|
||||||
void setPropertyId(const QString &text);
|
void setPropertyId(const QString &text);
|
||||||
void setEnabled(bool enable);
|
void setEnabled(bool enable);
|
||||||
|
void setSelectable(bool selectable);
|
||||||
void setModified(bool modified);
|
void setModified(bool modified);
|
||||||
|
|
||||||
bool isSubProperty()const;
|
bool isSubProperty()const;
|
||||||
|
@ -651,6 +651,11 @@ void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem *item)
|
|||||||
else
|
else
|
||||||
disableItem(item);
|
disableItem(item);
|
||||||
}
|
}
|
||||||
|
if (property->isSelectable()) {
|
||||||
|
item->setFlags(item->flags() | Qt::ItemIsSelectable);
|
||||||
|
} else {
|
||||||
|
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
|
||||||
|
}
|
||||||
m_treeWidget->viewport()->update();
|
m_treeWidget->viewport()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1339,6 +1339,7 @@ void addPropertyRecusively(QtVariantPropertyManager * manager,
|
|||||||
newProp->setWhatsThis(prop->whatsThis());
|
newProp->setWhatsThis(prop->whatsThis());
|
||||||
newProp->setModified(prop->isModified());
|
newProp->setModified(prop->isModified());
|
||||||
newProp->setEnabled(prop->isEnabled());
|
newProp->setEnabled(prop->isEnabled());
|
||||||
|
newProp->setSelectable(prop->isSelectable());
|
||||||
newProp->setValue(prop->value());
|
newProp->setValue(prop->value());
|
||||||
|
|
||||||
foreach(QtProperty * subProp, prop->subProperties())
|
foreach(QtProperty * subProp, prop->subProperties())
|
||||||
|
@ -12,59 +12,63 @@ independent.
|
|||||||
|
|
||||||
Valid commands for the input are as follows.
|
Valid commands for the input are as follows.
|
||||||
|
|
||||||
pre <string>
|
pre \<string\>
|
||||||
------------
|
--------------
|
||||||
|
|
||||||
When a C file is generated as output, all the "pre" strings will be included
|
When a C file is generated as output, all the "pre" strings will be included
|
||||||
before the binary blob.
|
before the binary blob.
|
||||||
|
|
||||||
post <string>
|
post \<string\>
|
||||||
-------------
|
---------------
|
||||||
|
|
||||||
When a C file is generated as output, all the "post" strings will be included
|
When a C file is generated as output, all the "post" strings will be included
|
||||||
after the binary blob.
|
after the binary blob.
|
||||||
|
|
||||||
push <name>
|
push \<name\>
|
||||||
-----------
|
-------------
|
||||||
|
|
||||||
All following commands up until the matching "pop" will be writen to stream
|
All following commands up until the matching "pop" will be writen to stream
|
||||||
<name>. Everything written to the same stream will end up in a continous
|
\<name\>. Everything written to the same stream will end up in a continous
|
||||||
region of the output.
|
region of the output. The statements `pop`, `label`, `ref`, `u8`, `u16`,
|
||||||
|
`u32`, and `str` are only valid within such a block. The name used in the
|
||||||
|
first push statement also determines the name of the variable in the generated
|
||||||
|
C output (when C is selected as output file format).
|
||||||
|
|
||||||
pop
|
pop
|
||||||
---
|
---
|
||||||
|
|
||||||
End of a push..pop block.
|
End of a push..pop block.
|
||||||
|
|
||||||
label <name> [<comment>]
|
label \<name\> \[\<comment\>\]
|
||||||
------------------------
|
------------------------------
|
||||||
|
|
||||||
Add a label for the current position.
|
Add a label for the current position.
|
||||||
|
|
||||||
ref <name> [<comment>]
|
ref \<name\> \[\<comment\>\]
|
||||||
----------------------
|
----------------------------
|
||||||
|
|
||||||
Add a 32-bit reference to the specified label. The reference will be a byte
|
Add a 32-bit reference to the specified label. The reference will be a byte
|
||||||
offset relative to the memory location of the reference itself.
|
offset relative to the memory location of the reference itself.
|
||||||
|
|
||||||
u8 <value> [<comment>]
|
u8 \<value\> \[\<comment\>\]
|
||||||
----------------------
|
----------------------------
|
||||||
|
|
||||||
Add a 8-bit value to the binary blob.
|
Add a 8-bit value to the binary blob.
|
||||||
|
|
||||||
u16 <value> [<comment>]
|
u16 \<value\> \[\<comment\>\]
|
||||||
-----------------------
|
-----------------------------
|
||||||
|
|
||||||
Add a 16-bit value to the binary blob. Note that the input must be structured
|
Add a 16-bit value to the binary blob. Note that the input must be structured
|
||||||
in a way that ensures that all u16 are aligned to 2-byte addresses.
|
in a way that ensures that all u16 are aligned to 2-byte addresses.
|
||||||
|
|
||||||
u32 <value> [<comment>]
|
u32 \<value\> \[\<comment\>\]
|
||||||
----------------------
|
-----------------------------
|
||||||
|
|
||||||
Add a 32-bit value to the binary blob. Note that the input must be structured
|
Add a 32-bit value to the binary blob. Note that the input must be structured
|
||||||
in a way that ensures that all u32 are aligned to 4-byte addresses.
|
in a way that ensures that all u32 are aligned to 4-byte addresses.
|
||||||
|
|
||||||
str <string>
|
str "\<string\>" \[\<comment\>\]
|
||||||
------------
|
--------------------------------
|
||||||
|
|
||||||
Add a reference to a zero-terminated copy of the specified string.
|
Add a reference to a zero-terminated copy of that string. Any character may be
|
||||||
|
used to quote the string, but the most common choices are `"` and `|`.
|
||||||
|
101
bba/main.cc
101
bba/main.cc
@ -52,6 +52,7 @@ std::map<std::string, int> streamIndex;
|
|||||||
std::vector<int> streamStack;
|
std::vector<int> streamStack;
|
||||||
|
|
||||||
std::vector<int> labels;
|
std::vector<int> labels;
|
||||||
|
std::vector<std::string> labelNames;
|
||||||
std::map<std::string, int> labelIndex;
|
std::map<std::string, int> labelIndex;
|
||||||
|
|
||||||
std::vector<std::string> preText, postText;
|
std::vector<std::string> preText, postText;
|
||||||
@ -67,6 +68,7 @@ const char *skipWhitespace(const char *p)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
bool debug = false;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
bool bigEndian = false;
|
bool bigEndian = false;
|
||||||
bool writeC = false;
|
bool writeC = false;
|
||||||
@ -76,6 +78,7 @@ int main(int argc, char **argv)
|
|||||||
po::positional_options_description pos;
|
po::positional_options_description pos;
|
||||||
po::options_description options("Allowed options");
|
po::options_description options("Allowed options");
|
||||||
options.add_options()("v", "verbose output");
|
options.add_options()("v", "verbose output");
|
||||||
|
options.add_options()("d", "debug output");
|
||||||
options.add_options()("b", "big endian");
|
options.add_options()("b", "big endian");
|
||||||
options.add_options()("c", "write c strings");
|
options.add_options()("c", "write c strings");
|
||||||
options.add_options()("files", po::value<std::vector<std::string>>(), "file parameters");
|
options.add_options()("files", po::value<std::vector<std::string>>(), "file parameters");
|
||||||
@ -94,6 +97,8 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (vm.count("v"))
|
if (vm.count("v"))
|
||||||
verbose = true;
|
verbose = true;
|
||||||
|
if (vm.count("d"))
|
||||||
|
debug = true;
|
||||||
if (vm.count("b"))
|
if (vm.count("b"))
|
||||||
bigEndian = true;
|
bigEndian = true;
|
||||||
if (vm.count("c"))
|
if (vm.count("c"))
|
||||||
@ -152,11 +157,13 @@ int main(int argc, char **argv)
|
|||||||
Stream &s = streams.at(streamStack.back());
|
Stream &s = streams.at(streamStack.back());
|
||||||
if (labelIndex.count(label) == 0) {
|
if (labelIndex.count(label) == 0) {
|
||||||
labelIndex[label] = labels.size();
|
labelIndex[label] = labels.size();
|
||||||
|
if (debug)
|
||||||
|
labelNames.push_back(label);
|
||||||
labels.push_back(-1);
|
labels.push_back(-1);
|
||||||
}
|
}
|
||||||
s.tokenTypes.push_back(cmd == "label" ? TOK_LABEL : TOK_REF);
|
s.tokenTypes.push_back(cmd == "label" ? TOK_LABEL : TOK_REF);
|
||||||
s.tokenValues.push_back(labelIndex.at(label));
|
s.tokenValues.push_back(labelIndex.at(label));
|
||||||
if (verbose)
|
if (debug)
|
||||||
s.tokenComments.push_back(comment);
|
s.tokenComments.push_back(comment);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -167,28 +174,41 @@ int main(int argc, char **argv)
|
|||||||
Stream &s = streams.at(streamStack.back());
|
Stream &s = streams.at(streamStack.back());
|
||||||
s.tokenTypes.push_back(cmd == "u8" ? TOK_U8 : cmd == "u16" ? TOK_U16 : TOK_U32);
|
s.tokenTypes.push_back(cmd == "u8" ? TOK_U8 : cmd == "u16" ? TOK_U16 : TOK_U32);
|
||||||
s.tokenValues.push_back(atoll(value));
|
s.tokenValues.push_back(atoll(value));
|
||||||
if (verbose)
|
if (debug)
|
||||||
s.tokenComments.push_back(comment);
|
s.tokenComments.push_back(comment);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd == "str") {
|
if (cmd == "str") {
|
||||||
const char *value = skipWhitespace(strtok(nullptr, "\r\n"));
|
const char *value = skipWhitespace(strtok(nullptr, "\r\n"));
|
||||||
|
char terminator[2] = {*value, 0};
|
||||||
|
assert(terminator[0] != 0);
|
||||||
|
value = strtok((char *)value + 1, terminator);
|
||||||
|
const char *comment = skipWhitespace(strtok(nullptr, "\r\n"));
|
||||||
std::string label = std::string("str:") + value;
|
std::string label = std::string("str:") + value;
|
||||||
Stream &s = streams.at(streamStack.back());
|
Stream &s = streams.at(streamStack.back());
|
||||||
if (labelIndex.count(label) == 0) {
|
if (labelIndex.count(label) == 0) {
|
||||||
labelIndex[label] = labels.size();
|
labelIndex[label] = labels.size();
|
||||||
|
if (debug)
|
||||||
|
labelNames.push_back(label);
|
||||||
labels.push_back(-1);
|
labels.push_back(-1);
|
||||||
}
|
}
|
||||||
s.tokenTypes.push_back(TOK_REF);
|
s.tokenTypes.push_back(TOK_REF);
|
||||||
s.tokenValues.push_back(labelIndex.at(label));
|
s.tokenValues.push_back(labelIndex.at(label));
|
||||||
if (verbose)
|
if (debug)
|
||||||
s.tokenComments.push_back(value);
|
s.tokenComments.push_back(comment);
|
||||||
stringStream.tokenTypes.push_back(TOK_LABEL);
|
stringStream.tokenTypes.push_back(TOK_LABEL);
|
||||||
stringStream.tokenValues.push_back(labelIndex.at(label));
|
stringStream.tokenValues.push_back(labelIndex.at(label));
|
||||||
|
stringStream.tokenComments.push_back("");
|
||||||
while (1) {
|
while (1) {
|
||||||
stringStream.tokenTypes.push_back(TOK_U8);
|
stringStream.tokenTypes.push_back(TOK_U8);
|
||||||
stringStream.tokenValues.push_back(*value);
|
stringStream.tokenValues.push_back(*value);
|
||||||
|
if (debug) {
|
||||||
|
char char_comment[4] = {'\'', *value, '\'', 0};
|
||||||
|
if (*value < 32 || *value >= 127)
|
||||||
|
char_comment[0] = 0;
|
||||||
|
stringStream.tokenComments.push_back(char_comment);
|
||||||
|
}
|
||||||
if (*value == 0)
|
if (*value == 0)
|
||||||
break;
|
break;
|
||||||
value++;
|
value++;
|
||||||
@ -208,8 +228,10 @@ int main(int argc, char **argv)
|
|||||||
assert(!streams.empty());
|
assert(!streams.empty());
|
||||||
assert(streamStack.empty());
|
assert(streamStack.empty());
|
||||||
streams.push_back(Stream());
|
streams.push_back(Stream());
|
||||||
|
streams.back().name = "strings";
|
||||||
streams.back().tokenTypes.swap(stringStream.tokenTypes);
|
streams.back().tokenTypes.swap(stringStream.tokenTypes);
|
||||||
streams.back().tokenValues.swap(stringStream.tokenValues);
|
streams.back().tokenValues.swap(stringStream.tokenValues);
|
||||||
|
streams.back().tokenComments.swap(stringStream.tokenComments);
|
||||||
|
|
||||||
int cursor = 0;
|
int cursor = 0;
|
||||||
for (auto &s : streams) {
|
for (auto &s : streams) {
|
||||||
@ -247,6 +269,9 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
for (auto &s : streams) {
|
for (auto &s : streams) {
|
||||||
|
if (debug)
|
||||||
|
printf("-- %s --\n", s.name.c_str());
|
||||||
|
|
||||||
for (int i = 0; i < int(s.tokenTypes.size()); i++) {
|
for (int i = 0; i < int(s.tokenTypes.size()); i++) {
|
||||||
uint32_t value = s.tokenValues[i];
|
uint32_t value = s.tokenValues[i];
|
||||||
int numBytes = 0;
|
int numBytes = 0;
|
||||||
@ -276,13 +301,13 @@ int main(int argc, char **argv)
|
|||||||
case 4:
|
case 4:
|
||||||
data[cursor++] = value >> 24;
|
data[cursor++] = value >> 24;
|
||||||
data[cursor++] = value >> 16;
|
data[cursor++] = value >> 16;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case 2:
|
case 2:
|
||||||
data[cursor++] = value >> 8;
|
data[cursor++] = value >> 8;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case 1:
|
case 1:
|
||||||
data[cursor++] = value;
|
data[cursor++] = value;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -293,13 +318,13 @@ int main(int argc, char **argv)
|
|||||||
case 4:
|
case 4:
|
||||||
data[cursor + 3] = value >> 24;
|
data[cursor + 3] = value >> 24;
|
||||||
data[cursor + 2] = value >> 16;
|
data[cursor + 2] = value >> 16;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case 2:
|
case 2:
|
||||||
data[cursor + 1] = value >> 8;
|
data[cursor + 1] = value >> 8;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case 1:
|
case 1:
|
||||||
data[cursor] = value;
|
data[cursor] = value;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -307,6 +332,51 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
cursor += numBytes;
|
cursor += numBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
printf("%08x ", cursor - numBytes);
|
||||||
|
for (int k = cursor - numBytes; k < cursor; k++)
|
||||||
|
printf("%02x ", data[k]);
|
||||||
|
for (int k = numBytes; k < 4; k++)
|
||||||
|
printf(" ");
|
||||||
|
|
||||||
|
unsigned long long v = s.tokenValues[i];
|
||||||
|
|
||||||
|
switch (s.tokenTypes[i]) {
|
||||||
|
case TOK_LABEL:
|
||||||
|
if (s.tokenComments[i].empty())
|
||||||
|
printf("label %s\n", labelNames[v].c_str());
|
||||||
|
else
|
||||||
|
printf("label %-24s %s\n", labelNames[v].c_str(), s.tokenComments[i].c_str());
|
||||||
|
break;
|
||||||
|
case TOK_REF:
|
||||||
|
if (s.tokenComments[i].empty())
|
||||||
|
printf("ref %s %s\n", labelNames[v].c_str());
|
||||||
|
else
|
||||||
|
printf("ref %-26s %s\n", labelNames[v].c_str(), s.tokenComments[i].c_str());
|
||||||
|
break;
|
||||||
|
case TOK_U8:
|
||||||
|
if (s.tokenComments[i].empty())
|
||||||
|
printf("u8 %llu\n", v);
|
||||||
|
else
|
||||||
|
printf("u8 %-27llu %s\n", v, s.tokenComments[i].c_str());
|
||||||
|
break;
|
||||||
|
case TOK_U16:
|
||||||
|
if (s.tokenComments[i].empty())
|
||||||
|
printf("u16 %-26llu\n", v);
|
||||||
|
else
|
||||||
|
printf("u16 %-26llu %s\n", v, s.tokenComments[i].c_str());
|
||||||
|
break;
|
||||||
|
case TOK_U32:
|
||||||
|
if (s.tokenComments[i].empty())
|
||||||
|
printf("u32 %-26llu\n", v);
|
||||||
|
else
|
||||||
|
printf("u32 %-26llu %s\n", v, s.tokenComments[i].c_str());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +389,8 @@ int main(int argc, char **argv)
|
|||||||
fprintf(fileOut, "const char %s[%d] =\n\"", streams[0].name.c_str(), int(data.size()) + 1);
|
fprintf(fileOut, "const char %s[%d] =\n\"", streams[0].name.c_str(), int(data.size()) + 1);
|
||||||
|
|
||||||
cursor = 1;
|
cursor = 1;
|
||||||
for (auto d : data) {
|
for (int i = 0; i < int(data.size()); i++) {
|
||||||
|
auto d = data[i];
|
||||||
if (cursor > 70) {
|
if (cursor > 70) {
|
||||||
fputc('\"', fileOut);
|
fputc('\"', fileOut);
|
||||||
fputc('\n', fileOut);
|
fputc('\n', fileOut);
|
||||||
@ -329,9 +400,11 @@ int main(int argc, char **argv)
|
|||||||
fputc('\"', fileOut);
|
fputc('\"', fileOut);
|
||||||
cursor = 1;
|
cursor = 1;
|
||||||
}
|
}
|
||||||
if (d < 32 || d >= 128) {
|
if (d < 32 || d >= 127) {
|
||||||
fprintf(fileOut, "\\%03o", int(d));
|
if (i + 1 < int(data.size()) && (data[i + 1] < '0' || '9' < data[i + 1]))
|
||||||
cursor += 4;
|
cursor += fprintf(fileOut, "\\%o", int(d));
|
||||||
|
else
|
||||||
|
cursor += fprintf(fileOut, "\\%03o", int(d));
|
||||||
} else if (d == '\"' || d == '\'' || d == '\\') {
|
} else if (d == '\"' || d == '\'' || d == '\\') {
|
||||||
fputc('\\', fileOut);
|
fputc('\\', fileOut);
|
||||||
fputc(d, fileOut);
|
fputc(d, fileOut);
|
||||||
|
@ -155,10 +155,10 @@ struct GraphicElement
|
|||||||
|
|
||||||
enum style_t
|
enum style_t
|
||||||
{
|
{
|
||||||
G_FRAME,
|
G_FRAME, // Static "frame". Contrast between G_INACTIVE and G_ACTIVE
|
||||||
G_HIDDEN,
|
G_HIDDEN, // Only display when object is selected or highlighted
|
||||||
G_INACTIVE,
|
G_INACTIVE, // Render using low-contrast color
|
||||||
G_ACTIVE,
|
G_ACTIVE, // Render using high-contast color
|
||||||
} style = G_FRAME;
|
} style = G_FRAME;
|
||||||
|
|
||||||
float x1 = 0, y1 = 0, x2 = 0, y2 = 0, z = 0;
|
float x1 = 0, y1 = 0, x2 = 0, y2 = 0, z = 0;
|
||||||
@ -276,11 +276,11 @@ struct CellInfo : ArchCellInfo
|
|||||||
|
|
||||||
// placement constraints
|
// placement constraints
|
||||||
CellInfo *constr_parent;
|
CellInfo *constr_parent;
|
||||||
std::vector<CellInfo*> constr_children;
|
std::vector<CellInfo *> constr_children;
|
||||||
const int UNCONSTR = INT_MIN;
|
const int UNCONSTR = INT_MIN;
|
||||||
int constr_x = UNCONSTR; // this.x - parent.x
|
int constr_x = UNCONSTR; // this.x - parent.x
|
||||||
int constr_y = UNCONSTR; // this.y - parent.y
|
int constr_y = UNCONSTR; // this.y - parent.y
|
||||||
int constr_z = UNCONSTR; // this.z - parent.z
|
int constr_z = UNCONSTR; // this.z - parent.z
|
||||||
bool constr_abs_z = false; // parent.z := 0
|
bool constr_abs_z = false; // parent.z := 0
|
||||||
// parent.[xyz] := 0 when (constr_parent == nullptr)
|
// parent.[xyz] := 0 when (constr_parent == nullptr)
|
||||||
};
|
};
|
||||||
|
@ -810,14 +810,14 @@ bool router1(Context *ctx)
|
|||||||
log_info("Checksum: 0x%08x\n", ctx->checksum());
|
log_info("Checksum: 0x%08x\n", ctx->checksum());
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
ctx->check();
|
ctx->check();
|
||||||
ctx->unlock();
|
|
||||||
#endif
|
#endif
|
||||||
|
ctx->unlock();
|
||||||
return true;
|
return true;
|
||||||
} catch (log_execution_error_exception) {
|
} catch (log_execution_error_exception) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
ctx->check();
|
ctx->check();
|
||||||
ctx->unlock();
|
|
||||||
#endif
|
#endif
|
||||||
|
ctx->unlock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,7 +328,8 @@ BelId Arch::getPackagePinBel(const std::string &pin) const
|
|||||||
std::string Arch::getBelPackagePin(BelId bel) const
|
std::string Arch::getBelPackagePin(BelId bel) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < package_info->num_pins; i++) {
|
for (int i = 0; i < package_info->num_pins; i++) {
|
||||||
if (package_info->pin_data[i].abs_loc == bel.location && package_info->pin_data[i].bel_index == bel.index) {
|
if (Location(package_info->pin_data[i].abs_loc) == bel.location &&
|
||||||
|
package_info->pin_data[i].bel_index == bel.index) {
|
||||||
return package_info->pin_data[i].name.get();
|
return package_info->pin_data[i].name.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,7 +339,7 @@ std::string Arch::getBelPackagePin(BelId bel) const
|
|||||||
int Arch::getPioBelBank(BelId bel) const
|
int Arch::getPioBelBank(BelId bel) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < chip_info->num_pios; i++) {
|
for (int i = 0; i < chip_info->num_pios; i++) {
|
||||||
if (chip_info->pio_info[i].abs_loc == bel.location && chip_info->pio_info[i].bel_index == bel.index) {
|
if (Location(chip_info->pio_info[i].abs_loc) == bel.location && chip_info->pio_info[i].bel_index == bel.index) {
|
||||||
return chip_info->pio_info[i].bank;
|
return chip_info->pio_info[i].bank;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -348,7 +349,7 @@ int Arch::getPioBelBank(BelId bel) const
|
|||||||
std::string Arch::getPioFunctionName(BelId bel) const
|
std::string Arch::getPioFunctionName(BelId bel) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < chip_info->num_pios; i++) {
|
for (int i = 0; i < chip_info->num_pios; i++) {
|
||||||
if (chip_info->pio_info[i].abs_loc == bel.location && chip_info->pio_info[i].bel_index == bel.index) {
|
if (Location(chip_info->pio_info[i].abs_loc) == bel.location && chip_info->pio_info[i].bel_index == bel.index) {
|
||||||
const char *func = chip_info->pio_info[i].function_name.get();
|
const char *func = chip_info->pio_info[i].function_name.get();
|
||||||
if (func == nullptr)
|
if (func == nullptr)
|
||||||
return "";
|
return "";
|
||||||
|
29
ecp5/arch.h
29
ecp5/arch.h
@ -98,7 +98,7 @@ NPNR_PACKED_STRUCT(struct LocationTypePOD {
|
|||||||
});
|
});
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct PIOInfoPOD {
|
NPNR_PACKED_STRUCT(struct PIOInfoPOD {
|
||||||
Location abs_loc;
|
LocationPOD abs_loc;
|
||||||
int32_t bel_index;
|
int32_t bel_index;
|
||||||
RelPtr<char> function_name;
|
RelPtr<char> function_name;
|
||||||
int16_t bank;
|
int16_t bank;
|
||||||
@ -107,7 +107,7 @@ NPNR_PACKED_STRUCT(struct PIOInfoPOD {
|
|||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct PackagePinPOD {
|
NPNR_PACKED_STRUCT(struct PackagePinPOD {
|
||||||
RelPtr<char> name;
|
RelPtr<char> name;
|
||||||
Location abs_loc;
|
LocationPOD abs_loc;
|
||||||
int32_t bel_index;
|
int32_t bel_index;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -117,6 +117,26 @@ NPNR_PACKED_STRUCT(struct PackageInfoPOD {
|
|||||||
RelPtr<PackagePinPOD> pin_data;
|
RelPtr<PackagePinPOD> pin_data;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
enum TapDirection : int8_t
|
||||||
|
{
|
||||||
|
TAP_DIR_LEFT = 0,
|
||||||
|
TAP_DIR_RIGHT = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GlobalQuadrant : int8_t
|
||||||
|
{
|
||||||
|
QUAD_UL = 0,
|
||||||
|
QUAD_UR = 1,
|
||||||
|
QUAD_LL = 2,
|
||||||
|
QUAD_LR = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
NPNR_PACKED_STRUCT(struct GlobalInfoPOD {
|
||||||
|
int16_t tap_col;
|
||||||
|
TapDirection tap_dir;
|
||||||
|
GlobalQuadrant quad;
|
||||||
|
});
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
||||||
int32_t width, height;
|
int32_t width, height;
|
||||||
int32_t num_tiles;
|
int32_t num_tiles;
|
||||||
@ -124,6 +144,7 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
|||||||
int32_t num_packages, num_pios;
|
int32_t num_packages, num_pios;
|
||||||
RelPtr<LocationTypePOD> locations;
|
RelPtr<LocationTypePOD> locations;
|
||||||
RelPtr<int32_t> location_type;
|
RelPtr<int32_t> location_type;
|
||||||
|
RelPtr<GlobalInfoPOD> location_glbinfo;
|
||||||
RelPtr<RelPtr<char>> tiletype_names;
|
RelPtr<RelPtr<char>> tiletype_names;
|
||||||
RelPtr<PackageInfoPOD> package_info;
|
RelPtr<PackageInfoPOD> package_info;
|
||||||
RelPtr<PIOInfoPOD> pio_info;
|
RelPtr<PIOInfoPOD> pio_info;
|
||||||
@ -517,6 +538,8 @@ struct Arch : BaseCtx
|
|||||||
return id(name.str());
|
return id(name.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdString getWireType(WireId wire) const { return IdString(); }
|
||||||
|
|
||||||
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
|
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
|
||||||
|
|
||||||
void bindWire(WireId wire, IdString net, PlaceStrength strength)
|
void bindWire(WireId wire, IdString net, PlaceStrength strength)
|
||||||
@ -595,6 +618,8 @@ struct Arch : BaseCtx
|
|||||||
PipId getPipByName(IdString name) const;
|
PipId getPipByName(IdString name) const;
|
||||||
IdString getPipName(PipId pip) const;
|
IdString getPipName(PipId pip) const;
|
||||||
|
|
||||||
|
IdString getPipType(PipId pip) const { return IdString(); }
|
||||||
|
|
||||||
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
|
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
|
||||||
|
|
||||||
void bindPip(PipId pip, IdString net, PlaceStrength strength)
|
void bindPip(PipId pip, IdString net, PlaceStrength strength)
|
||||||
|
@ -280,8 +280,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
|||||||
other = "PIOD";
|
other = "PIOD";
|
||||||
else
|
else
|
||||||
log_error("cannot place differential IO at location %s\n", pio.c_str());
|
log_error("cannot place differential IO at location %s\n", pio.c_str());
|
||||||
//cc.tiles[pio_tile].add_enum(other + ".BASE_TYPE", "_NONE_");
|
// cc.tiles[pio_tile].add_enum(other + ".BASE_TYPE", "_NONE_");
|
||||||
//cc.tiles[pic_tile].add_enum(other + ".BASE_TYPE", "_NONE_");
|
// cc.tiles[pic_tile].add_enum(other + ".BASE_TYPE", "_NONE_");
|
||||||
cc.tiles[pio_tile].add_enum(other + ".PULLMODE", "NONE");
|
cc.tiles[pio_tile].add_enum(other + ".PULLMODE", "NONE");
|
||||||
cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE");
|
cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE");
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,16 @@ if (MSVC)
|
|||||||
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ecp5/resources/chipdb.rc PROPERTIES LANGUAGE RC)
|
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ecp5/resources/chipdb.rc PROPERTIES LANGUAGE RC)
|
||||||
foreach (dev ${devices})
|
foreach (dev ${devices})
|
||||||
set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ecp5/chipdbs/chipdb-${dev}.bin)
|
set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ecp5/chipdbs/chipdb-${dev}.bin)
|
||||||
|
set(DEV_CC_BBA_DB ${CMAKE_CURRENT_SOURCE_DIR}/ecp5/chipdbs/chipdb-${dev}.bba)
|
||||||
set(DEV_PORTS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ecp5/portpins.inc)
|
set(DEV_PORTS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ecp5/portpins.inc)
|
||||||
add_custom_command(OUTPUT ${DEV_CC_DB}
|
add_custom_command(OUTPUT ${DEV_CC_BBA_DB}
|
||||||
COMMAND ${ENV_CMD} python3 ${DB_PY} -b -p ${DEV_PORTS_INC} ${dev} ${DEV_CC_DB}
|
COMMAND ${ENV_CMD} python3 ${DB_PY} -p ${DEV_PORTS_INC} ${dev} > ${DEV_CC_BBA_DB}
|
||||||
DEPENDS ${DB_PY}
|
DEPENDS ${DB_PY}
|
||||||
)
|
)
|
||||||
|
add_custom_command(OUTPUT ${DEV_CC_DB}
|
||||||
|
COMMAND bbasm ${DEV_CC_BBA_DB} ${DEV_CC_DB}
|
||||||
|
DEPENDS bbasm ${DEV_CC_BBA_DB}
|
||||||
|
)
|
||||||
target_sources(ecp5_chipdb PRIVATE ${DEV_CC_DB})
|
target_sources(ecp5_chipdb PRIVATE ${DEV_CC_DB})
|
||||||
set_source_files_properties(${DEV_CC_DB} PROPERTIES HEADER_FILE_ONLY TRUE)
|
set_source_files_properties(${DEV_CC_DB} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||||
foreach (target ${family_targets})
|
foreach (target ${family_targets})
|
||||||
@ -39,11 +44,18 @@ else()
|
|||||||
target_compile_options(ecp5_chipdb PRIVATE -g0 -O0 -w)
|
target_compile_options(ecp5_chipdb PRIVATE -g0 -O0 -w)
|
||||||
foreach (dev ${devices})
|
foreach (dev ${devices})
|
||||||
set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ecp5/chipdbs/chipdb-${dev}.cc)
|
set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ecp5/chipdbs/chipdb-${dev}.cc)
|
||||||
|
set(DEV_CC_BBA_DB ${CMAKE_CURRENT_SOURCE_DIR}/ecp5/chipdbs/chipdb-${dev}.bba)
|
||||||
set(DEV_PORTS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ecp5/portpins.inc)
|
set(DEV_PORTS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ecp5/portpins.inc)
|
||||||
add_custom_command(OUTPUT ${DEV_CC_DB}
|
add_custom_command(OUTPUT ${DEV_CC_BBA_DB}
|
||||||
COMMAND ${ENV_CMD} python3 ${DB_PY} -c -p ${DEV_PORTS_INC} ${dev} ${DEV_CC_DB}
|
COMMAND ${ENV_CMD} python3 ${DB_PY} -p ${DEV_PORTS_INC} ${dev} > ${DEV_CC_BBA_DB}.new
|
||||||
|
COMMAND mv ${DEV_CC_BBA_DB}.new ${DEV_CC_BBA_DB}
|
||||||
DEPENDS ${DB_PY}
|
DEPENDS ${DB_PY}
|
||||||
)
|
)
|
||||||
|
add_custom_command(OUTPUT ${DEV_CC_DB}
|
||||||
|
COMMAND bbasm --c ${DEV_CC_BBA_DB} ${DEV_CC_DB}.new
|
||||||
|
COMMAND mv ${DEV_CC_DB}.new ${DEV_CC_DB}
|
||||||
|
DEPENDS bbasm ${DEV_CC_BBA_DB}
|
||||||
|
)
|
||||||
target_sources(ecp5_chipdb PRIVATE ${DEV_CC_DB})
|
target_sources(ecp5_chipdb PRIVATE ${DEV_CC_DB})
|
||||||
foreach (target ${family_targets})
|
foreach (target ${family_targets})
|
||||||
target_sources(${target} PRIVATE $<TARGET_OBJECTS:ecp5_chipdb>)
|
target_sources(${target} PRIVATE $<TARGET_OBJECTS:ecp5_chipdb>)
|
||||||
|
10
ecp5/main.cc
10
ecp5/main.cc
@ -100,18 +100,16 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("help") || argc == 1) {
|
if (vm.count("help") || argc == 1) {
|
||||||
std::cout << boost::filesystem::basename(argv[0])
|
std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git "
|
||||||
<< " -- Next Generation Place and Route (git "
|
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
std::cout << options << "\n";
|
std::cout << options << "\n";
|
||||||
return argc != 1;
|
return argc != 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("version")) {
|
if (vm.count("version")) {
|
||||||
std::cout << boost::filesystem::basename(argv[0])
|
std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git "
|
||||||
<< " -- Next Generation Place and Route (git "
|
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,11 +10,7 @@ type_at_location = dict()
|
|||||||
tiletype_names = dict()
|
tiletype_names = dict()
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="import ECP5 routing and bels from Project Trellis")
|
parser = argparse.ArgumentParser(description="import ECP5 routing and bels from Project Trellis")
|
||||||
group = parser.add_mutually_exclusive_group()
|
|
||||||
group.add_argument("-b", "--binary", action="store_true")
|
|
||||||
group.add_argument("-c", "--c_file", action="store_true")
|
|
||||||
parser.add_argument("device", type=str, help="target device")
|
parser.add_argument("device", type=str, help="target device")
|
||||||
parser.add_argument("outfile", type=argparse.FileType('w'), help="output filename")
|
|
||||||
parser.add_argument("-p", "--portspins", type=str, help="path to portpins.inc")
|
parser.add_argument("-p", "--portspins", type=str, help="path to portpins.inc")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@ -36,284 +32,50 @@ portpins = dict()
|
|||||||
|
|
||||||
|
|
||||||
class BinaryBlobAssembler:
|
class BinaryBlobAssembler:
|
||||||
def __init__(self, cname, endianness, nodebug=False):
|
def l(self, name, ltype = None, export = False):
|
||||||
assert endianness in ["le", "be"]
|
if ltype is None:
|
||||||
self.cname = cname
|
print("label %s" % (name,))
|
||||||
self.endianness = endianness
|
else:
|
||||||
self.finalized = False
|
print("label %s %s" % (name, ltype))
|
||||||
self.data = bytearray()
|
|
||||||
self.comments = dict()
|
|
||||||
self.labels = dict()
|
|
||||||
self.exports = set()
|
|
||||||
self.labels_byaddr = dict()
|
|
||||||
self.ltypes_byaddr = dict()
|
|
||||||
self.strings = dict()
|
|
||||||
self.refs = dict()
|
|
||||||
self.nodebug = nodebug
|
|
||||||
|
|
||||||
def l(self, name, ltype=None, export=False):
|
|
||||||
assert not self.finalized
|
|
||||||
assert name not in self.labels
|
|
||||||
assert len(self.data) not in self.labels_byaddr
|
|
||||||
self.labels[name] = len(self.data)
|
|
||||||
if ltype is not None:
|
|
||||||
self.ltypes_byaddr[len(self.data)] = ltype
|
|
||||||
self.labels_byaddr[len(self.data)] = name
|
|
||||||
if export:
|
|
||||||
assert ltype is not None
|
|
||||||
self.exports.add(len(self.data))
|
|
||||||
|
|
||||||
def r(self, name, comment):
|
def r(self, name, comment):
|
||||||
assert not self.finalized
|
if comment is None:
|
||||||
assert len(self.data) % 4 == 0
|
print("ref %s" % (name,))
|
||||||
assert len(self.data) not in self.refs
|
else:
|
||||||
if self.nodebug:
|
print("ref %s %s" % (name, comment))
|
||||||
comment = None
|
|
||||||
if name is not None:
|
|
||||||
self.refs[len(self.data)] = (name, comment)
|
|
||||||
self.data.append(0)
|
|
||||||
self.data.append(0)
|
|
||||||
self.data.append(0)
|
|
||||||
self.data.append(0)
|
|
||||||
if (name is None) and (comment is not None):
|
|
||||||
self.comments[len(self.data)] = comment + " (null reference)"
|
|
||||||
|
|
||||||
def s(self, s, comment):
|
def s(self, s, comment):
|
||||||
assert not self.finalized
|
print("str %s" % s)
|
||||||
if self.nodebug:
|
|
||||||
comment = None
|
|
||||||
if s not in self.strings:
|
|
||||||
index = len(self.strings)
|
|
||||||
self.strings[s] = index
|
|
||||||
else:
|
|
||||||
index = self.strings[s]
|
|
||||||
if comment is not None:
|
|
||||||
self.r("str%d" % index, '%s: "%s"' % (comment, s))
|
|
||||||
else:
|
|
||||||
self.r("str%d" % index, None)
|
|
||||||
|
|
||||||
def u8(self, v, comment):
|
def u8(self, v, comment):
|
||||||
assert not self.finalized
|
if comment is None:
|
||||||
if self.nodebug:
|
print("u8 %d" % (v,))
|
||||||
comment = None
|
else:
|
||||||
self.data.append(v)
|
print("u8 %d %s" % (v, comment))
|
||||||
if comment is not None:
|
|
||||||
self.comments[len(self.data)] = comment
|
|
||||||
|
|
||||||
def u16(self, v, comment):
|
def u16(self, v, comment):
|
||||||
assert not self.finalized
|
if comment is None:
|
||||||
assert len(self.data) % 2 == 0
|
print("u16 %d" % (v,))
|
||||||
if self.nodebug:
|
|
||||||
comment = None
|
|
||||||
if self.endianness == "le":
|
|
||||||
self.data.append(v & 255)
|
|
||||||
self.data.append((v >> 8) & 255)
|
|
||||||
elif self.endianness == "be":
|
|
||||||
self.data.append((v >> 8) & 255)
|
|
||||||
self.data.append(v & 255)
|
|
||||||
else:
|
else:
|
||||||
assert 0
|
print("u16 %d %s" % (v, comment))
|
||||||
if comment is not None:
|
|
||||||
self.comments[len(self.data)] = comment
|
|
||||||
|
|
||||||
def s16(self, v, comment):
|
|
||||||
assert not self.finalized
|
|
||||||
assert len(self.data) % 2 == 0
|
|
||||||
if self.nodebug:
|
|
||||||
comment = None
|
|
||||||
c2val = (((-v) ^ 0xffff) + 1) if v < 0 else v
|
|
||||||
if self.endianness == "le":
|
|
||||||
self.data.append(c2val & 255)
|
|
||||||
self.data.append((c2val >> 8) & 255)
|
|
||||||
elif self.endianness == "be":
|
|
||||||
self.data.append((c2val >> 8) & 255)
|
|
||||||
self.data.append(c2val & 255)
|
|
||||||
else:
|
|
||||||
assert 0
|
|
||||||
if comment is not None:
|
|
||||||
self.comments[len(self.data)] = comment
|
|
||||||
|
|
||||||
def u32(self, v, comment):
|
def u32(self, v, comment):
|
||||||
assert not self.finalized
|
if comment is None:
|
||||||
assert len(self.data) % 4 == 0
|
print("u32 %d" % (v,))
|
||||||
if self.nodebug:
|
|
||||||
comment = None
|
|
||||||
if self.endianness == "le":
|
|
||||||
self.data.append(v & 255)
|
|
||||||
self.data.append((v >> 8) & 255)
|
|
||||||
self.data.append((v >> 16) & 255)
|
|
||||||
self.data.append((v >> 24) & 255)
|
|
||||||
elif self.endianness == "be":
|
|
||||||
self.data.append((v >> 24) & 255)
|
|
||||||
self.data.append((v >> 16) & 255)
|
|
||||||
self.data.append((v >> 8) & 255)
|
|
||||||
self.data.append(v & 255)
|
|
||||||
else:
|
else:
|
||||||
assert 0
|
print("u32 %d %s" % (v, comment))
|
||||||
if comment is not None:
|
|
||||||
self.comments[len(self.data)] = comment
|
|
||||||
|
|
||||||
def finalize(self):
|
def pre(self, s):
|
||||||
assert not self.finalized
|
print("pre %s" % s)
|
||||||
for s, index in sorted(self.strings.items()):
|
|
||||||
self.l("str%d" % index, "char")
|
|
||||||
for c in s:
|
|
||||||
self.data.append(ord(c))
|
|
||||||
self.data.append(0)
|
|
||||||
self.finalized = True
|
|
||||||
cursor = 0
|
|
||||||
while cursor < len(self.data):
|
|
||||||
if cursor in self.refs:
|
|
||||||
v = self.labels[self.refs[cursor][0]] - cursor
|
|
||||||
if self.endianness == "le":
|
|
||||||
self.data[cursor + 0] = (v & 255)
|
|
||||||
self.data[cursor + 1] = ((v >> 8) & 255)
|
|
||||||
self.data[cursor + 2] = ((v >> 16) & 255)
|
|
||||||
self.data[cursor + 3] = ((v >> 24) & 255)
|
|
||||||
elif self.endianness == "be":
|
|
||||||
self.data[cursor + 0] = ((v >> 24) & 255)
|
|
||||||
self.data[cursor + 1] = ((v >> 16) & 255)
|
|
||||||
self.data[cursor + 2] = ((v >> 8) & 255)
|
|
||||||
self.data[cursor + 3] = (v & 255)
|
|
||||||
else:
|
|
||||||
assert 0
|
|
||||||
cursor += 4
|
|
||||||
else:
|
|
||||||
cursor += 1
|
|
||||||
|
|
||||||
def write_verbose_c(self, f, ctype="const unsigned char"):
|
def post(self, s):
|
||||||
assert self.finalized
|
print("post %s" % s)
|
||||||
print("%s %s[%d] = {" % (ctype, self.cname, len(self.data)), file=f)
|
|
||||||
cursor = 0
|
|
||||||
bytecnt = 0
|
|
||||||
while cursor < len(self.data):
|
|
||||||
if cursor in self.comments:
|
|
||||||
if bytecnt == 0:
|
|
||||||
print(" ", end="", file=f)
|
|
||||||
print(" // %s" % self.comments[cursor], file=f)
|
|
||||||
bytecnt = 0
|
|
||||||
if cursor in self.labels_byaddr:
|
|
||||||
if bytecnt != 0:
|
|
||||||
print(file=f)
|
|
||||||
if cursor in self.exports:
|
|
||||||
print("#define %s ((%s*)(%s+%d))" % (
|
|
||||||
self.labels_byaddr[cursor], self.ltypes_byaddr[cursor], self.cname, cursor), file=f)
|
|
||||||
else:
|
|
||||||
print(" // [%d] %s" % (cursor, self.labels_byaddr[cursor]), file=f)
|
|
||||||
bytecnt = 0
|
|
||||||
if cursor in self.refs:
|
|
||||||
if bytecnt != 0:
|
|
||||||
print(file=f)
|
|
||||||
print(" ", end="", file=f)
|
|
||||||
print(" %-4s" % ("%d," % self.data[cursor + 0]), end="", file=f)
|
|
||||||
print(" %-4s" % ("%d," % self.data[cursor + 1]), end="", file=f)
|
|
||||||
print(" %-4s" % ("%d," % self.data[cursor + 2]), end="", file=f)
|
|
||||||
print(" %-4s" % ("%d," % self.data[cursor + 3]), end="", file=f)
|
|
||||||
print(" // [%d] %s (reference to %s)" % (cursor, self.refs[cursor][1], self.refs[cursor][0]), file=f)
|
|
||||||
bytecnt = 0
|
|
||||||
cursor += 4
|
|
||||||
else:
|
|
||||||
if bytecnt == 0:
|
|
||||||
print(" ", end="", file=f)
|
|
||||||
print(" %-4s" % ("%d," % self.data[cursor]), end=("" if bytecnt < 15 else "\n"), file=f)
|
|
||||||
bytecnt = (bytecnt + 1) & 15
|
|
||||||
cursor += 1
|
|
||||||
if bytecnt != 0:
|
|
||||||
print(file=f)
|
|
||||||
print("};", file=f)
|
|
||||||
|
|
||||||
def write_compact_c(self, f, ctype="const unsigned char"):
|
def push(self, name):
|
||||||
assert self.finalized
|
print("push %s" % name)
|
||||||
print("%s %s[%d] = {" % (ctype, self.cname, len(self.data)), file=f)
|
|
||||||
column = 0
|
|
||||||
for v in self.data:
|
|
||||||
if column == 0:
|
|
||||||
print(" ", end="", file=f)
|
|
||||||
column += 2
|
|
||||||
s = "%d," % v
|
|
||||||
print(s, end="", file=f)
|
|
||||||
column += len(s)
|
|
||||||
if column > 75:
|
|
||||||
print(file=f)
|
|
||||||
column = 0
|
|
||||||
if column != 0:
|
|
||||||
print(file=f)
|
|
||||||
for cursor in self.exports:
|
|
||||||
print("#define %s ((%s*)(%s+%d))" % (
|
|
||||||
self.labels_byaddr[cursor], self.ltypes_byaddr[cursor], self.cname, cursor), file=f)
|
|
||||||
print("};", file=f)
|
|
||||||
|
|
||||||
def write_uint64_c(self, f, ctype="const uint64_t"):
|
|
||||||
assert self.finalized
|
|
||||||
print("%s %s[%d] = {" % (ctype, self.cname, (len(self.data) + 7) // 8), file=f)
|
|
||||||
column = 0
|
|
||||||
for i in range((len(self.data) + 7) // 8):
|
|
||||||
v0 = self.data[8 * i + 0] if 8 * i + 0 < len(self.data) else 0
|
|
||||||
v1 = self.data[8 * i + 1] if 8 * i + 1 < len(self.data) else 0
|
|
||||||
v2 = self.data[8 * i + 2] if 8 * i + 2 < len(self.data) else 0
|
|
||||||
v3 = self.data[8 * i + 3] if 8 * i + 3 < len(self.data) else 0
|
|
||||||
v4 = self.data[8 * i + 4] if 8 * i + 4 < len(self.data) else 0
|
|
||||||
v5 = self.data[8 * i + 5] if 8 * i + 5 < len(self.data) else 0
|
|
||||||
v6 = self.data[8 * i + 6] if 8 * i + 6 < len(self.data) else 0
|
|
||||||
v7 = self.data[8 * i + 7] if 8 * i + 7 < len(self.data) else 0
|
|
||||||
if self.endianness == "le":
|
|
||||||
v = v0 << 0
|
|
||||||
v |= v1 << 8
|
|
||||||
v |= v2 << 16
|
|
||||||
v |= v3 << 24
|
|
||||||
v |= v4 << 32
|
|
||||||
v |= v5 << 40
|
|
||||||
v |= v6 << 48
|
|
||||||
v |= v7 << 56
|
|
||||||
elif self.endianness == "be":
|
|
||||||
v = v7 << 0
|
|
||||||
v |= v6 << 8
|
|
||||||
v |= v5 << 16
|
|
||||||
v |= v4 << 24
|
|
||||||
v |= v3 << 32
|
|
||||||
v |= v2 << 40
|
|
||||||
v |= v1 << 48
|
|
||||||
v |= v0 << 56
|
|
||||||
else:
|
|
||||||
assert 0
|
|
||||||
if column == 3:
|
|
||||||
print(" 0x%016x," % v, file=f)
|
|
||||||
column = 0
|
|
||||||
else:
|
|
||||||
if column == 0:
|
|
||||||
print(" ", end="", file=f)
|
|
||||||
print(" 0x%016x," % v, end="", file=f)
|
|
||||||
column += 1
|
|
||||||
if column != 0:
|
|
||||||
print("", file=f)
|
|
||||||
print("};", file=f)
|
|
||||||
|
|
||||||
def write_string_c(self, f, ctype="const char"):
|
|
||||||
assert self.finalized
|
|
||||||
assert self.data[len(self.data) - 1] == 0
|
|
||||||
print("%s %s[%d] =" % (ctype, self.cname, len(self.data)), file=f)
|
|
||||||
print(" \"", end="", file=f)
|
|
||||||
column = 0
|
|
||||||
for i in range(len(self.data) - 1):
|
|
||||||
if (self.data[i] < 32) or (self.data[i] > 126):
|
|
||||||
print("\\%03o" % self.data[i], end="", file=f)
|
|
||||||
column += 4
|
|
||||||
elif self.data[i] == ord('"') or self.data[i] == ord('\\'):
|
|
||||||
print("\\" + chr(self.data[i]), end="", file=f)
|
|
||||||
column += 2
|
|
||||||
else:
|
|
||||||
print(chr(self.data[i]), end="", file=f)
|
|
||||||
column += 1
|
|
||||||
if column > 70 and (i != len(self.data) - 2):
|
|
||||||
print("\"\n \"", end="", file=f)
|
|
||||||
column = 0
|
|
||||||
print("\";", file=f)
|
|
||||||
|
|
||||||
def write_binary(self, f):
|
|
||||||
assert self.finalized
|
|
||||||
assert self.data[len(self.data) - 1] == 0
|
|
||||||
f.buffer.write(self.data)
|
|
||||||
|
|
||||||
|
def pop(self):
|
||||||
|
print("pop")
|
||||||
|
|
||||||
bel_types = {
|
bel_types = {
|
||||||
"NONE": 0,
|
"NONE": 0,
|
||||||
@ -364,13 +126,25 @@ def process_pio_db(ddrg, device):
|
|||||||
if bel_idx is not None:
|
if bel_idx is not None:
|
||||||
pindata.append((loc, bel_idx, bank, pinfunc))
|
pindata.append((loc, bel_idx, bank, pinfunc))
|
||||||
|
|
||||||
|
global_data = {}
|
||||||
|
quadrants = ["UL", "UR", "LL", "LR"]
|
||||||
|
def process_loc_globals(chip):
|
||||||
|
for y in range(0, max_row+1):
|
||||||
|
for x in range(0, max_col+1):
|
||||||
|
quad = chip.global_data.get_quadrant(y, x)
|
||||||
|
tapdrv = chip.global_data.get_tap_driver(y, x)
|
||||||
|
global_data[x, y] = (quadrants.index(quad), int(tapdrv.dir), tapdrv.col)
|
||||||
|
|
||||||
def write_database(dev_name, ddrg, endianness):
|
def write_database(dev_name, ddrg, endianness):
|
||||||
def write_loc(loc, sym_name):
|
def write_loc(loc, sym_name):
|
||||||
bba.s16(loc.x, "%s.x" % sym_name)
|
bba.u16(loc.x, "%s.x" % sym_name)
|
||||||
bba.s16(loc.y, "%s.y" % sym_name)
|
bba.u16(loc.y, "%s.y" % sym_name)
|
||||||
|
|
||||||
bba = BinaryBlobAssembler("chipdb_blob_%s" % dev_name, endianness)
|
bba = BinaryBlobAssembler()
|
||||||
|
bba.pre('#include "nextpnr.h"')
|
||||||
|
bba.pre('NEXTPNR_NAMESPACE_BEGIN')
|
||||||
|
bba.post('NEXTPNR_NAMESPACE_END')
|
||||||
|
bba.push("chipdb_blob_%s" % dev_name)
|
||||||
bba.r("chip_info", "chip_info")
|
bba.r("chip_info", "chip_info")
|
||||||
|
|
||||||
loctypes = list([_.key() for _ in ddrg.locationTypes])
|
loctypes = list([_.key() for _ in ddrg.locationTypes])
|
||||||
@ -450,6 +224,14 @@ def write_database(dev_name, ddrg, endianness):
|
|||||||
for y in range(0, max_row+1):
|
for y in range(0, max_row+1):
|
||||||
for x in range(0, max_col+1):
|
for x in range(0, max_col+1):
|
||||||
bba.u32(loctypes.index(ddrg.typeAtLocation[pytrellis.Location(x, y)]), "loctype")
|
bba.u32(loctypes.index(ddrg.typeAtLocation[pytrellis.Location(x, y)]), "loctype")
|
||||||
|
|
||||||
|
bba.l("location_glbinfo", "GlobalInfoPOD")
|
||||||
|
for y in range(0, max_row+1):
|
||||||
|
for x in range(0, max_col+1):
|
||||||
|
bba.u16(global_data[x, y][2], "tap_col")
|
||||||
|
bba.u8(global_data[x, y][1], "tap_dir")
|
||||||
|
bba.u8(global_data[x, y][0], "quad")
|
||||||
|
|
||||||
for package, pkgdata in sorted(packages.items()):
|
for package, pkgdata in sorted(packages.items()):
|
||||||
bba.l("package_data_%s" % package, "PackagePinPOD")
|
bba.l("package_data_%s" % package, "PackagePinPOD")
|
||||||
for pin in pkgdata:
|
for pin in pkgdata:
|
||||||
@ -491,11 +273,12 @@ def write_database(dev_name, ddrg, endianness):
|
|||||||
|
|
||||||
bba.r("locations", "locations")
|
bba.r("locations", "locations")
|
||||||
bba.r("location_types", "location_type")
|
bba.r("location_types", "location_type")
|
||||||
|
bba.r("location_glbinfo", "location_glbinfo")
|
||||||
bba.r("tiletype_names", "tiletype_names")
|
bba.r("tiletype_names", "tiletype_names")
|
||||||
bba.r("package_data", "package_info")
|
bba.r("package_data", "package_info")
|
||||||
bba.r("pio_info", "pio_info")
|
bba.r("pio_info", "pio_info")
|
||||||
|
|
||||||
bba.finalize()
|
bba.pop()
|
||||||
return bba
|
return bba
|
||||||
|
|
||||||
dev_names = {"25k": "LFE5U-25F", "45k": "LFE5U-45F", "85k": "LFE5U-85F"}
|
dev_names = {"25k": "LFE5U-25F", "45k": "LFE5U-45F", "85k": "LFE5U-85F"}
|
||||||
@ -518,30 +301,18 @@ def main():
|
|||||||
idx = len(portpins) + 1
|
idx = len(portpins) + 1
|
||||||
portpins[line[1]] = idx
|
portpins[line[1]] = idx
|
||||||
|
|
||||||
print("Initialising chip...")
|
# print("Initialising chip...")
|
||||||
chip = pytrellis.Chip(dev_names[args.device])
|
chip = pytrellis.Chip(dev_names[args.device])
|
||||||
print("Building routing graph...")
|
# print("Building routing graph...")
|
||||||
ddrg = pytrellis.make_dedup_chipdb(chip)
|
ddrg = pytrellis.make_dedup_chipdb(chip)
|
||||||
max_row = chip.get_max_row()
|
max_row = chip.get_max_row()
|
||||||
max_col = chip.get_max_col()
|
max_col = chip.get_max_col()
|
||||||
process_pio_db(ddrg, args.device)
|
process_pio_db(ddrg, args.device)
|
||||||
print("{} unique location types".format(len(ddrg.locationTypes)))
|
process_loc_globals(chip)
|
||||||
|
# print("{} unique location types".format(len(ddrg.locationTypes)))
|
||||||
bba = write_database(args.device, ddrg, "le")
|
bba = write_database(args.device, ddrg, "le")
|
||||||
|
|
||||||
|
|
||||||
if args.c_file:
|
|
||||||
print('#include "nextpnr.h"', file=args.outfile)
|
|
||||||
print('NEXTPNR_NAMESPACE_BEGIN', file=args.outfile)
|
|
||||||
|
|
||||||
|
|
||||||
if args.binary:
|
|
||||||
bba.write_binary(args.outfile)
|
|
||||||
|
|
||||||
if args.c_file:
|
|
||||||
bba.write_string_c(args.outfile)
|
|
||||||
|
|
||||||
if args.c_file:
|
|
||||||
print('NEXTPNR_NAMESPACE_END', file=args.outfile)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -24,22 +24,24 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
void Arch::addWire(IdString name, int x, int y)
|
void Arch::addWire(IdString name, IdString type, int x, int y)
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(wires.count(name) == 0);
|
NPNR_ASSERT(wires.count(name) == 0);
|
||||||
WireInfo &wi = wires[name];
|
WireInfo &wi = wires[name];
|
||||||
wi.name = name;
|
wi.name = name;
|
||||||
|
wi.type = type;
|
||||||
wi.x = x;
|
wi.x = x;
|
||||||
wi.y = y;
|
wi.y = y;
|
||||||
|
|
||||||
wire_ids.push_back(name);
|
wire_ids.push_back(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arch::addPip(IdString name, IdString srcWire, IdString dstWire, DelayInfo delay)
|
void Arch::addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay)
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(pips.count(name) == 0);
|
NPNR_ASSERT(pips.count(name) == 0);
|
||||||
PipInfo &pi = pips[name];
|
PipInfo &pi = pips[name];
|
||||||
pi.name = name;
|
pi.name = name;
|
||||||
|
pi.type = type;
|
||||||
pi.srcWire = srcWire;
|
pi.srcWire = srcWire;
|
||||||
pi.dstWire = dstWire;
|
pi.dstWire = dstWire;
|
||||||
pi.delay = delay;
|
pi.delay = delay;
|
||||||
@ -49,11 +51,12 @@ void Arch::addPip(IdString name, IdString srcWire, IdString dstWire, DelayInfo d
|
|||||||
pip_ids.push_back(name);
|
pip_ids.push_back(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arch::addAlias(IdString name, IdString srcWire, IdString dstWire, DelayInfo delay)
|
void Arch::addAlias(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay)
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(pips.count(name) == 0);
|
NPNR_ASSERT(pips.count(name) == 0);
|
||||||
PipInfo &pi = pips[name];
|
PipInfo &pi = pips[name];
|
||||||
pi.name = name;
|
pi.name = name;
|
||||||
|
pi.type = type;
|
||||||
pi.srcWire = srcWire;
|
pi.srcWire = srcWire;
|
||||||
pi.dstWire = dstWire;
|
pi.dstWire = dstWire;
|
||||||
pi.delay = delay;
|
pi.delay = delay;
|
||||||
@ -207,15 +210,9 @@ BelId Arch::getBelByLocation(Loc loc) const
|
|||||||
return BelId();
|
return BelId();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<BelId> &Arch::getBelsByTile(int x, int y) const
|
const std::vector<BelId> &Arch::getBelsByTile(int x, int y) const { return bels_by_tile.at(x).at(y); }
|
||||||
{
|
|
||||||
return bels_by_tile.at(x).at(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Arch::getBelGlobalBuf(BelId bel) const
|
bool Arch::getBelGlobalBuf(BelId bel) const { return bels.at(bel).gb; }
|
||||||
{
|
|
||||||
return bels.at(bel).gb;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Arch::getBelChecksum(BelId bel) const
|
uint32_t Arch::getBelChecksum(BelId bel) const
|
||||||
{
|
{
|
||||||
@ -272,6 +269,8 @@ WireId Arch::getWireByName(IdString name) const
|
|||||||
|
|
||||||
IdString Arch::getWireName(WireId wire) const { return wire; }
|
IdString Arch::getWireName(WireId wire) const { return wire; }
|
||||||
|
|
||||||
|
IdString Arch::getWireType(WireId wire) const { return wires.at(wire).type; }
|
||||||
|
|
||||||
uint32_t Arch::getWireChecksum(WireId wire) const
|
uint32_t Arch::getWireChecksum(WireId wire) const
|
||||||
{
|
{
|
||||||
// FIXME
|
// FIXME
|
||||||
@ -322,6 +321,8 @@ PipId Arch::getPipByName(IdString name) const
|
|||||||
|
|
||||||
IdString Arch::getPipName(PipId pip) const { return pip; }
|
IdString Arch::getPipName(PipId pip) const { return pip; }
|
||||||
|
|
||||||
|
IdString Arch::getPipType(PipId pip) const { return pips.at(pip).type; }
|
||||||
|
|
||||||
uint32_t Arch::getPipChecksum(PipId wire) const
|
uint32_t Arch::getPipChecksum(PipId wire) const
|
||||||
{
|
{
|
||||||
// FIXME
|
// FIXME
|
||||||
|
@ -31,7 +31,7 @@ struct WireInfo;
|
|||||||
|
|
||||||
struct PipInfo
|
struct PipInfo
|
||||||
{
|
{
|
||||||
IdString name, bound_net;
|
IdString name, type, bound_net;
|
||||||
WireId srcWire, dstWire;
|
WireId srcWire, dstWire;
|
||||||
DelayInfo delay;
|
DelayInfo delay;
|
||||||
DecalXY decalxy;
|
DecalXY decalxy;
|
||||||
@ -39,7 +39,7 @@ struct PipInfo
|
|||||||
|
|
||||||
struct WireInfo
|
struct WireInfo
|
||||||
{
|
{
|
||||||
IdString name, bound_net;
|
IdString name, type, bound_net;
|
||||||
std::vector<PipId> downhill, uphill, aliases;
|
std::vector<PipId> downhill, uphill, aliases;
|
||||||
BelPin uphill_bel_pin;
|
BelPin uphill_bel_pin;
|
||||||
std::vector<BelPin> downhill_bel_pins;
|
std::vector<BelPin> downhill_bel_pins;
|
||||||
@ -96,9 +96,9 @@ struct Arch : BaseCtx
|
|||||||
|
|
||||||
float grid_distance_to_delay;
|
float grid_distance_to_delay;
|
||||||
|
|
||||||
void addWire(IdString name, int x, int y);
|
void addWire(IdString name, IdString type, int x, int y);
|
||||||
void addPip(IdString name, IdString srcWire, IdString dstWire, DelayInfo delay);
|
void addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay);
|
||||||
void addAlias(IdString name, IdString srcWire, IdString dstWire, DelayInfo delay);
|
void addAlias(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay);
|
||||||
|
|
||||||
void addBel(IdString name, IdString type, Loc loc, bool gb);
|
void addBel(IdString name, IdString type, Loc loc, bool gb);
|
||||||
void addBelInput(IdString bel, IdString name, IdString wire);
|
void addBelInput(IdString bel, IdString name, IdString wire);
|
||||||
@ -157,6 +157,7 @@ struct Arch : BaseCtx
|
|||||||
|
|
||||||
WireId getWireByName(IdString name) const;
|
WireId getWireByName(IdString name) const;
|
||||||
IdString getWireName(WireId wire) const;
|
IdString getWireName(WireId wire) const;
|
||||||
|
IdString getWireType(WireId wire) const;
|
||||||
uint32_t getWireChecksum(WireId wire) const;
|
uint32_t getWireChecksum(WireId wire) const;
|
||||||
void bindWire(WireId wire, IdString net, PlaceStrength strength);
|
void bindWire(WireId wire, IdString net, PlaceStrength strength);
|
||||||
void unbindWire(WireId wire);
|
void unbindWire(WireId wire);
|
||||||
@ -169,6 +170,7 @@ struct Arch : BaseCtx
|
|||||||
|
|
||||||
PipId getPipByName(IdString name) const;
|
PipId getPipByName(IdString name) const;
|
||||||
IdString getPipName(PipId pip) const;
|
IdString getPipName(PipId pip) const;
|
||||||
|
IdString getPipType(PipId pip) const;
|
||||||
uint32_t getPipChecksum(PipId pip) const;
|
uint32_t getPipChecksum(PipId pip) const;
|
||||||
void bindPip(PipId pip, IdString net, PlaceStrength strength);
|
void bindPip(PipId pip, IdString net, PlaceStrength strength);
|
||||||
void unbindPip(PipId pip);
|
void unbindPip(PipId pip);
|
||||||
|
@ -75,18 +75,16 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("help") || argc == 1) {
|
if (vm.count("help") || argc == 1) {
|
||||||
std::cout << boost::filesystem::basename(argv[0])
|
std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git "
|
||||||
<< " -- Next Generation Place and Route (git "
|
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
std::cout << options << "\n";
|
std::cout << options << "\n";
|
||||||
return argc != 1;
|
return argc != 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("version")) {
|
if (vm.count("version")) {
|
||||||
std::cout << boost::filesystem::basename(argv[0])
|
std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git "
|
||||||
<< " -- Next Generation Place and Route (git "
|
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,5 +10,9 @@
|
|||||||
<file>resources/resultset_next.png</file>
|
<file>resources/resultset_next.png</file>
|
||||||
<file>resources/resultset_last.png</file>
|
<file>resources/resultset_last.png</file>
|
||||||
<file>resources/cross.png</file>
|
<file>resources/cross.png</file>
|
||||||
|
<file>resources/zoom_in.png</file>
|
||||||
|
<file>resources/zoom_out.png</file>
|
||||||
|
<file>resources/shape_handles.png</file>
|
||||||
|
<file>resources/shape_square.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include <QSplitter>
|
#include <QSplitter>
|
||||||
#include "designwidget.h"
|
#include "designwidget.h"
|
||||||
#include "fpgaviewwidget.h"
|
#include "fpgaviewwidget.h"
|
||||||
#include "jsonparse.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "pythontab.h"
|
#include "pythontab.h"
|
||||||
@ -76,7 +75,7 @@ BaseMainWindow::BaseMainWindow(std::unique_ptr<Context> context, QWidget *parent
|
|||||||
centralTabWidget->setTabsClosable(true);
|
centralTabWidget->setTabsClosable(true);
|
||||||
connect(centralTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
|
connect(centralTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
|
||||||
|
|
||||||
FPGAViewWidget *fpgaView = new FPGAViewWidget();
|
fpgaView = new FPGAViewWidget();
|
||||||
centralTabWidget->addTab(fpgaView, "Graphics");
|
centralTabWidget->addTab(fpgaView, "Graphics");
|
||||||
centralTabWidget->tabBar()->tabButton(0, QTabBar::RightSide)->resize(0, 0);
|
centralTabWidget->tabBar()->tabButton(0, QTabBar::RightSide)->resize(0, 0);
|
||||||
|
|
||||||
@ -164,4 +163,30 @@ void BaseMainWindow::createMenusAndBars()
|
|||||||
mainToolBar->addAction(actionSave);
|
mainToolBar->addAction(actionSave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseMainWindow::createGraphicsBar()
|
||||||
|
{
|
||||||
|
QAction *actionZoomIn = new QAction("Zoom In", this);
|
||||||
|
actionZoomIn->setIcon(QIcon(":/icons/resources/zoom_in.png"));
|
||||||
|
connect(actionZoomIn, SIGNAL(triggered()), fpgaView, SLOT(zoom_in()));
|
||||||
|
|
||||||
|
QAction *actionZoomOut = new QAction("Zoom Out", this);
|
||||||
|
actionZoomOut->setIcon(QIcon(":/icons/resources/zoom_out.png"));
|
||||||
|
connect(actionZoomOut, SIGNAL(triggered()), fpgaView, SLOT(zoom_out()));
|
||||||
|
|
||||||
|
QAction *actionZoomSelected = new QAction("Zoom Selected", this);
|
||||||
|
actionZoomSelected->setIcon(QIcon(":/icons/resources/shape_handles.png"));
|
||||||
|
connect(actionZoomSelected, SIGNAL(triggered()), fpgaView, SLOT(zoom_selected()));
|
||||||
|
|
||||||
|
QAction *actionZoomOutbound = new QAction("Zoom Outbound", this);
|
||||||
|
actionZoomOutbound->setIcon(QIcon(":/icons/resources/shape_square.png"));
|
||||||
|
connect(actionZoomOutbound, SIGNAL(triggered()), fpgaView, SLOT(zoom_outbound()));
|
||||||
|
|
||||||
|
graphicsToolBar = new QToolBar();
|
||||||
|
addToolBar(Qt::TopToolBarArea, graphicsToolBar);
|
||||||
|
graphicsToolBar->addAction(actionZoomIn);
|
||||||
|
graphicsToolBar->addAction(actionZoomOut);
|
||||||
|
graphicsToolBar->addAction(actionZoomSelected);
|
||||||
|
graphicsToolBar->addAction(actionZoomOutbound);
|
||||||
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -37,6 +37,7 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
class PythonTab;
|
class PythonTab;
|
||||||
class DesignWidget;
|
class DesignWidget;
|
||||||
|
class FPGAViewWidget;
|
||||||
|
|
||||||
class BaseMainWindow : public QMainWindow
|
class BaseMainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
@ -49,6 +50,7 @@ class BaseMainWindow : public QMainWindow
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void createMenusAndBars();
|
void createMenusAndBars();
|
||||||
|
void createGraphicsBar();
|
||||||
|
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
void writeInfo(std::string text);
|
void writeInfo(std::string text);
|
||||||
@ -70,12 +72,14 @@ class BaseMainWindow : public QMainWindow
|
|||||||
|
|
||||||
QMenuBar *menuBar;
|
QMenuBar *menuBar;
|
||||||
QToolBar *mainToolBar;
|
QToolBar *mainToolBar;
|
||||||
|
QToolBar *graphicsToolBar;
|
||||||
QStatusBar *statusBar;
|
QStatusBar *statusBar;
|
||||||
QAction *actionNew;
|
QAction *actionNew;
|
||||||
QAction *actionOpen;
|
QAction *actionOpen;
|
||||||
QAction *actionSave;
|
QAction *actionSave;
|
||||||
QProgressBar *progressBar;
|
QProgressBar *progressBar;
|
||||||
DesignWidget *designview;
|
DesignWidget *designview;
|
||||||
|
FPGAViewWidget *fpgaView;
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -35,6 +35,7 @@ class ElementTreeItem : public QTreeWidgetItem
|
|||||||
ElementTreeItem(ElementType t, QString str, QTreeWidgetItem *parent)
|
ElementTreeItem(ElementType t, QString str, QTreeWidgetItem *parent)
|
||||||
: QTreeWidgetItem(parent, QStringList(str)), type(t)
|
: QTreeWidgetItem(parent, QStringList(str)), type(t)
|
||||||
{
|
{
|
||||||
|
this->setFlags(this->flags() & ~Qt::ItemIsSelectable);
|
||||||
}
|
}
|
||||||
virtual ~ElementTreeItem(){};
|
virtual ~ElementTreeItem(){};
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ class IdStringTreeItem : public ElementTreeItem
|
|||||||
public:
|
public:
|
||||||
IdStringTreeItem(IdString d, ElementType t, QString str, QTreeWidgetItem *parent) : ElementTreeItem(t, str, parent)
|
IdStringTreeItem(IdString d, ElementType t, QString str, QTreeWidgetItem *parent) : ElementTreeItem(t, str, parent)
|
||||||
{
|
{
|
||||||
|
this->setFlags(this->flags() | Qt::ItemIsSelectable);
|
||||||
this->data = d;
|
this->data = d;
|
||||||
}
|
}
|
||||||
virtual ~IdStringTreeItem(){};
|
virtual ~IdStringTreeItem(){};
|
||||||
@ -68,6 +70,7 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), net
|
|||||||
treeWidget->setColumnCount(1);
|
treeWidget->setColumnCount(1);
|
||||||
treeWidget->setHeaderLabel("Items");
|
treeWidget->setHeaderLabel("Items");
|
||||||
treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
|
||||||
// Add property view
|
// Add property view
|
||||||
variantManager = new QtVariantPropertyManager(this);
|
variantManager = new QtVariantPropertyManager(this);
|
||||||
@ -79,6 +82,7 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), net
|
|||||||
propertyEditor->setPropertiesWithoutValueMarked(true);
|
propertyEditor->setPropertiesWithoutValueMarked(true);
|
||||||
propertyEditor->show();
|
propertyEditor->show();
|
||||||
propertyEditor->treeWidget()->setContextMenuPolicy(Qt::CustomContextMenu);
|
propertyEditor->treeWidget()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
propertyEditor->treeWidget()->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
|
||||||
QLineEdit *lineEdit = new QLineEdit();
|
QLineEdit *lineEdit = new QLineEdit();
|
||||||
lineEdit->setClearButtonEnabled(true);
|
lineEdit->setClearButtonEnabled(true);
|
||||||
@ -248,6 +252,7 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
QTreeWidgetItem *bel_root = new QTreeWidgetItem(treeWidget);
|
QTreeWidgetItem *bel_root = new QTreeWidgetItem(treeWidget);
|
||||||
QMap<QString, QTreeWidgetItem *> bel_items;
|
QMap<QString, QTreeWidgetItem *> bel_items;
|
||||||
bel_root->setText(0, "Bels");
|
bel_root->setText(0, "Bels");
|
||||||
|
bel_root->setFlags(bel_root->flags() & ~Qt::ItemIsSelectable);
|
||||||
treeWidget->insertTopLevelItem(0, bel_root);
|
treeWidget->insertTopLevelItem(0, bel_root);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
for (auto bel : ctx->getBels()) {
|
for (auto bel : ctx->getBels()) {
|
||||||
@ -280,6 +285,7 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
QTreeWidgetItem *wire_root = new QTreeWidgetItem(treeWidget);
|
QTreeWidgetItem *wire_root = new QTreeWidgetItem(treeWidget);
|
||||||
QMap<QString, QTreeWidgetItem *> wire_items;
|
QMap<QString, QTreeWidgetItem *> wire_items;
|
||||||
wire_root->setText(0, "Wires");
|
wire_root->setText(0, "Wires");
|
||||||
|
wire_root->setFlags(wire_root->flags() & ~Qt::ItemIsSelectable);
|
||||||
treeWidget->insertTopLevelItem(0, wire_root);
|
treeWidget->insertTopLevelItem(0, wire_root);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
for (auto wire : ctx->getWires()) {
|
for (auto wire : ctx->getWires()) {
|
||||||
@ -311,6 +317,7 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
QTreeWidgetItem *pip_root = new QTreeWidgetItem(treeWidget);
|
QTreeWidgetItem *pip_root = new QTreeWidgetItem(treeWidget);
|
||||||
QMap<QString, QTreeWidgetItem *> pip_items;
|
QMap<QString, QTreeWidgetItem *> pip_items;
|
||||||
pip_root->setText(0, "Pips");
|
pip_root->setText(0, "Pips");
|
||||||
|
pip_root->setFlags(pip_root->flags() & ~Qt::ItemIsSelectable);
|
||||||
treeWidget->insertTopLevelItem(0, pip_root);
|
treeWidget->insertTopLevelItem(0, pip_root);
|
||||||
#ifndef ARCH_ECP5
|
#ifndef ARCH_ECP5
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
@ -343,10 +350,12 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
|
|
||||||
nets_root = new QTreeWidgetItem(treeWidget);
|
nets_root = new QTreeWidgetItem(treeWidget);
|
||||||
nets_root->setText(0, "Nets");
|
nets_root->setText(0, "Nets");
|
||||||
|
nets_root->setFlags(nets_root->flags() & ~Qt::ItemIsSelectable);
|
||||||
treeWidget->insertTopLevelItem(0, nets_root);
|
treeWidget->insertTopLevelItem(0, nets_root);
|
||||||
|
|
||||||
cells_root = new QTreeWidgetItem(treeWidget);
|
cells_root = new QTreeWidgetItem(treeWidget);
|
||||||
cells_root->setText(0, "Cells");
|
cells_root->setText(0, "Cells");
|
||||||
|
cells_root->setFlags(cells_root->flags() & ~Qt::ItemIsSelectable);
|
||||||
treeWidget->insertTopLevelItem(0, cells_root);
|
treeWidget->insertTopLevelItem(0, cells_root);
|
||||||
|
|
||||||
updateTree();
|
updateTree();
|
||||||
@ -418,6 +427,7 @@ QtProperty *DesignWidget::addTopLevelProperty(const QString &id)
|
|||||||
QtProperty *topItem = groupManager->addProperty(id);
|
QtProperty *topItem = groupManager->addProperty(id);
|
||||||
propertyToId[topItem] = id;
|
propertyToId[topItem] = id;
|
||||||
idToProperty[id] = topItem;
|
idToProperty[id] = topItem;
|
||||||
|
topItem->setSelectable(false);
|
||||||
propertyEditor->addProperty(topItem);
|
propertyEditor->addProperty(topItem);
|
||||||
return topItem;
|
return topItem;
|
||||||
}
|
}
|
||||||
@ -485,12 +495,14 @@ void DesignWidget::addProperty(QtProperty *topItem, int propertyType, const QStr
|
|||||||
QtVariantProperty *item = readOnlyManager->addProperty(propertyType, name);
|
QtVariantProperty *item = readOnlyManager->addProperty(propertyType, name);
|
||||||
item->setValue(value);
|
item->setValue(value);
|
||||||
item->setPropertyId(getElementTypeName(type));
|
item->setPropertyId(getElementTypeName(type));
|
||||||
|
item->setSelectable(type != ElementType::NONE);
|
||||||
topItem->addSubProperty(item);
|
topItem->addSubProperty(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
QtProperty *DesignWidget::addSubGroup(QtProperty *topItem, const QString &name)
|
QtProperty *DesignWidget::addSubGroup(QtProperty *topItem, const QString &name)
|
||||||
{
|
{
|
||||||
QtProperty *item = groupManager->addProperty(name);
|
QtProperty *item = groupManager->addProperty(name);
|
||||||
|
item->setSelectable(false);
|
||||||
topItem->addSubProperty(item);
|
topItem->addSubProperty(item);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
@ -507,6 +519,18 @@ void DesignWidget::onItemSelectionChanged()
|
|||||||
if (treeWidget->selectedItems().size() == 0)
|
if (treeWidget->selectedItems().size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (treeWidget->selectedItems().size() > 1) {
|
||||||
|
std::vector<DecalXY> decals;
|
||||||
|
for (auto clickItem : treeWidget->selectedItems()) {
|
||||||
|
IdString value = static_cast<IdStringTreeItem *>(clickItem)->getData();
|
||||||
|
ElementType type = static_cast<ElementTreeItem *>(clickItem)->getType();
|
||||||
|
std::vector<DecalXY> d = getDecals(type, value);
|
||||||
|
std::move(d.begin(), d.end(), std::back_inserter(decals));
|
||||||
|
}
|
||||||
|
Q_EMIT selected(decals);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QTreeWidgetItem *clickItem = treeWidget->selectedItems().at(0);
|
QTreeWidgetItem *clickItem = treeWidget->selectedItems().at(0);
|
||||||
|
|
||||||
if (!clickItem->parent())
|
if (!clickItem->parent())
|
||||||
@ -550,6 +574,7 @@ void DesignWidget::onItemSelectionChanged()
|
|||||||
QtProperty *topItem = addTopLevelProperty("Wire");
|
QtProperty *topItem = addTopLevelProperty("Wire");
|
||||||
|
|
||||||
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
|
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
|
||||||
|
addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx));
|
||||||
addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire));
|
addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire));
|
||||||
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundWireNet(wire).c_str(ctx), ElementType::NET);
|
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundWireNet(wire).c_str(ctx), ElementType::NET);
|
||||||
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingWireNet(wire).c_str(ctx),
|
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingWireNet(wire).c_str(ctx),
|
||||||
@ -601,6 +626,7 @@ void DesignWidget::onItemSelectionChanged()
|
|||||||
QtProperty *topItem = addTopLevelProperty("Pip");
|
QtProperty *topItem = addTopLevelProperty("Pip");
|
||||||
|
|
||||||
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
|
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
|
||||||
|
addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx));
|
||||||
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip));
|
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip));
|
||||||
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundPipNet(pip).c_str(ctx), ElementType::NET);
|
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundPipNet(pip).c_str(ctx), ElementType::NET);
|
||||||
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingPipNet(pip).c_str(ctx),
|
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingPipNet(pip).c_str(ctx),
|
||||||
@ -758,54 +784,53 @@ std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value)
|
|||||||
return decals;
|
return decals;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignWidget::updateHighlightGroup(QTreeWidgetItem *item, int group)
|
void DesignWidget::updateHighlightGroup(QList<QTreeWidgetItem *> items, int group)
|
||||||
{
|
{
|
||||||
if (highlightSelected.contains(item)) {
|
const bool shouldClear = items.size() == 1;
|
||||||
if (highlightSelected[item] == group) {
|
for (auto item : items) {
|
||||||
highlightSelected.remove(item);
|
if (highlightSelected.contains(item)) {
|
||||||
|
if (shouldClear && highlightSelected[item] == group) {
|
||||||
|
highlightSelected.remove(item);
|
||||||
|
} else
|
||||||
|
highlightSelected[item] = group;
|
||||||
} else
|
} else
|
||||||
highlightSelected[item] = group;
|
highlightSelected.insert(item, group);
|
||||||
} else
|
}
|
||||||
highlightSelected.insert(item, group);
|
std::vector<DecalXY> decals[8];
|
||||||
|
|
||||||
std::vector<DecalXY> decals;
|
|
||||||
|
|
||||||
for (auto it : highlightSelected.toStdMap()) {
|
for (auto it : highlightSelected.toStdMap()) {
|
||||||
if (it.second == group) {
|
ElementType type = static_cast<ElementTreeItem *>(it.first)->getType();
|
||||||
ElementType type = static_cast<ElementTreeItem *>(it.first)->getType();
|
IdString value = static_cast<IdStringTreeItem *>(it.first)->getData();
|
||||||
IdString value = static_cast<IdStringTreeItem *>(it.first)->getData();
|
std::vector<DecalXY> d = getDecals(type, value);
|
||||||
std::vector<DecalXY> d = getDecals(type, value);
|
std::move(d.begin(), d.end(), std::back_inserter(decals[it.second]));
|
||||||
std::move(d.begin(), d.end(), std::back_inserter(decals));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
Q_EMIT highlight(decals, group);
|
Q_EMIT highlight(decals[i], i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignWidget::prepareMenuProperty(const QPoint &pos)
|
void DesignWidget::prepareMenuProperty(const QPoint &pos)
|
||||||
{
|
{
|
||||||
QTreeWidget *tree = propertyEditor->treeWidget();
|
QTreeWidget *tree = propertyEditor->treeWidget();
|
||||||
|
QList<QTreeWidgetItem *> items;
|
||||||
itemContextMenu = tree->itemAt(pos);
|
for (auto itemContextMenu : tree->selectedItems()) {
|
||||||
if (itemContextMenu->parent() == nullptr)
|
QtBrowserItem *browserItem = propertyEditor->itemToBrowserItem(itemContextMenu);
|
||||||
return;
|
if (!browserItem)
|
||||||
|
continue;
|
||||||
QtBrowserItem *browserItem = propertyEditor->itemToBrowserItem(itemContextMenu);
|
QtProperty *selectedProperty = browserItem->property();
|
||||||
if (!browserItem)
|
ElementType type = getElementTypeByName(selectedProperty->propertyId());
|
||||||
return;
|
if (type == ElementType::NONE)
|
||||||
QtProperty *selectedProperty = browserItem->property();
|
continue;
|
||||||
ElementType type = getElementTypeByName(selectedProperty->propertyId());
|
IdString value = ctx->id(selectedProperty->valueText().toStdString());
|
||||||
if (type == ElementType::NONE)
|
items.append(nameToItem[getElementIndex(type)].value(value.c_str(ctx)));
|
||||||
return;
|
}
|
||||||
IdString value = ctx->id(selectedProperty->valueText().toStdString());
|
int selectedIndex = -1;
|
||||||
|
if (items.size() == 1) {
|
||||||
QTreeWidgetItem *item = nameToItem[getElementIndex(type)].value(value.c_str(ctx));
|
QTreeWidgetItem *item = items.at(0);
|
||||||
|
if (highlightSelected.contains(item))
|
||||||
|
selectedIndex = highlightSelected[item];
|
||||||
|
}
|
||||||
|
|
||||||
QMenu menu(this);
|
QMenu menu(this);
|
||||||
QAction *selectAction = new QAction("&Select", this);
|
|
||||||
connect(selectAction, &QAction::triggered, this, [this, type, value] { Q_EMIT selected(getDecals(type, value)); });
|
|
||||||
menu.addAction(selectAction);
|
|
||||||
|
|
||||||
QMenu *subMenu = menu.addMenu("Highlight");
|
QMenu *subMenu = menu.addMenu("Highlight");
|
||||||
QActionGroup *group = new QActionGroup(this);
|
QActionGroup *group = new QActionGroup(this);
|
||||||
group->setExclusive(true);
|
group->setExclusive(true);
|
||||||
@ -816,27 +841,24 @@ void DesignWidget::prepareMenuProperty(const QPoint &pos)
|
|||||||
action->setCheckable(true);
|
action->setCheckable(true);
|
||||||
subMenu->addAction(action);
|
subMenu->addAction(action);
|
||||||
group->addAction(action);
|
group->addAction(action);
|
||||||
if (highlightSelected.contains(item) && highlightSelected[item] == i)
|
if (selectedIndex == i)
|
||||||
action->setChecked(true);
|
action->setChecked(true);
|
||||||
connect(action, &QAction::triggered, this, [this, i, item] { updateHighlightGroup(item, i); });
|
connect(action, &QAction::triggered, this, [this, i, items] { updateHighlightGroup(items, i); });
|
||||||
}
|
}
|
||||||
menu.exec(tree->mapToGlobal(pos));
|
menu.exec(tree->mapToGlobal(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignWidget::prepareMenuTree(const QPoint &pos)
|
void DesignWidget::prepareMenuTree(const QPoint &pos)
|
||||||
{
|
{
|
||||||
QTreeWidget *tree = treeWidget;
|
if (treeWidget->selectedItems().size() == 0)
|
||||||
|
|
||||||
itemContextMenu = tree->itemAt(pos);
|
|
||||||
|
|
||||||
ElementType type = static_cast<ElementTreeItem *>(itemContextMenu)->getType();
|
|
||||||
IdString value = static_cast<IdStringTreeItem *>(itemContextMenu)->getData();
|
|
||||||
|
|
||||||
if (type == ElementType::NONE)
|
|
||||||
return;
|
return;
|
||||||
|
int selectedIndex = -1;
|
||||||
QTreeWidgetItem *item = nameToItem[getElementIndex(type)].value(value.c_str(ctx));
|
QList<QTreeWidgetItem *> items = treeWidget->selectedItems();
|
||||||
|
if (treeWidget->selectedItems().size() == 1) {
|
||||||
|
QTreeWidgetItem *item = treeWidget->selectedItems().at(0);
|
||||||
|
if (highlightSelected.contains(item))
|
||||||
|
selectedIndex = highlightSelected[item];
|
||||||
|
}
|
||||||
QMenu menu(this);
|
QMenu menu(this);
|
||||||
QMenu *subMenu = menu.addMenu("Highlight");
|
QMenu *subMenu = menu.addMenu("Highlight");
|
||||||
QActionGroup *group = new QActionGroup(this);
|
QActionGroup *group = new QActionGroup(this);
|
||||||
@ -848,11 +870,11 @@ void DesignWidget::prepareMenuTree(const QPoint &pos)
|
|||||||
action->setCheckable(true);
|
action->setCheckable(true);
|
||||||
subMenu->addAction(action);
|
subMenu->addAction(action);
|
||||||
group->addAction(action);
|
group->addAction(action);
|
||||||
if (highlightSelected.contains(item) && highlightSelected[item] == i)
|
if (selectedIndex == i)
|
||||||
action->setChecked(true);
|
action->setChecked(true);
|
||||||
connect(action, &QAction::triggered, this, [this, i, item] { updateHighlightGroup(item, i); });
|
connect(action, &QAction::triggered, this, [this, i, items] { updateHighlightGroup(items, i); });
|
||||||
}
|
}
|
||||||
menu.exec(tree->mapToGlobal(pos));
|
menu.exec(treeWidget->mapToGlobal(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignWidget::onItemDoubleClicked(QTreeWidgetItem *item, int column)
|
void DesignWidget::onItemDoubleClicked(QTreeWidgetItem *item, int column)
|
||||||
|
@ -60,7 +60,7 @@ class DesignWidget : public QWidget
|
|||||||
void updateButtons();
|
void updateButtons();
|
||||||
void addToHistory(QTreeWidgetItem *item);
|
void addToHistory(QTreeWidgetItem *item);
|
||||||
std::vector<DecalXY> getDecals(ElementType type, IdString value);
|
std::vector<DecalXY> getDecals(ElementType type, IdString value);
|
||||||
void updateHighlightGroup(QTreeWidgetItem *item, int group);
|
void updateHighlightGroup(QList<QTreeWidgetItem *> item, int group);
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void info(std::string text);
|
void info(std::string text);
|
||||||
void selected(std::vector<DecalXY> decal);
|
void selected(std::vector<DecalXY> decal);
|
||||||
@ -86,7 +86,6 @@ class DesignWidget : public QWidget
|
|||||||
QtGroupPropertyManager *groupManager;
|
QtGroupPropertyManager *groupManager;
|
||||||
QtVariantEditorFactory *variantFactory;
|
QtVariantEditorFactory *variantFactory;
|
||||||
QtTreePropertyBrowser *propertyEditor;
|
QtTreePropertyBrowser *propertyEditor;
|
||||||
QTreeWidgetItem *itemContextMenu;
|
|
||||||
|
|
||||||
QMap<QtProperty *, QString> propertyToId;
|
QMap<QtProperty *, QString> propertyToId;
|
||||||
QMap<QString, QtProperty *> idToProperty;
|
QMap<QString, QtProperty *> idToProperty;
|
||||||
|
@ -624,21 +624,32 @@ void FPGAViewWidget::wheelEvent(QWheelEvent *event)
|
|||||||
{
|
{
|
||||||
QPoint degree = event->angleDelta() / 8;
|
QPoint degree = event->angleDelta() / 8;
|
||||||
|
|
||||||
if (!degree.isNull()) {
|
if (!degree.isNull())
|
||||||
|
zoom(degree.y());
|
||||||
if (zoom_ < zoomNear_) {
|
|
||||||
zoom_ = zoomNear_;
|
|
||||||
} else if (zoom_ < zoomLvl1_) {
|
|
||||||
zoom_ -= degree.y() / 10.0;
|
|
||||||
} else if (zoom_ < zoomLvl2_) {
|
|
||||||
zoom_ -= degree.y() / 5.0;
|
|
||||||
} else if (zoom_ < zoomFar_) {
|
|
||||||
zoom_ -= degree.y();
|
|
||||||
} else {
|
|
||||||
zoom_ = zoomFar_;
|
|
||||||
}
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FPGAViewWidget::zoom(int level)
|
||||||
|
{
|
||||||
|
if (zoom_ < zoomNear_) {
|
||||||
|
zoom_ = zoomNear_;
|
||||||
|
} else if (zoom_ < zoomLvl1_) {
|
||||||
|
zoom_ -= level / 10.0;
|
||||||
|
} else if (zoom_ < zoomLvl2_) {
|
||||||
|
zoom_ -= level / 5.0;
|
||||||
|
} else if (zoom_ < zoomFar_) {
|
||||||
|
zoom_ -= level;
|
||||||
|
} else {
|
||||||
|
zoom_ = zoomFar_;
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPGAViewWidget::zoom_in() { zoom(10); }
|
||||||
|
|
||||||
|
void FPGAViewWidget::zoom_out() { zoom(-10); }
|
||||||
|
|
||||||
|
void FPGAViewWidget::zoom_selected() {}
|
||||||
|
|
||||||
|
void FPGAViewWidget::zoom_outbound() {}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -293,11 +293,17 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
|
|||||||
void onSelectedArchItem(std::vector<DecalXY> decals);
|
void onSelectedArchItem(std::vector<DecalXY> decals);
|
||||||
void onHighlightGroupChanged(std::vector<DecalXY> decals, int group);
|
void onHighlightGroupChanged(std::vector<DecalXY> decals, int group);
|
||||||
void pokeRenderer(void);
|
void pokeRenderer(void);
|
||||||
|
void zoom_in();
|
||||||
|
void zoom_out();
|
||||||
|
void zoom_selected();
|
||||||
|
void zoom_outbound();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void clickedBel(BelId bel);
|
void clickedBel(BelId bel);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void renderLines(void);
|
void renderLines(void);
|
||||||
|
void zoom(int level);
|
||||||
|
|
||||||
QPoint lastPos_;
|
QPoint lastPos_;
|
||||||
LineShader lineShader_;
|
LineShader lineShader_;
|
||||||
|
@ -159,6 +159,8 @@ void MainWindow::createMenu()
|
|||||||
taskToolBar->addAction(actionPlay);
|
taskToolBar->addAction(actionPlay);
|
||||||
taskToolBar->addAction(actionPause);
|
taskToolBar->addAction(actionPause);
|
||||||
taskToolBar->addAction(actionStop);
|
taskToolBar->addAction(actionStop);
|
||||||
|
|
||||||
|
createGraphicsBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
BIN
gui/resources/shape_handles.png
Normal file
BIN
gui/resources/shape_handles.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 538 B |
BIN
gui/resources/shape_square.png
Normal file
BIN
gui/resources/shape_square.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 353 B |
BIN
gui/resources/zoom_in.png
Normal file
BIN
gui/resources/zoom_in.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 725 B |
BIN
gui/resources/zoom_out.png
Normal file
BIN
gui/resources/zoom_out.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 708 B |
292
ice40/arch.cc
292
ice40/arch.cc
@ -188,6 +188,13 @@ Arch::Arch(ArchArgs args) : args(args)
|
|||||||
id_i3 = id("I3");
|
id_i3 = id("I3");
|
||||||
id_dff_en = id("DFF_ENABLE");
|
id_dff_en = id("DFF_ENABLE");
|
||||||
id_neg_clk = id("NEG_CLK");
|
id_neg_clk = id("NEG_CLK");
|
||||||
|
id_cin = id("CIN");
|
||||||
|
id_cout = id("COUT");
|
||||||
|
id_o = id("O");
|
||||||
|
id_lo = id("LO");
|
||||||
|
id_icestorm_ram = id("ICESTORM_RAM");
|
||||||
|
id_rclk = id("RCLK");
|
||||||
|
id_wclk = id("WCLK");
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
@ -433,11 +440,103 @@ GroupId Arch::getGroupByName(IdString name) const
|
|||||||
return GroupId();
|
return GroupId();
|
||||||
}
|
}
|
||||||
|
|
||||||
IdString Arch::getGroupName(GroupId group) const { return IdString(); }
|
IdString Arch::getGroupName(GroupId group) const
|
||||||
|
{
|
||||||
|
std::string suffix;
|
||||||
|
|
||||||
|
switch (group.type) {
|
||||||
|
case GroupId::TYPE_FRAME:
|
||||||
|
suffix = "tile";
|
||||||
|
break;
|
||||||
|
case GroupId::TYPE_MAIN_SW:
|
||||||
|
suffix = "main_sw";
|
||||||
|
break;
|
||||||
|
case GroupId::TYPE_LOCAL_SW:
|
||||||
|
suffix = "local_sw";
|
||||||
|
break;
|
||||||
|
case GroupId::TYPE_LC0_SW:
|
||||||
|
suffix = "lc0_sw";
|
||||||
|
break;
|
||||||
|
case GroupId::TYPE_LC1_SW:
|
||||||
|
suffix = "lc1_sw";
|
||||||
|
break;
|
||||||
|
case GroupId::TYPE_LC2_SW:
|
||||||
|
suffix = "lc2_sw";
|
||||||
|
break;
|
||||||
|
case GroupId::TYPE_LC3_SW:
|
||||||
|
suffix = "lc3_sw";
|
||||||
|
break;
|
||||||
|
case GroupId::TYPE_LC4_SW:
|
||||||
|
suffix = "lc4_sw";
|
||||||
|
break;
|
||||||
|
case GroupId::TYPE_LC5_SW:
|
||||||
|
suffix = "lc5_sw";
|
||||||
|
break;
|
||||||
|
case GroupId::TYPE_LC6_SW:
|
||||||
|
suffix = "lc6_sw";
|
||||||
|
break;
|
||||||
|
case GroupId::TYPE_LC7_SW:
|
||||||
|
suffix = "lc7_sw";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return IdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return id("X" + std::to_string(group.x) + "/Y" + std::to_string(group.y) + "/" + suffix);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<GroupId> Arch::getGroups() const
|
std::vector<GroupId> Arch::getGroups() const
|
||||||
{
|
{
|
||||||
std::vector<GroupId> ret;
|
std::vector<GroupId> ret;
|
||||||
|
|
||||||
|
for (int y = 0; y < chip_info->height; y++) {
|
||||||
|
for (int x = 0; x < chip_info->width; x++) {
|
||||||
|
TileType type = chip_info->tile_grid[y * chip_info->width + x];
|
||||||
|
if (type == TILE_NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
GroupId group;
|
||||||
|
group.type = GroupId::TYPE_FRAME;
|
||||||
|
group.x = x;
|
||||||
|
group.y = y;
|
||||||
|
// ret.push_back(group);
|
||||||
|
|
||||||
|
group.type = GroupId::TYPE_MAIN_SW;
|
||||||
|
ret.push_back(group);
|
||||||
|
|
||||||
|
group.type = GroupId::TYPE_LOCAL_SW;
|
||||||
|
ret.push_back(group);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (type == TILE_LOGIC)
|
||||||
|
{
|
||||||
|
group.type = GroupId::TYPE_LC0_SW;
|
||||||
|
ret.push_back(group);
|
||||||
|
|
||||||
|
group.type = GroupId::TYPE_LC1_SW;
|
||||||
|
ret.push_back(group);
|
||||||
|
|
||||||
|
group.type = GroupId::TYPE_LC2_SW;
|
||||||
|
ret.push_back(group);
|
||||||
|
|
||||||
|
group.type = GroupId::TYPE_LC3_SW;
|
||||||
|
ret.push_back(group);
|
||||||
|
|
||||||
|
group.type = GroupId::TYPE_LC4_SW;
|
||||||
|
ret.push_back(group);
|
||||||
|
|
||||||
|
group.type = GroupId::TYPE_LC5_SW;
|
||||||
|
ret.push_back(group);
|
||||||
|
|
||||||
|
group.type = GroupId::TYPE_LC6_SW;
|
||||||
|
ret.push_back(group);
|
||||||
|
|
||||||
|
group.type = GroupId::TYPE_LC7_SW;
|
||||||
|
ret.push_back(group);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,15 +644,63 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
|||||||
std::vector<GraphicElement> ret;
|
std::vector<GraphicElement> ret;
|
||||||
|
|
||||||
if (decal.type == DecalId::TYPE_FRAME) {
|
if (decal.type == DecalId::TYPE_FRAME) {
|
||||||
for (int x = 0; x <= chip_info->width; x++)
|
/* nothing */
|
||||||
for (int y = 0; y <= chip_info->height; y++) {
|
}
|
||||||
GraphicElement el;
|
|
||||||
el.type = GraphicElement::G_LINE;
|
if (decal.type == DecalId::TYPE_GROUP) {
|
||||||
el.x1 = x - 0.05, el.x2 = x + 0.05, el.y1 = y, el.y2 = y, el.z = 0;
|
int type = (decal.index >> 16) & 255;
|
||||||
ret.push_back(el);
|
int x = (decal.index >> 8) & 255;
|
||||||
el.x1 = x, el.x2 = x, el.y1 = y - 0.05, el.y2 = y + 0.05, el.z = 0;
|
int y = decal.index & 255;
|
||||||
ret.push_back(el);
|
|
||||||
}
|
if (type == GroupId::TYPE_FRAME) {
|
||||||
|
GraphicElement el;
|
||||||
|
el.type = GraphicElement::G_LINE;
|
||||||
|
el.style = GraphicElement::G_FRAME;
|
||||||
|
|
||||||
|
el.x1 = x + 0.01, el.x2 = x + 0.02, el.y1 = y + 0.01, el.y2 = y + 0.01;
|
||||||
|
ret.push_back(el);
|
||||||
|
el.x1 = x + 0.01, el.x2 = x + 0.01, el.y1 = y + 0.01, el.y2 = y + 0.02;
|
||||||
|
ret.push_back(el);
|
||||||
|
|
||||||
|
el.x1 = x + 0.99, el.x2 = x + 0.98, el.y1 = y + 0.01, el.y2 = y + 0.01;
|
||||||
|
ret.push_back(el);
|
||||||
|
el.x1 = x + 0.99, el.x2 = x + 0.99, el.y1 = y + 0.01, el.y2 = y + 0.02;
|
||||||
|
ret.push_back(el);
|
||||||
|
|
||||||
|
el.x1 = x + 0.99, el.x2 = x + 0.98, el.y1 = y + 0.99, el.y2 = y + 0.99;
|
||||||
|
ret.push_back(el);
|
||||||
|
el.x1 = x + 0.99, el.x2 = x + 0.99, el.y1 = y + 0.99, el.y2 = y + 0.98;
|
||||||
|
ret.push_back(el);
|
||||||
|
|
||||||
|
el.x1 = x + 0.01, el.x2 = x + 0.02, el.y1 = y + 0.99, el.y2 = y + 0.99;
|
||||||
|
ret.push_back(el);
|
||||||
|
el.x1 = x + 0.01, el.x2 = x + 0.01, el.y1 = y + 0.99, el.y2 = y + 0.98;
|
||||||
|
ret.push_back(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == GroupId::TYPE_MAIN_SW) {
|
||||||
|
GraphicElement el;
|
||||||
|
el.type = GraphicElement::G_BOX;
|
||||||
|
el.style = GraphicElement::G_FRAME;
|
||||||
|
|
||||||
|
el.x1 = x + main_swbox_x1;
|
||||||
|
el.x2 = x + main_swbox_x2;
|
||||||
|
el.y1 = y + main_swbox_y1;
|
||||||
|
el.y2 = y + main_swbox_y2;
|
||||||
|
ret.push_back(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == GroupId::TYPE_LOCAL_SW) {
|
||||||
|
GraphicElement el;
|
||||||
|
el.type = GraphicElement::G_BOX;
|
||||||
|
el.style = GraphicElement::G_FRAME;
|
||||||
|
|
||||||
|
el.x1 = x + local_swbox_x1;
|
||||||
|
el.x2 = x + local_swbox_x2;
|
||||||
|
el.y1 = y + local_swbox_y1;
|
||||||
|
el.y2 = y + local_swbox_y2;
|
||||||
|
ret.push_back(el);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decal.type == DecalId::TYPE_WIRE) {
|
if (decal.type == DecalId::TYPE_WIRE) {
|
||||||
@ -588,103 +735,32 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
|||||||
(chip_info->bel_data[bel.index].z) * logic_cell_pitch;
|
(chip_info->bel_data[bel.index].z) * logic_cell_pitch;
|
||||||
el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 +
|
el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 +
|
||||||
(chip_info->bel_data[bel.index].z) * logic_cell_pitch;
|
(chip_info->bel_data[bel.index].z) * logic_cell_pitch;
|
||||||
el.z = 0;
|
|
||||||
ret.push_back(el);
|
ret.push_back(el);
|
||||||
|
|
||||||
if (chip_info->bel_data[bel.index].z == 0) {
|
|
||||||
int tx = chip_info->bel_data[bel.index].x;
|
|
||||||
int ty = chip_info->bel_data[bel.index].y;
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bel_type == TYPE_SB_IO) {
|
if (bel_type == TYPE_SB_IO) {
|
||||||
if (chip_info->bel_data[bel.index].x == 0 || chip_info->bel_data[bel.index].x == chip_info->width - 1) {
|
GraphicElement el;
|
||||||
GraphicElement el;
|
el.type = GraphicElement::G_BOX;
|
||||||
el.type = GraphicElement::G_BOX;
|
el.style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
|
||||||
el.x1 = chip_info->bel_data[bel.index].x + 0.1;
|
el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1;
|
||||||
el.x2 = chip_info->bel_data[bel.index].x + 0.9;
|
el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2;
|
||||||
if (chip_info->bel_data[bel.index].z == 0) {
|
el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1 +
|
||||||
el.y1 = chip_info->bel_data[bel.index].y + 0.10;
|
(4 * chip_info->bel_data[bel.index].z) * logic_cell_pitch;
|
||||||
el.y2 = chip_info->bel_data[bel.index].y + 0.45;
|
el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 +
|
||||||
} else {
|
(4 * chip_info->bel_data[bel.index].z + 3) * logic_cell_pitch;
|
||||||
el.y1 = chip_info->bel_data[bel.index].y + 0.55;
|
ret.push_back(el);
|
||||||
el.y2 = chip_info->bel_data[bel.index].y + 0.90;
|
|
||||||
}
|
|
||||||
el.z = 0;
|
|
||||||
ret.push_back(el);
|
|
||||||
} else {
|
|
||||||
GraphicElement el;
|
|
||||||
el.type = GraphicElement::G_BOX;
|
|
||||||
if (chip_info->bel_data[bel.index].z == 0) {
|
|
||||||
el.x1 = chip_info->bel_data[bel.index].x + 0.10;
|
|
||||||
el.x2 = chip_info->bel_data[bel.index].x + 0.45;
|
|
||||||
} else {
|
|
||||||
el.x1 = chip_info->bel_data[bel.index].x + 0.55;
|
|
||||||
el.x2 = chip_info->bel_data[bel.index].x + 0.90;
|
|
||||||
}
|
|
||||||
el.y1 = chip_info->bel_data[bel.index].y + 0.1;
|
|
||||||
el.y2 = chip_info->bel_data[bel.index].y + 0.9;
|
|
||||||
el.z = 0;
|
|
||||||
ret.push_back(el);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bel_type == TYPE_ICESTORM_RAM) {
|
if (bel_type == TYPE_ICESTORM_RAM) {
|
||||||
for (int i = 0; i < 2; i++) {
|
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;
|
GraphicElement el;
|
||||||
el.type = GraphicElement::G_BOX;
|
el.type = GraphicElement::G_BOX;
|
||||||
el.style = decal.active ? 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 + i;
|
||||||
el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + 7 * logic_cell_pitch;
|
el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + i + 7 * logic_cell_pitch;
|
||||||
el.z = 0;
|
|
||||||
ret.push_back(el);
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -696,26 +772,26 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
|||||||
|
|
||||||
bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, delay_t &delay) const
|
bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, delay_t &delay) const
|
||||||
{
|
{
|
||||||
if (cell->type == id("ICESTORM_LC")) {
|
if (cell->type == id_icestorm_lc) {
|
||||||
if ((fromPort == id("I0") || fromPort == id("I1") || fromPort == id("I2") || fromPort == id("I3")) &&
|
if ((fromPort == id_i0 || fromPort == id_i1 || fromPort == id_i2 || fromPort == id_i3) &&
|
||||||
(toPort == id("O") || toPort == id("LO"))) {
|
(toPort == id_o || toPort == id_lo)) {
|
||||||
delay = 450;
|
delay = 450;
|
||||||
return true;
|
return true;
|
||||||
} else if (fromPort == id("CIN") && toPort == id("COUT")) {
|
} else if (fromPort == id_cin && toPort == id_cout) {
|
||||||
delay = 120;
|
delay = 120;
|
||||||
return true;
|
return true;
|
||||||
} else if (fromPort == id("I1") && toPort == id("COUT")) {
|
} else if (fromPort == id_i1 && toPort == id_cout) {
|
||||||
delay = 260;
|
delay = 260;
|
||||||
return true;
|
return true;
|
||||||
} else if (fromPort == id("I2") && toPort == id("COUT")) {
|
} else if (fromPort == id_i2 && toPort == id_cout) {
|
||||||
delay = 230;
|
delay = 230;
|
||||||
return true;
|
return true;
|
||||||
} else if (fromPort == id("CLK") && toPort == id("O")) {
|
} else if (fromPort == id_clk && toPort == id_o) {
|
||||||
delay = 540;
|
delay = 540;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (cell->type == id("ICESTORM_RAM")) {
|
} else if (cell->type == id_icestorm_ram) {
|
||||||
if (fromPort == id("RCLK")) {
|
if (fromPort == id_rclk) {
|
||||||
delay = 2140;
|
delay = 2140;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -725,14 +801,14 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort
|
|||||||
|
|
||||||
IdString Arch::getPortClock(const CellInfo *cell, IdString port) const
|
IdString Arch::getPortClock(const CellInfo *cell, IdString port) const
|
||||||
{
|
{
|
||||||
if (cell->type == id("ICESTORM_LC") && bool_or_default(cell->params, id("DFF_ENABLE"))) {
|
if (cell->type == id_icestorm_lc && cell->lcInfo.dffEnable) {
|
||||||
if (port != id("LO") && port != id("CIN") && port != id("COUT"))
|
if (port != id_lo && port != id_cin && port != id_cout)
|
||||||
return id("CLK");
|
return id_clk;
|
||||||
} else if (cell->type == id("ICESTORM_RAM")) {
|
} else if (cell->type == id_icestorm_ram) {
|
||||||
if (port.str(this)[0] == 'R')
|
if (port.str(this)[0] == 'R')
|
||||||
return id("RCLK");
|
return id_rclk;
|
||||||
else
|
else
|
||||||
return id("WCLK");
|
return id_wclk;
|
||||||
}
|
}
|
||||||
return IdString();
|
return IdString();
|
||||||
}
|
}
|
||||||
|
@ -469,6 +469,8 @@ struct Arch : BaseCtx
|
|||||||
return id(chip_info->wire_data[wire.index].name.get());
|
return id(chip_info->wire_data[wire.index].name.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdString getWireType(WireId wire) const { return IdString(); }
|
||||||
|
|
||||||
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
|
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
|
||||||
|
|
||||||
void bindWire(WireId wire, IdString net, PlaceStrength strength)
|
void bindWire(WireId wire, IdString net, PlaceStrength strength)
|
||||||
@ -611,6 +613,8 @@ struct Arch : BaseCtx
|
|||||||
|
|
||||||
IdString getPipName(PipId pip) const;
|
IdString getPipName(PipId pip) const;
|
||||||
|
|
||||||
|
IdString getPipType(PipId pip) const { return IdString(); }
|
||||||
|
|
||||||
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
|
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
|
||||||
|
|
||||||
WireId getPipSrcWire(PipId pip) const
|
WireId getPipSrcWire(PipId pip) const
|
||||||
@ -739,6 +743,9 @@ struct Arch : BaseCtx
|
|||||||
IdString id_cen, id_clk, id_sr;
|
IdString id_cen, id_clk, id_sr;
|
||||||
IdString id_i0, id_i1, id_i2, id_i3;
|
IdString id_i0, id_i1, id_i2, id_i3;
|
||||||
IdString id_dff_en, id_neg_clk;
|
IdString id_dff_en, id_neg_clk;
|
||||||
|
IdString id_cin, id_cout;
|
||||||
|
IdString id_o, id_lo;
|
||||||
|
IdString id_icestorm_ram, id_rclk, id_wclk;
|
||||||
|
|
||||||
// -------------------------------------------------
|
// -------------------------------------------------
|
||||||
BelPin getIOBSharingPLLPin(BelId pll, PortPin pll_pin) const
|
BelPin getIOBSharingPLLPin(BelId pll, PortPin pll_pin) const
|
||||||
|
6
ice40/benchmark/.gitignore
vendored
Normal file
6
ice40/benchmark/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
hx8kdemo.log
|
||||||
|
hx8kdemo.blif
|
||||||
|
hx8kdemo.json
|
||||||
|
hx8kdemo_[an][0-9].asc
|
||||||
|
hx8kdemo_[an][0-9].log
|
||||||
|
report_[an][0-9].txt
|
@ -10,14 +10,18 @@ report_n$1.txt: hx8kdemo_n$1.asc
|
|||||||
icetime -m -r report_n$1.txt -d hx8k hx8kdemo_n$1.asc
|
icetime -m -r report_n$1.txt -d hx8k hx8kdemo_n$1.asc
|
||||||
|
|
||||||
hx8kdemo_a$1.asc: hx8kdemo.blif
|
hx8kdemo_a$1.asc: hx8kdemo.blif
|
||||||
arachne-pnr -d 8k -p hx8kdemo.pcf -o hx8kdemo_a$1.asc -s $1 hx8kdemo.blif
|
arachne-pnr -d 8k -p hx8kdemo.pcf -o hx8kdemo_a$1.asc -s 1$1 hx8kdemo.blif > hx8kdemo_a$1.log 2>&1
|
||||||
|
|
||||||
hx8kdemo_n$1.asc: hx8kdemo.json
|
hx8kdemo_n$1.asc: hx8kdemo.json
|
||||||
nextpnr-ice40 --asc hx8kdemo_n$1.asc --json hx8kdemo.json --pcf hx8kdemo.pcf --hx8k --seed $1
|
../../nextpnr-ice40 --asc hx8kdemo_n$1.asc --json hx8kdemo.json --pcf hx8kdemo.pcf --hx8k --seed 1$1 > hx8kdemo_n$1.log 2>&1
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(foreach i,1 2 3 4 5 6 7 8,$(eval $(call mkreport,$(i))))
|
$(foreach i,0 1 2 3 4 5 6 7 8 9,$(eval $(call mkreport,$(i))))
|
||||||
|
|
||||||
hx8kdemo.blif: hx8kdemo.json
|
hx8kdemo.blif: hx8kdemo.json
|
||||||
hx8kdemo.json: hx8kdemo.v spimemio.v simpleuart.v picosoc.v picorv32.v
|
hx8kdemo.json: hx8kdemo.v spimemio.v simpleuart.v picosoc.v picorv32.v
|
||||||
yosys -ql hx8kdemo.log -p 'synth_ice40 -top hx8kdemo -blif hx8kdemo.blif -json hx8kdemo.json' $^
|
yosys -ql hx8kdemo.log -p 'synth_ice40 -top hx8kdemo -blif hx8kdemo.blif -json hx8kdemo.json' $^
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f hx8kdemo.log hx8kdemo.blif hx8kdemo.json
|
||||||
|
rm -f hx8kdemo_[an][0-9].asc hx8kdemo_[an][0-9].log report_[an][0-9].txt
|
||||||
|
69
ice40/benchmark/report.ipynb
Normal file
69
ice40/benchmark/report.ipynb
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"collapsed": false
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"%matplotlib inline\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import matplotlib.pyplot as plt\n",
|
||||||
|
"import subprocess\n",
|
||||||
|
"\n",
|
||||||
|
"gitrev = subprocess.getoutput(\"git rev-parse --short HEAD\")\n",
|
||||||
|
"\n",
|
||||||
|
"data_a = 1 + np.zeros(10)\n",
|
||||||
|
"data_n = 1 + np.zeros(10)\n",
|
||||||
|
"\n",
|
||||||
|
"for i in range(10):\n",
|
||||||
|
" try:\n",
|
||||||
|
" with open(\"report_a%d.txt\" % i, \"r\") as f:\n",
|
||||||
|
" for line in f:\n",
|
||||||
|
" if line.startswith(\"Total path delay:\"):\n",
|
||||||
|
" data_a[i] = float(line.split()[3])\n",
|
||||||
|
" except:\n",
|
||||||
|
" pass\n",
|
||||||
|
" try:\n",
|
||||||
|
" with open(\"report_n%d.txt\" % i, \"r\") as f:\n",
|
||||||
|
" for line in f:\n",
|
||||||
|
" if line.startswith(\"Total path delay:\"):\n",
|
||||||
|
" data_n[i] = float(line.split()[3])\n",
|
||||||
|
" except:\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"plt.figure(figsize=(9,3))\n",
|
||||||
|
"plt.title(\"nextpnr -- ice40/benchmark/ -- %s\" % gitrev)\n",
|
||||||
|
"plt.bar(np.arange(10), data_a, color='blue')\n",
|
||||||
|
"plt.bar(15+np.arange(10), data_n, color='red')\n",
|
||||||
|
"plt.ylabel('Longest path (ns)')\n",
|
||||||
|
"plt.xticks([5, 20], [\"arachne-pnr\", \"nextpnr\"])\n",
|
||||||
|
"plt.xlim(-2, 27)\n",
|
||||||
|
"plt.show()"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.5.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 1
|
||||||
|
}
|
@ -566,9 +566,8 @@ void write_asc(const Context *ctx, std::ostream &out)
|
|||||||
set_config(ti, config.at(y).at(x),
|
set_config(ti, config.at(y).at(x),
|
||||||
"Cascade.IPCON_LC0" + std::to_string(lc_idx) + "_inmux02_5", true);
|
"Cascade.IPCON_LC0" + std::to_string(lc_idx) + "_inmux02_5", true);
|
||||||
else
|
else
|
||||||
set_config(ti, config.at(y).at(x),
|
set_config(ti, config.at(y).at(x), "Cascade.MULT" + std::to_string(int(tile - TILE_DSP0)) +
|
||||||
"Cascade.MULT" + std::to_string(int(tile - TILE_DSP0)) + "_LC0" +
|
"_LC0" + std::to_string(lc_idx) + "_inmux02_5",
|
||||||
std::to_string(lc_idx) + "_inmux02_5",
|
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,7 +675,8 @@ class BinaryBlobAssembler:
|
|||||||
print("ref %s %s" % (name, comment))
|
print("ref %s %s" % (name, comment))
|
||||||
|
|
||||||
def s(self, s, comment):
|
def s(self, s, comment):
|
||||||
print("str %s" % s)
|
assert "|" not in s
|
||||||
|
print("str |%s| %s" % (s, comment))
|
||||||
|
|
||||||
def u8(self, v, comment):
|
def u8(self, v, comment):
|
||||||
if comment is None:
|
if comment is None:
|
||||||
|
11
ice40/gfx.cc
11
ice40/gfx.cc
@ -701,6 +701,17 @@ void gfxTilePip(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId src,
|
|||||||
|
|
||||||
if (getWireXY_local(src, x1, y1) && getWireXY_local(dst, x2, y2))
|
if (getWireXY_local(src, x1, y1) && getWireXY_local(dst, x2, y2))
|
||||||
pipGfx(g, x, y, x1, y1, x2, y2, local_swbox_x1, local_swbox_y1, local_swbox_x2, local_swbox_y2, style);
|
pipGfx(g, x, y, x1, y1, x2, y2, local_swbox_x1, local_swbox_y1, local_swbox_x2, local_swbox_y2, style);
|
||||||
|
|
||||||
|
if (src == TILE_WIRE_CARRY_IN && dst == TILE_WIRE_CARRY_IN_MUX) {
|
||||||
|
GraphicElement el;
|
||||||
|
el.type = GraphicElement::G_ARROW;
|
||||||
|
el.style = style;
|
||||||
|
el.x1 = x + logic_cell_x1 + 0.005 * 3;
|
||||||
|
el.x2 = el.x1;
|
||||||
|
el.y1 = y + 0.01;
|
||||||
|
el.y2 = y + 0.02;
|
||||||
|
g.push_back(el);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -144,18 +144,16 @@ int main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
if (vm.count("help") || argc == 1) {
|
if (vm.count("help") || argc == 1) {
|
||||||
help:
|
help:
|
||||||
std::cout << boost::filesystem::basename(argv[0])
|
std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git "
|
||||||
<< " -- Next Generation Place and Route (git "
|
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
std::cout << options << "\n";
|
std::cout << options << "\n";
|
||||||
return argc != 1;
|
return argc != 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("version")) {
|
if (vm.count("version")) {
|
||||||
std::cout << boost::filesystem::basename(argv[0])
|
std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git "
|
||||||
<< " -- Next Generation Place and Route (git "
|
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,12 +662,12 @@ static void pack_special(Context *ctx)
|
|||||||
|
|
||||||
auto feedback_path = packed->params[ctx->id("FEEDBACK_PATH")];
|
auto feedback_path = packed->params[ctx->id("FEEDBACK_PATH")];
|
||||||
packed->params[ctx->id("FEEDBACK_PATH")] =
|
packed->params[ctx->id("FEEDBACK_PATH")] =
|
||||||
feedback_path == "DELAY"
|
feedback_path == "DELAY" ? "0" : feedback_path == "SIMPLE"
|
||||||
? "0"
|
? "1"
|
||||||
: feedback_path == "SIMPLE" ? "1"
|
: feedback_path == "PHASE_AND_DELAY"
|
||||||
: feedback_path == "PHASE_AND_DELAY"
|
? "2"
|
||||||
? "2"
|
: feedback_path == "EXTERNAL" ? "6"
|
||||||
: feedback_path == "EXTERNAL" ? "6" : feedback_path;
|
: feedback_path;
|
||||||
packed->params[ctx->id("PLLTYPE")] = std::to_string(sb_pll40_type(ctx, ci));
|
packed->params[ctx->id("PLLTYPE")] = std::to_string(sb_pll40_type(ctx, ci));
|
||||||
|
|
||||||
NetInfo *pad_packagepin_net = nullptr;
|
NetInfo *pad_packagepin_net = nullptr;
|
||||||
|
@ -7,7 +7,6 @@ import re
|
|||||||
num_runs = 8
|
num_runs = 8
|
||||||
|
|
||||||
if not path.exists("picorv32.json"):
|
if not path.exists("picorv32.json"):
|
||||||
os.remove("picorv32.json")
|
|
||||||
subprocess.run(["wget", "https://raw.githubusercontent.com/cliffordwolf/picorv32/master/picorv32.v"], check=True)
|
subprocess.run(["wget", "https://raw.githubusercontent.com/cliffordwolf/picorv32/master/picorv32.v"], check=True)
|
||||||
subprocess.run(["yosys", "-q", "-p", "synth_ice40 -json picorv32.json -top top", "picorv32.v", "picorv32_top.v"], check=True)
|
subprocess.run(["yosys", "-q", "-p", "synth_ice40 -json picorv32.json -top top", "picorv32.v", "picorv32_top.v"], check=True)
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ for i in range(num_runs):
|
|||||||
ascfile = "picorv32_work/picorv32_s{}.asc".format(run)
|
ascfile = "picorv32_work/picorv32_s{}.asc".format(run)
|
||||||
if path.exists(ascfile):
|
if path.exists(ascfile):
|
||||||
os.remove(ascfile)
|
os.remove(ascfile)
|
||||||
result = subprocess.run(["../nextpnr-ice40", "--hx8k", "--seed", str(run), "--json", "picorv32.json", "--asc", ascfile], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
|
result = subprocess.run(["../nextpnr-ice40", "--hx8k", "--seed", str(run), "--json", "picorv32.json", "--asc", ascfile, "--freq", "70"], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
print("Run {} failed!".format(run))
|
print("Run {} failed!".format(run))
|
||||||
else:
|
else:
|
||||||
|
@ -90,21 +90,20 @@ static int get_cell_evilness(const Context *ctx, const CellInfo *cell)
|
|||||||
// This returns how "evil" a logic cell is, and thus how likely it is to be ripped up
|
// This returns how "evil" a logic cell is, and thus how likely it is to be ripped up
|
||||||
// during logic tile legalisation
|
// during logic tile legalisation
|
||||||
int score = 0;
|
int score = 0;
|
||||||
if (get_net_or_empty(cell, ctx->id("I0")))
|
if (get_net_or_empty(cell, ctx->id_i0))
|
||||||
++score;
|
++score;
|
||||||
if (get_net_or_empty(cell, ctx->id("I1")))
|
if (get_net_or_empty(cell, ctx->id_i1))
|
||||||
++score;
|
++score;
|
||||||
if (get_net_or_empty(cell, ctx->id("I2")))
|
if (get_net_or_empty(cell, ctx->id_i2))
|
||||||
++score;
|
++score;
|
||||||
if (get_net_or_empty(cell, ctx->id("I3")))
|
if (get_net_or_empty(cell, ctx->id_i3))
|
||||||
++score;
|
++score;
|
||||||
if (bool_or_default(cell->params, ctx->id("DFF_ENABLE"))) {
|
if (cell->lcInfo.dffEnable) {
|
||||||
const NetInfo *cen = get_net_or_empty(cell, ctx->id("CEN")), *sr = get_net_or_empty(cell, ctx->id("SR"));
|
if (cell->lcInfo.cen)
|
||||||
if (cen)
|
|
||||||
score += 10;
|
score += 10;
|
||||||
if (sr)
|
if (cell->lcInfo.sr)
|
||||||
score += 10;
|
score += 10;
|
||||||
if (bool_or_default(cell->params, ctx->id("NEG_CLK")))
|
if (cell->lcInfo.negClk)
|
||||||
score += 5;
|
score += 5;
|
||||||
}
|
}
|
||||||
return score;
|
return score;
|
||||||
|
Loading…
Reference in New Issue
Block a user