aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-12-17 07:11:31 +0000
committerGitHub <noreply@github.com>2021-12-17 07:11:31 +0000
commita12057777334be8e45e540c63c0da199a59489ba (patch)
tree2394fb1f6461efcffc7c7d169bf67d9ea414c369
parentd04cfd5f0f6da184f5b8a03f0ce18fbd1d98eca3 (diff)
parent064b6d808e9b91c93258a53ac1a18b3b84431545 (diff)
downloadnextpnr-a12057777334be8e45e540c63c0da199a59489ba.tar.gz
nextpnr-a12057777334be8e45e540c63c0da199a59489ba.tar.bz2
nextpnr-a12057777334be8e45e540c63c0da199a59489ba.zip
Merge pull request #858 from cr1901/machxo2
MachXO2 Checkpoint 2
-rw-r--r--README.md1
-rw-r--r--machxo2/bitstream.cc37
-rw-r--r--machxo2/examples/demo-vhdl.sh2
-rw-r--r--machxo2/examples/demo.sh2
-rw-r--r--machxo2/examples/mitertest.sh5
-rw-r--r--machxo2/examples/simple.sh2
-rw-r--r--machxo2/examples/simtest.sh2
-rw-r--r--machxo2/main.cc3
-rw-r--r--machxo2/pack.cc47
9 files changed, 83 insertions, 18 deletions
diff --git a/README.md b/README.md
index c1b28f15..14128b87 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ Currently nextpnr supports:
* Lattice Nexus devices supported by [Project Oxide](https://github.com/gatecat/prjoxide)
* Gowin LittleBee devices supported by [Project Apicula](https://github.com/YosysHQ/apicula)
* *(experimental)* Cyclone V devices supported by [Mistral](https://github.com/Ravenslofty/mistral)
+ * *(experimental)* Lattice MachXO2 devices supported by [Project Trellis](https://github.com/YosysHQ/prjtrellis)
* *(experimental)* a "generic" back-end for user-defined architectures
There is some work in progress towards [support for Xilinx devices](https://github.com/gatecat/nextpnr-xilinx/) but it is not upstream and not intended for end users at the present time. We hope to see more FPGA families supported in the future. We would love your help in developing this awesome new project!
diff --git a/machxo2/bitstream.cc b/machxo2/bitstream.cc
index ed67975a..f624d91b 100644
--- a/machxo2/bitstream.cc
+++ b/machxo2/bitstream.cc
@@ -19,6 +19,7 @@
*/
#include <fstream>
+#include <iostream>
#include "bitstream.h"
#include "config.h"
@@ -59,16 +60,25 @@ static std::string get_trellis_wirename(Context *ctx, Location loc, WireId wire)
// Handle MachXO2's wonderful naming quirks for wires in left/right tiles, whose
// relative coords push them outside the bounds of the chip.
+ // Indents are based on wires proximity/purpose.
auto is_pio_wire = [](std::string name) {
+ // clang-format off
return (name.find("DI") != std::string::npos || name.find("JDI") != std::string::npos ||
- name.find("PADD") != std::string::npos || name.find("INDD") != std::string::npos ||
- name.find("IOLDO") != std::string::npos || name.find("IOLTO") != std::string::npos ||
- name.find("JCE") != std::string::npos || name.find("JCLK") != std::string::npos ||
- name.find("JLSR") != std::string::npos || name.find("JONEG") != std::string::npos ||
- name.find("JOPOS") != std::string::npos || name.find("JTS") != std::string::npos ||
+ name.find("PADD") != std::string::npos || name.find("INDD") != std::string::npos ||
+ name.find("IOLDO") != std::string::npos || name.find("IOLTO") != std::string::npos ||
+ // JCE0-3, JCLK0-3, JLSR0-3 connect to PIO wires named JCEA-D, JCLKA-D, JLSRA-D.
+ name.find("JCEA") != std::string::npos || name.find("JCEB") != std::string::npos ||
+ name.find("JCEC") != std::string::npos || name.find("JCED") != std::string::npos ||
+ name.find("JCLKA") != std::string::npos || name.find("JCLKB") != std::string::npos ||
+ name.find("JCLKC") != std::string::npos || name.find("JCLKD") != std::string::npos ||
+ name.find("JLSRA") != std::string::npos || name.find("JLSRB") != std::string::npos ||
+ name.find("JLSRC") != std::string::npos || name.find("JLSRD") != std::string::npos ||
+ name.find("JONEG") != std::string::npos || name.find("JOPOS") != std::string::npos ||
+ name.find("JTS") != std::string::npos ||
name.find("JIN") != std::string::npos || name.find("JIP") != std::string::npos ||
// Connections to global mux
name.find("JINCK") != std::string::npos);
+ // clang-format on
};
if (prefix2 == "G_" || prefix2 == "L_" || prefix2 == "R_" || prefix7 == "BRANCH_")
@@ -92,10 +102,19 @@ static std::string get_trellis_wirename(Context *ctx, Location loc, WireId wire)
if (loc == wire.location) {
// TODO: JINCK is not currently handled by this.
if (is_pio_wire(basename)) {
- if (wire.location.x == 0)
- return "W1_" + basename;
- else if (wire.location.x == max_col)
- return "E1_" + basename;
+ if (wire.location.x == 0) {
+ std::string pio_name = "W1_" + basename;
+ if (ctx->verbose)
+ log_info("PIO wire %s was adjusted by W1 to form Trellis name %s.\n", ctx->nameOfWire(wire),
+ pio_name.c_str());
+ return pio_name;
+ } else if (wire.location.x == max_col) {
+ std::string pio_name = "E1_" + basename;
+ if (ctx->verbose)
+ log_info("PIO wire %s was adjusted by E1 to form Trellis name %s.\n", ctx->nameOfWire(wire),
+ pio_name.c_str());
+ return pio_name;
+ }
}
return basename;
}
diff --git a/machxo2/examples/demo-vhdl.sh b/machxo2/examples/demo-vhdl.sh
index 4bdab54a..ed1f7d80 100644
--- a/machxo2/examples/demo-vhdl.sh
+++ b/machxo2/examples/demo-vhdl.sh
@@ -19,6 +19,6 @@ set -ex
${YOSYS:-yosys} -p "ghdl --std=08 prims.vhd ${1}.vhd -e;
attrmap -tocase LOC
synth_machxo2 -json ${1}-vhdl.json"
-${NEXTPNR:-../../nextpnr-machxo2} --1200 --package QFN32 --no-iobs --json $1-vhdl.json --textcfg $1-vhdl.txt
+${NEXTPNR:-../../nextpnr-machxo2} --1200 --package QFN32 --json $1-vhdl.json --textcfg $1-vhdl.txt
ecppack --compress $DB_ARG $1-vhdl.txt $1-vhdl.bit
tinyproga -b $1-vhdl.bit
diff --git a/machxo2/examples/demo.sh b/machxo2/examples/demo.sh
index 00cb0cd0..634fbb4d 100644
--- a/machxo2/examples/demo.sh
+++ b/machxo2/examples/demo.sh
@@ -17,6 +17,6 @@ fi
set -ex
${YOSYS:-yosys} -p "synth_machxo2 -json $1.json" $1.v
-${NEXTPNR:-../../nextpnr-machxo2} --1200 --package QFN32 --no-iobs --json $1.json --textcfg $1.txt
+${NEXTPNR:-../../nextpnr-machxo2} --1200 --package QFN32 --json $1.json --textcfg $1.txt
ecppack --compress $DB_ARG $1.txt $1.bit
tinyproga -b $1.bit
diff --git a/machxo2/examples/mitertest.sh b/machxo2/examples/mitertest.sh
index cfae28b7..b7ec2695 100644
--- a/machxo2/examples/mitertest.sh
+++ b/machxo2/examples/mitertest.sh
@@ -61,6 +61,7 @@ do_smt() {
miter -equiv -make_assert gold gate ${2}${1}_miter
hierarchy -top ${2}${1}_miter; proc;
opt_clean
+ flatten t:*FACADE_IO*
write_verilog ${2}${1}_miter.v
write_smt2 ${2}${1}_miter.smt2"
@@ -71,8 +72,8 @@ do_smt() {
set -ex
${YOSYS:-yosys} -p "read_verilog ${1}.v
- synth_machxo2 -noiopad -json ${1}.json"
-${NEXTPNR:-../../nextpnr-machxo2} $NEXTPNR_MODE --1200 --package QFN32 --no-iobs --json ${1}.json --write ${2}${1}.json
+ synth_machxo2 -json ${1}.json"
+${NEXTPNR:-../../nextpnr-machxo2} $NEXTPNR_MODE --1200 --package QFN32 --json ${1}.json --write ${2}${1}.json
${YOSYS:-yosys} -p "read_verilog -lib +/machxo2/cells_sim.v
read_json ${2}${1}.json
clean -purge
diff --git a/machxo2/examples/simple.sh b/machxo2/examples/simple.sh
index 1da60933..69706b9c 100644
--- a/machxo2/examples/simple.sh
+++ b/machxo2/examples/simple.sh
@@ -26,7 +26,7 @@ set -ex
${YOSYS:-yosys} -p "read_verilog ${1}.v
synth_machxo2 -json ${1}.json
show -format png -prefix ${1}"
-${NEXTPNR:-../../nextpnr-machxo2} $NEXTPNR_MODE --1200 --package QFN32 --no-iobs --json ${1}.json --write ${2}${1}.json
+${NEXTPNR:-../../nextpnr-machxo2} $NEXTPNR_MODE --1200 --package QFN32 --json ${1}.json --write ${2}${1}.json
${YOSYS:-yosys} -p "read_verilog -lib +/machxo2/cells_sim.v
read_json ${2}${1}.json
clean -purge
diff --git a/machxo2/examples/simtest.sh b/machxo2/examples/simtest.sh
index 2c7f6f30..0adf1751 100644
--- a/machxo2/examples/simtest.sh
+++ b/machxo2/examples/simtest.sh
@@ -30,7 +30,7 @@ set -ex
${YOSYS:-yosys} -p "read_verilog ${1}.v
synth_machxo2 -json ${1}.json"
-${NEXTPNR:-../../nextpnr-machxo2} $NEXTPNR_MODE --1200 --package QFN32 --no-iobs --json ${1}.json --write ${2}${1}.json
+${NEXTPNR:-../../nextpnr-machxo2} $NEXTPNR_MODE --1200 --package QFN32 --json ${1}.json --write ${2}${1}.json
${YOSYS:-yosys} -p "read_verilog -lib +/machxo2/cells_sim.v
read_json ${2}${1}.json
clean -purge
diff --git a/machxo2/main.cc b/machxo2/main.cc
index 53b765fb..e29e117b 100644
--- a/machxo2/main.cc
+++ b/machxo2/main.cc
@@ -69,7 +69,6 @@ po::options_description MachXO2CommandHandler::getArchOptions()
// specific.add_options()("lpf", po::value<std::vector<std::string>>(), "LPF pin constraint file(s)");
- specific.add_options()("no-iobs", "disable automatic IO buffer insertion (unimplemented- always enabled)");
return specific;
}
@@ -108,8 +107,6 @@ std::unique_ptr<Context> MachXO2CommandHandler::createContext(dict<std::string,
}
auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
- if (vm.count("no-iobs"))
- ctx->settings[ctx->id("disable_iobs")] = Property::State::S1;
return ctx;
}
diff --git a/machxo2/pack.cc b/machxo2/pack.cc
index 66d2d411..c53229ba 100644
--- a/machxo2/pack.cc
+++ b/machxo2/pack.cc
@@ -229,6 +229,45 @@ static bool is_nextpnr_iob(Context *ctx, CellInfo *cell)
static bool is_facade_iob(const Context *ctx, const CellInfo *cell) { return cell->type == id_FACADE_IO; }
+static bool nextpnr_iob_connects_only_facade_iob(Context *ctx, CellInfo *iob, NetInfo *&top)
+{
+ NPNR_ASSERT(is_nextpnr_iob(ctx, iob));
+
+ if (iob->type == ctx->id("$nextpnr_ibuf")) {
+ NetInfo *o = iob->ports.at(id_O).net;
+ top = o;
+
+ CellInfo *fio = net_only_drives(ctx, o, is_facade_iob, id_PAD, true);
+ return fio != nullptr;
+ } else if (iob->type == ctx->id("$nextpnr_obuf")) {
+ NetInfo *i = iob->ports.at(id_I).net;
+ top = i;
+
+ // If connected to a FACADE_IO PAD, the net attached to an I port of an
+ // $nextpnr_obuf will not have a driver, only users; an inout port
+ // like PAD cannot be a driver in nextpnr. So net_driven_by won't
+ // return anything. We exclude the IOB as one of the two users because
+ // we already know that the net drives the $nextpnr_obuf.
+ CellInfo *fio = net_only_drives(ctx, i, is_facade_iob, id_PAD, true, iob);
+ return fio != nullptr;
+ } else if (iob->type == ctx->id("$nextpnr_iobuf")) {
+ NetInfo *o = iob->ports.at(id_O).net;
+ top = o;
+
+ // When split_io is enabled in a frontend (it is for JSON), the I and O
+ // ports of a $nextpnr_iobuf are split; the I port connects to the
+ // driver of the original net before IOB insertion, and the O port
+ // connects everything else. Because FACADE_IO PADs cannot be a driver
+ // in nextpnr, the we can safely ignore the I port of an $nextpnr_iobuf
+ // for any JSON input we're interested in accepting.
+ CellInfo *fio_o = net_only_drives(ctx, o, is_facade_iob, id_PAD, true);
+ return fio_o != nullptr;
+ }
+
+ // Unreachable!
+ NPNR_ASSERT(false);
+}
+
// Pack IO buffers- Right now, all this does is remove $nextpnr_[io]buf cells.
// User is expected to manually instantiate FACADE_IO with BEL/IO_TYPE
// attributes.
@@ -241,6 +280,14 @@ static void pack_io(Context *ctx)
for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get();
if (is_nextpnr_iob(ctx, ci)) {
+ NetInfo *top;
+
+ if (!nextpnr_iob_connects_only_facade_iob(ctx, ci, top))
+ log_error("Top level net '%s' is not connected to a FACADE_IO PAD port.\n", top->name.c_str(ctx));
+
+ if (ctx->verbose)
+ log_info("Removing top-level IOBUF '%s' of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
+
for (auto &p : ci->ports)
disconnect_port(ctx, ci, p.first);
packed_cells.insert(ci->name);