From 3362b92cb11c2532577819fd7c65f37abff270da Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 23 Jul 2017 13:57:59 +0200 Subject: [PATCH] Add bitread and add SLICEBIT extraction to gridinfo Signed-off-by: Clifford Wolf Signed-off-by: Tim 'mithro' Ansell --- gridinfo/.gitignore | 2 + gridinfo/runme.sh | 15 ++ tools/.gitignore | 1 + tools/Makefile | 14 ++ tools/bitread.cc | 545 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 577 insertions(+) create mode 100644 tools/.gitignore create mode 100644 tools/Makefile create mode 100644 tools/bitread.cc diff --git a/gridinfo/.gitignore b/gridinfo/.gitignore index d502a6c6..ee33be77 100644 --- a/gridinfo/.gitignore +++ b/gridinfo/.gitignore @@ -6,3 +6,5 @@ /design.log /design.dcp /logicframes_SLICE_*.bit +/logicframes_SLICE_*.asc +/grid-*-db.txt diff --git a/gridinfo/runme.sh b/gridinfo/runme.sh index f9477521..e27f557b 100644 --- a/gridinfo/runme.sh +++ b/gridinfo/runme.sh @@ -54,3 +54,18 @@ EOT rm -f design.log vivado -nojournal -log design.log -mode batch -source design.tcl +{ + sed -e '/^--tiledata--/ { s/[^ ]* //; p; }; d;' design.log + + for f0 in logicframes_SLICE_*_0.bit; do + f1=${f0%_0.bit}_1.bit + ../tools/bitread -xo ${f0%.bit}.asc < $f0 > /dev/null + ../tools/bitread -xo ${f1%.bit}.asc < $f1 > /dev/null + f0=${f0%.bit}.asc + f1=${f1%.bit}.asc + n=${f0%_0.asc} + n=${n#logicframes_} + echo SLICEBIT $n $( diff $f0 $f1 | grep '^>' | cut -c3-; ) + done +} > grid-${XRAY_PART}-db.txt + diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 00000000..247a16f6 --- /dev/null +++ b/tools/.gitignore @@ -0,0 +1 @@ +/bitread diff --git a/tools/Makefile b/tools/Makefile new file mode 100644 index 00000000..1d1420af --- /dev/null +++ b/tools/Makefile @@ -0,0 +1,14 @@ + +# CXXFLAGS = -Wall -Wextra -O0 -ggdb +CXXFLAGS = -Wall -Wextra -O3 + +all: bitread + +bitread: bitread.cc + clang $(CXXFLAGS) -static -std=c++11 -o $@ $< -lstdc++ + +clean: + rm -f bitread + +.PHONY: all clean + diff --git a/tools/bitread.cc b/tools/bitread.cc new file mode 100644 index 00000000..66e82632 --- /dev/null +++ b/tools/bitread.cc @@ -0,0 +1,545 @@ +#include +#include +#include +#include +#include +#include +#include + +bool mode_c = false; +bool mode_r = false; +bool mode_m = false; +bool mode_x = false; +bool mode_z = false; +bool chksum = false; +char *outfile = nullptr; +std::set frames; + +std::vector bitdata; +int cursor; + +std::string header_a, header_b, header_c, header_d; +std::vector configdata; + +uint32_t frameptr = 0; +std::map> configframes; +std::set configframes_autoincr; + +std::vector zero_frame(101); + +uint32_t selbits(uint32_t value, int msb, int lsb) +{ + return (value >> lsb) & ((1 << (msb-lsb+1)) - 1); +} + +void print_hexblock(int len) +{ + if (!mode_r) { + cursor += len; + return; + } + + int index = 0; + std::vector lastbuf; + bool in_continue = false; + + while (len > 0) + { + char asciibuf[17]; + asciibuf[16] = 0; + + if (len > 16 && mode_c) { + std::vector thisbuf(bitdata.begin()+cursor, bitdata.begin()+cursor+16); + if (lastbuf == thisbuf) { + if (!in_continue) + printf("*\n"); + in_continue = true; + cursor += 16; + index += 16; + len -= 16; + continue; + } + lastbuf.swap(thisbuf); + in_continue = false; + } + + printf("%06x: ", index); + index += 16; + + for (int i = 0; i < 16; i++) { + if (i % 4 == 0) + printf(" "); + if (len > 0) { + printf("%02x ", bitdata.at(cursor)); + asciibuf[i] = (32 <= bitdata.at(cursor) && bitdata.at(cursor) < 128) ? bitdata.at(cursor) : '.'; + cursor++, len--; + } else { + printf(" "); + asciibuf[i] = ' '; + } + } + + printf(" |%s|\n", asciibuf); + } +} + +void print_pkt_len2() +{ + int len = (bitdata.at(cursor) << 8) + bitdata.at(cursor+1); + + if (mode_r) + printf("\nPkt at byte %d with length %d:\n", cursor, len); + cursor += 2; + + print_hexblock(len); +} + +void print_pkt_key_len2() +{ + int key = bitdata.at(cursor); + int len = (bitdata.at(cursor+1) << 8) + bitdata.at(cursor+2); + + if (mode_r) + printf("\nPkt '%c' at byte %d with length %d:\n", key, cursor, len); + cursor += 3; + + print_hexblock(len); +} + +void print_pkt_key_len4() +{ + int key = bitdata.at(cursor); + int len = (bitdata.at(cursor+1) << 24) + (bitdata.at(cursor+2) << 16) + (bitdata.at(cursor+3) << 8) + bitdata.at(cursor+4); + + if (mode_r) + printf("\nPkt '%c' at byte %d with length %d:\n", key, cursor, len); + cursor += 5; + + for (int i = 0; i < len; i+= 4) + configdata.push_back((bitdata.at(cursor+i) << 24) + (bitdata.at(cursor+i+1) << 16) + + (bitdata.at(cursor+i+2) << 8) + bitdata.at(cursor+i+3)); + + print_hexblock(len); +} + +#define REG_CRC 0 +#define REG_FAR 1 +#define REG_FDRI 2 +#define REG_FDRO 3 +#define REG_CMD 4 +#define REG_CTL0 5 +#define REG_MASK 6 +#define REG_STAT 7 +#define REG_LOUT 8 +#define REG_COR0 9 +#define REG_MFWR 10 +#define REG_CBC 11 +#define REG_IDCODE 12 +#define REG_AXSS 13 +#define REG_COR1 14 +#define REG_WBSTAR 16 +#define REG_TIMER 17 +#define REG_CRCSET 19 +#define REG_BOOTSTS 22 +#define REG_CTL1 24 +#define REG_BSPI 31 + +const char *regname(int addr) +{ + switch (addr) + { + case REG_CRC: return "CRC"; + case REG_FAR: return "FAR"; + case REG_FDRI: return "FDRI"; + case REG_FDRO: return "FDRO"; + case REG_CMD: return "CMD"; + case REG_CTL0: return "CTL0"; + case REG_MASK: return "MASK"; + case REG_STAT: return "STAT"; + case REG_LOUT: return "LOUT"; + case REG_COR0: return "COR0"; + case REG_MFWR: return "MFWR"; + case REG_CBC: return "CBC"; + case REG_IDCODE: return "IDCODE"; + case REG_AXSS: return "AXSS"; + case REG_COR1: return "COR1"; + case REG_WBSTAR: return "WBSTAR"; + case REG_TIMER: return "TIMER"; + case REG_CRCSET: return "CRCSET"; + case REG_BOOTSTS: return "BOOTSTS"; + case REG_CTL1: return "CTL1"; + case REG_BSPI: return "BSPI"; + default: return "UNKOWN"; + } +} + +void handle_write(int regaddr, uint32_t data) +{ + if (regaddr == REG_FAR) { + frameptr = data; + configframes_autoincr.erase(frameptr); + } + + if (regaddr == REG_FDRI) { + if (configframes[frameptr].size() == 101) { + configframes[++frameptr].clear(); + configframes_autoincr.insert(frameptr); + } + configframes[frameptr].push_back(data); + } +} + +class frameid +{ + uint32_t value; + +public: + frameid(uint32_t v) : value(v) { } + + uint32_t get_value() const { + return value; + } + + int get_type() const { + return selbits(value, 25, 23); + } + + int get_topflag() const { + return selbits(value, 22, 22); + } + + int get_rowaddr() const { + return selbits(value, 21, 17); + } + + int get_coladdr() const { + return selbits(value, 16, 7); + } + + int get_minor() const { + return selbits(value, 6, 0); + } +}; + +int main(int argc, char **argv) +{ + int opt; + while ((opt = getopt(argc, argv, "crmxzCf:o:")) != -1) + switch (opt) + { + case 'c': + mode_c = true; + break; + case 'r': + mode_r = true; + break; + case 'm': + mode_m = true; + break; + case 'x': + mode_x = true; + break; + case 'z': + mode_z = true; + break; + case 'C': + chksum = true; + break; + case 'f': + frames.insert(strtol(optarg, nullptr, 0)); + break; + case 'o': + outfile = optarg; + break; + default: + goto help; + } + + if (optind != argc) { +help: + fprintf(stderr, "\n"); + fprintf(stderr, "Usage: %s [options] < bitfile.bit\n", argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, " -c\n"); + fprintf(stderr, " continuation mode. output '*' for repeating patterns\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -r\n"); + fprintf(stderr, " raw mode. only decode top-level .bit file format framing\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -m\n"); + fprintf(stderr, " command mode. print commands in config stream\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -z\n"); + fprintf(stderr, " skip zero frames (frames with all bits cleared) in outout\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -x\n"); + fprintf(stderr, " use format 'bit_%%08x_%%02x_%%02x_t%%d_h%%d_r%%d_c%%d_m%%d_w%%d_b%%d'\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -C\n"); + fprintf(stderr, " do not ignore the checksum in each frame\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -f \n"); + fprintf(stderr, " only dump the specified frame (might be used more than once)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -o \n"); + fprintf(stderr, " write machine-readable output file with config frames\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "In -x format the fields have the following meaning:\n"); + fprintf(stderr, " - complete 32 bit hex frame id\n"); + fprintf(stderr, " - hex word index within that frame\n"); + fprintf(stderr, " - hex bit index within that word\n"); + fprintf(stderr, " - decoded frame type from frame id\n"); + fprintf(stderr, " - decoded top/botttom from frame id (top=0)\n"); + fprintf(stderr, " - decoded row address from frame id\n"); + fprintf(stderr, " - decoded column address from frame id\n"); + fprintf(stderr, " - decoded minor address from frame id\n"); + fprintf(stderr, " - word index with that frame (decimal)\n"); + fprintf(stderr, " - bit index with that word (decimal)\n"); + fprintf(stderr, "\n"); + return 1; + } + + while (1) { + int c = getchar(); + if (c == EOF) break; + bitdata.push_back(c); + } + + printf("Bitstream size: %d bytes\n", int(bitdata.size())); + + cursor = 0; + while (cursor < int(bitdata.size())) + { + if (bitdata.at(cursor) == 0x00) { + header_a = (const char*)&bitdata.at(cursor+2); + print_pkt_len2(); + continue; + } + + if (bitdata.at(cursor) == 0x62) { + header_b = (const char*)&bitdata.at(cursor+3); + print_pkt_key_len2(); + continue; + } + + if (bitdata.at(cursor) == 0x63) { + header_c = (const char*)&bitdata.at(cursor+3); + print_pkt_key_len2(); + continue; + } + + if (bitdata.at(cursor) == 0x64) { + header_d = (const char*)&bitdata.at(cursor+3); + print_pkt_key_len2(); + continue; + } + + if (bitdata.at(cursor) == 0x65) { + print_pkt_key_len4(); + continue; + } + + printf("Top-level framing error at byte %d.\n", cursor); + return 1; + } + + if (!mode_r) + { + printf("Header A: %s\n", header_a.c_str()); + printf("Header B: %s\n", header_b.c_str()); + printf("Header C: %s\n", header_c.c_str()); + printf("Header D: %s\n", header_d.c_str()); + printf("Config size: %d words\n", int(configdata.size())); + + cursor = 0; + while (cursor < int(configdata.size())) + if (configdata.at(cursor++) == 0xAA995566) + break; + + printf("Skipped %d padding/header words.\n", cursor); + + int current_write_reg = -1; + + while (cursor < int(configdata.size())) + { + uint32_t cmd = configdata.at(cursor); + int cmd_header = selbits(cmd, 31, 29); + + // Type 1 Packet + if (cmd_header == 1) + { + int opcode = selbits(cmd, 28, 27); + int regaddr = selbits(cmd, 26, 13); + int reserved = selbits(cmd, 12, 11); + int wcount = selbits(cmd, 10, 0); + + if (reserved != 0 || regaddr > 31) + goto cmderror; + + if (opcode == 0) { + if (mode_m) { + printf("%8d: 0x%08x NOP\n", cursor, configdata.at(cursor)); + if (mode_c && cmd == 0x20000000 && cursor+1 < int(configdata.size()) && cmd == configdata.at(cursor+1)) { + while (cursor+1 < int(configdata.size()) && cmd == configdata.at(cursor+1)) cursor++; + printf("*\n"); + } + } + goto handle_type1_payload; + } + + if (opcode == 1) { + if (mode_m) + printf("%8d: 0x%08x Read %s register (%d)\n", cursor, configdata.at(cursor), regname(regaddr), regaddr); + goto handle_type1_payload; + } + + if (opcode == 2) { + if (mode_m) + printf("%8d: 0x%08x Write %s register (%d)\n", cursor, configdata.at(cursor), regname(regaddr), regaddr); + current_write_reg = regaddr; + goto handle_type1_payload; + } + + if (0) { + handle_type1_payload: + cursor++; + + uint32_t last_word = wcount ? ~configdata.at(cursor) : 0; + bool in_continue = false; + + while (wcount--) { + if (mode_m) { + uint32_t this_word = configdata.at(cursor); + if (mode_c && last_word == this_word) { + if (!in_continue) + printf("*\n"); + in_continue = true; + } else { + if (current_write_reg == REG_FAR) { + frameid fid(this_word); + printf("%8d: 0x%08x FAR: Type=%d, Top=%d, Row=%d, Col=%d, Minor=%d\n", + cursor, fid.get_value(), fid.get_type(), fid.get_topflag(), + fid.get_rowaddr(), fid.get_coladdr(), fid.get_minor()); + } else + printf("%8d: 0x%08x\n", cursor, this_word); + in_continue = false; + } + last_word = this_word; + } + handle_write(regaddr, configdata.at(cursor)); + cursor++; + } + continue; + } + } + + // Type 2 Packet + if (cmd_header == 2) + { + int opcode = selbits(cmd, 28, 27); + int wcount = selbits(cmd, 26, 0); + + if (opcode != 2) + goto cmderror; + + if (mode_m) + printf("%8d: 0x%08x Type 2 write\n", cursor, configdata.at(cursor)); + + uint32_t last_word = configdata.at(cursor); + bool in_continue = false; + + cursor++; + while (wcount--) + { + uint32_t this_word = configdata.at(cursor); + handle_write(current_write_reg, this_word); + + if (mode_m) { + if (mode_c && last_word == this_word) { + if (!in_continue) + printf("*\n"); + in_continue = true; + } else { + in_continue = false; + printf("%8d: Payload: 0x%08x\n", cursor, this_word); + } + } + + last_word = this_word; + cursor++; + } + continue; + } + + cmderror: + printf("%8d: Unknown config command: 0x%08x\n", cursor, cmd); + return 1; + } + + printf("Number of configuration frames: %d\n", int(configframes.size())); + + FILE *f = stdout; + + if (outfile != nullptr) + { + f = fopen(outfile, "w"); + + if (f == nullptr) { + printf("Can't open output file '%s' for writing!\n", outfile); + return 1; + } + } + + if (outfile == nullptr) + fprintf(f, "\n"); + + for (auto &it : configframes) + { + if (mode_z && it.second == zero_frame) + continue; + + frameid fid(it.first); + + if (!frames.empty() && !frames.count(fid.get_value())) + continue; + + if (outfile == nullptr) + printf("Frame 0x%08x (Type=%d Top=%d Row=%d Column=%d Minor=%d%s):\n", fid.get_value(), fid.get_type(), fid.get_topflag(), + fid.get_rowaddr(), fid.get_coladdr(), fid.get_minor(), configframes_autoincr.count(fid.get_value()) ? " AUTO_INCREMENT" : ""); + + if (it.second.size() != 101) { + printf(" unusual frame size: %d\n", int(it.second.size())); + return 1; + } + + + if (mode_x) + { + for (int i = 0; i < 101; i++) + for (int k = 0; k < 32; k++) + if ((i != 50 || chksum) && ((it.second.at(i) & (1 << k)) != 0)) + fprintf(f, "bit_%08x_%02x_%02x_t%d_h%d_r%d_c%d_m%d_w%d_b%d\n", + fid.get_value(), i, k, fid.get_type(), fid.get_topflag(), fid.get_rowaddr(), + fid.get_coladdr(), fid.get_minor(), i, k); + if (outfile == nullptr) + fprintf(f, "\n"); + } + else + { + if (outfile != nullptr) + fprintf(f, ".frame 0x%08x%s\n", fid.get_value(), configframes_autoincr.count(fid.get_value()) ? " AI" : ""); + + for (int i = 0; i < 101; i++) + fprintf(f, "%08x%s", (i != 50 || chksum) ? it.second.at(i) : 0, (i % 6) == 5 ? "\n" : " "); + fprintf(f, "\n\n"); + } + } + + if (outfile != nullptr) + fclose(f); + } + + printf("DONE\n"); + return 0; +} +