<86>Aug 16 10:08:17 userdel[2202418]: delete user 'rooter' <86>Aug 16 10:08:17 userdel[2202418]: removed group 'rooter' owned by 'rooter' <86>Aug 16 10:08:17 groupadd[2202424]: group added to /etc/group: name=rooter, GID=519 <86>Aug 16 10:08:17 groupadd[2202424]: group added to /etc/gshadow: name=rooter <86>Aug 16 10:08:17 groupadd[2202424]: new group: name=rooter, GID=519 <86>Aug 16 10:08:17 useradd[2202428]: new user: name=rooter, UID=519, GID=519, home=/root, shell=/bin/bash <86>Aug 16 10:08:17 userdel[2202437]: delete user 'builder' <86>Aug 16 10:08:17 userdel[2202437]: removed group 'builder' owned by 'builder' <86>Aug 16 10:08:17 userdel[2202437]: removed shadow group 'builder' owned by 'builder' <86>Aug 16 10:08:17 groupadd[2202446]: group added to /etc/group: name=builder, GID=520 <86>Aug 16 10:08:17 groupadd[2202446]: group added to /etc/gshadow: name=builder <86>Aug 16 10:08:17 groupadd[2202446]: new group: name=builder, GID=520 <86>Aug 16 10:08:17 useradd[2202451]: new user: name=builder, UID=520, GID=520, home=/usr/src, shell=/bin/bash <13>Aug 16 10:08:18 rpmi: libgdbm-1.8.3-alt10 1454943334 installed <13>Aug 16 10:08:18 rpmi: libexpat-2.2.4-alt1 1503305345 installed <13>Aug 16 10:08:19 rpmi: libp11-kit-0.23.15-alt1 sisyphus+226408.100.2.1 1554288204 installed <13>Aug 16 10:08:19 rpmi: libtasn1-4.14-alt1 p9+235792.100.2.1 1565425233 installed <13>Aug 16 10:08:19 rpmi: rpm-macros-alternatives-0.5.1-alt1 sisyphus+226946.100.1.1 1554830426 installed <13>Aug 16 10:08:19 rpmi: alternatives-0.5.1-alt1 sisyphus+226946.100.1.1 1554830426 installed <13>Aug 16 10:08:19 rpmi: ca-certificates-2020.01.23-alt1 p9+245253.100.3.1 1580749631 installed <13>Aug 16 10:08:19 rpmi: ca-trust-0.1.2-alt1 p9+233349.100.1.1 1561655062 installed <13>Aug 16 10:08:19 rpmi: p11-kit-trust-0.23.15-alt1 sisyphus+226408.100.2.1 1554288204 installed <13>Aug 16 10:08:19 rpmi: libcrypto1.1-1.1.1g-alt1 p9+250580.100.5.1 1588175266 installed <13>Aug 16 10:08:19 rpmi: libssl1.1-1.1.1g-alt1 p9+250580.100.5.1 1588175266 installed <13>Aug 16 10:08:19 rpmi: python3-3.7.4-alt3 p9+249932.100.2.1 1587127349 installed <13>Aug 16 10:08:19 rpmi: libpython3-3.7.4-alt3 p9+249932.100.2.1 1587127349 installed <13>Aug 16 10:08:19 rpmi: python3-base-3.7.4-alt3 p9+249932.100.2.1 1587127349 installed <13>Aug 16 10:08:19 rpmi: tests-for-installed-python3-pkgs-0.1.13.1-alt2 1535450458 installed <13>Aug 16 10:08:19 rpmi: rpm-build-python3-0.1.13.1-alt2 1535450458 installed <13>Aug 16 10:08:21 rpmi: libusb-1.0.22-alt1 1525452055 installed <13>Aug 16 10:08:21 rpmi: libftdi1-1.4-alt3 sisyphus+222595.100.1.1 1550919564 installed <13>Aug 16 10:08:21 rpmi: libusb-devel-1.0.22-alt1 1525452055 installed <13>Aug 16 10:08:21 rpmi: gcc-c++-common-1.4.23-alt1 sisyphus+221902.2500.4.1 1550596716 installed <13>Aug 16 10:08:22 rpmi: libstdc++8-devel-8.4.1-alt0.p9.1 p9+247559.100.2.1 1585587912 installed <13>Aug 16 10:08:23 rpmi: gcc8-c++-8.4.1-alt0.p9.1 p9+247559.100.2.1 1585587912 installed <13>Aug 16 10:08:23 rpmi: gcc-c++-8-alt2 p9+246536.100.3.1 1582643803 installed <13>Aug 16 10:08:23 rpmi: libftdi1-devel-1.4-alt3 sisyphus+222595.100.1.1 1550919564 installed Building target platforms: i586 Building for target i586 Wrote: /usr/src/in/nosrpm/icestorm-0.0.0.618.gf029975-alt2.nosrc.rpm Installing icestorm-0.0.0.618.gf029975-alt2.src.rpm Building target platforms: i586 Building for target i586 Executing(%prep): /bin/sh -e /usr/src/tmp/rpm-tmp.98184 + umask 022 + /bin/mkdir -p /usr/src/RPM/BUILD + cd /usr/src/RPM/BUILD + cd /usr/src/RPM/BUILD + rm -rf icestorm-0.0.0.618.gf029975 + echo 'Source #0 (icestorm-0.0.0.618.gf029975.tar):' Source #0 (icestorm-0.0.0.618.gf029975.tar): + /bin/tar -xf /usr/src/RPM/SOURCES/icestorm-0.0.0.618.gf029975.tar + cd icestorm-0.0.0.618.gf029975 + /bin/chmod -c -Rf u+rwX,go-w . + exit 0 Executing(%build): /bin/sh -e /usr/src/tmp/rpm-tmp.98184 + umask 022 + /bin/mkdir -p /usr/src/RPM/BUILD + cd /usr/src/RPM/BUILD + cd icestorm-0.0.0.618.gf029975 ++ pkg-config --cflags libftdi1 ++ pkg-config --libs libftdi1 + make -j8 CC=gcc CXX=g++ 'CFLAGS=-pipe -frecord-gcc-switches -Wall -g -O2 -march=i586 -mtune=generic -Wextra -I/usr/include/libftdi1 -I/usr/include/libusb-1.0' 'CXXFLAGS=-pipe -frecord-gcc-switches -Wall -g -O2 -march=i586 -mtune=generic -Wextra' 'LDLIBS=-lftdi1 -lusb-1.0 -lm' for dir in icebox icepack iceprog icemulti icepll icetime icebram; do \ make -C $dir all || exit; \ done make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' python3 icebox_chipdb.py -3 > chipdb-384.new mv chipdb-384.new chipdb-384.txt make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' python3 icebox_chipdb.py > chipdb-1k.new mv chipdb-1k.new chipdb-1k.txt make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' python3 icebox_chipdb.py -4 > chipdb-lm4k.new mv chipdb-lm4k.new chipdb-lm4k.txt make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' python3 icebox_chipdb.py -5 > chipdb-5k.new mv chipdb-5k.new chipdb-5k.txt make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' python3 icebox_chipdb.py -8 > chipdb-8k.new mv chipdb-8k.new chipdb-8k.txt make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepack' g++ -pipe -frecord-gcc-switches -Wall -g -O2 -march=i586 -mtune=generic -Wextra -c -o icepack.o icepack.cc icepack.cc: In member function 'void FpgaConfig::write_ascii(std::ostream&) const': icepack.cc:53:41: warning: format '%lu' expects argument of type 'long unsigned int', but argument 6 has type 'std::vector >::size_type' {aka 'unsigned int'} [-Wformat=] #define error(...) do { fprintf(stderr, "Error: " __VA_ARGS__); exit(1); } while (0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define panic(fmt, ...) do { fprintf(stderr, "Internal Error at %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__); abort(); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string vstringf(const char *fmt, va_list ap) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ string string; ~~~~~~~~~~~~~~ char *str = NULL; ~~~~~~~~~~~~~~~~~ #ifdef _WIN32 ~~~~~~~~~~~~~ int sz = 64, rc; ~~~~~~~~~~~~~~~~ while (1) { ~~~~~~~~~~~ va_list apc; ~~~~~~~~~~~~ va_copy(apc, ap); ~~~~~~~~~~~~~~~~~ str = (char*)realloc(str, sz); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ rc = vsnprintf(str, sz, fmt, apc); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(apc); ~~~~~~~~~~~~ if (rc >= 0 && rc < sz) ~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ sz *= 2; ~~~~~~~~ } ~ #else ~~~~~ if (vasprintf(&str, fmt, ap) < 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ str = NULL; ~~~~~~~~~~~ #endif ~~~~~~ if (str != NULL) { ~~~~~~~~~~~~~~~~~~ string = str; ~~~~~~~~~~~~~ free(str); ~~~~~~~~~~ } ~ return string; ~~~~~~~~~~~~~~ } ~ string stringf(const char *fmt, ...) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ string string; ~~~~~~~~~~~~~~ va_list ap; ~~~~~~~~~~~ va_start(ap, fmt); ~~~~~~~~~~~~~~~~~~ string = vstringf(fmt, ap); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(ap); ~~~~~~~~~~~ return string; ~~~~~~~~~~~~~~ } ~ // ================================================================== ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // FpgaConfig stuff ~~~~~~~~~~~~~~~~~~~ struct FpgaConfig ~~~~~~~~~~~~~~~~~ { ~ string device; ~~~~~~~~~~~~~~ string freqrange; ~~~~~~~~~~~~~~~~~ string nosleep; ~~~~~~~~~~~~~~~ string warmboot; ~~~~~~~~~~~~~~~~ // cram[BANK][X][Y] ~~~~~~~~~~~~~~~~~~~ int cram_width, cram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vector>> cram; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bram[BANK][X][Y] ~~~~~~~~~~~~~~~~~~~ int bram_width, bram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vector>> bram; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // data before preamble ~~~~~~~~~~~~~~~~~~~~~~~ vector initblop; ~~~~~~~~~~~~~~~~~~~~~~~~~ // bitstream i/o ~~~~~~~~~~~~~~~~ void read_bits(std::istream &ifs); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_bits(std::ostream &ofs) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // icebox i/o ~~~~~~~~~~~~~ void read_ascii(std::istream &ifs, bool nosleep); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_ascii(std::ostream &ofs) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // netpbm i/o ~~~~~~~~~~~~~ void write_cram_pbm(std::ostream &ofs, int bank_num = -1) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_bram_pbm(std::ostream &ofs, int bank_num = -1) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // query chip type metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~ int chip_width() const; ~~~~~~~~~~~~~~~~~~~~~~~ int chip_height() const; ~~~~~~~~~~~~~~~~~~~~~~~~ vector chip_cols() const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // query tile metadata ~~~~~~~~~~~~~~~~~~~~~~ string tile_type(int x, int y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_width(const string &type) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // cram bit manipulation ~~~~~~~~~~~~~~~~~~~~~~~~ void cram_clear(); ~~~~~~~~~~~~~~~~~~ void cram_fill_tiles(); ~~~~~~~~~~~~~~~~~~~~~~~ void cram_checkerboard(int m = 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ struct CramIndexConverter ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ const FpgaConfig *fpga; ~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ string tile_type; ~~~~~~~~~~~~~~~~~ int tile_width; ~~~~~~~~~~~~~~~ int column_width; ~~~~~~~~~~~~~~~~~ bool left_right_io; ~~~~~~~~~~~~~~~~~~~ bool right_half; ~~~~~~~~~~~~~~~~ bool top_half; ~~~~~~~~~~~~~~ int bank_num; ~~~~~~~~~~~~~ int bank_tx; ~~~~~~~~~~~~ int bank_ty; ~~~~~~~~~~~~ int bank_xoff; ~~~~~~~~~~~~~~ int bank_yoff; ~~~~~~~~~~~~~~ CramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void get_cram_index(int bit_x, int bit_y, int &cram_bank, int &cram_x, int &cram_y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ struct BramIndexConverter ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ const FpgaConfig *fpga; ~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ int bank_num; ~~~~~~~~~~~~~ int bank_off; ~~~~~~~~~~~~~ BramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void get_bram_index(int bit_x, int bit_y, int &bram_bank, int &bram_x, int &bram_y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ static void update_crc16(uint16_t &crc, uint8_t byte) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ // CRC-16-CCITT, Initialize to 0xFFFF, No zero padding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 7; i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint16_t xor_value = ((crc >> 15) ^ ((byte >> i) & 1)) ? 0x1021 : 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ crc = (crc << 1) ^ xor_value; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ static uint8_t read_byte(std::istream &ifs, uint16_t &crc_value, int &file_offset) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int byte = ifs.get(); ~~~~~~~~~~~~~~~~~~~~~ if (byte < 0) ~~~~~~~~~~~~~ error("Unexpected end of file.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ file_offset++; ~~~~~~~~~~~~~~ update_crc16(crc_value, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return byte; ~~~~~~~~~~~~ } ~ static void write_byte(std::ostream &ofs, uint16_t &crc_value, int &file_offset, uint8_t byte) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ ofs << byte; ~~~~~~~~~~~~ file_offset++; ~~~~~~~~~~~~~~ update_crc16(crc_value, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::read_bits(std::istream &ifs) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int file_offset = 0; ~~~~~~~~~~~~~~~~~~~~ uint16_t crc_value = 0; ~~~~~~~~~~~~~~~~~~~~~~~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Parsing bitstream file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // skip initial comments until preamble is found ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint32_t preamble = 0; ~~~~~~~~~~~~~~~~~~~~~~ while (1) ~~~~~~~~~ { ~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ preamble = (preamble << 8) | byte; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (preamble == 0xffffffff) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("No preamble found in bitstream.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (preamble == 0x7EAA997E) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Found preamble at offset %d.\n", file_offset-4); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ initblop.push_back(byte); ~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ // main parser loop ~~~~~~~~~~~~~~~~~~~ int current_bank = 0; ~~~~~~~~~~~~~~~~~~~~~ int current_width = 0; ~~~~~~~~~~~~~~~~~~~~~~ int current_height = 0; ~~~~~~~~~~~~~~~~~~~~~~~ int current_offset = 0; ~~~~~~~~~~~~~~~~~~~~~~~ bool wakeup = false; ~~~~~~~~~~~~~~~~~~~~ this->cram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ while (!wakeup) ~~~~~~~~~~~~~~~ { ~ // one command byte. the lower 4 bits of the command byte specify ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // the length of the command payload. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t command = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint32_t payload = 0; ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (command & 0x0f); i++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ payload = (payload << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Next command at offset %d: 0x%02x 0x%0*x\n", file_offset - 1 - (command & 0x0f), ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ command, 2*(command & 0x0f), payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint16_t end_token; ~~~~~~~~~~~~~~~~~~~ switch (command & 0xf0) ~~~~~~~~~~~~~~~~~~~~~~~ { ~ case 0x00: ~~~~~~~~~~ switch (payload) ~~~~~~~~~~~~~~~~ { ~ case 0x01: ~~~~~~~~~~ info("CRAM Data [%d]: %d x %d bits = %d bits = %d bytes\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_bank, current_width, current_height, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_height*current_width, (current_height*current_width)/8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = std::max(this->cram_width, current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = std::max(this->cram_height, current_offset + current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < current_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank][x].resize(this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (current_height*current_width)/8; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int x = (i*8 + j) % current_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int y = (i*8 + j) / current_width + current_offset; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank][x][y] = ((byte << j) & 0x80) != 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ end_token = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end_token = (end_token << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (end_token) ~~~~~~~~~~~~~~ error("Expeded 0x0000 after CRAM data, got 0x%04x\n", end_token); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x03: ~~~~~~~~~~ info("BRAM Data [%d]: %d x %d bits = %d bits = %d bytes\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_bank, current_width, current_height, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_height*current_width, (current_height*current_width)/8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = std::max(this->bram_width, current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = std::max(this->bram_height, current_offset + current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank].resize(this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < current_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (current_height*current_width)/8; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int x = (i*8 + j) % current_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int y = (i*8 + j) / current_width + current_offset; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank][x][y] = ((byte << j) & 0x80) != 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ end_token = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end_token = (end_token << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (end_token) ~~~~~~~~~~~~~~ error("Expeded 0x0000 after BRAM data, got 0x%04x\n", end_token); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x05: ~~~~~~~~~~ debug("Resetting CRC.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~ crc_value = 0xffff; ~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x06: ~~~~~~~~~~ info("Wakeup.\n"); ~~~~~~~~~~~~~~~~~~ wakeup = true; ~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown command: 0x%02x 0x%02x\n", command, payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ break; ~~~~~~ case 0x10: ~~~~~~~~~~ current_bank = payload; ~~~~~~~~~~~~~~~~~~~~~~~ debug("Set bank to %d.\n", current_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x20: ~~~~~~~~~~ if (crc_value != 0) ~~~~~~~~~~~~~~~~~~~ error("CRC Check FAILED.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("CRC Check OK.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x50: ~~~~~~~~~~ if (payload == 0) ~~~~~~~~~~~~~~~~~ this->freqrange = "low"; ~~~~~~~~~~~~~~~~~~~~~~~~ else if (payload == 1) ~~~~~~~~~~~~~~~~~~~~~~ this->freqrange = "medium"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (payload == 2) ~~~~~~~~~~~~~~~~~~~~~~ this->freqrange = "high"; ~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown freqrange payload 0x%02x\n", payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Setting freqrange to '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x60: ~~~~~~~~~~ current_width = payload + 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank width to %d.\n", current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x70: ~~~~~~~~~~ current_height = payload; ~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank height to %d.\n", current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x80: ~~~~~~~~~~ current_offset = payload; ~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank offset to %d.\n", current_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x90: ~~~~~~~~~~ switch(payload) ~~~~~~~~~~~~~~~ { ~ case 0: ~~~~~~~ this->warmboot = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ this->warmboot = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 32: ~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 33: ~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown warmboot/nosleep payload 0x%02x\n", payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ info("Setting warmboot to '%s', nosleep to '%s'.\n", this->warmboot.c_str(), this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown command: 0x%02x 0x%02x\n", command, payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ if (this->cram_width == 182 && this->cram_height == 80) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "384"; ~~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 332 && this->cram_height == 144) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "1k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 872 && this->cram_height == 272) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "8k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 692 && this->cram_height == 336) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "5k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 692 && this->cram_height == 176) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "u4k"; ~~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 656 && this->cram_height == 176) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "lm4k"; ~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Failed to detect chip type.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Chip type is '%s'.\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::write_bits(std::ostream &ofs) const ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int file_offset = 0; ~~~~~~~~~~~~~~~~~~~~ uint16_t crc_value = 0; ~~~~~~~~~~~~~~~~~~~~~~~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Writing bitstream file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (auto byte : this->initblop) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << byte; ~~~~~~~~~~~~ debug("Writing preamble.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x7E); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0xAA); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x99); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x7E); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting freqrange to '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x51); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->freqrange == "low") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->freqrange == "medium") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->freqrange == "high") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x02); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown freqrange '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Resetting CRC.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x05); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ crc_value = 0xffff; ~~~~~~~~~~~~~~~~~~~ { ~ uint8_t nosleep_flag; ~~~~~~~~~~~~~~~~~~~~~ debug("Setting warmboot to '%s', nosleep to '%s'.\n", this->warmboot.c_str(), this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x92); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->nosleep == "disabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nosleep_flag = 0; ~~~~~~~~~~~~~~~~~ else if (this->nosleep == "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nosleep_flag = 1; ~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown nosleep setting '%s'.\n", this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot == "disabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00 | nosleep_flag); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->warmboot == "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x20 | nosleep_flag); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown warmboot setting '%s'.\n", this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank width to %d.\n", this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->cram_width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->cram_width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device != "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Setting bank height to %d.\n", this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, this->cram_height >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank offset to 0.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x82); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_bank = 0; cram_bank < 4; cram_bank++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ vector cram_bits; ~~~~~~~~~~~~~~~~~~~~~~~ int height = this->cram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k" && ((cram_bank % 2) == 1)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ height = height / 2 + 8; ~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_y = 0; cram_y < height; cram_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_x = 0; cram_x < this->cram_width; cram_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cram_bits.push_back(this->cram[cram_bank][cram_x][cram_y]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Setting bank height to %d.\n", height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, height >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank %d.\n", cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x11); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Writing bank %d data.\n", cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < int(cram_bits.size()); i += 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = 0; ~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ byte = (byte << 1) | (cram_bits[i+j] ? 1 : 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int bram_chunk_size = 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->bram_width && this->bram_height) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if(this->device != "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank width to %d.\n", this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->bram_width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->bram_width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("BRAM: Setting bank height to %d.\n", this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_chunk_size >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_chunk_size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bram_bank = 0; bram_bank < 4; bram_bank++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("BRAM: Setting bank %d.\n", bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x11); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int offset = 0; offset < this->bram_height; offset += bram_chunk_size) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ vector bram_bits; ~~~~~~~~~~~~~~~~~~~~~~~ int width = this->bram_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k" && ((bram_bank % 2) == 1)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ width = width / 2; ~~~~~~~~~~~~~~~~~~ for (int bram_y = 0; bram_y < bram_chunk_size; bram_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bram_x = 0; bram_x < width; bram_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bram_bits.push_back(this->bram[bram_bank][bram_x][bram_y+offset]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank offset to %d.\n", offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x82); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, offset >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank width to %d.\n", width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("BRAM: Writing bank %d data.\n", bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x03); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < int(bram_bits.size()); i += 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = 0; ~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ byte = (byte << 1) | (bram_bits[i+j] ? 1 : 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ } ~ debug("Writing CRC value.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x22); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t crc_hi = crc_value >> 8, crc_lo = crc_value; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, crc_hi); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, crc_lo); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Wakeup.\n"); ~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x06); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Padding byte.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::read_ascii(std::istream &ifs, bool nosleep) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Parsing ascii file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool got_device = false; ~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.clear(); ~~~~~~~~~~~~~~~~~~~ this->bram.clear(); ~~~~~~~~~~~~~~~~~~~ this->freqrange = "low"; ~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool reuse_line = true; ~~~~~~~~~~~~~~~~~~~~~~~ string line, command; ~~~~~~~~~~~~~~~~~~~~~ while (reuse_line || getline(ifs, line)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ reuse_line = false; ~~~~~~~~~~~~~~~~~~~ std::istringstream is(line); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> command; ~~~~~~~~~~~~~~ if (command.empty()) ~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ debug("Next command: %s\n", line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (command == ".comment") ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ this->initblop.clear(); ~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0xff); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (getline(ifs, line)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (auto ch : line) ~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(ch); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->initblop.push_back(0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0xff); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".device") ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (got_device) ~~~~~~~~~~~~~~~ error("More than one .device statement.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> this->device; ~~~~~~~~~~~~~~~~~~~ if (this->device == "384") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 182; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 80; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "1k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 332; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 144; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 64; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "8k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 872; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 272; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 128; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 692; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 336; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 160; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "u4k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 692; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 176; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 80; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "lm4k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 656; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 176; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 80; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ error("Unsupported chip type '%s'.\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->cram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i][x].resize(((i % 2) == 1) ? (this->cram_height / 2 + 8) : this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int width = ((i % 2) == 1) ? (this->bram_width / 2) : this->bram_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i].resize(width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } else { ~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->cram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i][x].resize(this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i].resize(this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->bram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ got_device = true; ~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".warmboot") ~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ is >> this->warmboot; ~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot != "disabled" && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot != "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unknown warmboot setting '%s'.\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ // No ".nosleep" section despite sharing the same byte as .warmboot. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ".nosleep" is specified when icepack is invoked, which is too late. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // So we inject the section based on command line argument. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (nosleep) ~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (command == ".io_tile" || command == ".logic_tile" || command == ".ramb_tile" || command == ".ramt_tile" || command.substr(0, 4) == ".dsp" || command == ".ipcon_tile") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ is >> tile_x >> tile_y; ~~~~~~~~~~~~~~~~~~~~~~~ CramIndexConverter cic(this, tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (("." + cic.tile_type + "_tile") != command) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Got %s statement for %s tile %d %d.\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ command.c_str(), cic.tile_type.c_str(), tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16 && getline(ifs, line); bit_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (int bit_x = 0; bit_x < int(line.size()) && bit_x < cic.tile_width; bit_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (line[bit_x] == '1') { ~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[cram_bank][cram_x][cram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ continue; ~~~~~~~~~ } ~ if (command == ".ram_data") ~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ is >> tile_x >> tile_y; ~~~~~~~~~~~~~~~~~~~~~~~ BramIndexConverter bic(this, tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16 && getline(ifs, line); bit_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (int bit_x = 256-4, ch_idx = 0; ch_idx < int(line.size()) && bit_x >= 0; bit_x -= 4, ch_idx++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int value = -1; ~~~~~~~~~~~~~~~ if ('0' <= line[ch_idx] && line[ch_idx] <= '9') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - '0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ('a' <= line[ch_idx] && line[ch_idx] <= 'f') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - 'a' + 10; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ('A' <= line[ch_idx] && line[ch_idx] <= 'F') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - 'A' + 10; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (value < 0) ~~~~~~~~~~~~~~ error("Not a hex character: '%c' (in line '%s')\n", line[ch_idx], line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ((value & (1 << i)) != 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int bram_bank, bram_x, bram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bic.get_bram_index(bit_x+i, bit_y, bram_bank, bram_x, bram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[bram_bank][bram_x][bram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ } ~ continue; ~~~~~~~~~ } ~ if (command == ".extra_bit") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> cram_bank >> cram_x >> cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[cram_bank][cram_x][cram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".sym") ~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ if (command.substr(0, 1) == ".") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unknown statement: %s\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unexpected data line: %s\n", line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ void FpgaConfig::write_ascii(std::ostream &ofs) const ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Writing ascii file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << ".comment"; ~~~~~~~~~~~~~~~~~~ bool insert_newline = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (auto ch : this->initblop) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ch == 0) { ~~~~~~~~~~~~~~ insert_newline = true; ~~~~~~~~~~~~~~~~~~~~~~ } else if (ch == 0xff) { ~~~~~~~~~~~~~~~~~~~~~~~~ insert_newline = false; ~~~~~~~~~~~~~~~~~~~~~~~ } else { ~~~~~~~~ if (insert_newline) ~~~~~~~~~~~~~~~~~~~ ofs << '\n'; ~~~~~~~~~~~~ ofs << ch; ~~~~~~~~~~ insert_newline = false; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ ofs << stringf("\n.device %s\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot != "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << stringf(".warmboot %s\n", this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // As "nosleep" is an icepack command, we do not write out a ".nosleep" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // section. However, we parse it in read_bits() and notify the user in ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // info. ~~~~~~~~ typedef std::tuple tile_bit_t; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ std::set tile_bits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int y = 0; y <= this->chip_height()+1; y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x <= this->chip_width()+1; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ CramIndexConverter cic(this, x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (cic.tile_type == "corner" || cic.tile_type == "unsupported") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ ofs << stringf(".%s_tile %d %d\n", cic.tile_type.c_str(), x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16; bit_y++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_x = 0; bit_x < cic.tile_width; bit_x++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tile_bits.insert(tile_bit_t(cram_bank, cram_x, cram_y)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (cram_x > int(this->cram[cram_bank].size())) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("cram_x %d (bit %d, %d) larger than bank size %lu\n", cram_x, bit_x, bit_y, this->cram[cram_bank].size()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ icepack.cc:902:6: note: in expansion of macro 'error' error("cram_x %d (bit %d, %d) larger than bank size %lu\n", cram_x, bit_x, bit_y, this->cram[cram_bank].size()); ^~~~~ icepack.cc:53:41: warning: format '%lu' expects argument of type 'long unsigned int', but argument 7 has type 'std::vector::size_type' {aka 'unsigned int'} [-Wformat=] #define error(...) do { fprintf(stderr, "Error: " __VA_ARGS__); exit(1); } while (0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define panic(fmt, ...) do { fprintf(stderr, "Internal Error at %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__); abort(); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string vstringf(const char *fmt, va_list ap) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ string string; ~~~~~~~~~~~~~~ char *str = NULL; ~~~~~~~~~~~~~~~~~ #ifdef _WIN32 ~~~~~~~~~~~~~ int sz = 64, rc; ~~~~~~~~~~~~~~~~ while (1) { ~~~~~~~~~~~ va_list apc; ~~~~~~~~~~~~ va_copy(apc, ap); ~~~~~~~~~~~~~~~~~ str = (char*)realloc(str, sz); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ rc = vsnprintf(str, sz, fmt, apc); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(apc); ~~~~~~~~~~~~ if (rc >= 0 && rc < sz) ~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ sz *= 2; ~~~~~~~~ } ~ #else ~~~~~ if (vasprintf(&str, fmt, ap) < 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ str = NULL; ~~~~~~~~~~~ #endif ~~~~~~ if (str != NULL) { ~~~~~~~~~~~~~~~~~~ string = str; ~~~~~~~~~~~~~ free(str); ~~~~~~~~~~ } ~ return string; ~~~~~~~~~~~~~~ } ~ string stringf(const char *fmt, ...) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ string string; ~~~~~~~~~~~~~~ va_list ap; ~~~~~~~~~~~ va_start(ap, fmt); ~~~~~~~~~~~~~~~~~~ string = vstringf(fmt, ap); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(ap); ~~~~~~~~~~~ return string; ~~~~~~~~~~~~~~ } ~ // ================================================================== ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // FpgaConfig stuff ~~~~~~~~~~~~~~~~~~~ struct FpgaConfig ~~~~~~~~~~~~~~~~~ { ~ string device; ~~~~~~~~~~~~~~ string freqrange; ~~~~~~~~~~~~~~~~~ string nosleep; ~~~~~~~~~~~~~~~ string warmboot; ~~~~~~~~~~~~~~~~ // cram[BANK][X][Y] ~~~~~~~~~~~~~~~~~~~ int cram_width, cram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vector>> cram; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bram[BANK][X][Y] ~~~~~~~~~~~~~~~~~~~ int bram_width, bram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vector>> bram; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // data before preamble ~~~~~~~~~~~~~~~~~~~~~~~ vector initblop; ~~~~~~~~~~~~~~~~~~~~~~~~~ // bitstream i/o ~~~~~~~~~~~~~~~~ void read_bits(std::istream &ifs); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_bits(std::ostream &ofs) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // icebox i/o ~~~~~~~~~~~~~ void read_ascii(std::istream &ifs, bool nosleep); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_ascii(std::ostream &ofs) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // netpbm i/o ~~~~~~~~~~~~~ void write_cram_pbm(std::ostream &ofs, int bank_num = -1) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_bram_pbm(std::ostream &ofs, int bank_num = -1) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // query chip type metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~ int chip_width() const; ~~~~~~~~~~~~~~~~~~~~~~~ int chip_height() const; ~~~~~~~~~~~~~~~~~~~~~~~~ vector chip_cols() const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // query tile metadata ~~~~~~~~~~~~~~~~~~~~~~ string tile_type(int x, int y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_width(const string &type) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // cram bit manipulation ~~~~~~~~~~~~~~~~~~~~~~~~ void cram_clear(); ~~~~~~~~~~~~~~~~~~ void cram_fill_tiles(); ~~~~~~~~~~~~~~~~~~~~~~~ void cram_checkerboard(int m = 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ struct CramIndexConverter ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ const FpgaConfig *fpga; ~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ string tile_type; ~~~~~~~~~~~~~~~~~ int tile_width; ~~~~~~~~~~~~~~~ int column_width; ~~~~~~~~~~~~~~~~~ bool left_right_io; ~~~~~~~~~~~~~~~~~~~ bool right_half; ~~~~~~~~~~~~~~~~ bool top_half; ~~~~~~~~~~~~~~ int bank_num; ~~~~~~~~~~~~~ int bank_tx; ~~~~~~~~~~~~ int bank_ty; ~~~~~~~~~~~~ int bank_xoff; ~~~~~~~~~~~~~~ int bank_yoff; ~~~~~~~~~~~~~~ CramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void get_cram_index(int bit_x, int bit_y, int &cram_bank, int &cram_x, int &cram_y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ struct BramIndexConverter ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ const FpgaConfig *fpga; ~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ int bank_num; ~~~~~~~~~~~~~ int bank_off; ~~~~~~~~~~~~~ BramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void get_bram_index(int bit_x, int bit_y, int &bram_bank, int &bram_x, int &bram_y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ static void update_crc16(uint16_t &crc, uint8_t byte) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ // CRC-16-CCITT, Initialize to 0xFFFF, No zero padding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 7; i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint16_t xor_value = ((crc >> 15) ^ ((byte >> i) & 1)) ? 0x1021 : 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ crc = (crc << 1) ^ xor_value; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ static uint8_t read_byte(std::istream &ifs, uint16_t &crc_value, int &file_offset) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int byte = ifs.get(); ~~~~~~~~~~~~~~~~~~~~~ if (byte < 0) ~~~~~~~~~~~~~ error("Unexpected end of file.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ file_offset++; ~~~~~~~~~~~~~~ update_crc16(crc_value, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return byte; ~~~~~~~~~~~~ } ~ static void write_byte(std::ostream &ofs, uint16_t &crc_value, int &file_offset, uint8_t byte) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ ofs << byte; ~~~~~~~~~~~~ file_offset++; ~~~~~~~~~~~~~~ update_crc16(crc_value, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::read_bits(std::istream &ifs) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int file_offset = 0; ~~~~~~~~~~~~~~~~~~~~ uint16_t crc_value = 0; ~~~~~~~~~~~~~~~~~~~~~~~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Parsing bitstream file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // skip initial comments until preamble is found ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint32_t preamble = 0; ~~~~~~~~~~~~~~~~~~~~~~ while (1) ~~~~~~~~~ { ~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ preamble = (preamble << 8) | byte; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (preamble == 0xffffffff) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("No preamble found in bitstream.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (preamble == 0x7EAA997E) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Found preamble at offset %d.\n", file_offset-4); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ initblop.push_back(byte); ~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ // main parser loop ~~~~~~~~~~~~~~~~~~~ int current_bank = 0; ~~~~~~~~~~~~~~~~~~~~~ int current_width = 0; ~~~~~~~~~~~~~~~~~~~~~~ int current_height = 0; ~~~~~~~~~~~~~~~~~~~~~~~ int current_offset = 0; ~~~~~~~~~~~~~~~~~~~~~~~ bool wakeup = false; ~~~~~~~~~~~~~~~~~~~~ this->cram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ while (!wakeup) ~~~~~~~~~~~~~~~ { ~ // one command byte. the lower 4 bits of the command byte specify ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // the length of the command payload. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t command = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint32_t payload = 0; ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (command & 0x0f); i++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ payload = (payload << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Next command at offset %d: 0x%02x 0x%0*x\n", file_offset - 1 - (command & 0x0f), ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ command, 2*(command & 0x0f), payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint16_t end_token; ~~~~~~~~~~~~~~~~~~~ switch (command & 0xf0) ~~~~~~~~~~~~~~~~~~~~~~~ { ~ case 0x00: ~~~~~~~~~~ switch (payload) ~~~~~~~~~~~~~~~~ { ~ case 0x01: ~~~~~~~~~~ info("CRAM Data [%d]: %d x %d bits = %d bits = %d bytes\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_bank, current_width, current_height, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_height*current_width, (current_height*current_width)/8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = std::max(this->cram_width, current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = std::max(this->cram_height, current_offset + current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < current_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank][x].resize(this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (current_height*current_width)/8; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int x = (i*8 + j) % current_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int y = (i*8 + j) / current_width + current_offset; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank][x][y] = ((byte << j) & 0x80) != 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ end_token = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end_token = (end_token << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (end_token) ~~~~~~~~~~~~~~ error("Expeded 0x0000 after CRAM data, got 0x%04x\n", end_token); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x03: ~~~~~~~~~~ info("BRAM Data [%d]: %d x %d bits = %d bits = %d bytes\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_bank, current_width, current_height, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_height*current_width, (current_height*current_width)/8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = std::max(this->bram_width, current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = std::max(this->bram_height, current_offset + current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank].resize(this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < current_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (current_height*current_width)/8; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int x = (i*8 + j) % current_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int y = (i*8 + j) / current_width + current_offset; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank][x][y] = ((byte << j) & 0x80) != 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ end_token = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end_token = (end_token << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (end_token) ~~~~~~~~~~~~~~ error("Expeded 0x0000 after BRAM data, got 0x%04x\n", end_token); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x05: ~~~~~~~~~~ debug("Resetting CRC.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~ crc_value = 0xffff; ~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x06: ~~~~~~~~~~ info("Wakeup.\n"); ~~~~~~~~~~~~~~~~~~ wakeup = true; ~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown command: 0x%02x 0x%02x\n", command, payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ break; ~~~~~~ case 0x10: ~~~~~~~~~~ current_bank = payload; ~~~~~~~~~~~~~~~~~~~~~~~ debug("Set bank to %d.\n", current_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x20: ~~~~~~~~~~ if (crc_value != 0) ~~~~~~~~~~~~~~~~~~~ error("CRC Check FAILED.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("CRC Check OK.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x50: ~~~~~~~~~~ if (payload == 0) ~~~~~~~~~~~~~~~~~ this->freqrange = "low"; ~~~~~~~~~~~~~~~~~~~~~~~~ else if (payload == 1) ~~~~~~~~~~~~~~~~~~~~~~ this->freqrange = "medium"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (payload == 2) ~~~~~~~~~~~~~~~~~~~~~~ this->freqrange = "high"; ~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown freqrange payload 0x%02x\n", payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Setting freqrange to '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x60: ~~~~~~~~~~ current_width = payload + 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank width to %d.\n", current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x70: ~~~~~~~~~~ current_height = payload; ~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank height to %d.\n", current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x80: ~~~~~~~~~~ current_offset = payload; ~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank offset to %d.\n", current_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x90: ~~~~~~~~~~ switch(payload) ~~~~~~~~~~~~~~~ { ~ case 0: ~~~~~~~ this->warmboot = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ this->warmboot = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 32: ~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 33: ~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown warmboot/nosleep payload 0x%02x\n", payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ info("Setting warmboot to '%s', nosleep to '%s'.\n", this->warmboot.c_str(), this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown command: 0x%02x 0x%02x\n", command, payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ if (this->cram_width == 182 && this->cram_height == 80) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "384"; ~~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 332 && this->cram_height == 144) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "1k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 872 && this->cram_height == 272) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "8k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 692 && this->cram_height == 336) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "5k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 692 && this->cram_height == 176) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "u4k"; ~~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 656 && this->cram_height == 176) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "lm4k"; ~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Failed to detect chip type.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Chip type is '%s'.\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::write_bits(std::ostream &ofs) const ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int file_offset = 0; ~~~~~~~~~~~~~~~~~~~~ uint16_t crc_value = 0; ~~~~~~~~~~~~~~~~~~~~~~~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Writing bitstream file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (auto byte : this->initblop) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << byte; ~~~~~~~~~~~~ debug("Writing preamble.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x7E); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0xAA); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x99); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x7E); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting freqrange to '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x51); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->freqrange == "low") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->freqrange == "medium") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->freqrange == "high") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x02); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown freqrange '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Resetting CRC.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x05); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ crc_value = 0xffff; ~~~~~~~~~~~~~~~~~~~ { ~ uint8_t nosleep_flag; ~~~~~~~~~~~~~~~~~~~~~ debug("Setting warmboot to '%s', nosleep to '%s'.\n", this->warmboot.c_str(), this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x92); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->nosleep == "disabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nosleep_flag = 0; ~~~~~~~~~~~~~~~~~ else if (this->nosleep == "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nosleep_flag = 1; ~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown nosleep setting '%s'.\n", this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot == "disabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00 | nosleep_flag); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->warmboot == "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x20 | nosleep_flag); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown warmboot setting '%s'.\n", this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank width to %d.\n", this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->cram_width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->cram_width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device != "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Setting bank height to %d.\n", this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, this->cram_height >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank offset to 0.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x82); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_bank = 0; cram_bank < 4; cram_bank++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ vector cram_bits; ~~~~~~~~~~~~~~~~~~~~~~~ int height = this->cram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k" && ((cram_bank % 2) == 1)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ height = height / 2 + 8; ~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_y = 0; cram_y < height; cram_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_x = 0; cram_x < this->cram_width; cram_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cram_bits.push_back(this->cram[cram_bank][cram_x][cram_y]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Setting bank height to %d.\n", height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, height >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank %d.\n", cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x11); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Writing bank %d data.\n", cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < int(cram_bits.size()); i += 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = 0; ~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ byte = (byte << 1) | (cram_bits[i+j] ? 1 : 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int bram_chunk_size = 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->bram_width && this->bram_height) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if(this->device != "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank width to %d.\n", this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->bram_width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->bram_width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("BRAM: Setting bank height to %d.\n", this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_chunk_size >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_chunk_size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bram_bank = 0; bram_bank < 4; bram_bank++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("BRAM: Setting bank %d.\n", bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x11); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int offset = 0; offset < this->bram_height; offset += bram_chunk_size) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ vector bram_bits; ~~~~~~~~~~~~~~~~~~~~~~~ int width = this->bram_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k" && ((bram_bank % 2) == 1)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ width = width / 2; ~~~~~~~~~~~~~~~~~~ for (int bram_y = 0; bram_y < bram_chunk_size; bram_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bram_x = 0; bram_x < width; bram_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bram_bits.push_back(this->bram[bram_bank][bram_x][bram_y+offset]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank offset to %d.\n", offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x82); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, offset >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank width to %d.\n", width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("BRAM: Writing bank %d data.\n", bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x03); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < int(bram_bits.size()); i += 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = 0; ~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ byte = (byte << 1) | (bram_bits[i+j] ? 1 : 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ } ~ debug("Writing CRC value.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x22); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t crc_hi = crc_value >> 8, crc_lo = crc_value; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, crc_hi); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, crc_lo); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Wakeup.\n"); ~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x06); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Padding byte.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::read_ascii(std::istream &ifs, bool nosleep) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Parsing ascii file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool got_device = false; ~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.clear(); ~~~~~~~~~~~~~~~~~~~ this->bram.clear(); ~~~~~~~~~~~~~~~~~~~ this->freqrange = "low"; ~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool reuse_line = true; ~~~~~~~~~~~~~~~~~~~~~~~ string line, command; ~~~~~~~~~~~~~~~~~~~~~ while (reuse_line || getline(ifs, line)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ reuse_line = false; ~~~~~~~~~~~~~~~~~~~ std::istringstream is(line); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> command; ~~~~~~~~~~~~~~ if (command.empty()) ~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ debug("Next command: %s\n", line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (command == ".comment") ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ this->initblop.clear(); ~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0xff); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (getline(ifs, line)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (auto ch : line) ~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(ch); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->initblop.push_back(0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0xff); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".device") ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (got_device) ~~~~~~~~~~~~~~~ error("More than one .device statement.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> this->device; ~~~~~~~~~~~~~~~~~~~ if (this->device == "384") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 182; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 80; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "1k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 332; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 144; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 64; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "8k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 872; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 272; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 128; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 692; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 336; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 160; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "u4k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 692; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 176; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 80; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "lm4k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 656; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 176; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 80; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ error("Unsupported chip type '%s'.\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->cram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i][x].resize(((i % 2) == 1) ? (this->cram_height / 2 + 8) : this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int width = ((i % 2) == 1) ? (this->bram_width / 2) : this->bram_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i].resize(width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } else { ~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->cram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i][x].resize(this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i].resize(this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->bram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ got_device = true; ~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".warmboot") ~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ is >> this->warmboot; ~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot != "disabled" && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot != "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unknown warmboot setting '%s'.\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ // No ".nosleep" section despite sharing the same byte as .warmboot. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ".nosleep" is specified when icepack is invoked, which is too late. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // So we inject the section based on command line argument. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (nosleep) ~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (command == ".io_tile" || command == ".logic_tile" || command == ".ramb_tile" || command == ".ramt_tile" || command.substr(0, 4) == ".dsp" || command == ".ipcon_tile") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ is >> tile_x >> tile_y; ~~~~~~~~~~~~~~~~~~~~~~~ CramIndexConverter cic(this, tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (("." + cic.tile_type + "_tile") != command) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Got %s statement for %s tile %d %d.\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ command.c_str(), cic.tile_type.c_str(), tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16 && getline(ifs, line); bit_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (int bit_x = 0; bit_x < int(line.size()) && bit_x < cic.tile_width; bit_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (line[bit_x] == '1') { ~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[cram_bank][cram_x][cram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ continue; ~~~~~~~~~ } ~ if (command == ".ram_data") ~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ is >> tile_x >> tile_y; ~~~~~~~~~~~~~~~~~~~~~~~ BramIndexConverter bic(this, tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16 && getline(ifs, line); bit_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (int bit_x = 256-4, ch_idx = 0; ch_idx < int(line.size()) && bit_x >= 0; bit_x -= 4, ch_idx++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int value = -1; ~~~~~~~~~~~~~~~ if ('0' <= line[ch_idx] && line[ch_idx] <= '9') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - '0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ('a' <= line[ch_idx] && line[ch_idx] <= 'f') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - 'a' + 10; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ('A' <= line[ch_idx] && line[ch_idx] <= 'F') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - 'A' + 10; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (value < 0) ~~~~~~~~~~~~~~ error("Not a hex character: '%c' (in line '%s')\n", line[ch_idx], line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ((value & (1 << i)) != 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int bram_bank, bram_x, bram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bic.get_bram_index(bit_x+i, bit_y, bram_bank, bram_x, bram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[bram_bank][bram_x][bram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ } ~ continue; ~~~~~~~~~ } ~ if (command == ".extra_bit") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> cram_bank >> cram_x >> cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[cram_bank][cram_x][cram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".sym") ~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ if (command.substr(0, 1) == ".") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unknown statement: %s\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unexpected data line: %s\n", line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ void FpgaConfig::write_ascii(std::ostream &ofs) const ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Writing ascii file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << ".comment"; ~~~~~~~~~~~~~~~~~~ bool insert_newline = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (auto ch : this->initblop) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ch == 0) { ~~~~~~~~~~~~~~ insert_newline = true; ~~~~~~~~~~~~~~~~~~~~~~ } else if (ch == 0xff) { ~~~~~~~~~~~~~~~~~~~~~~~~ insert_newline = false; ~~~~~~~~~~~~~~~~~~~~~~~ } else { ~~~~~~~~ if (insert_newline) ~~~~~~~~~~~~~~~~~~~ ofs << '\n'; ~~~~~~~~~~~~ ofs << ch; ~~~~~~~~~~ insert_newline = false; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ ofs << stringf("\n.device %s\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot != "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << stringf(".warmboot %s\n", this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // As "nosleep" is an icepack command, we do not write out a ".nosleep" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // section. However, we parse it in read_bits() and notify the user in ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // info. ~~~~~~~~ typedef std::tuple tile_bit_t; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ std::set tile_bits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int y = 0; y <= this->chip_height()+1; y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x <= this->chip_width()+1; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ CramIndexConverter cic(this, x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (cic.tile_type == "corner" || cic.tile_type == "unsupported") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ ofs << stringf(".%s_tile %d %d\n", cic.tile_type.c_str(), x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16; bit_y++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_x = 0; bit_x < cic.tile_width; bit_x++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tile_bits.insert(tile_bit_t(cram_bank, cram_x, cram_y)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (cram_x > int(this->cram[cram_bank].size())) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("cram_x %d (bit %d, %d) larger than bank size %lu\n", cram_x, bit_x, bit_y, this->cram[cram_bank].size()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ if (cram_y > int(this->cram[cram_bank][cram_x].size())) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("cram_y %d (bit %d, %d) larger than bank %d size %lu\n", cram_y, bit_x, bit_y, cram_bank, this->cram[cram_bank][cram_x].size()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ icepack.cc:905:6: note: in expansion of macro 'error' error("cram_y %d (bit %d, %d) larger than bank %d size %lu\n", cram_y, bit_x, bit_y, cram_bank, this->cram[cram_bank][cram_x].size()); ^~~~~ icepack.cc:53:41: warning: format '%lu' expects argument of type 'long unsigned int', but argument 6 has type 'std::vector >::size_type' {aka 'unsigned int'} [-Wformat=] #define error(...) do { fprintf(stderr, "Error: " __VA_ARGS__); exit(1); } while (0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define panic(fmt, ...) do { fprintf(stderr, "Internal Error at %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__); abort(); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string vstringf(const char *fmt, va_list ap) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ string string; ~~~~~~~~~~~~~~ char *str = NULL; ~~~~~~~~~~~~~~~~~ #ifdef _WIN32 ~~~~~~~~~~~~~ int sz = 64, rc; ~~~~~~~~~~~~~~~~ while (1) { ~~~~~~~~~~~ va_list apc; ~~~~~~~~~~~~ va_copy(apc, ap); ~~~~~~~~~~~~~~~~~ str = (char*)realloc(str, sz); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ rc = vsnprintf(str, sz, fmt, apc); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(apc); ~~~~~~~~~~~~ if (rc >= 0 && rc < sz) ~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ sz *= 2; ~~~~~~~~ } ~ #else ~~~~~ if (vasprintf(&str, fmt, ap) < 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ str = NULL; ~~~~~~~~~~~ #endif ~~~~~~ if (str != NULL) { ~~~~~~~~~~~~~~~~~~ string = str; ~~~~~~~~~~~~~ free(str); ~~~~~~~~~~ } ~ return string; ~~~~~~~~~~~~~~ } ~ string stringf(const char *fmt, ...) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ string string; ~~~~~~~~~~~~~~ va_list ap; ~~~~~~~~~~~ va_start(ap, fmt); ~~~~~~~~~~~~~~~~~~ string = vstringf(fmt, ap); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(ap); ~~~~~~~~~~~ return string; ~~~~~~~~~~~~~~ } ~ // ================================================================== ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // FpgaConfig stuff ~~~~~~~~~~~~~~~~~~~ struct FpgaConfig ~~~~~~~~~~~~~~~~~ { ~ string device; ~~~~~~~~~~~~~~ string freqrange; ~~~~~~~~~~~~~~~~~ string nosleep; ~~~~~~~~~~~~~~~ string warmboot; ~~~~~~~~~~~~~~~~ // cram[BANK][X][Y] ~~~~~~~~~~~~~~~~~~~ int cram_width, cram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vector>> cram; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bram[BANK][X][Y] ~~~~~~~~~~~~~~~~~~~ int bram_width, bram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vector>> bram; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // data before preamble ~~~~~~~~~~~~~~~~~~~~~~~ vector initblop; ~~~~~~~~~~~~~~~~~~~~~~~~~ // bitstream i/o ~~~~~~~~~~~~~~~~ void read_bits(std::istream &ifs); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_bits(std::ostream &ofs) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // icebox i/o ~~~~~~~~~~~~~ void read_ascii(std::istream &ifs, bool nosleep); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_ascii(std::ostream &ofs) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // netpbm i/o ~~~~~~~~~~~~~ void write_cram_pbm(std::ostream &ofs, int bank_num = -1) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_bram_pbm(std::ostream &ofs, int bank_num = -1) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // query chip type metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~ int chip_width() const; ~~~~~~~~~~~~~~~~~~~~~~~ int chip_height() const; ~~~~~~~~~~~~~~~~~~~~~~~~ vector chip_cols() const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // query tile metadata ~~~~~~~~~~~~~~~~~~~~~~ string tile_type(int x, int y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_width(const string &type) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // cram bit manipulation ~~~~~~~~~~~~~~~~~~~~~~~~ void cram_clear(); ~~~~~~~~~~~~~~~~~~ void cram_fill_tiles(); ~~~~~~~~~~~~~~~~~~~~~~~ void cram_checkerboard(int m = 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ struct CramIndexConverter ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ const FpgaConfig *fpga; ~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ string tile_type; ~~~~~~~~~~~~~~~~~ int tile_width; ~~~~~~~~~~~~~~~ int column_width; ~~~~~~~~~~~~~~~~~ bool left_right_io; ~~~~~~~~~~~~~~~~~~~ bool right_half; ~~~~~~~~~~~~~~~~ bool top_half; ~~~~~~~~~~~~~~ int bank_num; ~~~~~~~~~~~~~ int bank_tx; ~~~~~~~~~~~~ int bank_ty; ~~~~~~~~~~~~ int bank_xoff; ~~~~~~~~~~~~~~ int bank_yoff; ~~~~~~~~~~~~~~ CramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void get_cram_index(int bit_x, int bit_y, int &cram_bank, int &cram_x, int &cram_y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ struct BramIndexConverter ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ const FpgaConfig *fpga; ~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ int bank_num; ~~~~~~~~~~~~~ int bank_off; ~~~~~~~~~~~~~ BramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void get_bram_index(int bit_x, int bit_y, int &bram_bank, int &bram_x, int &bram_y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ static void update_crc16(uint16_t &crc, uint8_t byte) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ // CRC-16-CCITT, Initialize to 0xFFFF, No zero padding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 7; i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint16_t xor_value = ((crc >> 15) ^ ((byte >> i) & 1)) ? 0x1021 : 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ crc = (crc << 1) ^ xor_value; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ static uint8_t read_byte(std::istream &ifs, uint16_t &crc_value, int &file_offset) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int byte = ifs.get(); ~~~~~~~~~~~~~~~~~~~~~ if (byte < 0) ~~~~~~~~~~~~~ error("Unexpected end of file.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ file_offset++; ~~~~~~~~~~~~~~ update_crc16(crc_value, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return byte; ~~~~~~~~~~~~ } ~ static void write_byte(std::ostream &ofs, uint16_t &crc_value, int &file_offset, uint8_t byte) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ ofs << byte; ~~~~~~~~~~~~ file_offset++; ~~~~~~~~~~~~~~ update_crc16(crc_value, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::read_bits(std::istream &ifs) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int file_offset = 0; ~~~~~~~~~~~~~~~~~~~~ uint16_t crc_value = 0; ~~~~~~~~~~~~~~~~~~~~~~~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Parsing bitstream file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // skip initial comments until preamble is found ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint32_t preamble = 0; ~~~~~~~~~~~~~~~~~~~~~~ while (1) ~~~~~~~~~ { ~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ preamble = (preamble << 8) | byte; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (preamble == 0xffffffff) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("No preamble found in bitstream.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (preamble == 0x7EAA997E) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Found preamble at offset %d.\n", file_offset-4); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ initblop.push_back(byte); ~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ // main parser loop ~~~~~~~~~~~~~~~~~~~ int current_bank = 0; ~~~~~~~~~~~~~~~~~~~~~ int current_width = 0; ~~~~~~~~~~~~~~~~~~~~~~ int current_height = 0; ~~~~~~~~~~~~~~~~~~~~~~~ int current_offset = 0; ~~~~~~~~~~~~~~~~~~~~~~~ bool wakeup = false; ~~~~~~~~~~~~~~~~~~~~ this->cram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ while (!wakeup) ~~~~~~~~~~~~~~~ { ~ // one command byte. the lower 4 bits of the command byte specify ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // the length of the command payload. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t command = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint32_t payload = 0; ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (command & 0x0f); i++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ payload = (payload << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Next command at offset %d: 0x%02x 0x%0*x\n", file_offset - 1 - (command & 0x0f), ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ command, 2*(command & 0x0f), payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint16_t end_token; ~~~~~~~~~~~~~~~~~~~ switch (command & 0xf0) ~~~~~~~~~~~~~~~~~~~~~~~ { ~ case 0x00: ~~~~~~~~~~ switch (payload) ~~~~~~~~~~~~~~~~ { ~ case 0x01: ~~~~~~~~~~ info("CRAM Data [%d]: %d x %d bits = %d bits = %d bytes\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_bank, current_width, current_height, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_height*current_width, (current_height*current_width)/8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = std::max(this->cram_width, current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = std::max(this->cram_height, current_offset + current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < current_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank][x].resize(this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (current_height*current_width)/8; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int x = (i*8 + j) % current_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int y = (i*8 + j) / current_width + current_offset; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank][x][y] = ((byte << j) & 0x80) != 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ end_token = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end_token = (end_token << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (end_token) ~~~~~~~~~~~~~~ error("Expeded 0x0000 after CRAM data, got 0x%04x\n", end_token); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x03: ~~~~~~~~~~ info("BRAM Data [%d]: %d x %d bits = %d bits = %d bytes\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_bank, current_width, current_height, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_height*current_width, (current_height*current_width)/8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = std::max(this->bram_width, current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = std::max(this->bram_height, current_offset + current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank].resize(this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < current_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (current_height*current_width)/8; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int x = (i*8 + j) % current_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int y = (i*8 + j) / current_width + current_offset; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank][x][y] = ((byte << j) & 0x80) != 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ end_token = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end_token = (end_token << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (end_token) ~~~~~~~~~~~~~~ error("Expeded 0x0000 after BRAM data, got 0x%04x\n", end_token); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x05: ~~~~~~~~~~ debug("Resetting CRC.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~ crc_value = 0xffff; ~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x06: ~~~~~~~~~~ info("Wakeup.\n"); ~~~~~~~~~~~~~~~~~~ wakeup = true; ~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown command: 0x%02x 0x%02x\n", command, payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ break; ~~~~~~ case 0x10: ~~~~~~~~~~ current_bank = payload; ~~~~~~~~~~~~~~~~~~~~~~~ debug("Set bank to %d.\n", current_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x20: ~~~~~~~~~~ if (crc_value != 0) ~~~~~~~~~~~~~~~~~~~ error("CRC Check FAILED.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("CRC Check OK.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x50: ~~~~~~~~~~ if (payload == 0) ~~~~~~~~~~~~~~~~~ this->freqrange = "low"; ~~~~~~~~~~~~~~~~~~~~~~~~ else if (payload == 1) ~~~~~~~~~~~~~~~~~~~~~~ this->freqrange = "medium"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (payload == 2) ~~~~~~~~~~~~~~~~~~~~~~ this->freqrange = "high"; ~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown freqrange payload 0x%02x\n", payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Setting freqrange to '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x60: ~~~~~~~~~~ current_width = payload + 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank width to %d.\n", current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x70: ~~~~~~~~~~ current_height = payload; ~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank height to %d.\n", current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x80: ~~~~~~~~~~ current_offset = payload; ~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank offset to %d.\n", current_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x90: ~~~~~~~~~~ switch(payload) ~~~~~~~~~~~~~~~ { ~ case 0: ~~~~~~~ this->warmboot = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ this->warmboot = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 32: ~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 33: ~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown warmboot/nosleep payload 0x%02x\n", payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ info("Setting warmboot to '%s', nosleep to '%s'.\n", this->warmboot.c_str(), this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown command: 0x%02x 0x%02x\n", command, payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ if (this->cram_width == 182 && this->cram_height == 80) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "384"; ~~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 332 && this->cram_height == 144) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "1k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 872 && this->cram_height == 272) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "8k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 692 && this->cram_height == 336) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "5k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 692 && this->cram_height == 176) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "u4k"; ~~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 656 && this->cram_height == 176) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "lm4k"; ~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Failed to detect chip type.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Chip type is '%s'.\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::write_bits(std::ostream &ofs) const ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int file_offset = 0; ~~~~~~~~~~~~~~~~~~~~ uint16_t crc_value = 0; ~~~~~~~~~~~~~~~~~~~~~~~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Writing bitstream file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (auto byte : this->initblop) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << byte; ~~~~~~~~~~~~ debug("Writing preamble.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x7E); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0xAA); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x99); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x7E); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting freqrange to '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x51); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->freqrange == "low") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->freqrange == "medium") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->freqrange == "high") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x02); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown freqrange '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Resetting CRC.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x05); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ crc_value = 0xffff; ~~~~~~~~~~~~~~~~~~~ { ~ uint8_t nosleep_flag; ~~~~~~~~~~~~~~~~~~~~~ debug("Setting warmboot to '%s', nosleep to '%s'.\n", this->warmboot.c_str(), this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x92); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->nosleep == "disabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nosleep_flag = 0; ~~~~~~~~~~~~~~~~~ else if (this->nosleep == "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nosleep_flag = 1; ~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown nosleep setting '%s'.\n", this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot == "disabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00 | nosleep_flag); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->warmboot == "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x20 | nosleep_flag); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown warmboot setting '%s'.\n", this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank width to %d.\n", this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->cram_width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->cram_width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device != "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Setting bank height to %d.\n", this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, this->cram_height >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank offset to 0.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x82); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_bank = 0; cram_bank < 4; cram_bank++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ vector cram_bits; ~~~~~~~~~~~~~~~~~~~~~~~ int height = this->cram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k" && ((cram_bank % 2) == 1)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ height = height / 2 + 8; ~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_y = 0; cram_y < height; cram_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_x = 0; cram_x < this->cram_width; cram_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cram_bits.push_back(this->cram[cram_bank][cram_x][cram_y]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Setting bank height to %d.\n", height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, height >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank %d.\n", cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x11); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Writing bank %d data.\n", cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < int(cram_bits.size()); i += 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = 0; ~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ byte = (byte << 1) | (cram_bits[i+j] ? 1 : 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int bram_chunk_size = 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->bram_width && this->bram_height) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if(this->device != "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank width to %d.\n", this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->bram_width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->bram_width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("BRAM: Setting bank height to %d.\n", this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_chunk_size >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_chunk_size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bram_bank = 0; bram_bank < 4; bram_bank++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("BRAM: Setting bank %d.\n", bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x11); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int offset = 0; offset < this->bram_height; offset += bram_chunk_size) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ vector bram_bits; ~~~~~~~~~~~~~~~~~~~~~~~ int width = this->bram_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k" && ((bram_bank % 2) == 1)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ width = width / 2; ~~~~~~~~~~~~~~~~~~ for (int bram_y = 0; bram_y < bram_chunk_size; bram_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bram_x = 0; bram_x < width; bram_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bram_bits.push_back(this->bram[bram_bank][bram_x][bram_y+offset]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank offset to %d.\n", offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x82); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, offset >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank width to %d.\n", width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("BRAM: Writing bank %d data.\n", bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x03); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < int(bram_bits.size()); i += 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = 0; ~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ byte = (byte << 1) | (bram_bits[i+j] ? 1 : 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ } ~ debug("Writing CRC value.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x22); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t crc_hi = crc_value >> 8, crc_lo = crc_value; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, crc_hi); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, crc_lo); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Wakeup.\n"); ~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x06); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Padding byte.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::read_ascii(std::istream &ifs, bool nosleep) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Parsing ascii file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool got_device = false; ~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.clear(); ~~~~~~~~~~~~~~~~~~~ this->bram.clear(); ~~~~~~~~~~~~~~~~~~~ this->freqrange = "low"; ~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool reuse_line = true; ~~~~~~~~~~~~~~~~~~~~~~~ string line, command; ~~~~~~~~~~~~~~~~~~~~~ while (reuse_line || getline(ifs, line)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ reuse_line = false; ~~~~~~~~~~~~~~~~~~~ std::istringstream is(line); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> command; ~~~~~~~~~~~~~~ if (command.empty()) ~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ debug("Next command: %s\n", line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (command == ".comment") ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ this->initblop.clear(); ~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0xff); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (getline(ifs, line)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (auto ch : line) ~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(ch); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->initblop.push_back(0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0xff); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".device") ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (got_device) ~~~~~~~~~~~~~~~ error("More than one .device statement.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> this->device; ~~~~~~~~~~~~~~~~~~~ if (this->device == "384") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 182; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 80; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "1k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 332; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 144; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 64; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "8k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 872; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 272; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 128; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 692; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 336; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 160; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "u4k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 692; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 176; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 80; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "lm4k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 656; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 176; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 80; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ error("Unsupported chip type '%s'.\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->cram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i][x].resize(((i % 2) == 1) ? (this->cram_height / 2 + 8) : this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int width = ((i % 2) == 1) ? (this->bram_width / 2) : this->bram_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i].resize(width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } else { ~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->cram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i][x].resize(this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i].resize(this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->bram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ got_device = true; ~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".warmboot") ~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ is >> this->warmboot; ~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot != "disabled" && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot != "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unknown warmboot setting '%s'.\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ // No ".nosleep" section despite sharing the same byte as .warmboot. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ".nosleep" is specified when icepack is invoked, which is too late. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // So we inject the section based on command line argument. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (nosleep) ~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (command == ".io_tile" || command == ".logic_tile" || command == ".ramb_tile" || command == ".ramt_tile" || command.substr(0, 4) == ".dsp" || command == ".ipcon_tile") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ is >> tile_x >> tile_y; ~~~~~~~~~~~~~~~~~~~~~~~ CramIndexConverter cic(this, tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (("." + cic.tile_type + "_tile") != command) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Got %s statement for %s tile %d %d.\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ command.c_str(), cic.tile_type.c_str(), tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16 && getline(ifs, line); bit_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (int bit_x = 0; bit_x < int(line.size()) && bit_x < cic.tile_width; bit_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (line[bit_x] == '1') { ~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[cram_bank][cram_x][cram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ continue; ~~~~~~~~~ } ~ if (command == ".ram_data") ~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ is >> tile_x >> tile_y; ~~~~~~~~~~~~~~~~~~~~~~~ BramIndexConverter bic(this, tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16 && getline(ifs, line); bit_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (int bit_x = 256-4, ch_idx = 0; ch_idx < int(line.size()) && bit_x >= 0; bit_x -= 4, ch_idx++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int value = -1; ~~~~~~~~~~~~~~~ if ('0' <= line[ch_idx] && line[ch_idx] <= '9') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - '0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ('a' <= line[ch_idx] && line[ch_idx] <= 'f') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - 'a' + 10; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ('A' <= line[ch_idx] && line[ch_idx] <= 'F') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - 'A' + 10; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (value < 0) ~~~~~~~~~~~~~~ error("Not a hex character: '%c' (in line '%s')\n", line[ch_idx], line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ((value & (1 << i)) != 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int bram_bank, bram_x, bram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bic.get_bram_index(bit_x+i, bit_y, bram_bank, bram_x, bram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[bram_bank][bram_x][bram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ } ~ continue; ~~~~~~~~~ } ~ if (command == ".extra_bit") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> cram_bank >> cram_x >> cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[cram_bank][cram_x][cram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".sym") ~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ if (command.substr(0, 1) == ".") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unknown statement: %s\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unexpected data line: %s\n", line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ void FpgaConfig::write_ascii(std::ostream &ofs) const ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Writing ascii file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << ".comment"; ~~~~~~~~~~~~~~~~~~ bool insert_newline = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (auto ch : this->initblop) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ch == 0) { ~~~~~~~~~~~~~~ insert_newline = true; ~~~~~~~~~~~~~~~~~~~~~~ } else if (ch == 0xff) { ~~~~~~~~~~~~~~~~~~~~~~~~ insert_newline = false; ~~~~~~~~~~~~~~~~~~~~~~~ } else { ~~~~~~~~ if (insert_newline) ~~~~~~~~~~~~~~~~~~~ ofs << '\n'; ~~~~~~~~~~~~ ofs << ch; ~~~~~~~~~~ insert_newline = false; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ ofs << stringf("\n.device %s\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot != "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << stringf(".warmboot %s\n", this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // As "nosleep" is an icepack command, we do not write out a ".nosleep" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // section. However, we parse it in read_bits() and notify the user in ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // info. ~~~~~~~~ typedef std::tuple tile_bit_t; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ std::set tile_bits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int y = 0; y <= this->chip_height()+1; y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x <= this->chip_width()+1; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ CramIndexConverter cic(this, x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (cic.tile_type == "corner" || cic.tile_type == "unsupported") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ ofs << stringf(".%s_tile %d %d\n", cic.tile_type.c_str(), x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16; bit_y++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_x = 0; bit_x < cic.tile_width; bit_x++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tile_bits.insert(tile_bit_t(cram_bank, cram_x, cram_y)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (cram_x > int(this->cram[cram_bank].size())) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("cram_x %d (bit %d, %d) larger than bank size %lu\n", cram_x, bit_x, bit_y, this->cram[cram_bank].size()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ if (cram_y > int(this->cram[cram_bank][cram_x].size())) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("cram_y %d (bit %d, %d) larger than bank %d size %lu\n", cram_y, bit_x, bit_y, cram_bank, this->cram[cram_bank][cram_x].size()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ ofs << (this->cram[cram_bank][cram_x][cram_y] ? '1' : '0'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ ofs << '\n'; ~~~~~~~~~~~~ } ~ if (cic.tile_type == "ramb") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ BramIndexConverter bic(this, x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << stringf(".ram_data %d %d\n", x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16; bit_y++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_x = 256-4; bit_x >= 0; bit_x -= 4) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int value = 0; ~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int bram_bank, bram_x, bram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bic.get_bram_index(bit_x+i, bit_y, bram_bank, bram_x, bram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (bram_x >= int(this->bram[bram_bank].size())) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("%d %d bram_x %d higher than loaded bram size %lu\n",bit_x+i, bit_y, bram_x, this->bram[bram_bank].size()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ icepack.cc:924:8: note: in expansion of macro 'error' error("%d %d bram_x %d higher than loaded bram size %lu\n",bit_x+i, bit_y, bram_x, this->bram[bram_bank].size()); ^~~~~ icepack.cc:53:41: warning: format '%lu' expects argument of type 'long unsigned int', but argument 4 has type 'std::vector::size_type' {aka 'unsigned int'} [-Wformat=] #define error(...) do { fprintf(stderr, "Error: " __VA_ARGS__); exit(1); } while (0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define panic(fmt, ...) do { fprintf(stderr, "Internal Error at %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__); abort(); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string vstringf(const char *fmt, va_list ap) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ string string; ~~~~~~~~~~~~~~ char *str = NULL; ~~~~~~~~~~~~~~~~~ #ifdef _WIN32 ~~~~~~~~~~~~~ int sz = 64, rc; ~~~~~~~~~~~~~~~~ while (1) { ~~~~~~~~~~~ va_list apc; ~~~~~~~~~~~~ va_copy(apc, ap); ~~~~~~~~~~~~~~~~~ str = (char*)realloc(str, sz); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ rc = vsnprintf(str, sz, fmt, apc); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(apc); ~~~~~~~~~~~~ if (rc >= 0 && rc < sz) ~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ sz *= 2; ~~~~~~~~ } ~ #else ~~~~~ if (vasprintf(&str, fmt, ap) < 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ str = NULL; ~~~~~~~~~~~ #endif ~~~~~~ if (str != NULL) { ~~~~~~~~~~~~~~~~~~ string = str; ~~~~~~~~~~~~~ free(str); ~~~~~~~~~~ } ~ return string; ~~~~~~~~~~~~~~ } ~ string stringf(const char *fmt, ...) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ string string; ~~~~~~~~~~~~~~ va_list ap; ~~~~~~~~~~~ va_start(ap, fmt); ~~~~~~~~~~~~~~~~~~ string = vstringf(fmt, ap); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(ap); ~~~~~~~~~~~ return string; ~~~~~~~~~~~~~~ } ~ // ================================================================== ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // FpgaConfig stuff ~~~~~~~~~~~~~~~~~~~ struct FpgaConfig ~~~~~~~~~~~~~~~~~ { ~ string device; ~~~~~~~~~~~~~~ string freqrange; ~~~~~~~~~~~~~~~~~ string nosleep; ~~~~~~~~~~~~~~~ string warmboot; ~~~~~~~~~~~~~~~~ // cram[BANK][X][Y] ~~~~~~~~~~~~~~~~~~~ int cram_width, cram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vector>> cram; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bram[BANK][X][Y] ~~~~~~~~~~~~~~~~~~~ int bram_width, bram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vector>> bram; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // data before preamble ~~~~~~~~~~~~~~~~~~~~~~~ vector initblop; ~~~~~~~~~~~~~~~~~~~~~~~~~ // bitstream i/o ~~~~~~~~~~~~~~~~ void read_bits(std::istream &ifs); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_bits(std::ostream &ofs) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // icebox i/o ~~~~~~~~~~~~~ void read_ascii(std::istream &ifs, bool nosleep); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_ascii(std::ostream &ofs) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // netpbm i/o ~~~~~~~~~~~~~ void write_cram_pbm(std::ostream &ofs, int bank_num = -1) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void write_bram_pbm(std::ostream &ofs, int bank_num = -1) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // query chip type metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~ int chip_width() const; ~~~~~~~~~~~~~~~~~~~~~~~ int chip_height() const; ~~~~~~~~~~~~~~~~~~~~~~~~ vector chip_cols() const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // query tile metadata ~~~~~~~~~~~~~~~~~~~~~~ string tile_type(int x, int y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_width(const string &type) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // cram bit manipulation ~~~~~~~~~~~~~~~~~~~~~~~~ void cram_clear(); ~~~~~~~~~~~~~~~~~~ void cram_fill_tiles(); ~~~~~~~~~~~~~~~~~~~~~~~ void cram_checkerboard(int m = 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ struct CramIndexConverter ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ const FpgaConfig *fpga; ~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ string tile_type; ~~~~~~~~~~~~~~~~~ int tile_width; ~~~~~~~~~~~~~~~ int column_width; ~~~~~~~~~~~~~~~~~ bool left_right_io; ~~~~~~~~~~~~~~~~~~~ bool right_half; ~~~~~~~~~~~~~~~~ bool top_half; ~~~~~~~~~~~~~~ int bank_num; ~~~~~~~~~~~~~ int bank_tx; ~~~~~~~~~~~~ int bank_ty; ~~~~~~~~~~~~ int bank_xoff; ~~~~~~~~~~~~~~ int bank_yoff; ~~~~~~~~~~~~~~ CramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void get_cram_index(int bit_x, int bit_y, int &cram_bank, int &cram_x, int &cram_y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ struct BramIndexConverter ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ const FpgaConfig *fpga; ~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ int bank_num; ~~~~~~~~~~~~~ int bank_off; ~~~~~~~~~~~~~ BramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void get_bram_index(int bit_x, int bit_y, int &bram_bank, int &bram_x, int &bram_y) const; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }; ~~ static void update_crc16(uint16_t &crc, uint8_t byte) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ // CRC-16-CCITT, Initialize to 0xFFFF, No zero padding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 7; i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint16_t xor_value = ((crc >> 15) ^ ((byte >> i) & 1)) ? 0x1021 : 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ crc = (crc << 1) ^ xor_value; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ static uint8_t read_byte(std::istream &ifs, uint16_t &crc_value, int &file_offset) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int byte = ifs.get(); ~~~~~~~~~~~~~~~~~~~~~ if (byte < 0) ~~~~~~~~~~~~~ error("Unexpected end of file.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ file_offset++; ~~~~~~~~~~~~~~ update_crc16(crc_value, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return byte; ~~~~~~~~~~~~ } ~ static void write_byte(std::ostream &ofs, uint16_t &crc_value, int &file_offset, uint8_t byte) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ ofs << byte; ~~~~~~~~~~~~ file_offset++; ~~~~~~~~~~~~~~ update_crc16(crc_value, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::read_bits(std::istream &ifs) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int file_offset = 0; ~~~~~~~~~~~~~~~~~~~~ uint16_t crc_value = 0; ~~~~~~~~~~~~~~~~~~~~~~~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Parsing bitstream file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // skip initial comments until preamble is found ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint32_t preamble = 0; ~~~~~~~~~~~~~~~~~~~~~~ while (1) ~~~~~~~~~ { ~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ preamble = (preamble << 8) | byte; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (preamble == 0xffffffff) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("No preamble found in bitstream.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (preamble == 0x7EAA997E) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Found preamble at offset %d.\n", file_offset-4); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ initblop.push_back(byte); ~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ initblop.pop_back(); ~~~~~~~~~~~~~~~~~~~~ // main parser loop ~~~~~~~~~~~~~~~~~~~ int current_bank = 0; ~~~~~~~~~~~~~~~~~~~~~ int current_width = 0; ~~~~~~~~~~~~~~~~~~~~~~ int current_height = 0; ~~~~~~~~~~~~~~~~~~~~~~~ int current_offset = 0; ~~~~~~~~~~~~~~~~~~~~~~~ bool wakeup = false; ~~~~~~~~~~~~~~~~~~~~ this->cram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ while (!wakeup) ~~~~~~~~~~~~~~~ { ~ // one command byte. the lower 4 bits of the command byte specify ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // the length of the command payload. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t command = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint32_t payload = 0; ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (command & 0x0f); i++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ payload = (payload << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Next command at offset %d: 0x%02x 0x%0*x\n", file_offset - 1 - (command & 0x0f), ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ command, 2*(command & 0x0f), payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint16_t end_token; ~~~~~~~~~~~~~~~~~~~ switch (command & 0xf0) ~~~~~~~~~~~~~~~~~~~~~~~ { ~ case 0x00: ~~~~~~~~~~ switch (payload) ~~~~~~~~~~~~~~~~ { ~ case 0x01: ~~~~~~~~~~ info("CRAM Data [%d]: %d x %d bits = %d bits = %d bytes\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_bank, current_width, current_height, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_height*current_width, (current_height*current_width)/8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = std::max(this->cram_width, current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = std::max(this->cram_height, current_offset + current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < current_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank][x].resize(this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (current_height*current_width)/8; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int x = (i*8 + j) % current_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int y = (i*8 + j) / current_width + current_offset; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[current_bank][x][y] = ((byte << j) & 0x80) != 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ end_token = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end_token = (end_token << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (end_token) ~~~~~~~~~~~~~~ error("Expeded 0x0000 after CRAM data, got 0x%04x\n", end_token); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x03: ~~~~~~~~~~ info("BRAM Data [%d]: %d x %d bits = %d bits = %d bytes\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_bank, current_width, current_height, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ current_height*current_width, (current_height*current_width)/8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = std::max(this->bram_width, current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = std::max(this->bram_height, current_offset + current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank].resize(this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < current_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < (current_height*current_width)/8; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int x = (i*8 + j) % current_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int y = (i*8 + j) / current_width + current_offset; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[current_bank][x][y] = ((byte << j) & 0x80) != 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ end_token = read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end_token = (end_token << 8) | read_byte(ifs, crc_value, file_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (end_token) ~~~~~~~~~~~~~~ error("Expeded 0x0000 after BRAM data, got 0x%04x\n", end_token); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x05: ~~~~~~~~~~ debug("Resetting CRC.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~ crc_value = 0xffff; ~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x06: ~~~~~~~~~~ info("Wakeup.\n"); ~~~~~~~~~~~~~~~~~~ wakeup = true; ~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown command: 0x%02x 0x%02x\n", command, payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ break; ~~~~~~ case 0x10: ~~~~~~~~~~ current_bank = payload; ~~~~~~~~~~~~~~~~~~~~~~~ debug("Set bank to %d.\n", current_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x20: ~~~~~~~~~~ if (crc_value != 0) ~~~~~~~~~~~~~~~~~~~ error("CRC Check FAILED.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("CRC Check OK.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x50: ~~~~~~~~~~ if (payload == 0) ~~~~~~~~~~~~~~~~~ this->freqrange = "low"; ~~~~~~~~~~~~~~~~~~~~~~~~ else if (payload == 1) ~~~~~~~~~~~~~~~~~~~~~~ this->freqrange = "medium"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (payload == 2) ~~~~~~~~~~~~~~~~~~~~~~ this->freqrange = "high"; ~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown freqrange payload 0x%02x\n", payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Setting freqrange to '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x60: ~~~~~~~~~~ current_width = payload + 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank width to %d.\n", current_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x70: ~~~~~~~~~~ current_height = payload; ~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank height to %d.\n", current_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x80: ~~~~~~~~~~ current_offset = payload; ~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting bank offset to %d.\n", current_offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 0x90: ~~~~~~~~~~ switch(payload) ~~~~~~~~~~~~~~~ { ~ case 0: ~~~~~~~ this->warmboot = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ this->warmboot = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 32: ~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 33: ~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown warmboot/nosleep payload 0x%02x\n", payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ info("Setting warmboot to '%s', nosleep to '%s'.\n", this->warmboot.c_str(), this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ error("Unknown command: 0x%02x 0x%02x\n", command, payload); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ if (this->cram_width == 182 && this->cram_height == 80) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "384"; ~~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 332 && this->cram_height == 144) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "1k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 872 && this->cram_height == 272) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "8k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 692 && this->cram_height == 336) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "5k"; ~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 692 && this->cram_height == 176) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "u4k"; ~~~~~~~~~~~~~~~~~~~~~ else if (this->cram_width == 656 && this->cram_height == 176) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->device = "lm4k"; ~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Failed to detect chip type.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Chip type is '%s'.\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::write_bits(std::ostream &ofs) const ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int file_offset = 0; ~~~~~~~~~~~~~~~~~~~~ uint16_t crc_value = 0; ~~~~~~~~~~~~~~~~~~~~~~~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Writing bitstream file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (auto byte : this->initblop) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << byte; ~~~~~~~~~~~~ debug("Writing preamble.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x7E); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0xAA); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x99); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x7E); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Setting freqrange to '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x51); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->freqrange == "low") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->freqrange == "medium") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->freqrange == "high") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x02); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown freqrange '%s'.\n", this->freqrange.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Resetting CRC.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x05); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ crc_value = 0xffff; ~~~~~~~~~~~~~~~~~~~ { ~ uint8_t nosleep_flag; ~~~~~~~~~~~~~~~~~~~~~ debug("Setting warmboot to '%s', nosleep to '%s'.\n", this->warmboot.c_str(), this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x92); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->nosleep == "disabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nosleep_flag = 0; ~~~~~~~~~~~~~~~~~ else if (this->nosleep == "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nosleep_flag = 1; ~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown nosleep setting '%s'.\n", this->nosleep.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot == "disabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00 | nosleep_flag); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (this->warmboot == "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x20 | nosleep_flag); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ error("Unknown warmboot setting '%s'.\n", this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank width to %d.\n", this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->cram_width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->cram_width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device != "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Setting bank height to %d.\n", this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, this->cram_height >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank offset to 0.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x82); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_bank = 0; cram_bank < 4; cram_bank++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ vector cram_bits; ~~~~~~~~~~~~~~~~~~~~~~~ int height = this->cram_height; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k" && ((cram_bank % 2) == 1)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ height = height / 2 + 8; ~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_y = 0; cram_y < height; cram_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int cram_x = 0; cram_x < this->cram_width; cram_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cram_bits.push_back(this->cram[cram_bank][cram_x][cram_y]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Setting bank height to %d.\n", height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, height >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("CRAM: Setting bank %d.\n", cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x11); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("CRAM: Writing bank %d data.\n", cram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < int(cram_bits.size()); i += 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = 0; ~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ byte = (byte << 1) | (cram_bits[i+j] ? 1 : 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int bram_chunk_size = 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->bram_width && this->bram_height) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if(this->device != "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank width to %d.\n", this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->bram_width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (this->bram_width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("BRAM: Setting bank height to %d.\n", this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x72); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_chunk_size >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_chunk_size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bram_bank = 0; bram_bank < 4; bram_bank++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("BRAM: Setting bank %d.\n", bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x11); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int offset = 0; offset < this->bram_height; offset += bram_chunk_size) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ vector bram_bits; ~~~~~~~~~~~~~~~~~~~~~~~ int width = this->bram_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k" && ((bram_bank % 2) == 1)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ width = width / 2; ~~~~~~~~~~~~~~~~~~ for (int bram_y = 0; bram_y < bram_chunk_size; bram_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bram_x = 0; bram_x < width; bram_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bram_bits.push_back(this->bram[bram_bank][bram_x][bram_y+offset]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank offset to %d.\n", offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x82); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, offset >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, offset); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("BRAM: Setting bank width to %d.\n", width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x62); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (width-1) >> 8); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, (width-1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("BRAM: Writing bank %d data.\n", bram_bank); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x03); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < int(bram_bits.size()); i += 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t byte = 0; ~~~~~~~~~~~~~~~~~ for (int j = 0; j < 8; j++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ byte = (byte << 1) | (bram_bits[i+j] ? 1 : 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, byte); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ } ~ debug("Writing CRC value.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x22); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint8_t crc_hi = crc_value >> 8, crc_lo = crc_value; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, crc_hi); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, crc_lo); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Wakeup.\n"); ~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x01); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x06); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("Padding byte.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~ write_byte(ofs, crc_value, file_offset, 0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void FpgaConfig::read_ascii(std::istream &ifs, bool nosleep) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Parsing ascii file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool got_device = false; ~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.clear(); ~~~~~~~~~~~~~~~~~~~ this->bram.clear(); ~~~~~~~~~~~~~~~~~~~ this->freqrange = "low"; ~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool reuse_line = true; ~~~~~~~~~~~~~~~~~~~~~~~ string line, command; ~~~~~~~~~~~~~~~~~~~~~ while (reuse_line || getline(ifs, line)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ reuse_line = false; ~~~~~~~~~~~~~~~~~~~ std::istringstream is(line); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> command; ~~~~~~~~~~~~~~ if (command.empty()) ~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ debug("Next command: %s\n", line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (command == ".comment") ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ this->initblop.clear(); ~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0xff); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (getline(ifs, line)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (auto ch : line) ~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(ch); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->initblop.push_back(0x00); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->initblop.push_back(0xff); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".device") ~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (got_device) ~~~~~~~~~~~~~~~ error("More than one .device statement.\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> this->device; ~~~~~~~~~~~~~~~~~~~ if (this->device == "384") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 182; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 80; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 0; ~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 0; ~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "1k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 332; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 144; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 64; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "8k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 872; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 272; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 128; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 692; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 336; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 160; ~~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "u4k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 692; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 176; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 80; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ if (this->device == "lm4k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram_width = 656; ~~~~~~~~~~~~~~~~~~~~~~~ this->cram_height = 176; ~~~~~~~~~~~~~~~~~~~~~~~~ this->bram_width = 80; ~~~~~~~~~~~~~~~~~~~~~~ this->bram_height = 2 * 128; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } else ~~~~~~ error("Unsupported chip type '%s'.\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ if(this->device == "5k") { ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->cram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i][x].resize(((i % 2) == 1) ? (this->cram_height / 2 + 8) : this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int width = ((i % 2) == 1) ? (this->bram_width / 2) : this->bram_width; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i].resize(width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } else { ~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i].resize(this->cram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->cram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[i][x].resize(this->cram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ this->bram.resize(4); ~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i].resize(this->bram_width); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x < this->bram_width; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[i][x].resize(this->bram_height); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ got_device = true; ~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".warmboot") ~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ is >> this->warmboot; ~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot != "disabled" && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot != "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unknown warmboot setting '%s'.\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ // No ".nosleep" section despite sharing the same byte as .warmboot. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ".nosleep" is specified when icepack is invoked, which is too late. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // So we inject the section based on command line argument. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (nosleep) ~~~~~~~~~~~~ this->nosleep = "enabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~ else ~~~~ this->nosleep = "disabled"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (command == ".io_tile" || command == ".logic_tile" || command == ".ramb_tile" || command == ".ramt_tile" || command.substr(0, 4) == ".dsp" || command == ".ipcon_tile") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ is >> tile_x >> tile_y; ~~~~~~~~~~~~~~~~~~~~~~~ CramIndexConverter cic(this, tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (("." + cic.tile_type + "_tile") != command) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Got %s statement for %s tile %d %d.\n", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ command.c_str(), cic.tile_type.c_str(), tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16 && getline(ifs, line); bit_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (int bit_x = 0; bit_x < int(line.size()) && bit_x < cic.tile_width; bit_x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (line[bit_x] == '1') { ~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[cram_bank][cram_x][cram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ continue; ~~~~~~~~~ } ~ if (command == ".ram_data") ~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int tile_x, tile_y; ~~~~~~~~~~~~~~~~~~~ is >> tile_x >> tile_y; ~~~~~~~~~~~~~~~~~~~~~~~ BramIndexConverter bic(this, tile_x, tile_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16 && getline(ifs, line); bit_y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (line.substr(0, 1) == ".") { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reuse_line = true; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ for (int bit_x = 256-4, ch_idx = 0; ch_idx < int(line.size()) && bit_x >= 0; bit_x -= 4, ch_idx++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int value = -1; ~~~~~~~~~~~~~~~ if ('0' <= line[ch_idx] && line[ch_idx] <= '9') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - '0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ('a' <= line[ch_idx] && line[ch_idx] <= 'f') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - 'a' + 10; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ('A' <= line[ch_idx] && line[ch_idx] <= 'F') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = line[ch_idx] - 'A' + 10; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (value < 0) ~~~~~~~~~~~~~~ error("Not a hex character: '%c' (in line '%s')\n", line[ch_idx], line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ((value & (1 << i)) != 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int bram_bank, bram_x, bram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bic.get_bram_index(bit_x+i, bit_y, bram_bank, bram_x, bram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->bram[bram_bank][bram_x][bram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ } ~ continue; ~~~~~~~~~ } ~ if (command == ".extra_bit") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (!got_device) ~~~~~~~~~~~~~~~~ error("Missing .device statement before %s.\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is >> cram_bank >> cram_x >> cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this->cram[cram_bank][cram_x][cram_y] = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (command == ".sym") ~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ if (command.substr(0, 1) == ".") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unknown statement: %s\n", command.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("Unexpected data line: %s\n", line.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ void FpgaConfig::write_ascii(std::ostream &ofs) const ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ debug("## %s\n", __PRETTY_FUNCTION__); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ info("Writing ascii file..\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << ".comment"; ~~~~~~~~~~~~~~~~~~ bool insert_newline = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (auto ch : this->initblop) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ch == 0) { ~~~~~~~~~~~~~~ insert_newline = true; ~~~~~~~~~~~~~~~~~~~~~~ } else if (ch == 0xff) { ~~~~~~~~~~~~~~~~~~~~~~~~ insert_newline = false; ~~~~~~~~~~~~~~~~~~~~~~~ } else { ~~~~~~~~ if (insert_newline) ~~~~~~~~~~~~~~~~~~~ ofs << '\n'; ~~~~~~~~~~~~ ofs << ch; ~~~~~~~~~~ insert_newline = false; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ ofs << stringf("\n.device %s\n", this->device.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (this->warmboot != "enabled") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << stringf(".warmboot %s\n", this->warmboot.c_str()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // As "nosleep" is an icepack command, we do not write out a ".nosleep" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // section. However, we parse it in read_bits() and notify the user in ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // info. ~~~~~~~~ typedef std::tuple tile_bit_t; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ std::set tile_bits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int y = 0; y <= this->chip_height()+1; y++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int x = 0; x <= this->chip_width()+1; x++) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ CramIndexConverter cic(this, x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (cic.tile_type == "corner" || cic.tile_type == "unsupported") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ ofs << stringf(".%s_tile %d %d\n", cic.tile_type.c_str(), x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16; bit_y++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_x = 0; bit_x < cic.tile_width; bit_x++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int cram_bank, cram_x, cram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tile_bits.insert(tile_bit_t(cram_bank, cram_x, cram_y)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (cram_x > int(this->cram[cram_bank].size())) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("cram_x %d (bit %d, %d) larger than bank size %lu\n", cram_x, bit_x, bit_y, this->cram[cram_bank].size()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ if (cram_y > int(this->cram[cram_bank][cram_x].size())) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("cram_y %d (bit %d, %d) larger than bank %d size %lu\n", cram_y, bit_x, bit_y, cram_bank, this->cram[cram_bank][cram_x].size()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ ofs << (this->cram[cram_bank][cram_x][cram_y] ? '1' : '0'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ ofs << '\n'; ~~~~~~~~~~~~ } ~ if (cic.tile_type == "ramb") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ BramIndexConverter bic(this, x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ofs << stringf(".ram_data %d %d\n", x, y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_y = 0; bit_y < 16; bit_y++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int bit_x = 256-4; bit_x >= 0; bit_x -= 4) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int value = 0; ~~~~~~~~~~~~~~ for (int i = 0; i < 4; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int bram_bank, bram_x, bram_y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bic.get_bram_index(bit_x+i, bit_y, bram_bank, bram_x, bram_y); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (bram_x >= int(this->bram[bram_bank].size())) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("%d %d bram_x %d higher than loaded bram size %lu\n",bit_x+i, bit_y, bram_x, this->bram[bram_bank].size()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ if (bram_y >= int(this->bram[bram_bank][bram_x].size())) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error("bram_y %d higher than loaded bram size %lu\n", bram_y, this->bram[bram_bank][bram_x].size()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ icepack.cc:928:8: note: in expansion of macro 'error' error("bram_y %d higher than loaded bram size %lu\n", bram_y, this->bram[bram_bank][bram_x].size()); ^~~~~ make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepack' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepack' g++ -o icepack icepack.o -lftdi1 -lusb-1.0 -lm make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepack' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepack' ln -sf icepack iceunpack make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepack' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/iceprog' gcc -pipe -frecord-gcc-switches -Wall -g -O2 -march=i586 -mtune=generic -Wextra -I/usr/include/libftdi1 -I/usr/include/libusb-1.0 -c -o iceprog.o iceprog.c make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/iceprog' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/iceprog' gcc -o iceprog iceprog.o -lftdi1 -lusb-1.0 -lm make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/iceprog' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icemulti' g++ -pipe -frecord-gcc-switches -Wall -g -O2 -march=i586 -mtune=generic -Wextra -c -o icemulti.o icemulti.cc make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icemulti' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icemulti' g++ -o icemulti icemulti.o -lftdi1 -lusb-1.0 -lm make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icemulti' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepll' g++ -pipe -frecord-gcc-switches -Wall -g -O2 -march=i586 -mtune=generic -Wextra -c -o icepll.o icepll.cc make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepll' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepll' g++ -o icepll icepll.o -lftdi1 -lusb-1.0 -lm make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepll' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icetime' python3 timings.py > timings.inc.new mv timings.inc.new timings.inc make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icetime' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icetime' g++ -pipe -frecord-gcc-switches -Wall -g -O2 -march=i586 -mtune=generic -Wextra -DPREFIX='"/usr/local"' -DCHIPDB_SUBDIR='"icebox"' -c -o icetime.o icetime.cc icetime.cc: In function 'std::__cxx11::string ecnetname_to_vlog(std::__cxx11::string)': icetime.cc:1318:32: warning: catching polymorphic type 'class std::invalid_argument' by value [-Wcatch-value=] } catch(std::invalid_argument e) { // Not numeric and stoi throws exception ^ make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icetime' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icetime' g++ -o icetime icetime.o -lftdi1 -lusb-1.0 -lm make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icetime' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebram' g++ -pipe -frecord-gcc-switches -Wall -g -O2 -march=i586 -mtune=generic -Wextra -c -o icebram.o icebram.cc make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebram' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebram' g++ -o icebram icebram.o -lftdi1 -lusb-1.0 -lm make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebram' + exit 0 Executing(%install): /bin/sh -e /usr/src/tmp/rpm-tmp.19621 + umask 022 + /bin/mkdir -p /usr/src/RPM/BUILD + cd /usr/src/RPM/BUILD + /bin/chmod -Rf u+rwX -- /usr/src/tmp/icestorm-buildroot + : + /bin/rm -rf -- /usr/src/tmp/icestorm-buildroot + cd icestorm-0.0.0.618.gf029975 + make 'INSTALL=/bin/install -p' install DESTDIR=/usr/src/tmp/icestorm-buildroot PREFIX=/usr make: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975' for dir in icebox icepack iceprog icemulti icepll icetime icebram; do \ make -C $dir install || exit; \ done make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' mkdir -p /usr/src/tmp/icestorm-buildroot/usr/share/icebox mkdir -p /usr/src/tmp/icestorm-buildroot/usr/bin cp chipdb-384.txt /usr/src/tmp/icestorm-buildroot/usr/share/icebox/ cp chipdb-1k.txt /usr/src/tmp/icestorm-buildroot/usr/share/icebox/ cp chipdb-8k.txt /usr/src/tmp/icestorm-buildroot/usr/share/icebox/ cp chipdb-5k.txt /usr/src/tmp/icestorm-buildroot/usr/share/icebox/ cp chipdb-lm4k.txt /usr/src/tmp/icestorm-buildroot/usr/share/icebox/ cp icebox.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox.py cp iceboxdb.py /usr/src/tmp/icestorm-buildroot/usr/bin/iceboxdb.py cp icebox_chipdb.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_chipdb cp icebox_diff.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_diff cp icebox_explain.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_explain cp icebox_asc2hlc.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_asc2hlc cp icebox_hlc2asc.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_hlc2asc cp icebox_colbuf.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_colbuf cp icebox_html.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_html cp icebox_maps.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_maps cp icebox_vlog.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_vlog cp icebox_stat.py /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_stat make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebox' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepack' mkdir -p /usr/src/tmp/icestorm-buildroot/usr/bin cp icepack /usr/src/tmp/icestorm-buildroot/usr/bin/icepack ln -sf icepack /usr/src/tmp/icestorm-buildroot/usr/bin/iceunpack make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepack' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/iceprog' mkdir -p /usr/src/tmp/icestorm-buildroot/usr/bin cp iceprog /usr/src/tmp/icestorm-buildroot/usr/bin/iceprog make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/iceprog' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icemulti' mkdir -p /usr/src/tmp/icestorm-buildroot/usr/bin cp icemulti /usr/src/tmp/icestorm-buildroot/usr/bin/icemulti make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icemulti' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepll' mkdir -p /usr/src/tmp/icestorm-buildroot/usr/bin cp icepll /usr/src/tmp/icestorm-buildroot/usr/bin/icepll make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icepll' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icetime' mkdir -p /usr/src/tmp/icestorm-buildroot/usr/bin cp icetime /usr/src/tmp/icestorm-buildroot/usr/bin/icetime make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icetime' make[1]: Entering directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebram' mkdir -p /usr/src/tmp/icestorm-buildroot/usr/bin cp icebram /usr/src/tmp/icestorm-buildroot/usr/bin/icebram make[1]: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975/icebram' make: Leaving directory '/usr/src/RPM/BUILD/icestorm-0.0.0.618.gf029975' + mkdir -p /usr/src/tmp/icestorm-buildroot/usr/lib/python3/site-packages + mv /usr/src/tmp/icestorm-buildroot/usr/bin/iceboxdb.py /usr/src/tmp/icestorm-buildroot/usr/lib/python3/site-packages/ + ln -rs /usr/src/tmp/icestorm-buildroot/usr/lib/python3/site-packages/iceboxdb.py /usr/src/tmp/icestorm-buildroot/usr/bin/ + chmod a+x /usr/src/tmp/icestorm-buildroot/usr/bin/icebox.py + /usr/lib/rpm/brp-alt Cleaning files in /usr/src/tmp/icestorm-buildroot (auto) Verifying and fixing files in /usr/src/tmp/icestorm-buildroot (binconfig,pkgconfig,libtool,desktop) Checking contents of files in /usr/src/tmp/icestorm-buildroot/ (default) Compressing files in /usr/src/tmp/icestorm-buildroot (auto) Adjusting library links in /usr/src/tmp/icestorm-buildroot ./usr/lib: Verifying ELF objects in /usr/src/tmp/icestorm-buildroot (arch=normal,fhs=normal,lfs=relaxed,lint=relaxed,rpath=normal,stack=normal,textrel=normal,unresolved=normal) verify-elf: WARNING: ./usr/bin/icetime: uses non-LFS functions: fopen verify-elf: WARNING: ./usr/bin/icepll: uses non-LFS functions: fopen verify-elf: WARNING: ./usr/bin/iceprog: uses non-LFS functions: fopen tmpfile Bytecompiling python modules in /usr/src/tmp/icestorm-buildroot using /usr/bin/python Bytecompiling python modules with optimization in /usr/src/tmp/icestorm-buildroot using /usr/bin/python -O Bytecompiling python3 modules in /usr/src/tmp/icestorm-buildroot using /usr/bin/python3 compile /usr/src/tmp/icestorm-buildroot/usr/lib/python3/site-packages/iceboxdb.py Bytecompiling python3 modules with optimization in /usr/src/tmp/icestorm-buildroot using /usr/bin/python3 -O compile /usr/src/tmp/icestorm-buildroot/usr/lib/python3/site-packages/iceboxdb.py Bytecompiling python3 modules with optimization-2 in /usr/src/tmp/icestorm-buildroot using /usr/bin/python3 -OO compile /usr/src/tmp/icestorm-buildroot/usr/lib/python3/site-packages/iceboxdb.py Hardlinking identical .pyc and .opt-?.pyc files './usr/lib/python3/site-packages/__pycache__/iceboxdb.cpython-37.opt-1.pyc' => './usr/lib/python3/site-packages/__pycache__/iceboxdb.cpython-37.pyc' './usr/lib/python3/site-packages/__pycache__/iceboxdb.cpython-37.opt-2.pyc' => './usr/lib/python3/site-packages/__pycache__/iceboxdb.cpython-37.opt-1.pyc' Hardlinking identical .pyc and .pyo files Processing files: icestorm-0.0.0.618.gf029975-alt2 Finding Provides (using /usr/lib/rpm/find-provides) Executing: /bin/sh -e /usr/src/tmp/rpm-tmp.LHlceM find-provides: running scripts (alternatives,debuginfo,lib,pam,perl,pkgconfig,python,python3,shell) Finding Requires (using /usr/lib/rpm/find-requires) Executing: /bin/sh -e /usr/src/tmp/rpm-tmp.L9740P find-requires: running scripts (cpp,debuginfo,files,lib,pam,perl,pkgconfig,pkgconfiglib,python,python3,rpmlib,shebang,shell,static,symlinks,systemd-services) python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox.py: skipping sys python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_asc2hlc: skipping sys python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_chipdb: skipping sys python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_colbuf: skipping sys python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_diff: skipping sys python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_explain: skipping sys python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_hlc2asc: skipping sys python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_html: skipping sys python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_maps: skipping sys python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_stat: skipping sys python3.req: /usr/src/tmp/icestorm-buildroot/usr/bin/icebox_vlog: skipping sys find-requires: FINDPACKAGE-COMMANDS: python3 Provides: python3(iceboxdb) Requires: /lib/ld-linux.so.2, /usr/bin/env, /usr/lib/python3/site-packages, libc.so.6(GLIBC_2.0), libc.so.6(GLIBC_2.1), libc.so.6(GLIBC_2.1.3), libc.so.6(GLIBC_2.3.4), libc.so.6(GLIBC_2.4), libc.so.6(GLIBC_2.7), libc.so.6(GLIBC_2.8), libftdi1.so.2 >= set:kg1x6Lx22DeGigb1uoeCEZjeWaddZFDyCKfeNok, libgcc_s.so.1(GCC_3.0), libm.so.6(GLIBC_2.1), libstdc++.so.6(CXXABI_1.3), libstdc++.so.6(CXXABI_1.3.1), libstdc++.so.6(CXXABI_1.3.9), libstdc++.so.6(GLIBCXX_3.4), libstdc++.so.6(GLIBCXX_3.4.11), libstdc++.so.6(GLIBCXX_3.4.14), libstdc++.so.6(GLIBCXX_3.4.20), libstdc++.so.6(GLIBCXX_3.4.21), libstdc++.so.6(GLIBCXX_3.4.9), python3, python3(getopt) < 0, python3(os) < 0, python3(re) < 0, rtld(GNU_HASH) Requires(rpmlib): rpmlib(SetVersions) Finding debuginfo files (using /usr/lib/rpm/find-debuginfo-files) Executing: /bin/sh -e /usr/src/tmp/rpm-tmp.3vcz3l Creating icestorm-debuginfo package Processing files: icestorm-chipdb-0.0.0.618.gf029975-alt2 Finding Provides (using /usr/lib/rpm/find-provides) Executing: /bin/sh -e /usr/src/tmp/rpm-tmp.2xZUgu find-provides: running scripts (alternatives,debuginfo,lib,pam,perl,pkgconfig,python,python3,shell) Finding Requires (using /usr/lib/rpm/find-requires) Executing: /bin/sh -e /usr/src/tmp/rpm-tmp.VthWqM find-requires: running scripts (cpp,debuginfo,files,lib,pam,perl,pkgconfig,pkgconfiglib,python,python3,rpmlib,shebang,shell,static,symlinks,systemd-services) Processing files: icestorm-debuginfo-0.0.0.618.gf029975-alt2 Finding Provides (using /usr/lib/rpm/find-provides) Executing: /bin/sh -e /usr/src/tmp/rpm-tmp.hyknLp find-provides: running scripts (debuginfo) Finding Requires (using /usr/lib/rpm/find-requires) Executing: /bin/sh -e /usr/src/tmp/rpm-tmp.cAvhek find-requires: running scripts (debuginfo) Requires: icestorm = 0.0.0.618.gf029975-alt2, /usr/lib/debug/lib/ld-linux.so.2.debug, debug(libc.so.6), debug(libftdi1.so.2), debug(libgcc_s.so.1), debug(libm.so.6), debug(libstdc++.so.6) Adding to icestorm-debuginfo a strict dependency on icestorm Wrote: /usr/src/RPM/RPMS/i586/icestorm-0.0.0.618.gf029975-alt2.i586.rpm Wrote: /usr/src/RPM/RPMS/noarch/icestorm-chipdb-0.0.0.618.gf029975-alt2.noarch.rpm Wrote: /usr/src/RPM/RPMS/i586/icestorm-debuginfo-0.0.0.618.gf029975-alt2.i586.rpm 371.15user 3.44system 4:00.47elapsed 155%CPU (0avgtext+0avgdata 1170272maxresident)k 0inputs+0outputs (0major+1440764minor)pagefaults 0swaps 378.17user 6.24system 4:10.03elapsed 153%CPU (0avgtext+0avgdata 1170272maxresident)k 0inputs+0outputs (0major+1861575minor)pagefaults 0swaps