From ebafe63481090b580811ea946b013e9f97d6833a Mon Sep 17 00:00:00 2001 From: Patrick Urban Date: Thu, 3 Jul 2025 17:02:47 +0200 Subject: [PATCH] Enable crc error behaviour and spi io width selection in bitstream --- libgm/include/Bitstream.hpp | 2 +- libgm/src/Bitstream.cpp | 57 ++++++++++++++++++++++++++++++++++++- libgm/tools/gmpack.cpp | 17 ++++++++++- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/libgm/include/Bitstream.hpp b/libgm/include/Bitstream.hpp index 30bd482..dd8fa3a 100644 --- a/libgm/include/Bitstream.hpp +++ b/libgm/include/Bitstream.hpp @@ -39,7 +39,7 @@ class Bitstream public: static Bitstream read(std::istream &in); // Serialise a Chip back to a bitstream - static Bitstream serialise_chip(const Chip &chip); + static Bitstream serialise_chip(const Chip &chip, const std::map options); // Deserialise a bitstream to a Chip Chip deserialise_chip(); diff --git a/libgm/src/Bitstream.cpp b/libgm/src/Bitstream.cpp index 7655b43..27f3d1e 100644 --- a/libgm/src/Bitstream.cpp +++ b/libgm/src/Bitstream.cpp @@ -58,6 +58,18 @@ static constexpr const uint8_t CFG_CPE_RESET = 0x10; static constexpr const uint8_t CFG_FILL_RAM = 0x20; static constexpr const uint8_t CFG_SERDES = 0x40; +static const std::vector> crc_modes = { + {"check", 0x00}, + {"ignore", 0x01}, + {"unused", 0x02} +}; + +static const std::vector>> spi_modes = { + {"single", {}}, + {"dual", {0x50, 0x21, 0x18, 0x3B}}, + {"quad", {0xF0, 0x23, 0x18, 0x6B}} +}; + static const uint16_t crc_table_x25[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, @@ -265,6 +277,21 @@ class BitstreamReadWriter write_nops(4); } + void write_cmd_cfgmode(uint8_t crcmode, std::vector spimode) + { + write_header(CMD_CFGMODE, spimode.size() > 0 ? 6 : 1); + write_byte(0xFF); // crc retries + write_byte(crcmode); // crc error behaviour + if (spimode.size() > 0) { + write_byte(spimode[0]); // spi io width + write_byte(spimode[1]); // spi dummy cycles + write_byte(spimode[2]); // flash address field length + write_byte(spimode[3]); // flash READ command + } + insert_crc16(); + write_nops(4); + } + void write_cmd_spll(uint8_t data) { write_header(CMD_SPLL, 1); @@ -767,7 +794,7 @@ bool is_edge_location(int x, int y) return ((x == 0) || (x == Die::MAX_COLS - 1) || (y == 0) || (y == Die::MAX_ROWS - 1)); } -Bitstream Bitstream::serialise_chip(const Chip &chip) +Bitstream Bitstream::serialise_chip(const Chip &chip, const std::map options) { BitstreamReadWriter wr; for (int d = chip.get_max_die() - 1; d >= 0; d--) { @@ -806,6 +833,34 @@ Bitstream Bitstream::serialise_chip(const Chip &chip) } wr.write_cmd_path(0x10); + bool change_crc = false; + auto crcmode = crc_modes.begin(); + if (options.count("crcmode")) { + change_crc = true; + crcmode = find_if(crc_modes.begin(), crc_modes.end(), [&](const std::pair &fp){ + return fp.first == options.at("crcmode"); + }); + if (crcmode == crc_modes.end()) { + throw std::runtime_error("bad crcmode option " + options.at("crcmode")); + } + } + + bool change_spi = false; + auto spimode = spi_modes.begin(); + if (options.count("spimode")) { + change_spi = true; + spimode = find_if(spi_modes.begin(), spi_modes.end(), [&](const std::pair> &fp){ + return fp.first == options.at("spimode"); + }); + if (spimode == spi_modes.end()) { + throw std::runtime_error("bad spimode option " + options.at("spimode")); + } + } + + if (change_crc || change_spi) { + wr.write_cmd_cfgmode(uint8_t(crcmode->second), std::vector(spimode->second)); + } + uint8_t d2d = die.get_d2d_config(); if (d2d) wr.write_cmd_d2d(d2d); diff --git a/libgm/tools/gmpack.cpp b/libgm/tools/gmpack.cpp index b71b214..3dd5c2f 100644 --- a/libgm/tools/gmpack.cpp +++ b/libgm/tools/gmpack.cpp @@ -37,6 +37,8 @@ int main(int argc, char *argv[]) po::options_description options("Allowed options"); options.add_options()("help,h", "show help"); options.add_options()("verbose,v", "verbose output"); + options.add_options()("crcmode", po::value(), "CRC error behaviour (check, ignore, unused)"); + options.add_options()("spimode", po::value(), "SPI Mode to use (single, dual, quad)"); po::positional_options_description pos; options.add_options()("input", po::value()->required(), "input textual configuration"); pos.add("input", 1); @@ -77,6 +79,19 @@ int main(int argc, char *argv[]) return 1; } + std::map bitopts; + + if (vm.count("crcmode")) { + bitopts["crcmode"] = vm["crcmode"].as(); + } + + if (vm.count("spimode")) { + bitopts["spimode"] = vm["spimode"].as(); + } + + if (vm.count("background")) { + } + std::string textcfg((std::istreambuf_iterator(config_file)), std::istreambuf_iterator()); ChipConfig cc; @@ -88,7 +103,7 @@ int main(int argc, char *argv[]) } Chip c = cc.to_chip(); - Bitstream b = Bitstream::serialise_chip(c); + Bitstream b = Bitstream::serialise_chip(c, bitopts); if (vm.count("bit")) { std::ofstream bit_file(vm["bit"].as(), std::ios::binary); if (!bit_file) {