aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/nextpnr.h2
-rw-r--r--common/pybindings.cc5
-rw-r--r--gui/mainwindow.cc12
-rw-r--r--gui/mainwindow.ui2
-rw-r--r--ice40/pack.cc39
-rw-r--r--ice40/pack_tests/place_constr.v54
-rwxr-xr-xice40/pack_tests/test.sh3
7 files changed, 104 insertions, 13 deletions
diff --git a/common/nextpnr.h b/common/nextpnr.h
index fc14299d..4288f7fc 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -110,7 +110,7 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX IdString>
return obj.index;
}
};
-}
+} // namespace std
NEXTPNR_NAMESPACE_BEGIN
diff --git a/common/pybindings.cc b/common/pybindings.cc
index 8aa831ca..7c43c84f 100644
--- a/common/pybindings.cc
+++ b/common/pybindings.cc
@@ -123,6 +123,11 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
def("parse_json", parse_json_shim);
def("load_design", load_design_shim);
+ class_<IdString>("IdString")
+ .def("__str__", &IdString::str,
+ return_value_policy<copy_const_reference>())
+ .def(self < self)
+ .def(self == self);
arch_wrap_python();
}
diff --git a/gui/mainwindow.cc b/gui/mainwindow.cc
index 31ce8fae..c436fd6c 100644
--- a/gui/mainwindow.cc
+++ b/gui/mainwindow.cc
@@ -16,6 +16,18 @@ MainWindow::MainWindow(Design *_design, QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow), design(_design)
{
ui->setupUi(this);
+ ui->treeWidget->setColumnCount(1);
+ ui->treeWidget->setHeaderLabel(QString("Items"));
+ QTreeWidgetItem *belroot = new QTreeWidgetItem(ui->treeWidget);
+ belroot->setText(0, QString("Bels"));
+ ui->treeWidget->insertTopLevelItem(0, belroot);
+ QList<QTreeWidgetItem *> items;
+ for (auto bel : design->chip.getBels()) {
+ auto name = design->chip.getBelName(bel);
+ items.append(new QTreeWidgetItem((QTreeWidget *)nullptr,
+ QStringList(QString(name.c_str()))));
+ }
+ belroot->addChildren(items);
PyImport_ImportModule("emb");
write = [this](std::string s) {
diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui
index 3fe0f400..7352af1f 100644
--- a/gui/mainwindow.ui
+++ b/gui/mainwindow.ui
@@ -64,7 +64,7 @@
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
- <widget class="QTreeView" name="treeView">
+ <widget class="QTreeWidget" name="treeWidget">
<property name="minimumSize">
<size>
<width>300</width>
diff --git a/ice40/pack.cc b/ice40/pack.cc
index a971dcc3..8f770a07 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -19,12 +19,12 @@
*/
#include "pack.h"
+#include <algorithm>
+#include <unordered_set>
#include "cells.h"
#include "design_utils.h"
#include "log.h"
-#include <unordered_set>
-
NEXTPNR_NAMESPACE_BEGIN
// Pack LUTs and LUT-FF pairs
@@ -39,6 +39,8 @@ static void pack_lut_lutffs(Design *design)
if (is_lut(ci)) {
CellInfo *packed = create_ice_cell(design, "ICESTORM_LC",
ci->name.str() + "_LC");
+ std::copy(ci->attrs.begin(), ci->attrs.end(),
+ std::inserter(packed->attrs, packed->attrs.begin()));
packed_cells.insert(ci->name);
new_cells.push_back(packed);
log_info("packed cell %s into %s\n", ci->name.c_str(),
@@ -47,14 +49,27 @@ static void pack_lut_lutffs(Design *design)
// TODO: LUT cascade
NetInfo *o = ci->ports.at("O").net;
CellInfo *dff = net_only_drives(o, is_ff, "D", true);
+ auto lut_bel = ci->attrs.find("BEL");
+ bool packed_dff = false;
if (dff) {
- lut_to_lc(ci, packed, false);
- dff_to_lc(dff, packed, false);
- design->nets.erase(o->name);
- packed_cells.insert(dff->name);
- log_info("packed cell %s into %s\n", dff->name.c_str(),
- packed->name.c_str());
- } else {
+ log_info("found attached dff %s\n", dff->name.c_str());
+ auto dff_bel = dff->attrs.find("BEL");
+ if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() &&
+ lut_bel->second != dff_bel->second) {
+ // Locations don't match, can't pack
+ } else {
+ lut_to_lc(ci, packed, false);
+ dff_to_lc(dff, packed, false);
+ design->nets.erase(o->name);
+ if (dff_bel != dff->attrs.end())
+ packed->attrs["BEL"] = dff_bel->second;
+ packed_cells.insert(dff->name);
+ log_info("packed cell %s into %s\n", dff->name.c_str(),
+ packed->name.c_str());
+ packed_dff = true;
+ }
+ }
+ if (!packed_dff) {
lut_to_lc(ci, packed, true);
}
}
@@ -77,7 +92,11 @@ static void pack_nonlut_ffs(Design *design)
CellInfo *ci = cell.second;
if (is_ff(ci)) {
CellInfo *packed = create_ice_cell(design, "ICESTORM_LC",
- ci->name.str() + "_LC");
+ ci->name.str() + "_DFFLC");
+ std::copy(ci->attrs.begin(), ci->attrs.end(),
+ std::inserter(packed->attrs, packed->attrs.begin()));
+ log_info("packed cell %s into %s\n", ci->name.c_str(),
+ packed->name.c_str());
packed_cells.insert(ci->name);
new_cells.push_back(packed);
dff_to_lc(ci, packed, true);
diff --git a/ice40/pack_tests/place_constr.v b/ice40/pack_tests/place_constr.v
new file mode 100644
index 00000000..f915a203
--- /dev/null
+++ b/ice40/pack_tests/place_constr.v
@@ -0,0 +1,54 @@
+module top(input clk, cen, rst, ina, inb, output outa, outb, outc, outd);
+
+wire temp0, temp1;
+
+(* BEL="1_1_lc0" *)
+SB_LUT4 #(
+ .LUT_INIT(2'b01)
+) lut0 (
+ .I3(),
+ .I2(),
+ .I1(),
+ .I0(ina),
+ .O(temp0)
+);
+
+
+(* BEL="1_3_lc0" *)
+SB_LUT4 #(
+ .LUT_INIT(2'b01)
+) lut1 (
+ .I3(),
+ .I2(),
+ .I1(),
+ .I0(inb),
+ .O(temp1)
+);
+
+(* BEL="1_1_lc0" *)
+SB_DFF ff0 (
+ .C(clk),
+ .D(temp1),
+ .Q(outa)
+);
+
+
+(* BEL="1_1_lc7" *)
+SB_DFF ff1 (
+ .C(clk),
+ .D(inb),
+ .Q(outb)
+);
+
+
+(* BEL="1_6_lc7" *)
+SB_DFF ff2 (
+ .C(clk),
+ .D(temp1),
+ .Q(outc)
+);
+
+
+assign outd = 1'b0;
+
+endmodule
diff --git a/ice40/pack_tests/test.sh b/ice40/pack_tests/test.sh
index 88ff5b1d..dd1f345c 100755
--- a/ice40/pack_tests/test.sh
+++ b/ice40/pack_tests/test.sh
@@ -5,7 +5,8 @@ yosys -p "synth_ice40 -nocarry -top io_wrapper; write_json ${NAME}.json" $1 io_w
../../nextpnr-ice40 --json ${NAME}.json --pack --asc ${NAME}.asc
icebox_vlog -p test.pcf ${NAME}.asc > ${NAME}_out.v
-yosys -p "rename chip gate;\
+yosys -p "read_verilog +/ice40/cells_sim.v;\
+ rename chip gate;\
read_verilog $1;\
rename top gold;\
hierarchy;\