From 515eacf55a70a261d754516f8a08911610a755a9 Mon Sep 17 00:00:00 2001 From: John Fabienke Date: Sat, 13 Jun 2026 07:57:31 +0200 Subject: [PATCH] mistral: emit compressed bitstreams by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nextpnr-mistral defaulted to UNCOMPRESSED RBFs (--compress-rbf opted in to compression). An uncompressed bitstream configures the device (the socfpga FPGA manager reports 'operating'), but on the FPGA-manager load path it leaves user IO non-functional — verified on a DE10-Nano/MiSTer: an uncompressed single-LED design stays dark, the byte-identical compressed encoding lights it. Quartus also emits compressed. OPT_B already tracked the compression choice in-tree (the compressed branch set the same OPT_B value Quartus uses), so this is purely a default flip: read a new 'uncompressed_rbf' opt-out instead of a 'compress_rbf' opt-in. --compress-rbf is kept as a deprecated no-op; --uncompressed-rbf restores the old behaviour for debugging. Verified: regenerating a design with no flags now produces bytes identical to a bitstream confirmed working on silicon. Co-Authored-By: Claude Opus 4.8 (1M context) --- mistral/bitstream.cc | 10 +++++++++- mistral/constids.inc | 1 + mistral/main.cc | 10 ++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/mistral/bitstream.cc b/mistral/bitstream.cc index b46a9f6b..3f088035 100644 --- a/mistral/bitstream.cc +++ b/mistral/bitstream.cc @@ -60,7 +60,15 @@ struct MistralBitgen void options() { - if (!ctx->setting("compress_rbf", false)) { + // Cyclone V bitstreams may be emitted compressed or uncompressed. + // We default to COMPRESSED. An uncompressed bitstream still + // configures the device (the FPGA manager reports "operating"), + // but on the socfpga FPGA-manager load path (verified on a + // DE10-Nano / MiSTer) it leaves user IO non-functional; the + // compressed encoding matches Quartus output and works on + // silicon. OPT_B carries the compression-format flag in the + // header and must track the chosen encoding. + if (ctx->setting("uncompressed_rbf", false)) { cv->opt_b_set(CycloneV::COMPRESSION_DIS, true); cv->opt_r_set(CycloneV::OPT_B, 0xffffff40adffffffULL); } else diff --git a/mistral/constids.inc b/mistral/constids.inc index 754a96b3..f46cd1a7 100644 --- a/mistral/constids.inc +++ b/mistral/constids.inc @@ -109,6 +109,7 @@ X(CFG_DBITS) X(clkout) X(clkout1) X(compress_rbf) +X(uncompressed_rbf) X(oscena) X(placer) X(router) diff --git a/mistral/main.cc b/mistral/main.cc index d6d9333c..d40f1a81 100644 --- a/mistral/main.cc +++ b/mistral/main.cc @@ -49,7 +49,10 @@ po::options_description MistralCommandHandler::getArchOptions() specific.add_options()("device", po::value(), "device name (e.g. 5CSEBA6U23I7)"); specific.add_options()("qsf", po::value(), "path to QSF constraints file"); specific.add_options()("rbf", po::value(), "RBF bitstream to write"); - specific.add_options()("compress-rbf", "generate compressed bitstream"); + specific.add_options()("uncompressed-rbf", + "emit an uncompressed bitstream (default is compressed; uncompressed " + "configures the device but may leave IO non-functional on some loaders)"); + specific.add_options()("compress-rbf", "deprecated, no-op: compressed output is now the default"); return specific; } @@ -79,8 +82,11 @@ std::unique_ptr MistralCommandHandler::createContext(dict(); auto ctx = std::unique_ptr(new Context(chipArgs)); + if (vm.count("uncompressed-rbf")) + ctx->settings[id_uncompressed_rbf] = Property::State::S1; if (vm.count("compress-rbf")) - ctx->settings[id_compress_rbf] = Property::State::S1; + log_warning("--compress-rbf is deprecated and has no effect; compressed output is now the " + "default (pass --uncompressed-rbf to opt out).\n"); return ctx; }