From d2ac6dffbcd1bcb6dbf3cadd03f33794b2af5c80 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Fri, 29 Oct 2021 18:00:05 -0400 Subject: machxo2: Correct which PIO wires get adjusted when writing text bitstream. Add verbose logging for adjustments. --- machxo2/bitstream.cc | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'machxo2') diff --git a/machxo2/bitstream.cc b/machxo2/bitstream.cc index ed67975a..913d7b58 100644 --- a/machxo2/bitstream.cc +++ b/machxo2/bitstream.cc @@ -19,6 +19,7 @@ */ #include +#include #include "bitstream.h" #include "config.h" @@ -59,13 +60,20 @@ 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) { 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); @@ -92,10 +100,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; } -- cgit v1.2.3 From 365a871908f3b945fb19cfefb642fbde87dbf584 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Wed, 3 Nov 2021 13:53:57 -0400 Subject: machxo2: Add packing logic to forbid designs lacking FACADE_IO top-level ports. --- machxo2/pack.cc | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'machxo2') diff --git a/machxo2/pack.cc b/machxo2/pack.cc index 66d2d411..231cc99d 100644 --- a/machxo2/pack.cc +++ b/machxo2/pack.cc @@ -229,6 +229,44 @@ 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 +279,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); -- cgit v1.2.3 From be3788fa3004cfee1058293d5da6ba758f913e7e Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Fri, 5 Nov 2021 12:49:24 -0400 Subject: machxo2: Remove -noiopad option when generating miters for post-pnr verification. --- machxo2/examples/mitertest.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'machxo2') diff --git a/machxo2/examples/mitertest.sh b/machxo2/examples/mitertest.sh index cfae28b7..feafc0dd 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,7 +72,7 @@ do_smt() { set -ex ${YOSYS:-yosys} -p "read_verilog ${1}.v - synth_machxo2 -noiopad -json ${1}.json" + synth_machxo2 -json ${1}.json" ${NEXTPNR:-../../nextpnr-machxo2} $NEXTPNR_MODE --1200 --package QFN32 --no-iobs --json ${1}.json --write ${2}${1}.json ${YOSYS:-yosys} -p "read_verilog -lib +/machxo2/cells_sim.v read_json ${2}${1}.json -- cgit v1.2.3 From 4d757922572e6009777c6d533d410cdb2257c363 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Fri, 5 Nov 2021 13:26:05 -0400 Subject: machxo2: Remove no-iobs option. It was always enabled and should remain an implementation detail. --- machxo2/examples/demo-vhdl.sh | 2 +- machxo2/examples/demo.sh | 2 +- machxo2/examples/mitertest.sh | 2 +- machxo2/examples/simple.sh | 2 +- machxo2/examples/simtest.sh | 2 +- machxo2/main.cc | 3 --- 6 files changed, 5 insertions(+), 8 deletions(-) (limited to 'machxo2') 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 feafc0dd..b7ec2695 100644 --- a/machxo2/examples/mitertest.sh +++ b/machxo2/examples/mitertest.sh @@ -73,7 +73,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/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>(), "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 MachXO2CommandHandler::createContext(dict(new Context(chipArgs)); - if (vm.count("no-iobs")) - ctx->settings[ctx->id("disable_iobs")] = Property::State::S1; return ctx; } -- cgit v1.2.3 From 064b6d808e9b91c93258a53ac1a18b3b84431545 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Thu, 16 Dec 2021 17:09:29 -0500 Subject: clangformat. --- machxo2/bitstream.cc | 10 ++++++---- machxo2/pack.cc | 11 ++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) (limited to 'machxo2') diff --git a/machxo2/bitstream.cc b/machxo2/bitstream.cc index 913d7b58..f624d91b 100644 --- a/machxo2/bitstream.cc +++ b/machxo2/bitstream.cc @@ -62,6 +62,7 @@ static std::string get_trellis_wirename(Context *ctx, Location loc, WireId wire) // 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 || @@ -77,6 +78,7 @@ static std::string get_trellis_wirename(Context *ctx, Location loc, WireId wire) 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_") @@ -103,14 +105,14 @@ static std::string get_trellis_wirename(Context *ctx, Location loc, WireId wire) 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()); + 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()); + 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; } } diff --git a/machxo2/pack.cc b/machxo2/pack.cc index 231cc99d..c53229ba 100644 --- a/machxo2/pack.cc +++ b/machxo2/pack.cc @@ -229,16 +229,17 @@ 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) { +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")) { + 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")) { + } else if (iob->type == ctx->id("$nextpnr_obuf")) { NetInfo *i = iob->ports.at(id_I).net; top = i; @@ -249,7 +250,7 @@ static bool nextpnr_iob_connects_only_facade_iob(Context *ctx, CellInfo *iob, Ne // 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")) { + } else if (iob->type == ctx->id("$nextpnr_iobuf")) { NetInfo *o = iob->ports.at(id_O).net; top = o; @@ -281,7 +282,7 @@ static void pack_io(Context *ctx) if (is_nextpnr_iob(ctx, ci)) { NetInfo *top; - if(!nextpnr_iob_connects_only_facade_iob(ctx, ci, 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) -- cgit v1.2.3