diff options
author | gatecat <gatecat@ds0.me> | 2021-12-17 07:11:31 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-17 07:11:31 +0000 |
commit | a12057777334be8e45e540c63c0da199a59489ba (patch) | |
tree | 2394fb1f6461efcffc7c7d169bf67d9ea414c369 /machxo2 | |
parent | d04cfd5f0f6da184f5b8a03f0ce18fbd1d98eca3 (diff) | |
parent | 064b6d808e9b91c93258a53ac1a18b3b84431545 (diff) | |
download | nextpnr-a12057777334be8e45e540c63c0da199a59489ba.tar.gz nextpnr-a12057777334be8e45e540c63c0da199a59489ba.tar.bz2 nextpnr-a12057777334be8e45e540c63c0da199a59489ba.zip |
Merge pull request #858 from cr1901/machxo2
MachXO2 Checkpoint 2
Diffstat (limited to 'machxo2')
-rw-r--r-- | machxo2/bitstream.cc | 37 | ||||
-rw-r--r-- | machxo2/examples/demo-vhdl.sh | 2 | ||||
-rw-r--r-- | machxo2/examples/demo.sh | 2 | ||||
-rw-r--r-- | machxo2/examples/mitertest.sh | 5 | ||||
-rw-r--r-- | machxo2/examples/simple.sh | 2 | ||||
-rw-r--r-- | machxo2/examples/simtest.sh | 2 | ||||
-rw-r--r-- | machxo2/main.cc | 3 | ||||
-rw-r--r-- | machxo2/pack.cc | 47 |
8 files changed, 82 insertions, 18 deletions
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); |