diff --git a/.gitignore b/.gitignore index bd5df6c..c5b22dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -bit2txt -bit2txt.o draw_svg_tiles draw_svg_tiles.o helper.o diff --git a/Makefile b/Makefile index c0d4ddc..f7d9b91 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ LDLIBS += `pkg-config libxml-2.0 --libs` MODEL_OBJ = model_main.o model_tiles.o model_devices.o model_ports.o model_conns.o model_switches.o model_helper.o all: new_fp fp2bit bit2fp draw_svg_tiles \ - autotest bit2txt hstrrep sort_seq merge_seq pair2net + autotest hstrrep sort_seq merge_seq pair2net autotest: autotest.o $(MODEL_OBJ) floorplan.o control.o helper.o model.h @@ -46,10 +46,6 @@ draw_svg_tiles: draw_svg_tiles.o $(MODEL_OBJ) helper.o control.o draw_svg_tiles.o: draw_svg_tiles.c model.h helper.h -bit2txt: bit2txt.o helper.o - -bit2txt.o: bit2txt.c helper.h - pair2net: pair2net.o helper.o pair2net.o: pair2net.c helper.h @@ -123,8 +119,7 @@ compare.%: xc6slx9_empty.% @cat $<|awk '{if ($$1=="sw") printf "%s %s %s %s %s\n",$$2,$$3,$$4,$$5,$$6}'|sort >$@ clean: - rm -f bit2txt bit2txt.o \ - draw_svg_tiles draw_svg_tiles.o \ + rm -f draw_svg_tiles draw_svg_tiles.o \ new_fp new_fp.o \ helper.o $(MODEL_OBJ) hstrrep hstrrep.o \ sort_seq sort_seq.o \ @@ -148,6 +143,6 @@ clean: install: all mkdir -p $(DESTDIR)/$(PREFIX)/bin/ install -m 755 new_fp $(DESTDIR)/$(PREFIX)/bin/ - install -m 755 bit2txt $(DESTDIR)/$(PREFIX)/bin/ + install -m 755 bit2fp $(DESTDIR)/$(PREFIX)/bin/ uninstall: - rm -f $(DESTDIR)/$(PREFIX)/bin/{new_fp,bit2txt} + rm -f $(DESTDIR)/$(PREFIX)/bin/{new_fp,bit2fp} diff --git a/README b/README index 7b4c3e8..c2d446e 100644 --- a/README +++ b/README @@ -27,7 +27,6 @@ Design Utilities fpgatools Development Utilities - autotest executes test suite -- bit2txt dumps .bit bitstream as text - hstrrep high-speed hashed array based search and replace util - sort_seq sorts line-based text file by sequence numbers in strings - merge_seq merges a pre-sorted text file into wire sequences diff --git a/autotest.c b/autotest.c index 1ebacf5..a5305f2 100644 --- a/autotest.c +++ b/autotest.c @@ -75,12 +75,12 @@ static int diff_printf(struct test_state* tstate) strcpy(&path[path_base], ".fp"); dest_f = fopen(path, "w"); - if (!dest_f) { rc = -1; FAIL(); } + if (!dest_f) FAIL(errno); rc = printf_devices(dest_f, tstate->model, /*config_only*/ 1); - if (rc) FAIL(); + if (rc) FAIL(rc); rc = printf_switches(dest_f, tstate->model, /*enabled_only*/ 1); - if (rc) FAIL(); + if (rc) FAIL(rc); fclose(dest_f); dest_f = 0; @@ -88,11 +88,11 @@ static int diff_printf(struct test_state* tstate) snprintf(tmp, sizeof(tmp), "./autotest_diff.sh %s %s.fp >%s.log 2>&1", prior_fp, path, path); rc = system(tmp); - if (rc) FAIL(); + if (rc) FAIL(rc); strcpy(&path[path_base], ".diff"); rc = dump_file(path); - if (rc) FAIL(); + if (rc) FAIL(rc); tstate->next_diff_counter++; return 0; @@ -132,13 +132,13 @@ int main(int argc, char** argv) strcpy(tstate.tmp_dir, AUTOTEST_TMP_DIR); mkdir(tstate.tmp_dir, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); rc = diff_start(&tstate, "and"); - if (rc) FAIL(); + if (rc) FAIL(rc); // configure P46 rc = fpga_find_iob(&model, "P46", &P46_y, &P46_x, &P46_idx); - if (rc) FAIL(); + if (rc) FAIL(rc); P46_dev = fpga_dev(&model, P46_y, P46_x, DEV_IOB, P46_idx); - if (!P46_dev) { rc = -1; FAIL(); } + if (!P46_dev) FAIL(EINVAL); P46_dev->instantiated = 1; strcpy(P46_dev->iob.istandard, IO_LVCMOS33); P46_dev->iob.bypass_mux = BYPASS_MUX_I; @@ -146,9 +146,9 @@ int main(int argc, char** argv) // configure P48 rc = fpga_find_iob(&model, "P48", &P48_y, &P48_x, &P48_idx); - if (rc) FAIL(); + if (rc) FAIL(rc); P48_dev = fpga_dev(&model, P48_y, P48_x, DEV_IOB, P48_idx); - if (!P48_dev) { rc = -1; FAIL(); } + if (!P48_dev) FAIL(EINVAL); P48_dev->instantiated = 1; strcpy(P48_dev->iob.ostandard, IO_LVCMOS33); P48_dev->iob.drive_strength = 12; @@ -158,13 +158,13 @@ int main(int argc, char** argv) // configure logic logic_dev = fpga_dev(&model, /*y*/ 68, /*x*/ 13, DEV_LOGIC, /*LOGIC_X*/ 1); - if (!logic_dev) { rc = -1; FAIL(); } + if (!logic_dev) FAIL(EINVAL); logic_dev->instantiated = 1; logic_dev->logic.D_used = 1; rc = fpga_set_lut(&model, logic_dev, D6_LUT, "A3", ZTERM); - if (rc) FAIL(); + if (rc) FAIL(rc); -#if 0 +#if 1 rc = diff_printf(&tstate); if (rc) goto fail; #endif diff --git a/bit2fp.c b/bit2fp.c index 9d01da5..5f7f139 100644 --- a/bit2fp.c +++ b/bit2fp.c @@ -12,9 +12,10 @@ int main(int argc, char** argv) { struct fpga_model model; - FILE* fbits = 0; int bits_only, file_arg, rc = -1; + struct fpga_config config; + // parameters if (argc < 2) { fprintf(stderr, "\n" @@ -23,7 +24,6 @@ int main(int argc, char** argv) "\n", argv[0], argv[0]); goto fail; } - bits_only = 0; file_arg = 1; if (!strcmp(argv[1], "--bits-only")) { @@ -31,22 +31,30 @@ int main(int argc, char** argv) file_arg = 2; } - fbits = fopen(argv[file_arg], "r"); - if (!fbits) { - fprintf(stderr, "Error opening %s.\n", argv[file_arg]); - goto fail; + // read bitstream file + { + FILE* fbits = fopen(argv[file_arg], "r"); + if (!fbits) { + fprintf(stderr, "Error opening %s.\n", argv[file_arg]); + goto fail; + } + rc = read_bitfile(&config, fbits); + fclose(fbits); + if (rc) FAIL(rc); } + // build model and fill from bitstream if ((rc = fpga_build_model(&model, XC6SLX9_ROWS, XC6SLX9_COLUMNS, - XC6SLX9_LEFT_WIRING, XC6SLX9_RIGHT_WIRING))) - goto fail; + XC6SLX9_LEFT_WIRING, XC6SLX9_RIGHT_WIRING))) FAIL(rc); + if ((rc = extract_model(&config, &model))) FAIL(rc); - if ((rc = read_bits(&model, fbits))) goto fail; + // dump model if ((rc = write_floorplan(stdout, &model, - bits_only ? FP_BITS_ONLY : FP_BITS_DEFAULT))) goto fail; - fclose(fbits); + bits_only ? FP_BITS_ONLY : FP_BITS_DEFAULT))) FAIL(rc); + + // dump what doesn't fit into the model + if ((rc = dump_config(&config, DUMP_BITS))) FAIL(rc); return EXIT_SUCCESS; fail: - if (fbits) fclose(fbits); return rc; } diff --git a/bit2txt.c b/bit2txt.c deleted file mode 100644 index a07ce26..0000000 --- a/bit2txt.c +++ /dev/null @@ -1,1634 +0,0 @@ -// -// Author: Wolfgang Spraul -// -// This is free and unencumbered software released into the public domain. -// For details see the UNLICENSE file at the root of the source tree. -// - -#include "helper.h" - -// 120 MB max bitstream size is enough for now -#define BITSTREAM_READ_PAGESIZE 4096 -#define BITSTREAM_READ_MAXPAGES 30000 // 120 MB max bitstream - -// -// xc6 configuration registers, documentation in ug380, page90 -// - -enum { - CRC = 0, FAR_MAJ, FAR_MIN, FDRI, FDRO, CMD, CTL, MASK, STAT, LOUT, COR1, - COR2, PWRDN_REG, FLR, IDCODE, CWDT, HC_OPT_REG, CSBO = 18, - GENERAL1, GENERAL2, GENERAL3, GENERAL4, GENERAL5, MODE_REG, PU_GWE, - PU_GTS, MFWR, CCLK_FREQ, SEU_OPT, EXP_SIGN, RDBK_SIGN, BOOTSTS, - EYE_MASK, CBC_REG -}; - -// The highest 4 bits are the binary revision and not -// used when performing IDCODE verification. -// ug380, Configuration Sequence, page 78 -typedef struct -{ - char* name; - uint32_t code; -} IDCODE_S; - -#define XC6SLX4 0x04000093 -#define XC6SLX9 0x04001093 -#define XC6SLX16 0x04002093 -#define XC6SLX25 0x04004093 -#define XC6SLX25T 0x04024093 -#define XC6SLX45 0x04008093 -#define XC6SLX45T 0x04028093 -#define XC6SLX75 0x0400E093 -#define XC6SLX75T 0x0402E093 -#define XC6SLX100 0x04011093 -#define XC6SLX100T 0x04031093 -#define XC6SLX150 0x0401D093 - -const IDCODE_S idcodes[] = -{ - {"XC6SLX4", XC6SLX4}, - {"XC6SLX9", XC6SLX9}, - {"XC6SLX16", XC6SLX16}, - {"XC6SLX25", XC6SLX25}, - {"XC6SLX25T", XC6SLX25T}, - {"XC6SLX45", XC6SLX45}, - {"XC6SLX45T", XC6SLX45T}, - {"XC6SLX75", XC6SLX75}, - {"XC6SLX75T", XC6SLX75T}, - {"XC6SLX100", XC6SLX100}, - {"XC6SLX100T", XC6SLX100T}, - {"XC6SLX150", XC6SLX150} -}; - -enum { - CMD_NULL = 0, CMD_WCFG, CMD_MFW, CMD_LFRM, CMD_RCFG, CMD_START, - CMD_RCRC = 7, CMD_AGHIGH, CMD_GRESTORE = 10, CMD_SHUTDOWN, - CMD_DESYNC = 13, CMD_IPROG -}; - -const char* cmds[] = -{ - [CMD_NULL] = "NULL", - [CMD_WCFG] = "WCFG", - [CMD_MFW] = "MFW", - [CMD_LFRM] = "LFRM", - [CMD_RCFG] = "RCFG", - [CMD_START] = "START", - [CMD_RCRC] = "RCRC", - [CMD_AGHIGH] = "AGHIGH", - [CMD_GRESTORE] = "GRESTORE", - [CMD_SHUTDOWN] = "SHUTDOWN", - [CMD_DESYNC] = "DESYNC", - [CMD_IPROG] = "IPROG" -}; - -typedef enum { - MAJ_EXTRA = -1, - MAJ_CLB, MAJ_BRAM, MAJ_DSP -} major_t; - -typedef struct -{ - char* name; - int minors; - major_t type; -} MAJOR; - -const MAJOR majors[] = -{ - /* 0 */ { 0, 4, MAJ_EXTRA }, // 505 bytes = middle 8-bit - // for each minor? - /* 1 */ { 0, 30, MAJ_EXTRA }, - /* 2 */ { "clb", 31, MAJ_CLB }, - /* 3 */ { 0, 30, MAJ_EXTRA }, - /* 4 */ { "bram", 25, MAJ_BRAM }, - /* 5 */ { "clb", 31, MAJ_CLB }, - /* 6 */ { 0, 30, MAJ_EXTRA }, - /* 7 */ { "dsp", 24, MAJ_DSP }, - /* 8 */ { "clb", 31, MAJ_CLB }, - /* 9 */ { 0, 31, MAJ_EXTRA }, - /* 10 */ { "clb", 31, MAJ_CLB }, - /* 11 */ { 0, 30, MAJ_EXTRA }, - /* 12 */ { 0, 31, MAJ_EXTRA }, - /* 13 */ { 0, 30, MAJ_EXTRA }, - /* 14 */ { 0, 25, MAJ_EXTRA }, - /* 15 */ { "clb", 31, MAJ_CLB }, - /* 16 */ { 0, 30, MAJ_EXTRA }, - /* 17 */ { 0, 30, MAJ_EXTRA } -}; - -typedef struct ramb16_cfg -{ - uint8_t byte[64]; -} __attribute((packed)) ramb16_cfg_t; - -static const cfg_atom_t ramb16_instance = -{ - {-1}, {12,13, 274,275,276,277,316,317,318,319, - 420,421,422,423,-1}, "default_bits" -}; - -static cfg_atom_t ramb16_atoms[] = -{ - // data_width_a - {{264,265,260,261,256,257,-1},{ -1},"data_width_a 1"}, - {{264,265,260,261, -1},{ 256,257,-1},"data_width_a 2"}, - {{264,265, 256,257,-1},{ 260,261, -1},"data_width_a 4"}, - {{264,265, -1},{ 260,261,256,257,-1},"data_width_a 9"}, - {{ 260,261,256,257,-1},{264,265, -1},"data_width_a 18"}, - {{ 260,261, -1},{264,265, 256,257,-1},"data_width_a 36"}, - {{ -1},{264,265,260,261,256,257,-1},"data_width_a 0"}, - - // data_width_b - {{262,263,286,287,258,259,-1},{ -1},"data_width_b 1"}, - {{262,263,286,287, -1},{ 258,259,-1},"data_width_b 2"}, - {{262,263, 258,259,-1},{ 286,287, -1},"data_width_b 4"}, - {{262,263, -1},{ 286,287,258,259,-1},"data_width_b 9"}, - {{ 286,287,258,259,-1},{262,263, -1},"data_width_b 18"}, - {{ 286,287, -1},{262,263, 258,259,-1},"data_width_b 36"}, - {{ -1},{262,263,286,287,258,259,-1},"data_width_b 0"}, - - // required - { { -1}, {266, 267, -1}, "RST_PRIORITY_B:CE" }, - { {266, 267, -1}, { -1}, "RST_PRIORITY_B:SR" }, - { { -1}, {268, 269, -1}, "RST_PRIORITY_A:CE" }, - { {268, 269, -1}, { -1}, "RST_PRIORITY_A:SR" }, - { { -1}, {290, 291, -1}, "EN_RSTRAM_A:TRUE" }, - { {290, 291, -1}, { -1}, "EN_RSTRAM_A:FALSE" }, - { { -1}, {444, 445, -1}, "EN_RSTRAM_B:TRUE" }, - { {444, 445, -1}, { -1}, "EN_RSTRAM_B:FALSE" }, - - // optional - { { -1}, { 26, 27, -1}, "CLKAINV:CLKA" }, - { { 26, 27, -1}, { -1}, "CLKAINV:CLKA_B" }, // def - { { -1}, { 30, 31, -1}, "CLKBINV:CLKB" }, - { { 30, 31, -1}, { -1}, "CLKBINV:CLKB_B" }, // def - { { -1}, {270, 271, -1}, "RSTTYPE:ASYNC" }, - { {270, 271, -1}, { -1}, "RSTTYPE:SYNC" }, // def - { { -1}, {278, 279, -1}, "WRITE_MODE_B:READ_FIRST" }, - { { -1}, {280, 281, -1}, "WRITE_MODE_A:READ_FIRST" }, - { { -1}, {282, 283, -1}, "WRITE_MODE_B:NO_CHANGE" }, - { { -1}, {284, 285, -1}, "WRITE_MODE_A:NO_CHANGE" }, - { {278, 279, 282, 283, -1}, {-1}, "WRITE_MODE_B:WRITE_FIRST" }, //def - { {280, 281, 284, 285, -1}, {-1}, "WRITE_MODE_A:WRITE_FIRST" }, //def - { { -1}, {306, 307, -1}, "DOB_REG:1" }, - { {306, 306, -1}, { -1}, "DOB_REG:0" }, // def - { { -1}, {308, 309, -1}, "DOA_REG:1" }, - { {308, 309, -1}, { -1}, "DOA_REG:0" }, // def - { {431, 467, -1}, {430, 466, -1}, "ENAINV:ENA" }, // def - { {430, 431, 466, 467, -1}, {-1}, "ENAINV:ENA_B" }, - { {465, 469, -1}, {464, 468, -1}, "ENBINV:ENB" }, // def - { {464, 465, 468, 469, -1}, {-1}, "ENBINV:ENB_B" }, - { { -1}, { 20, 21, -1}, "REGCEAINV:REGCEA" }, // def - { { 20, 21, -1}, { -1}, "REGCEAINV:REGCEA_B" }, - { { -1}, { 8, 9, -1}, "REGCEBINV:REGCEB" }, - { { 8, 9, -1}, { -1}, "REGCEBINV:REGCEB_B" }, // def - { { 24, 25, -1}, { -1}, "RSTAINV:RSTA" }, // def - { { -1}, { 24, 25, -1}, "RSTAINV:RSTA_B" }, - { { -1}, { 4, 5, -1}, "RSTBINV:RSTB" }, // def - { { 4, 5, -1}, { -1}, "RSTBINV:RSTB_B" }, - { { -1}, { 19, -1}, "WEA0INV:WEA0" }, // def - { { 19, -1}, { -1}, "WEA0INV:WEA0_B" }, - { { -1}, { 23, -1}, "WEA2INV:WEA1" }, // def - { { 23, -1}, { -1}, "WEA2INV:WEA1_B" }, - { { -1}, { 18, -1}, "WEA2INV:WEA2" }, // def - { { 18, -1}, { -1}, "WEA2INV:WEA2_B" }, - { { -1}, { 22, -1}, "WEA2INV:WEA3" }, // def - { { 22, -1}, { -1}, "WEA2INV:WEA3_B" }, - { { -1}, { 7, -1}, "WEB0INV:WEB0" }, // def - { { 7, -1}, { -1}, "WEB0INV:WEB0_B" }, - { { -1}, { 3, -1}, "WEB1INV:WEB1" }, // def - { { 3, -1}, { -1}, "WEB1INV:WEB1_B" }, - { { -1}, { 6, -1}, "WEB2INV:WEB2" }, // def - { { 6, -1}, { -1}, "WEB2INV:WEB2_B" }, - { { -1}, { 2, -1}, "WEB3INV:WEB3" }, // def - { { 2, -1}, { -1}, "WEB3INV:WEB3_B" }, -}; - -int g_cmd_frames = 0; -int g_cmd_info = 0; // whether to print #I info messages (offsets and others) -int g_bits_only = 0; - -static void print_ramb16_cfg(ramb16_cfg_t* cfg) -{ - char bits[512]; - uint8_t u8; - int i, first_extra; - - for (i = 0; i < 32; i++) { - u8 = cfg->byte[i*2]; - cfg->byte[i*2] = cfg->byte[i*2+1]; - cfg->byte[i*2+1] = u8; - } - for (i = 0; i < 64; i++) { - u8 = 0; - if (cfg->byte[i] & 0x01) u8 |= 0x80; - if (cfg->byte[i] & 0x02) u8 |= 0x40; - if (cfg->byte[i] & 0x04) u8 |= 0x20; - if (cfg->byte[i] & 0x08) u8 |= 0x10; - if (cfg->byte[i] & 0x10) u8 |= 0x08; - if (cfg->byte[i] & 0x20) u8 |= 0x04; - if (cfg->byte[i] & 0x40) u8 |= 0x02; - if (cfg->byte[i] & 0x80) u8 |= 0x01; - cfg->byte[i] = u8; - } - - // - // Bits 0..255 come from minor 23, Bits 256..511 from minor 24. - // Each set of 256 bits is divided into two halfs of 128 bits - // that are swept forward and backward to form 2-bit pairs, - // pairs 0..127 are formed out of bits 0..127 and 255..128, - // p128..p255 are formed out of b256..b383 and b511..b384. - // Since so much bit twiddling is already happening, we are sorting - // the bits so that pairs are next to each other. - // The notation for a pair is "p8=01". - - // minor 23 - for (i = 0; i < 128; i++) { - bits[i*2] = (cfg->byte[i/8] & (1<<(i%8))) != 0; - bits[i*2+1] = (cfg->byte[(255-i)/8] - & (1<<(7-(i%8)))) != 0; - } - // minor 24 - for (i = 0; i < 128; i++) { - bits[256+i*2] = (cfg->byte[32+i/8] & (1<<(i%8))) != 0; - bits[256+i*2+1] = (cfg->byte[32+(255-i)/8] - & (1<<(7-(i%8)))) != 0; - } - - printf("{\n"); - // hexdump(1 /* indent */, &cfg->byte[0], 64 /* len */); - for (i = 0; i < sizeof(ramb16_atoms)/sizeof(ramb16_atoms[0]); i++) { - if (atom_found(bits, &ramb16_atoms[i]) - && ramb16_atoms[i].must_1[0] != -1) { - printf(" %s\n", ramb16_atoms[i].str); - ramb16_atoms[i].flag = 1; - } else - ramb16_atoms[i].flag = 0; - } - for (i = 0; i < sizeof(ramb16_atoms)/sizeof(ramb16_atoms[0]); i++) { - if (ramb16_atoms[i].flag) - atom_remove(bits, &ramb16_atoms[i]); - } - // instantiation bits - if (ramb16_instance.must_1[0] != -1) { - if (atom_found(bits, &ramb16_instance)) { - for (i = 0; ramb16_instance.must_1[i] != -1; i++) - printf(" b%i\n", ramb16_instance.must_1[i]); - atom_remove(bits, &ramb16_instance); - } else - printf(" #W Not all instantiation bits set.\n"); - } - // extra bits - first_extra = 1; - for (i = 0; i < 512; i++) { - if (bits[i]) { - if (first_extra) { - printf(" #W Extra bits set.\n"); - first_extra = 0; - } - printf(" b%i\n", i); - } - } - printf("}\n"); -} - -static int FAR_pos(int FAR_row, int FAR_major, int FAR_minor) -{ - int result, i; - - if (FAR_row < 0 || FAR_major < 0 || FAR_minor < 0) - return -1; - if (FAR_row > 3 || FAR_major > 17 - || FAR_minor >= majors[FAR_major].minors) - return -1; - result = FAR_row * 505*130; - for (i = 0; i < FAR_major; i++) - result += majors[i].minors*130; - return result + FAR_minor*130; -} - -static int full_map(uint8_t* bit_file, int bf_len, int first_FAR_off, - uint8_t** bits, int* bits_len, int idcode, int FLR_len, int* outdelta) -{ - int src_off, packet_hdr_type, packet_hdr_opcode; - int packet_hdr_register, packet_hdr_wordcount; - int FAR_block, FAR_row, FAR_major, FAR_minor, i, j, MFW_src_off; - int offset_in_bits, block0_words, padding_frames; - uint16_t u16; - uint32_t u32; - - *bits = 0; - if (idcode != XC6SLX4 && idcode != XC6SLX9) { HERE(); goto fail; } - if (FLR_len != 896) { HERE(); goto fail; } - - *bits_len = (4*505 + 4*144) * 130 + 896*2; - *bits = calloc(*bits_len, 1 /* elsize */); - if (!(*bits)) { - fprintf(stderr, "#E Cannot allocate %i bytes for bits.\n", - *bits_len); - goto fail; - } - FAR_block = -1; - FAR_row = -1; - FAR_major = -1; - FAR_minor = -1; - MFW_src_off = -1; - // Go through bit_file from first_FAR_off until last byte of - // IOB was read, plus padding, plus CRC verification. - src_off = first_FAR_off; - while (src_off < bf_len) { - if (src_off + 2 > bf_len) goto fail; - u16 = __be16_to_cpu(*(uint16_t*)&bit_file[src_off]); - src_off += 2; - - // 3 bits: 001 = Type 1; 010 = Type 2 - packet_hdr_type = (u16 & 0xE000) >> 13; - if (packet_hdr_type != 1 && packet_hdr_type != 2) - goto fail; - - // 2 bits: 00 = noop; 01 = read; 10 = write; 11 = reserved - packet_hdr_opcode = (u16 & 0x1800) >> 11; - if (packet_hdr_opcode == 3) goto fail; - - if (packet_hdr_opcode == 0) { // noop - if (packet_hdr_type != 1 || u16 & 0x07FF) goto fail; - continue; - } - - // Now we must look at a Type 1 command - packet_hdr_register = (u16 & 0x07E0) >> 5; - packet_hdr_wordcount = u16 & 0x001F; - if (src_off + packet_hdr_wordcount*2 > bf_len) goto fail; - - if (packet_hdr_type == 1) { - if (packet_hdr_register == CMD) { - if (packet_hdr_wordcount != 1) goto fail; - u16 = __be16_to_cpu( - *(uint16_t*)&bit_file[src_off]); - if (u16 == CMD_GRESTORE || u16 == CMD_LFRM) { - src_off -= 2; - goto success; - } - if (u16 != CMD_MFW && u16 != CMD_WCFG) - goto fail; - if (u16 == CMD_MFW) { - if (FAR_block != 0) goto fail; - MFW_src_off = FAR_pos(FAR_row, FAR_major, FAR_minor); - if (MFW_src_off == -1) goto fail; - } - src_off += 2; - continue; - } - if (packet_hdr_register == FAR_MAJ) { - uint16_t maj, min; - - if (packet_hdr_wordcount != 2) goto fail; - maj = __be16_to_cpu(*(uint16_t*) - &bit_file[src_off]); - min = __be16_to_cpu(*(uint16_t*) - &bit_file[src_off+2]); - - FAR_block = (maj & 0xF000) >> 12; - if (FAR_block > 7) goto fail; - FAR_row = (maj & 0x0F00) >> 8; - FAR_major = maj & 0x00FF; - FAR_minor = min & 0x03FF; - src_off += 4; - continue; - } - if (packet_hdr_register == MFWR) { - uint32_t first_dword, second_dword; - - if (packet_hdr_wordcount != 4) goto fail; - first_dword = __be32_to_cpu( - *(uint32_t*)&bit_file[src_off]); - second_dword = __be32_to_cpu( - *(uint32_t*)&bit_file[src_off+4]); - if (first_dword || second_dword) goto fail; - // The first MFWR will overwrite itself, so - // use memmove(). - if (FAR_block != 0) goto fail; - offset_in_bits = FAR_pos(FAR_row, FAR_major, FAR_minor); - if (offset_in_bits == -1) goto fail; - memmove(&(*bits)[offset_in_bits], &(*bits)[MFW_src_off], 130); - - src_off += 8; - continue; - } - goto fail; - } - - // packet type must be 2 here - if (packet_hdr_wordcount != 0) goto fail; - if (packet_hdr_register != FDRI) goto fail; - - if (src_off + 4 > bf_len) goto fail; - u32 = __be32_to_cpu(*(uint32_t*)&bit_file[src_off]); - src_off += 4; - if (src_off+2*u32 > bf_len) goto fail; - if (2*u32 < 130) goto fail; - - // fdri words u32 - if (FAR_block == -1 || FAR_block > 1 || FAR_row == -1 - || FAR_major == -1 || FAR_minor == -1) - goto fail; - - block0_words = 0; - if (!FAR_block) { - - offset_in_bits = FAR_pos(FAR_row, FAR_major, FAR_minor); - if (offset_in_bits == -1) goto fail; - if (!FAR_row && !FAR_major && !FAR_minor - && u32 > 4*(505+2)*65) - block0_words = 4*(505+2)*65; - else { - block0_words = u32; - if (block0_words % 65) goto fail; - } - padding_frames = 0; - for (i = 0; i < block0_words/65; i++) { - if (i && i+1 == block0_words/65) { - for (j = 0; j < 130; j++) { - if (bit_file[src_off+i*130+j] - != 0xFF) break; - } - // Not sure about the exact logic to - // determine a padding frame. Maybe - // first word all 1? For now we skip - // the frame as a padding frame when - // it's the last frame of a block and - // all-1. - if (j >= 130) - break; - } - if (!FAR_major && !FAR_minor - && (i%507 == 505)) { - for (j = 0; j < 2*130; j++) { - if (bit_file[src_off+i*130+j] - != 0xFF) goto fail; - } - i++; - padding_frames += 2; - continue; - } - memcpy(&(*bits)[offset_in_bits - + (i-padding_frames)*130], - &bit_file[src_off - + i*130], 130); - } - } - if (u32 - block0_words > 0) { - int bram_data_words = 4*144*65 + 896; - if (u32 - block0_words != bram_data_words + 1) goto fail; - offset_in_bits = 4*505*130; - memcpy(&(*bits)[offset_in_bits], - &bit_file[src_off+block0_words*2], - bram_data_words*2); - u16 = __be16_to_cpu(*(uint16_t*)&bit_file[ - (src_off+block0_words+bram_data_words)*2]); - if (u16) goto fail; - } - src_off += 2*u32; - // two CRC words - u32 = __be32_to_cpu(*(uint32_t*)&bit_file[src_off]); - src_off += 4; - } -fail: - free(*bits); - *bits = 0; - return -1; -success: - *outdelta = src_off - first_FAR_off; - return 0; -} - -static void printf_clb(uint8_t* maj_bits, int row, int major) -{ - int i, j, start, max_idx, frame_off; - const char* lut_str; - uint64_t lut64; - - // the first two slots on top and bottom row are not used for clb - if (!row) { - start = 0; - max_idx = 14; - } else if (row == 3) { - start = 2; - max_idx = 16; - } else { - start = 0; - max_idx = 16; - } - - for (i = start; i < max_idx; i++) { - if (clb_empty(maj_bits, i)) - continue; - frame_off = i*64; - if (i >= 8) - frame_off += 16; // skip clock bits for idx >= 8 - - // LUTs - lut64 = read_lut64(&maj_bits[24*130], frame_off+32); - { int logic_base[6] = {0,1,0,0,1,0}; - lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); } - if (*lut_str) - printf("r%i ma%i clb i%i s0_A6LUT \"%s\"\n", - row, major, i-start, lut_str); - - lut64 = read_lut64(&maj_bits[21*130], frame_off+32); - { int logic_base[6] = {1,1,0,1,0,1}; - lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); } - if (*lut_str) - printf("r%i ma%i clb i%i s0_B6LUT \"%s\"\n", - row, major, i-start, lut_str); - - lut64 = read_lut64(&maj_bits[24*130], frame_off); - { int logic_base[6] = {0,1,0,0,1,0}; - lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); } - if (*lut_str) - printf("r%i ma%i clb i%i s0_C6LUT \"%s\"\n", - row, major, i-start, lut_str); - - lut64 = read_lut64(&maj_bits[21*130], frame_off); - { int logic_base[6] = {1,1,0,1,0,1}; - lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); } - if (*lut_str) - printf("r%i ma%i clb i%i s0_D6LUT \"%s\"\n", - row, major, i-start, lut_str); - - lut64 = read_lut64(&maj_bits[27*130], frame_off+32); - { int logic_base[6] = {1,1,0,1,1,0}; - lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); } - if (*lut_str) - printf("r%i ma%i clb i%i s1_A6LUT \"%s\"\n", - row, major, i-start, lut_str); - - lut64 = read_lut64(&maj_bits[29*130], frame_off+32); - { int logic_base[6] = {1,1,0,1,1,0}; - lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); } - if (*lut_str) - printf("r%i ma%i clb i%i s1_B6LUT \"%s\"\n", - row, major, i-start, lut_str); - - lut64 = read_lut64(&maj_bits[27*130], frame_off); - { int logic_base[6] = {0,1,0,0,0,1}; - lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); } - if (*lut_str) - printf("r%i ma%i clb i%i s1_C6LUT \"%s\"\n", - row, major, i-start, lut_str); - - lut64 = read_lut64(&maj_bits[29*130], frame_off); - { int logic_base[6] = {0,1,0,0,0,1}; - lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); } - if (*lut_str) - printf("r%i ma%i clb i%i s1_D6LUT \"%s\"\n", - row, major, i-start, lut_str); - - // bits - for (j = 0; j < 64; j++) { - if (bit_set(&maj_bits[20*130], frame_off + j)) - printf("r%i ma%i clb i%i mi20 bit %i\n", - row, major, i-start, j); - } - for (j = 0; j < 64; j++) { - if (bit_set(&maj_bits[23*130], frame_off + j)) - printf("r%i ma%i clb i%i mi23 bit %i\n", - row, major, i-start, j); - } - for (j = 0; j < 64; j++) { - if (bit_set(&maj_bits[26*130], frame_off + j)) - printf("r%i ma%i clb i%i mi26 bit %i\n", - row, major, i-start, j); - } - } -} - -static void printf_bits(uint8_t* bits, int bits_len, int idcode) -{ - int row, major, minor, i, j, off, bram_data_start; - int offset_in_frame, newline; - - // type0 - off = 0; - if (!g_bits_only) - printf("\n"); - for (row = 0; row < 4; row++) { - for (major = 0; major < 18; major++) { - if (majors[major].type == MAJ_DSP) { - int last_extra_minor; - - if (!row || row == 3) - last_extra_minor = 23; - else - last_extra_minor = 21; - minor = 0; - while (minor <= last_extra_minor) { - minor += printf_frames(&bits[off - +minor*130], 31 - minor, row, - major, minor, g_cmd_info); - } - - // clock - for (; minor < 24; minor++) - printf_clock(&bits[off+minor*130], - row, major, minor); - - for (i = 0; i < 4; i++) { - for (minor = last_extra_minor+1; minor < 24; - minor++) { - for (j = 0; j < 256; j++) { - if (bit_set(&bits[off+minor*130], i*256 + ((i>=2)?16:0) + j)) - printf("r%i ma%i dsp i%i mi%i bit %i\n", row, major, i, minor, i*256+j); - } - } - } - } else if (majors[major].type == MAJ_CLB) { - minor = 0; - while (minor < 20) { - minor += printf_frames(&bits[off - +minor*130], 31 - minor, row, - major, minor, g_cmd_info); - } - - // clock - for (minor = 20; minor < 31; minor++) - printf_clock(&bits[off+minor*130], - row, major, minor); - // extra bits at bottom of row0 and top of row3 - if (row == 3) - printf_extrabits(&bits[off], 20, 11, - 0, 128, row, major); - else if (!row) - printf_extrabits(&bits[off], 20, 11, - 14*64 + 16, 128, row, major); - - // clbs - printf_clb(&bits[off], row, major); - } else if (majors[major].type == MAJ_BRAM) { - ramb16_cfg_t ramb16_cfg[4]; - - // minors 0..22 - minor = 0; - while (minor < 23) { - minor += printf_frames(&bits[off - +minor*130], 23 - minor, row, - major, minor, g_cmd_info); - } - - // minors 23&24 - printf_clock(&bits[off+23*130], row, major, 23); - printf_clock(&bits[off+24*130], row, major, 24); - for (i = 0; i < 4; i++) { - offset_in_frame = i*32; - if (offset_in_frame >= 64) - offset_in_frame += 2; - for (j = 0; j < 32; j++) { - ramb16_cfg[i].byte[j] = bits[off+23*130+offset_in_frame+j]; - ramb16_cfg[i].byte[j+32] = bits[off+24*130+offset_in_frame+j]; - } - } - for (i = 0; i < 4; i++) { - for (j = 0; j < 64; j++) { - if (ramb16_cfg[i].byte[j]) - break; - } - if (j >= 64) - continue; - printf("r%i ma%i ramb16 i%i\n", - row, major, i); - print_ramb16_cfg(&ramb16_cfg[i]); - } - } else { - minor = 0; - while (minor < majors[major].minors) { - minor += printf_frames(&bits[off - +minor*130], majors[major].minors - - minor, row, major, minor, g_cmd_info); - } - } - off += majors[major].minors * 130; - } - } - - // bram - bram_data_start = 4*505*130; - newline = 0; - for (row = 0; row < 4; row++) { - for (i = 0; i < 8; i++) { - for (j = 0; j < 18*130; j++) { - if (bits[bram_data_start + row*144*130 - + i*18*130 + j]) - break; - } - if (j >= 18*130) - continue; - if (!newline) { - newline = 1; - printf("\n"); - } - printf("br%i ramb16 i%i\n", row, i); - printf("{\n"); - off = bram_data_start + row*144*130 + i*18*130; - printf_ramb16_data(bits, off); - printf("}\n"); - } - } - - // iob - if (!g_bits_only) printf("\n"); - if (printf_iob(bits, bits_len, bram_data_start + 4*144*130, 896*2/8)) { - if (!g_bits_only) printf("\n"); - } -} - -int main(int argc, char** argv) -{ - uint8_t* bit_data = 0; // file contents - uint8_t* bits = 0; // bits in chip layout - FILE* bitf = 0; - int bit_cur, try_full_map, first_FAR_off, bits_len; - uint32_t bit_eof, cmd_len, u32, u16_off; - uint16_t u16, packet_hdr_type, packet_hdr_opcode; - uint16_t packet_hdr_register, packet_hdr_wordcount; - char* bit_path = 0; - int i, num_frames, times; - - // state machine driven from file input - int m_FLR_value = -1; - int m_idcode = -1; // offset into idcodes - - // - // parse command line - // - - if (argc < 2) { - printf_help(); - return EXIT_SUCCESS; - } - for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "--help")) { - printf_help(); - return EXIT_SUCCESS; - } - if (!strcmp(argv[i], "--version")) { - printf("%s\n", PROGRAM_REVISION); - return EXIT_SUCCESS; - } - if (!strcmp(argv[i], "--info")) - g_cmd_info = 1; - else if (!strcmp(argv[i], "--frames")) - g_cmd_frames = 1; - else if (!strcmp(argv[i], "--bits-only")) - g_bits_only = 1; - else { - bit_path = argv[i]; - if (argc > i+1) { // only 1 path supported - printf_help(); - return EXIT_FAILURE; - } - } - } - if (!bit_path) { // shouldn't get here, just in case - printf_help(); - return EXIT_FAILURE; - } - - // - // read .bit into memory - // - - bit_data = malloc(BITSTREAM_READ_MAXPAGES * BITSTREAM_READ_PAGESIZE); - if (!bit_data) { - fprintf(stderr, "#E Cannot allocate %i bytes for filebuf.\n", - BITSTREAM_READ_MAXPAGES * BITSTREAM_READ_PAGESIZE); - goto fail; - } - if (!(bitf = fopen(bit_path, "rb"))) { - fprintf(stderr, "#E Error opening %s.\n", bit_path); - goto fail; - } - bit_eof = 0; - while (bit_eof < BITSTREAM_READ_MAXPAGES * BITSTREAM_READ_PAGESIZE) { - size_t num_read = fread(&bit_data[bit_eof], sizeof(uint8_t), - BITSTREAM_READ_PAGESIZE, bitf); - bit_eof += num_read; - if (num_read != BITSTREAM_READ_PAGESIZE) - break; - } - fclose(bitf); - if (bit_eof >= BITSTREAM_READ_MAXPAGES * BITSTREAM_READ_PAGESIZE) { - fprintf(stderr, "#E Bitstream size above maximum of " - "%i bytes.\n", BITSTREAM_READ_MAXPAGES * - BITSTREAM_READ_PAGESIZE); - goto fail; - } - - // - // header - // - - if (!g_bits_only) - printf("bit2txt_format 1\n"); - - if (printf_header(bit_data, bit_eof, 0 /* inpos */, &bit_cur, g_bits_only)) - goto fail; - - // - // commands - // - - if (bit_cur + 5 > bit_eof) goto fail_eof; - if (bit_data[bit_cur] != 'e') { - fprintf(stderr, "#E Expected string code 'e', got '%c'.\n", - bit_data[bit_cur]); - goto fail; - } - cmd_len = __be32_to_cpu(*(uint32_t*)&bit_data[bit_cur + 1]); - bit_cur += 5; - if (bit_cur + cmd_len > bit_eof) goto fail_eof; - if (bit_cur + cmd_len < bit_eof) { - printf("#W Unexpected continuation after offset " - "%i.\n", bit_cur + 5 + cmd_len); - } - - // hex-dump everything until 0xAA (sync word: 0xAA995566) - if (bit_cur >= bit_eof) goto fail_eof; - if (bit_data[bit_cur] != 0xAA) { - if (!g_bits_only) printf("hex"); - while (bit_cur < bit_eof && bit_data[bit_cur] != 0xAA) { - if (!g_bits_only) printf(" %.02x", bit_data[bit_cur]); - bit_cur++; if (bit_cur >= bit_eof) goto fail_eof; - } - if (!g_bits_only) printf("\n"); - } - if (bit_cur + 4 > bit_eof) goto fail_eof; - if (g_cmd_info) printf("#I sync word at offset 0x%x.\n", bit_cur); - u32 = __be32_to_cpu(*(uint32_t*)&bit_data[bit_cur]); - bit_cur += 4; - if (u32 != 0xAA995566) { - fprintf(stderr, "#E Unexpected sync word 0x%x.\n", u32); - goto fail; - } - if (!g_bits_only) - printf("sync_word\n"); - - try_full_map = !g_cmd_frames; - first_FAR_off = -1; - while (bit_cur < bit_eof) { - // packet header: ug380, Configuration Packets (p88) - if (g_cmd_info) printf("#I Packet header at off 0x%x.\n", bit_cur); - - if (bit_cur + 2 > bit_eof) goto fail_eof; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[bit_cur]); - u16_off = bit_cur; bit_cur += 2; - - // 3 bits: 001 = Type 1; 010 = Type 2 - packet_hdr_type = (u16 & 0xE000) >> 13; - - if (packet_hdr_type != 1 && packet_hdr_type != 2) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected packet type " - "%u.\n", u16_off, u16, packet_hdr_type); - goto fail; - } - - // 2 bits: 00 = noop; 01 = read; 10 = write; 11 = reserved - packet_hdr_opcode = (u16 & 0x1800) >> 11; - if (packet_hdr_opcode == 3) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected packet opcode " - "3.\n", u16_off, u16); - goto fail; - } - if (packet_hdr_opcode == 0) { // noop - if (packet_hdr_type != 1) - printf("#W 0x%x=0x%x Unexpected packet" - " type %u noop.\n", u16_off, - u16, packet_hdr_type); - if (u16 & 0x07FF) - printf("#W 0x%x=0x%x Unexpected noop " - "header.\n", u16_off, u16); - if (packet_hdr_type != 1 || (u16&0x07FF)) - times = 1; - else { // lookahead for more good noops - i = bit_cur; - while (i+1 < bit_eof) { - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[i]); - if (((u16 & 0xE000) >> 13) != 1 - || ((u16 & 0x1800) >> 11) - || (u16 & 0x7FF)) - break; - i += 2; - } - times = 1 + (i - bit_cur)/2; - if (times > 1) - bit_cur += (times-1)*2; - } - if (g_bits_only) continue; - if (times > 1) - printf("noop times %i\n", times); - else - printf("noop\n"); - continue; - } - - // Now we must look at a Type 1 read or write command - packet_hdr_register = (u16 & 0x07E0) >> 5; - packet_hdr_wordcount = u16 & 0x001F; - if (bit_cur + packet_hdr_wordcount*2 > bit_eof) goto fail_eof; - bit_cur += packet_hdr_wordcount*2; - - if (packet_hdr_type == 1) { - if (packet_hdr_register == IDCODE) { - if (packet_hdr_wordcount != 2) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected IDCODE" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - u32 = __be32_to_cpu(*(uint32_t*)&bit_data[u16_off+2]); - for (i = 0; i < sizeof(idcodes)/sizeof(idcodes[0]); i++) { - if ((u32 & 0x0FFFFFFF) == idcodes[i].code) { - if (!g_bits_only) - printf("T1 IDCODE %s\n", idcodes[i].name); - m_idcode = i; - break; - } - } - if (i >= sizeof(idcodes)/sizeof(idcodes[0])) - printf("#W Unknown IDCODE 0x%x.\n", u32); - else if (u32 & 0xF0000000) - printf("#W Unexpected revision bits in IDCODE 0x%x.\n", u32); - if ((idcodes[m_idcode].code == XC6SLX4 - || idcodes[m_idcode].code == XC6SLX9) - && m_FLR_value != 896) - printf("#W Unexpected FLR value %i on " - "idcode %s.\n", m_FLR_value, - idcodes[m_idcode].name); - continue; - } - if (packet_hdr_register == CMD) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected CMD" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - if (u16 >= sizeof(cmds) / sizeof(cmds[0]) - || cmds[u16][0] == 0) - printf("#W 0x%x=0x%x Unknown CMD.\n", - u16_off+2, u16); - else { - if (!g_bits_only) - printf("T1 CMD %s\n", cmds[u16]); - } - continue; - } - if (packet_hdr_register == FLR) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected FLR" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - if (!g_bits_only) - printf("T1 FLR %u\n", u16); - m_FLR_value = u16; - if ((m_FLR_value*2) % 8) - printf("#W FLR*2 should be multiple of " - "8, but modulo 8 is %i\n", (m_FLR_value*2) % 8); - // First come the type 0 frames (clb, bram - // config, dsp, etc). Then type 1 (bram data), - // then type 2, the IOB config data block. - // FLR is counted in 16-bit words, and there is - // 1 extra dummy 0x0000 after that. - continue; - } - if (packet_hdr_register == COR1) { - int unexpected_clk11 = 0; - - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected COR1" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - if (g_bits_only) continue; - printf("T1 COR1"); - if (u16 & 0x8000) { - printf(" DRIVE_AWAKE"); - u16 &= ~0x8000; - } - if (u16 & 0x0010) { - printf(" CRC_BYPASS"); - u16 &= ~0x0010; - } - if (u16 & 0x0008) { - printf(" DONE_PIPE"); - u16 &= ~0x0008; - } - if (u16 & 0x0004) { - printf(" DRIVE_DONE"); - u16 &= ~0x0004; - } - if (u16 & 0x0003) { - if (u16 & 0x0002) { - if (u16 & 0x0001) - unexpected_clk11 = 1; - printf(" SSCLKSRC=TCK"); - } else - printf(" SSCLKSRC=UserClk"); - u16 &= ~0x0003; - } - if (u16) - printf(" 0x%x", u16); - printf("\n"); - if (unexpected_clk11) - printf("#W Unexpected SSCLKSRC 11.\n"); - // Reserved bits 14:5 should be 0110111000 - // according to documentation. - if (u16 != 0x3700) - printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x3700, u16); - - continue; - } - if (packet_hdr_register == COR2) { - int unexpected_done_cycle = 0; - int unexpected_lck_cycle = 0; - unsigned cycle; - - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected COR2" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 COR2"); - if (u16 & 0x8000) { - printf(" RESET_ON_ERROR"); - u16 &= ~0x8000; - } - - // DONE_CYCLE - cycle = (u16 & 0x0E00) >> 9; - printf(" DONE_CYCLE=%s", bitstr(cycle, 3)); - if (!cycle || cycle == 7) - unexpected_done_cycle = 1; - u16 &= ~0x0E00; - - // LCK_CYCLE - cycle = (u16 & 0x01C0) >> 6; - printf(" LCK_CYCLE=%s", bitstr(cycle, 3)); - if (!cycle) - unexpected_lck_cycle = 1; - u16 &= ~0x01C0; - - // GTS_CYCLE - cycle = (u16 & 0x0038) >> 3; - printf(" GTS_CYCLE=%s", bitstr(cycle, 3)); - u16 &= ~0x0038; - - // GWE_CYCLE - cycle = u16 & 0x0007; - printf(" GWE_CYCLE=%s", bitstr(cycle, 3)); - u16 &= ~0x0007; - - if (u16) - printf(" 0x%x", u16); - printf("\n"); - if (unexpected_done_cycle) - printf("#W Unexpected DONE_CYCLE %s.\n", - bitstr((u16 & 0x01C0) >> 6, 3)); - if (unexpected_lck_cycle) - printf("#W Unexpected LCK_CYCLE 0b000.\n"); - // Reserved bits 14:12 should be 000 - // according to documentation. - if (u16) - printf("#W Expected reserved 0, got 0x%x.\n", u16); - continue; - } - if (packet_hdr_register == FAR_MAJ - && packet_hdr_wordcount == 2) { - uint16_t maj, min; - int unexpected_blk_bit4 = 0; - - if (first_FAR_off == -1) - first_FAR_off = u16_off; - if (g_bits_only) continue; - - maj = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - min = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+4]); - printf("T1 FAR_MAJ"); - - // BLK - u16 = (maj & 0xF000) >> 12; - printf(" BLK=%u", u16); - if (u16 > 7) - unexpected_blk_bit4 = 1; - // ROW - u16 = (maj & 0x0F00) >> 8; - printf(" ROW=%u", u16); - // MAJOR - u16 = maj & 0x00FF; - printf(" MAJOR=%u", u16); - // Block RAM - u16 = (min & 0xC000) >> 14; - printf(" BRAM=%u", u16); - // MINOR - u16 = min & 0x03FF; - printf(" MINOR=%u", u16); - - if (min & 0x3C00) - printf(" 0x%x", min & 0x3C00); - printf("\n"); - - if (unexpected_blk_bit4) - printf("#W Unexpected BLK bit 4 set.\n"); - // Reserved min bits 13:10 should be 000. - if (min & 0x3C00) - printf("#W Expected reserved 0, got 0x%x.\n", (min & 0x3C00) > 10); - continue; - } - if (packet_hdr_register == MFWR) { - uint32_t first_dword, second_dword; - - if (packet_hdr_wordcount != 4) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected " - "MFWR wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - first_dword = __be32_to_cpu(*(uint32_t*)&bit_data[u16_off+2]); - second_dword = __be32_to_cpu(*(uint32_t*)&bit_data[u16_off+6]); - if (first_dword || second_dword) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected " - "MFWR data 0x%x 0x%x.\n", u16_off, - u16, first_dword, second_dword); - goto fail; - } - if (!g_bits_only) - printf("T1 MFWR\n"); - continue; - } - if (packet_hdr_register == CTL) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected CTL" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 CTL"); - if (u16 & 0x0040) { - printf(" DECRYPT"); - u16 &= ~0x0040; - } - if (u16 & 0x0020) { - if (u16 & 0x0010) - printf(" SBITS=NO_RW"); - else - printf(" SBITS=NO_READ"); - u16 &= ~0x0030; - } else if (u16 & 0x0010) { - printf(" SBITS=ICAP_READ"); - u16 &= ~0x0010; - } - if (u16 & 0x0008) { - printf(" PERSIST"); - u16 &= ~0x0008; - } - if (u16 & 0x0004) { - printf(" USE_EFUSE_KEY"); - u16 &= ~0x0004; - } - if (u16 & 0x0002) { - printf(" CRC_EXTSTAT_DISABLE"); - u16 &= ~0x0002; - } - if (u16) - printf(" 0x%x", u16); - printf("\n"); - // bit0 is reserved as 1, and we have seen - // bit7 on as well. - if (u16 != 0x81) - printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x0081, u16); - continue; - } - if (packet_hdr_register == MASK) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected MASK" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 MASK"); - if (u16 & 0x0040) { - printf(" DECRYPT"); - u16 &= ~0x0040; - } - if ((u16 & 0x0030) == 0x0030) { - printf(" SECURITY"); - u16 &= ~0x0030; - } - if (u16 & 0x0008) { - printf(" PERSIST"); - u16 &= ~0x0008; - } - if (u16 & 0x0004) { - printf(" USE_EFUSE_KEY"); - u16 &= ~0x0004; - } - if (u16 & 0x0002) { - printf(" CRC_EXTSTAT_DISABLE"); - u16 &= ~0x0002; - } - if (u16) - printf(" 0x%x", u16); - printf("\n"); - // It seems bit7 and bit0 are always masked in. - if (u16 != 0x81) - printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x0081, u16); - continue; - } - if (packet_hdr_register == PWRDN_REG) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected PWRDN_REG" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 PWRDN_REG"); - if (u16 & 0x4000) { - printf(" EN_EYES"); - u16 &= ~0x4000; - } - if (u16 & 0x0020) { - printf(" FILTER_B"); - u16 &= ~0x0020; - } - if (u16 & 0x0010) { - printf(" EN_PGSR"); - u16 &= ~0x0010; - } - if (u16 & 0x0004) { - printf(" EN_PWRDN"); - u16 &= ~0x0004; - } - if (u16 & 0x0001) { - printf(" KEEP_SCLK"); - u16 &= ~0x0001; - } - if (u16) - printf(" 0x%x", u16); - printf("\n"); - // Reserved bits 13:6 should be 00100010 - // according to documentation. - if (u16 != 0x0880) - printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x0880, u16); - continue; - } - if (packet_hdr_register == HC_OPT_REG) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected HC_OPT_REG" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 HC_OPT_REG"); - if (u16 & 0x0040) { - printf(" INIT_SKIP"); - u16 &= ~0x0040; - } - if (u16) - printf(" 0x%x", u16); - printf("\n"); - // Reserved bits 5:0 should be 011111 - // according to documentation. - if (u16 != 0x001F) - printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x001F, u16); - continue; - } - if (packet_hdr_register == PU_GWE) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected PU_GWE" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 PU_GWE 0x%03X\n", u16); - continue; - } - if (packet_hdr_register == PU_GTS) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected PU_GTS" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 PU_GTS 0x%03X\n", u16); - continue; - } - if (packet_hdr_register == CWDT) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected CWDT" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 CWDT 0x%X\n", u16); - if (u16 < 0x0201) - printf("#W Watchdog timer clock below" - " minimum value of 0x0201.\n"); - continue; - } - if (packet_hdr_register == MODE_REG) { - int unexpected_buswidth = 0; - - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected MODE_REG" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 MODE_REG"); - if (u16 & (1<<13)) { - printf(" NEW_MODE=BITSTREAM"); - u16 &= ~(1<<13); - } - if ((u16 & (1<<12)) - && (u16 & (1<<11))) - unexpected_buswidth = 1; - else if (u16 & (1<<12)) { - printf(" BUSWIDTH=4"); - u16 &= ~(1<<12); - } else if (u16 & (1<<11)) { - printf(" BUSWIDTH=2"); - u16 &= ~(1<<11); - } - // BUSWIDTH=1 is the default and not displayed - - if (u16 & (1<<9)) { - printf(" BOOTMODE_1"); - u16 &= ~(1<<9); - } - if (u16 & (1<<8)) { - printf(" BOOTMODE_0"); - u16 &= ~(1<<8); - } - - if (unexpected_buswidth) - printf("#W Unexpected bus width 0b11.\n"); - if (u16) - printf(" 0x%x", u16); - printf("\n"); - if (u16) - printf("#W Expected reserved 0, got 0x%x.\n", u16); - continue; - } - if (packet_hdr_register == CCLK_FREQ) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected CCLK_FREQ" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 CCLK_FREQ"); - if (u16 & (1<<14)) { - printf(" EXT_MCLK"); - u16 &= ~(1<<14); - } - printf(" MCLK_FREQ=0x%03X", u16 & 0x03FF); - u16 &= ~(0x03FF); - if (u16) - printf(" 0x%x", u16); - printf("\n"); - if (u16) - printf("#W Expected reserved 0, got 0x%x.\n", u16); - continue; - } - if (packet_hdr_register == EYE_MASK) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected EYE_MASK" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 EYE_MASK 0x%X\n", u16); - continue; - } - if (packet_hdr_register == GENERAL1) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected GENERAL1" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 GENERAL1 0x%X\n", u16); - continue; - } - if (packet_hdr_register == GENERAL2) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected GENERAL1" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 GENERAL2 0x%X\n", u16); - continue; - } - if (packet_hdr_register == GENERAL3) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected GENERAL1" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 GENERAL3 0x%X\n", u16); - continue; - } - if (packet_hdr_register == GENERAL4) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected GENERAL1" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 GENERAL4 0x%X\n", u16); - continue; - } - if (packet_hdr_register == GENERAL5) { - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected GENERAL1" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - printf("T1 GENERAL5 0x%X\n", u16); - continue; - } - if (packet_hdr_register == EXP_SIGN) { - if (packet_hdr_wordcount != 2) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected EXP_SIGN" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u32 = __be32_to_cpu(*(uint32_t*)&bit_data[u16_off+2]); - printf("T1 EXP_SIGN 0x%X\n", u32); - continue; - } - if (packet_hdr_register == SEU_OPT) { - int seu_freq; - - if (packet_hdr_wordcount != 1) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected SEU_OPT" - " wordcount %u.\n", u16_off, - u16, packet_hdr_wordcount); - goto fail; - } - if (g_bits_only) continue; - u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); - seu_freq = (u16 & 0x3FF0) >> 4; - printf("T1 SEU_OPT SEU_FREQ=0x%X", seu_freq); - u16 &= ~(0x3FF0); - if (u16 & (1<<3)) { - printf(" SEU_RUN_ON_ERR"); - u16 &= ~(1<<3); - } - if (u16 & (1<<1)) { - printf(" GLUT_MASK"); - u16 &= ~(1<<1); - } - if (u16 & (1<<0)) { - printf(" SEU_ENABLE"); - u16 &= ~(1<<0); - } - if (u16) - printf(" 0x%x", u16); - printf("\n"); - if (u16) - printf("#W Expected reserved 0, got 0x%x.\n", u16); - continue; - } - if (packet_hdr_register == CRC) { - // Don't print CRC value for cleaner diff. - if (!g_bits_only) - printf("#W T1 CRC (%u words)\n", - packet_hdr_wordcount); - continue; - } - printf("#W 0x%x=0x%x T1 %i (%u words)", u16_off, u16, - packet_hdr_register, packet_hdr_wordcount); - for (i = 0; (i < 8) && (i < packet_hdr_wordcount); i++) - printf(" 0x%x", __be16_to_cpu(*(uint16_t*) - &bit_data[u16_off+2+i*2])); - printf("\n"); - continue; - } - - // packet type must be 2 here - if (packet_hdr_wordcount != 0) { - printf("#W 0x%x=0x%x Unexpected Type 2 " - "wordcount.\n", u16_off, u16); - } - if (packet_hdr_register != FDRI) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected Type 2 " - "register.\n", u16_off, u16); - goto fail; - } - if (bit_cur + 4 > bit_eof) goto fail_eof; - u32 = __be32_to_cpu(*(uint32_t*)&bit_data[bit_cur]); - if (bit_cur+4+2*u32 > bit_eof) goto fail_eof; - if (2*u32 < 130) { - fprintf(stderr, "#E 0x%x=0x%x Unexpected Type2" - " length %u.\n", u16_off, u16, 2*u32); - goto fail; - } - - if (!g_bits_only) - printf("T2 FDRI words=%i\n", u32); - bit_cur += 4; - if (try_full_map) { - try_full_map = 0; - if (first_FAR_off != -1) { - int outdelta; - if (!full_map(bit_data, bit_eof, first_FAR_off, - &bits, &bits_len, idcodes[m_idcode].code, - m_FLR_value, &outdelta)) { - printf_bits(bits, bits_len, - idcodes[m_idcode].code); - bit_cur = first_FAR_off + outdelta; - continue; - } - } - } - - num_frames = (2*u32)/130; - i = 0; - printf("\n"); - while (i < num_frames) { - i += printf_frames(&bit_data[bit_cur+i*130], - num_frames-i, -i /* row */, 0 /* major */, - 0 /* minor */, 1 /* print_empty */); - } - printf("\n"); - if (num_frames*130 < 2*u32) { - int dump_len = 2*u32 - num_frames*130; - printf("#D hexdump offset 0x%x, len 0x%x (%i)\n", - num_frames*130, dump_len, dump_len); - hexdump(1, &bit_data[bit_cur+num_frames*130], dump_len); - printf("\n"); - } - bit_cur += u32*2; - - if (bit_cur + 4 > bit_eof) goto fail_eof; - u32 = __be32_to_cpu(*(uint32_t*)&bit_data[bit_cur]); - if (g_cmd_info) printf("#I 0x%x=0x%x Ignoring Auto-CRC.\n", bit_cur, u32); - bit_cur += 4; - } - free(bits); - free(bit_data); - return EXIT_SUCCESS; - -fail_eof: - fprintf(stderr, "#E Unexpected EOF.\n"); -fail: - free(bits); - free(bit_data); - return EXIT_FAILURE; -} diff --git a/bits.c b/bits.c index b91b84b..d253977 100644 --- a/bits.c +++ b/bits.c @@ -8,12 +8,1460 @@ #include "model.h" #include "bits.h" -int read_bits(struct fpga_model* model, FILE* f) +static int parse_header(struct fpga_config* config, uint8_t* d, + int len, int inpos, int* outdelta); +static int parse_commands(struct fpga_config* config, uint8_t* d, + int len, int inpos); + +static const int minors_per_major[] = +{ + /* 0 */ 4, // 505 bytes = middle 8-bit for each minor? + /* 1 */ 30, // left + /* 2 */ 31, // logic M + /* 3 */ 30, // logic L + /* 4 */ 25, // bram + /* 5 */ 31, // logic M + /* 6 */ 30, // logic L + /* 7 */ 24, // macc + /* 8 */ 31, // logic M + /* 9 */ 31, // center + /* 10 */ 31, // logic M + /* 11 */ 30, // logic L + /* 12 */ 31, // logic M + /* 13 */ 30, // logic L + /* 14 */ 25, // bram + /* 15 */ 31, // logic M + /* 16 */ 30, // logic L + /* 17 */ 30, // right +}; + +#define BITSTREAM_READ_PAGESIZE 4096 + +int read_bitfile(struct fpga_config* cfg, FILE* f) +{ + uint8_t* bit_data = 0; + int rc, file_len, bit_len, bit_cur; + + memset(cfg, 0, sizeof(*cfg)); + cfg->num_regs_before_bits = -1; + cfg->idcode_reg = -1; + cfg->FLR_reg = -1; + + // read .bit into memory + if (fseek(f, 0, SEEK_END) == -1) + FAIL(errno); + if ((file_len = ftell(f)) == -1) + FAIL(errno); + if (fseek(f, 0, SEEK_SET) == -1) + FAIL(errno); + if (!file_len) + FAIL(EINVAL); + + if (!(bit_data = malloc(file_len))) + FAIL(ENOMEM); + bit_len = 0; + while (bit_len < file_len) { + size_t num_read = fread(&bit_data[bit_len], sizeof(uint8_t), + BITSTREAM_READ_PAGESIZE, f); + bit_len += num_read; + if (num_read != BITSTREAM_READ_PAGESIZE) + break; + } + if (bit_len != file_len) + FAIL(EINVAL); + + // parse header and commands + if ((rc = parse_header(cfg, bit_data, bit_len, /*inpos*/ 0, &bit_cur))) + FAIL(rc); + if ((rc = parse_commands(cfg, bit_data, bit_len, bit_cur))) + FAIL(rc); + + free(bit_data); + return 0; +fail: + free(bit_data); + return rc; +} + +int extract_model(struct fpga_config* cfg, struct fpga_model* model) { return 0; } +static void dump_header(struct fpga_config* cfg) +{ + int i; + for (i = 0; i < sizeof(cfg->header_str) + /sizeof(cfg->header_str[0]); i++) { + printf("header_str_%c %s\n", 'a'+i, + cfg->header_str[i]); + } +} + +static int dump_regs(struct fpga_config* cfg, int start, int end) +{ + uint16_t u16; + int i, rc; + + for (i = start; i < end; i++) { + if (cfg->reg[i].reg == REG_NOOP) { + int times = 1; + while (i+times < end && cfg->reg[i+times].reg + == REG_NOOP) + times++; + if (times > 1) + printf("noop times %i\n", times); + else + printf("noop\n"); + i += times-1; + continue; + } + if (cfg->reg[i].reg == IDCODE) { + switch (cfg->reg[i].int_v & IDCODE_MASK) { + case XC6SLX4: printf("T1 IDCODE XC6SLX4\n"); break; + case XC6SLX9: printf("T1 IDCODE XC6SLX9\n"); break; + case XC6SLX16: printf("T1 IDCODE XC6SLX16\n"); break; + case XC6SLX25: printf("T1 IDCODE XC6SLX25\n"); break; + case XC6SLX25T: printf("T1 IDCODE XC6SLX25T\n"); break; + case XC6SLX45: printf("T1 IDCODE XC6SLX45\n"); break; + case XC6SLX45T: printf("T1 IDCODE XC6SLX45T\n"); break; + case XC6SLX75: printf("T1 IDCODE XC6SLX75\n"); break; + case XC6SLX75T: printf("T1 IDCODE XC6SLX75T\n"); break; + case XC6SLX100: printf("T1 IDCODE XC6SLX100\n"); break; + case XC6SLX100T: printf("T1 IDCODE XC6SLX100T\n"); break; + case XC6SLX150: printf("T1 IDCODE XC6SLX150\n"); break; + default: + printf("#W Unknown IDCODE 0x%X.\n", cfg->reg[i].int_v); + break; + } + continue; + } + if (cfg->reg[i].reg == CMD) { + static const char* cmds[] = + { + [CMD_NULL] = "NULL", + [CMD_WCFG] = "WCFG", + [CMD_MFW] = "MFW", + [CMD_LFRM] = "LFRM", + [CMD_RCFG] = "RCFG", + [CMD_START] = "START", + [CMD_RCRC] = "RCRC", + [CMD_AGHIGH] = "AGHIGH", + [CMD_GRESTORE] = "GRESTORE", + [CMD_SHUTDOWN] = "SHUTDOWN", + [CMD_DESYNC] = "DESYNC", + [CMD_IPROG] = "IPROG" + }; + if (cfg->reg[i].int_v >= sizeof(cmds)/sizeof(cmds[0]) + || cmds[cfg->reg[i].int_v] == 0) + printf("#W Unknown CMD 0x%X.\n", cfg->reg[i].int_v); + else + printf("T1 CMD %s\n", cmds[cfg->reg[i].int_v]); + continue; + } + if (cfg->reg[i].reg == FLR) { + printf("T1 FLR %i\n", cfg->reg[i].int_v); + continue; + } + if (cfg->reg[i].reg == CRC) { + // Don't print CRC cfg->reg[i].int_v for cleaner diff. + printf("T1 CRC\n"); + continue; + } + if (cfg->reg[i].reg == COR1) { + int unexpected_clk11 = 0; + + u16 = cfg->reg[i].int_v; + printf("T1 COR1"); + if (u16 & 0x8000) { + printf(" DRIVE_AWAKE"); + u16 &= ~0x8000; + } + if (u16 & 0x0010) { + printf(" CRC_BYPASS"); + u16 &= ~0x0010; + } + if (u16 & 0x0008) { + printf(" DONE_PIPE"); + u16 &= ~0x0008; + } + if (u16 & 0x0004) { + printf(" DRIVE_DONE"); + u16 &= ~0x0004; + } + if (u16 & 0x0003) { + if (u16 & 0x0002) { + if (u16 & 0x0001) + unexpected_clk11 = 1; + printf(" SSCLKSRC=TCK"); + } else + printf(" SSCLKSRC=UserClk"); + u16 &= ~0x0003; + } + if (u16) + printf(" 0x%x", u16); + printf("\n"); + if (unexpected_clk11) + printf("#W Unexpected SSCLKSRC 11.\n"); + // Reserved bits 14:5 should be 0110111000 + // according to documentation. + if (u16 != 0x3700) + printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x3700, u16); + + continue; + } + if (cfg->reg[i].reg == COR2) { + int unexpected_done_cycle = 0; + int unexpected_lck_cycle = 0; + unsigned cycle; + + u16 = cfg->reg[i].int_v; + printf("T1 COR2"); + if (u16 & 0x8000) { + printf(" RESET_ON_ERROR"); + u16 &= ~0x8000; + } + + // DONE_CYCLE + cycle = (u16 & 0x0E00) >> 9; + printf(" DONE_CYCLE=%s", bitstr(cycle, 3)); + if (!cycle || cycle == 7) + unexpected_done_cycle = 1; + u16 &= ~0x0E00; + + // LCK_CYCLE + cycle = (u16 & 0x01C0) >> 6; + printf(" LCK_CYCLE=%s", bitstr(cycle, 3)); + if (!cycle) + unexpected_lck_cycle = 1; + u16 &= ~0x01C0; + + // GTS_CYCLE + cycle = (u16 & 0x0038) >> 3; + printf(" GTS_CYCLE=%s", bitstr(cycle, 3)); + u16 &= ~0x0038; + + // GWE_CYCLE + cycle = u16 & 0x0007; + printf(" GWE_CYCLE=%s", bitstr(cycle, 3)); + u16 &= ~0x0007; + + if (u16) + printf(" 0x%x", u16); + printf("\n"); + if (unexpected_done_cycle) + printf("#W Unexpected DONE_CYCLE %s.\n", + bitstr((u16 & 0x01C0) >> 6, 3)); + if (unexpected_lck_cycle) + printf("#W Unexpected LCK_CYCLE 0b000.\n"); + // Reserved bits 14:12 should be 000 + // according to documentation. + if (u16) + printf("#W Expected reserved 0, got 0x%x.\n", u16); + continue; + } + if (cfg->reg[i].reg == FAR_MAJ) { + uint16_t maj, min; + int unexpected_blk_bit4 = 0; + + maj = cfg->reg[i].far[FAR_MAJ_O]; + min = cfg->reg[i].far[FAR_MIN_O]; + printf("T1 FAR_MAJ"); + + // BLK + u16 = (maj & 0xF000) >> 12; + printf(" BLK=%u", u16); + if (u16 > 7) + unexpected_blk_bit4 = 1; + // ROW + u16 = (maj & 0x0F00) >> 8; + printf(" ROW=%u", u16); + // MAJOR + u16 = maj & 0x00FF; + printf(" MAJOR=%u", u16); + // Block RAM + u16 = (min & 0xC000) >> 14; + printf(" BRAM=%u", u16); + // MINOR + u16 = min & 0x03FF; + printf(" MINOR=%u", u16); + + if (min & 0x3C00) + printf(" 0x%x", min & 0x3C00); + printf("\n"); + + if (unexpected_blk_bit4) + printf("#W Unexpected BLK bit 4 set.\n"); + // Reserved min bits 13:10 should be 000. + if (min & 0x3C00) + printf("#W Expected reserved 0, got 0x%x.\n", (min & 0x3C00) > 10); + continue; + } + if (cfg->reg[i].reg == MFWR) { + printf("T1 MFWR\n"); + continue; + } + if (cfg->reg[i].reg == CTL) { + u16 = cfg->reg[i].int_v; + printf("T1 CTL"); + if (u16 & 0x0040) { + printf(" DECRYPT"); + u16 &= ~0x0040; + } + if (u16 & 0x0020) { + if (u16 & 0x0010) + printf(" SBITS=NO_RW"); + else + printf(" SBITS=NO_READ"); + u16 &= ~0x0030; + } else if (u16 & 0x0010) { + printf(" SBITS=ICAP_READ"); + u16 &= ~0x0010; + } + if (u16 & 0x0008) { + printf(" PERSIST"); + u16 &= ~0x0008; + } + if (u16 & 0x0004) { + printf(" USE_EFUSE_KEY"); + u16 &= ~0x0004; + } + if (u16 & 0x0002) { + printf(" CRC_EXTSTAT_DISABLE"); + u16 &= ~0x0002; + } + if (u16) + printf(" 0x%x", u16); + printf("\n"); + // bit0 is reserved as 1, and we have seen + // bit7 on as well. + if (u16 != 0x81) + printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x0081, u16); + continue; + } + if (cfg->reg[i].reg == MASK) { + u16 = cfg->reg[i].int_v; + printf("T1 MASK"); + if (u16 & 0x0040) { + printf(" DECRYPT"); + u16 &= ~0x0040; + } + if ((u16 & 0x0030) == 0x0030) { + printf(" SECURITY"); + u16 &= ~0x0030; + } + if (u16 & 0x0008) { + printf(" PERSIST"); + u16 &= ~0x0008; + } + if (u16 & 0x0004) { + printf(" USE_EFUSE_KEY"); + u16 &= ~0x0004; + } + if (u16 & 0x0002) { + printf(" CRC_EXTSTAT_DISABLE"); + u16 &= ~0x0002; + } + if (u16) + printf(" 0x%x", u16); + printf("\n"); + // It seems bit7 and bit0 are always masked in. + if (u16 != 0x81) + printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x0081, u16); + continue; + } + if (cfg->reg[i].reg == PWRDN_REG) { + u16 = cfg->reg[i].int_v; + printf("T1 PWRDN_REG"); + if (u16 & 0x4000) { + printf(" EN_EYES"); + u16 &= ~0x4000; + } + if (u16 & 0x0020) { + printf(" FILTER_B"); + u16 &= ~0x0020; + } + if (u16 & 0x0010) { + printf(" EN_PGSR"); + u16 &= ~0x0010; + } + if (u16 & 0x0004) { + printf(" EN_PWRDN"); + u16 &= ~0x0004; + } + if (u16 & 0x0001) { + printf(" KEEP_SCLK"); + u16 &= ~0x0001; + } + if (u16) + printf(" 0x%x", u16); + printf("\n"); + // Reserved bits 13:6 should be 00100010 + // according to documentation. + if (u16 != 0x0880) + printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x0880, u16); + continue; + } + if (cfg->reg[i].reg == HC_OPT_REG) { + u16 = cfg->reg[i].int_v; + printf("T1 HC_OPT_REG"); + if (u16 & 0x0040) { + printf(" INIT_SKIP"); + u16 &= ~0x0040; + } + if (u16) + printf(" 0x%x", u16); + printf("\n"); + // Reserved bits 5:0 should be 011111 + // according to documentation. + if (u16 != 0x001F) + printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x001F, u16); + continue; + } + if (cfg->reg[i].reg == PU_GWE) { + printf("T1 PU_GWE 0x%03X\n", cfg->reg[i].int_v); + continue; + } + if (cfg->reg[i].reg == PU_GTS) { + printf("T1 PU_GTS 0x%03X\n", cfg->reg[i].int_v); + continue; + } + if (cfg->reg[i].reg == CWDT) { + printf("T1 CWDT 0x%X\n", cfg->reg[i].int_v); + if (cfg->reg[i].int_v < 0x0201) + printf("#W Watchdog timer clock below" + " minimum value of 0x0201.\n"); + continue; + } + if (cfg->reg[i].reg == MODE_REG) { + int unexpected_buswidth = 0; + + u16 = cfg->reg[i].int_v; + printf("T1 MODE_REG"); + if (u16 & (1<<13)) { + printf(" NEW_MODE=BITSTREAM"); + u16 &= ~(1<<13); + } + if ((u16 & (1<<12)) + && (u16 & (1<<11))) + unexpected_buswidth = 1; + else if (u16 & (1<<12)) { + printf(" BUSWIDTH=4"); + u16 &= ~(1<<12); + } else if (u16 & (1<<11)) { + printf(" BUSWIDTH=2"); + u16 &= ~(1<<11); + } + // BUSWIDTH=1 is the default and not displayed + + if (u16 & (1<<9)) { + printf(" BOOTMODE_1"); + u16 &= ~(1<<9); + } + if (u16 & (1<<8)) { + printf(" BOOTMODE_0"); + u16 &= ~(1<<8); + } + + if (unexpected_buswidth) + printf("#W Unexpected bus width 0b11.\n"); + if (u16) + printf(" 0x%x", u16); + printf("\n"); + if (u16) + printf("#W Expected reserved 0, got 0x%x.\n", u16); + continue; + } + if (cfg->reg[i].reg == CCLK_FREQ) { + u16 = cfg->reg[i].int_v; + printf("T1 CCLK_FREQ"); + if (u16 & (1<<14)) { + printf(" EXT_MCLK"); + u16 &= ~(1<<14); + } + printf(" MCLK_FREQ=0x%03X", u16 & 0x03FF); + u16 &= ~(0x03FF); + if (u16) + printf(" 0x%x", u16); + printf("\n"); + if (u16) + printf("#W Expected reserved 0, got 0x%x.\n", u16); + continue; + } + if (cfg->reg[i].reg == EYE_MASK) { + printf("T1 EYE_MASK 0x%X\n", cfg->reg[i].int_v); + continue; + } + if (cfg->reg[i].reg == GENERAL1) { + printf("T1 GENERAL1 0x%X\n", cfg->reg[i].int_v); + continue; + } + if (cfg->reg[i].reg == GENERAL2) { + printf("T1 GENERAL2 0x%X\n", cfg->reg[i].int_v); + continue; + } + if (cfg->reg[i].reg == GENERAL3) { + printf("T1 GENERAL3 0x%X\n", cfg->reg[i].int_v); + continue; + } + if (cfg->reg[i].reg == GENERAL4) { + printf("T1 GENERAL4 0x%X\n", cfg->reg[i].int_v); + continue; + } + if (cfg->reg[i].reg == GENERAL5) { + printf("T1 GENERAL5 0x%X\n", cfg->reg[i].int_v); + continue; + } + if (cfg->reg[i].reg == EXP_SIGN) { + printf("T1 EXP_SIGN 0x%X\n", cfg->reg[i].int_v); + continue; + } + if (cfg->reg[i].reg == SEU_OPT) { + int seu_freq; + + u16 = cfg->reg[i].int_v; + seu_freq = (u16 & 0x3FF0) >> 4; + printf("T1 SEU_OPT SEU_FREQ=0x%X", seu_freq); + u16 &= ~(0x3FF0); + if (u16 & (1<<3)) { + printf(" SEU_RUN_ON_ERR"); + u16 &= ~(1<<3); + } + if (u16 & (1<<1)) { + printf(" GLUT_MASK"); + u16 &= ~(1<<1); + } + if (u16 & (1<<0)) { + printf(" SEU_ENABLE"); + u16 &= ~(1<<0); + } + if (u16) + printf(" 0x%x", u16); + printf("\n"); + if (u16) + printf("#W Expected reserved 0, got 0x%x.\n", u16); + continue; + } + FAIL(EINVAL); + } + return 0; +fail: + return rc; +} + +typedef struct ramb16_cfg +{ + uint8_t byte[64]; +} __attribute((packed)) ramb16_cfg_t; + +static const cfg_atom_t ramb16_instance = +{ + {-1}, {12,13, 274,275,276,277,316,317,318,319, + 420,421,422,423,-1}, "default_bits" +}; + +static cfg_atom_t ramb16_atoms[] = +{ + // data_width_a + {{264,265,260,261,256,257,-1},{ -1},"data_width_a 1"}, + {{264,265,260,261, -1},{ 256,257,-1},"data_width_a 2"}, + {{264,265, 256,257,-1},{ 260,261, -1},"data_width_a 4"}, + {{264,265, -1},{ 260,261,256,257,-1},"data_width_a 9"}, + {{ 260,261,256,257,-1},{264,265, -1},"data_width_a 18"}, + {{ 260,261, -1},{264,265, 256,257,-1},"data_width_a 36"}, + {{ -1},{264,265,260,261,256,257,-1},"data_width_a 0"}, + + // data_width_b + {{262,263,286,287,258,259,-1},{ -1},"data_width_b 1"}, + {{262,263,286,287, -1},{ 258,259,-1},"data_width_b 2"}, + {{262,263, 258,259,-1},{ 286,287, -1},"data_width_b 4"}, + {{262,263, -1},{ 286,287,258,259,-1},"data_width_b 9"}, + {{ 286,287,258,259,-1},{262,263, -1},"data_width_b 18"}, + {{ 286,287, -1},{262,263, 258,259,-1},"data_width_b 36"}, + {{ -1},{262,263,286,287,258,259,-1},"data_width_b 0"}, + + // required + { { -1}, {266, 267, -1}, "RST_PRIORITY_B:CE" }, + { {266, 267, -1}, { -1}, "RST_PRIORITY_B:SR" }, + { { -1}, {268, 269, -1}, "RST_PRIORITY_A:CE" }, + { {268, 269, -1}, { -1}, "RST_PRIORITY_A:SR" }, + { { -1}, {290, 291, -1}, "EN_RSTRAM_A:TRUE" }, + { {290, 291, -1}, { -1}, "EN_RSTRAM_A:FALSE" }, + { { -1}, {444, 445, -1}, "EN_RSTRAM_B:TRUE" }, + { {444, 445, -1}, { -1}, "EN_RSTRAM_B:FALSE" }, + + // optional + { { -1}, { 26, 27, -1}, "CLKAINV:CLKA" }, + { { 26, 27, -1}, { -1}, "CLKAINV:CLKA_B" }, // def + { { -1}, { 30, 31, -1}, "CLKBINV:CLKB" }, + { { 30, 31, -1}, { -1}, "CLKBINV:CLKB_B" }, // def + { { -1}, {270, 271, -1}, "RSTTYPE:ASYNC" }, + { {270, 271, -1}, { -1}, "RSTTYPE:SYNC" }, // def + { { -1}, {278, 279, -1}, "WRITE_MODE_B:READ_FIRST" }, + { { -1}, {280, 281, -1}, "WRITE_MODE_A:READ_FIRST" }, + { { -1}, {282, 283, -1}, "WRITE_MODE_B:NO_CHANGE" }, + { { -1}, {284, 285, -1}, "WRITE_MODE_A:NO_CHANGE" }, + { {278, 279, 282, 283, -1}, {-1}, "WRITE_MODE_B:WRITE_FIRST" }, //def + { {280, 281, 284, 285, -1}, {-1}, "WRITE_MODE_A:WRITE_FIRST" }, //def + { { -1}, {306, 307, -1}, "DOB_REG:1" }, + { {306, 306, -1}, { -1}, "DOB_REG:0" }, // def + { { -1}, {308, 309, -1}, "DOA_REG:1" }, + { {308, 309, -1}, { -1}, "DOA_REG:0" }, // def + { {431, 467, -1}, {430, 466, -1}, "ENAINV:ENA" }, // def + { {430, 431, 466, 467, -1}, {-1}, "ENAINV:ENA_B" }, + { {465, 469, -1}, {464, 468, -1}, "ENBINV:ENB" }, // def + { {464, 465, 468, 469, -1}, {-1}, "ENBINV:ENB_B" }, + { { -1}, { 20, 21, -1}, "REGCEAINV:REGCEA" }, // def + { { 20, 21, -1}, { -1}, "REGCEAINV:REGCEA_B" }, + { { -1}, { 8, 9, -1}, "REGCEBINV:REGCEB" }, + { { 8, 9, -1}, { -1}, "REGCEBINV:REGCEB_B" }, // def + { { 24, 25, -1}, { -1}, "RSTAINV:RSTA" }, // def + { { -1}, { 24, 25, -1}, "RSTAINV:RSTA_B" }, + { { -1}, { 4, 5, -1}, "RSTBINV:RSTB" }, // def + { { 4, 5, -1}, { -1}, "RSTBINV:RSTB_B" }, + { { -1}, { 19, -1}, "WEA0INV:WEA0" }, // def + { { 19, -1}, { -1}, "WEA0INV:WEA0_B" }, + { { -1}, { 23, -1}, "WEA2INV:WEA1" }, // def + { { 23, -1}, { -1}, "WEA2INV:WEA1_B" }, + { { -1}, { 18, -1}, "WEA2INV:WEA2" }, // def + { { 18, -1}, { -1}, "WEA2INV:WEA2_B" }, + { { -1}, { 22, -1}, "WEA2INV:WEA3" }, // def + { { 22, -1}, { -1}, "WEA2INV:WEA3_B" }, + { { -1}, { 7, -1}, "WEB0INV:WEB0" }, // def + { { 7, -1}, { -1}, "WEB0INV:WEB0_B" }, + { { -1}, { 3, -1}, "WEB1INV:WEB1" }, // def + { { 3, -1}, { -1}, "WEB1INV:WEB1_B" }, + { { -1}, { 6, -1}, "WEB2INV:WEB2" }, // def + { { 6, -1}, { -1}, "WEB2INV:WEB2_B" }, + { { -1}, { 2, -1}, "WEB3INV:WEB3" }, // def + { { 2, -1}, { -1}, "WEB3INV:WEB3_B" }, +}; + +static void print_ramb16_cfg(ramb16_cfg_t* cfg) +{ + char bits[512]; + uint8_t u8; + int i, first_extra; + + for (i = 0; i < 32; i++) { + u8 = cfg->byte[i*2]; + cfg->byte[i*2] = cfg->byte[i*2+1]; + cfg->byte[i*2+1] = u8; + } + for (i = 0; i < 64; i++) { + u8 = 0; + if (cfg->byte[i] & 0x01) u8 |= 0x80; + if (cfg->byte[i] & 0x02) u8 |= 0x40; + if (cfg->byte[i] & 0x04) u8 |= 0x20; + if (cfg->byte[i] & 0x08) u8 |= 0x10; + if (cfg->byte[i] & 0x10) u8 |= 0x08; + if (cfg->byte[i] & 0x20) u8 |= 0x04; + if (cfg->byte[i] & 0x40) u8 |= 0x02; + if (cfg->byte[i] & 0x80) u8 |= 0x01; + cfg->byte[i] = u8; + } + + // + // Bits 0..255 come from minor 23, Bits 256..511 from minor 24. + // Each set of 256 bits is divided into two halfs of 128 bits + // that are swept forward and backward to form 2-bit pairs, + // pairs 0..127 are formed out of bits 0..127 and 255..128, + // p128..p255 are formed out of b256..b383 and b511..b384. + // Since so much bit twiddling is already happening, we are sorting + // the bits so that pairs are next to each other. + // The notation for a pair is "p8=01". + + // minor 23 + for (i = 0; i < 128; i++) { + bits[i*2] = (cfg->byte[i/8] & (1<<(i%8))) != 0; + bits[i*2+1] = (cfg->byte[(255-i)/8] + & (1<<(7-(i%8)))) != 0; + } + // minor 24 + for (i = 0; i < 128; i++) { + bits[256+i*2] = (cfg->byte[32+i/8] & (1<<(i%8))) != 0; + bits[256+i*2+1] = (cfg->byte[32+(255-i)/8] + & (1<<(7-(i%8)))) != 0; + } + + printf("{\n"); + // hexdump(1 /* indent */, &cfg->byte[0], 64 /* len */); + for (i = 0; i < sizeof(ramb16_atoms)/sizeof(ramb16_atoms[0]); i++) { + if (atom_found(bits, &ramb16_atoms[i]) + && ramb16_atoms[i].must_1[0] != -1) { + printf(" %s\n", ramb16_atoms[i].str); + ramb16_atoms[i].flag = 1; + } else + ramb16_atoms[i].flag = 0; + } + for (i = 0; i < sizeof(ramb16_atoms)/sizeof(ramb16_atoms[0]); i++) { + if (ramb16_atoms[i].flag) + atom_remove(bits, &ramb16_atoms[i]); + } + // instantiation bits + if (ramb16_instance.must_1[0] != -1) { + if (atom_found(bits, &ramb16_instance)) { + for (i = 0; ramb16_instance.must_1[i] != -1; i++) + printf(" b%i\n", ramb16_instance.must_1[i]); + atom_remove(bits, &ramb16_instance); + } else + printf(" #W Not all instantiation bits set.\n"); + } + // extra bits + first_extra = 1; + for (i = 0; i < 512; i++) { + if (bits[i]) { + if (first_extra) { + printf(" #W Extra bits set.\n"); + first_extra = 0; + } + printf(" b%i\n", i); + } + } + printf("}\n"); +} + +static void printf_clb(uint8_t* maj_bits, int row, int major) +{ + int i, j, start, max_idx, frame_off; + const char* lut_str; + uint64_t lut64; + + // the first two slots on top and bottom row are not used for clb + if (!row) { + start = 0; + max_idx = 14; + } else if (row == 3) { + start = 2; + max_idx = 16; + } else { + start = 0; + max_idx = 16; + } + + for (i = start; i < max_idx; i++) { + if (clb_empty(maj_bits, i)) + continue; + frame_off = i*64; + if (i >= 8) + frame_off += 16; // skip clock bits for idx >= 8 + + // LUTs + lut64 = read_lut64(&maj_bits[24*130], frame_off+32); + { int logic_base[6] = {0,1,0,0,1,0}; + lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); } + if (*lut_str) + printf("r%i ma%i clb i%i s0_A6LUT \"%s\"\n", + row, major, i-start, lut_str); + + lut64 = read_lut64(&maj_bits[21*130], frame_off+32); + { int logic_base[6] = {1,1,0,1,0,1}; + lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); } + if (*lut_str) + printf("r%i ma%i clb i%i s0_B6LUT \"%s\"\n", + row, major, i-start, lut_str); + + lut64 = read_lut64(&maj_bits[24*130], frame_off); + { int logic_base[6] = {0,1,0,0,1,0}; + lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); } + if (*lut_str) + printf("r%i ma%i clb i%i s0_C6LUT \"%s\"\n", + row, major, i-start, lut_str); + + lut64 = read_lut64(&maj_bits[21*130], frame_off); + { int logic_base[6] = {1,1,0,1,0,1}; + lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); } + if (*lut_str) + printf("r%i ma%i clb i%i s0_D6LUT \"%s\"\n", + row, major, i-start, lut_str); + + lut64 = read_lut64(&maj_bits[27*130], frame_off+32); + { int logic_base[6] = {1,1,0,1,1,0}; + lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); } + if (*lut_str) + printf("r%i ma%i clb i%i s1_A6LUT \"%s\"\n", + row, major, i-start, lut_str); + + lut64 = read_lut64(&maj_bits[29*130], frame_off+32); + { int logic_base[6] = {1,1,0,1,1,0}; + lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); } + if (*lut_str) + printf("r%i ma%i clb i%i s1_B6LUT \"%s\"\n", + row, major, i-start, lut_str); + + lut64 = read_lut64(&maj_bits[27*130], frame_off); + { int logic_base[6] = {0,1,0,0,0,1}; + lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); } + if (*lut_str) + printf("r%i ma%i clb i%i s1_C6LUT \"%s\"\n", + row, major, i-start, lut_str); + + lut64 = read_lut64(&maj_bits[29*130], frame_off); + { int logic_base[6] = {0,1,0,0,0,1}; + lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); } + if (*lut_str) + printf("r%i ma%i clb i%i s1_D6LUT \"%s\"\n", + row, major, i-start, lut_str); + + // bits + for (j = 0; j < 64; j++) { + if (bit_set(&maj_bits[20*130], frame_off + j)) + printf("r%i ma%i clb i%i mi20 bit %i\n", + row, major, i-start, j); + } + for (j = 0; j < 64; j++) { + if (bit_set(&maj_bits[23*130], frame_off + j)) + printf("r%i ma%i clb i%i mi23 bit %i\n", + row, major, i-start, j); + } + for (j = 0; j < 64; j++) { + if (bit_set(&maj_bits[26*130], frame_off + j)) + printf("r%i ma%i clb i%i mi26 bit %i\n", + row, major, i-start, j); + } + } +} + +static int dump_bits(struct fpga_config* cfg) +{ + int row, major, minor, i, j, off, offset_in_frame; + + // type0 + off = 0; + for (row = 0; row < 4; row++) { + for (major = 0; major < 18; major++) { + if (major == 7) { // MACC + int last_extra_minor; + + if (!row || row == 3) + last_extra_minor = 23; + else + last_extra_minor = 21; + minor = 0; + while (minor <= last_extra_minor) { + minor += printf_frames(&cfg->bits[off + +minor*130], 31 - minor, row, + major, minor, /*print_empty*/ 0); + } + + // clock + for (; minor < 24; minor++) + printf_clock(&cfg->bits[off+minor*130], + row, major, minor); + + for (i = 0; i < 4; i++) { + for (minor = last_extra_minor+1; minor < 24; + minor++) { + for (j = 0; j < 256; j++) { + if (bit_set(&cfg->bits[off+minor*130], i*256 + ((i>=2)?16:0) + j)) + printf("r%i ma%i dsp i%i mi%i bit %i\n", row, major, i, minor, i*256+j); + } + } + } + } else if (major == 2 || major == 3 || major == 5 || major == 6 + || major == 8 || major == 10 || major == 11 || major == 12 + || major == 13 || major == 15 || major == 16) { // logic + minor = 0; + while (minor < 20) { + minor += printf_frames(&cfg->bits[off + +minor*130], 31 - minor, row, + major, minor, /*print_empty*/ 0); + } + + // clock + for (minor = 20; minor < 31; minor++) + printf_clock(&cfg->bits[off+minor*130], + row, major, minor); + // extra bits at bottom of row0 and top of row3 + if (row == 3) + printf_extrabits(&cfg->bits[off], 20, 11, + 0, 128, row, major); + else if (!row) + printf_extrabits(&cfg->bits[off], 20, 11, + 14*64 + 16, 128, row, major); + + // clbs + printf_clb(&cfg->bits[off], row, major); + } else if (major == 4 || major == 14) { // bram + ramb16_cfg_t ramb16_cfg[4]; + + // minors 0..22 + minor = 0; + while (minor < 23) { + minor += printf_frames(&cfg->bits[off + +minor*130], 23 - minor, row, + major, minor, /*print_empty*/ 0); + } + + // minors 23&24 + printf_clock(&cfg->bits[off+23*130], row, major, 23); + printf_clock(&cfg->bits[off+24*130], row, major, 24); + for (i = 0; i < 4; i++) { + offset_in_frame = i*32; + if (offset_in_frame >= 64) + offset_in_frame += 2; + for (j = 0; j < 32; j++) { + ramb16_cfg[i].byte[j] = cfg->bits[off+23*130+offset_in_frame+j]; + ramb16_cfg[i].byte[j+32] = cfg->bits[off+24*130+offset_in_frame+j]; + } + } + for (i = 0; i < 4; i++) { + for (j = 0; j < 64; j++) { + if (ramb16_cfg[i].byte[j]) + break; + } + if (j >= 64) + continue; + printf("r%i ma%i ramb16 i%i\n", + row, major, i); + print_ramb16_cfg(&ramb16_cfg[i]); + } + } else { + minor = 0; + while (minor < minors_per_major[major]) { + minor += printf_frames(&cfg->bits[off + +minor*130], minors_per_major[major] + - minor, row, major, minor, /*print_empty*/ 0); + } + } + off += minors_per_major[major] * 130; + } + } + return 0; +} + +static int dump_bram(struct fpga_config* cfg) +{ + int row, i, j, off, newline; + + newline = 0; + for (row = 0; row < 4; row++) { + for (i = 0; i < 8; i++) { + for (j = 0; j < 18*130; j++) { + if (cfg->bits[BRAM_DATA_START + row*144*130 + + i*18*130 + j]) + break; + } + if (j >= 18*130) + continue; + if (!newline) { + newline = 1; + printf("\n"); + } + printf("br%i ramb16 i%i\n", row, i); + printf("{\n"); + off = BRAM_DATA_START + row*144*130 + i*18*130; + printf_ramb16_data(cfg->bits, off); + printf("}\n"); + } + } + return 0; +} + +int dump_config(struct fpga_config* cfg, int flags) +{ + int rc; + + if (flags & DUMP_HEADER_STR) + dump_header(cfg); + if (flags & DUMP_REGS) { + rc = dump_regs(cfg, /*start*/ 0, cfg->num_regs_before_bits); + if (rc) FAIL(rc); + } + if (flags & DUMP_BITS) { + rc = dump_bits(cfg); + if (rc) FAIL(rc); + rc = dump_bram(cfg); + if (rc) FAIL(rc); + printf_iob(cfg->bits, cfg->bits_len, + BRAM_DATA_START + BRAM_DATA_LEN, 896*2/8); + } + if (flags & DUMP_REGS) { + rc = dump_regs(cfg, cfg->num_regs_before_bits, cfg->num_regs); + if (rc) FAIL(rc); + } + return 0; +fail: + return rc; +} + + +void free_config(struct fpga_config* cfg) +{ + free(cfg->bits); + cfg->bits = 0; + memset(cfg, 0, sizeof(*cfg)); +} + int write_bits(FILE* f, struct fpga_model* model) { return 0; } + +static int parse_header(struct fpga_config* cfg, uint8_t* d, int len, + int inpos, int* outdelta) +{ + int i, str_len; + static const uint8_t expected_bof[] = { + 0x00, 0x09, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, + 0x0F, 0xF0, 0x00, 0x00, 0x01 }; + + *outdelta = 0; + if (inpos + 13 > len) { + fprintf(stderr, "#E File size %i below minimum of 13 bytes.\n", + len); + return -1; + } + for (i = 0; i < 13; i++) { + if (d[inpos+*outdelta+i] == expected_bof[i]) + continue; + fprintf(stderr, "#E Expected 0x%x, got 0x%x at off %i\n", + expected_bof[i], d[inpos+*outdelta+i], + inpos+*outdelta+i); + } + *outdelta += 13; + // 4 strings 'a' - 'd', 16-bit length + for (i = 'a'; i <= 'd'; i++) { + if (inpos + *outdelta + 3 > len) { + fprintf(stderr, "#E Unexpected EOF at %i.\n", len); + return -1; + } + if (d[inpos + *outdelta] != i) { + fprintf(stderr, "#E Expected string code '%c', got " + "'%c'.\n", i, d[inpos + *outdelta]); + return -1; + } + str_len = __be16_to_cpu(*(uint16_t*)&d[inpos + *outdelta + 1]); + if (inpos + *outdelta + 3 + str_len > len) { + fprintf(stderr, "#E Unexpected EOF at %i.\n", len); + return -1; + } + if (d[inpos + *outdelta + 3 + str_len - 1]) { + fprintf(stderr, "#E z-terminated string ends with %0xh" + ".\n", d[inpos + *outdelta + 3 + str_len - 1]); + return -1; + } + strcpy(cfg->header_str[i-'a'], (char*) &d[inpos + *outdelta + 3]); + *outdelta += 3 + str_len; + } + return 0; +} + +static int FAR_pos(int FAR_row, int FAR_major, int FAR_minor) +{ + int result, i; + + if (FAR_row < 0 || FAR_major < 0 || FAR_minor < 0) + return -1; + if (FAR_row > 3 || FAR_major > 17 + || FAR_minor >= minors_per_major[FAR_major]) + return -1; + result = FAR_row * 505*130; + for (i = 0; i < FAR_major; i++) + result += minors_per_major[i]*130; + return result + FAR_minor*130; +} + +static int read_bits(struct fpga_config* cfg, uint8_t* d, int len, int inpos, int* outdelta) +{ + int src_off, packet_hdr_type, packet_hdr_opcode; + int packet_hdr_register, packet_hdr_wordcount; + int FAR_block, FAR_row, FAR_major, FAR_minor, i, j, rc, MFW_src_off; + int offset_in_bits, block0_words, padding_frames; + uint16_t u16; + uint32_t u32; + + *outdelta = 0; + if (cfg->idcode_reg == -1 || cfg->FLR_reg == -1 + || (cfg->reg[cfg->idcode_reg].int_v != XC6SLX4 + && cfg->reg[cfg->idcode_reg].int_v != XC6SLX9) + || cfg->reg[cfg->FLR_reg].int_v != 896) + FAIL(EINVAL); + + cfg->bits_len = (4*505 + 4*144) * 130 + 896*2; + cfg->bits = calloc(cfg->bits_len, 1 /* elsize */); + if (!cfg->bits) FAIL(ENOMEM); + cfg->bram_off = -1; + cfg->IOB_off = -1; + + FAR_block = -1; + FAR_row = -1; + FAR_major = -1; + FAR_minor = -1; + MFW_src_off = -1; + // Go through bit_file from first_FAR_off (inpos) until last byte + // of IOB was read, plus padding, plus CRC verification. + src_off = inpos; + while (src_off < len) { + if (src_off + 2 > len) FAIL(EINVAL); + u16 = __be16_to_cpu(*(uint16_t*)&d[src_off]); + src_off += 2; + + // 3 bits: 001 = Type 1; 010 = Type 2 + packet_hdr_type = (u16 & 0xE000) >> 13; + if (packet_hdr_type != 1 && packet_hdr_type != 2) + FAIL(EINVAL); + + // 2 bits: 00 = noop; 01 = read; 10 = write; 11 = reserved + packet_hdr_opcode = (u16 & 0x1800) >> 11; + if (packet_hdr_opcode == 3) FAIL(EINVAL); + + if (packet_hdr_opcode == 0) { // noop + if (packet_hdr_type != 1 || u16 & 0x07FF) FAIL(EINVAL); + continue; + } + + // Now we must look at a Type 1 command + packet_hdr_register = (u16 & 0x07E0) >> 5; + packet_hdr_wordcount = u16 & 0x001F; + if (src_off + packet_hdr_wordcount*2 > len) FAIL(EINVAL); + + if (packet_hdr_type == 1) { + if (packet_hdr_register == CMD) { + if (packet_hdr_wordcount != 1) FAIL(EINVAL); + u16 = __be16_to_cpu( + *(uint16_t*)&d[src_off]); + if (u16 == CMD_GRESTORE || u16 == CMD_LFRM) { + src_off -= 2; + goto success; + } + if (u16 != CMD_MFW && u16 != CMD_WCFG) + FAIL(EINVAL); + if (u16 == CMD_MFW) { + if (FAR_block != 0) FAIL(EINVAL); + MFW_src_off = FAR_pos(FAR_row, FAR_major, FAR_minor); + if (MFW_src_off == -1) FAIL(EINVAL); + } + src_off += 2; + continue; + } + if (packet_hdr_register == FAR_MAJ) { + uint16_t maj, min; + + if (packet_hdr_wordcount != 2) FAIL(EINVAL); + maj = __be16_to_cpu(*(uint16_t*) + &d[src_off]); + min = __be16_to_cpu(*(uint16_t*) + &d[src_off+2]); + + FAR_block = (maj & 0xF000) >> 12; + if (FAR_block > 7) FAIL(EINVAL); + FAR_row = (maj & 0x0F00) >> 8; + FAR_major = maj & 0x00FF; + FAR_minor = min & 0x03FF; + src_off += 4; + continue; + } + if (packet_hdr_register == MFWR) { + uint32_t first_dword, second_dword; + + if (packet_hdr_wordcount != 4) FAIL(EINVAL); + first_dword = __be32_to_cpu( + *(uint32_t*)&d[src_off]); + second_dword = __be32_to_cpu( + *(uint32_t*)&d[src_off+4]); + if (first_dword || second_dword) FAIL(EINVAL); + // The first MFWR will overwrite itself, so + // use memmove(). + if (FAR_block != 0) FAIL(EINVAL); + offset_in_bits = FAR_pos(FAR_row, FAR_major, FAR_minor); + if (offset_in_bits == -1) FAIL(EINVAL); + memmove(&cfg->bits[offset_in_bits], &cfg->bits[MFW_src_off], 130); + + src_off += 8; + continue; + } + FAIL(EINVAL); + } + + // packet type must be 2 here + if (packet_hdr_wordcount != 0) FAIL(EINVAL); + if (packet_hdr_register != FDRI) FAIL(EINVAL); + + if (src_off + 4 > len) FAIL(EINVAL); + u32 = __be32_to_cpu(*(uint32_t*)&d[src_off]); + src_off += 4; + if (src_off+2*u32 > len) FAIL(EINVAL); + if (2*u32 < 130) FAIL(EINVAL); + + // fdri words u32 + if (FAR_block == -1 || FAR_block > 1 || FAR_row == -1 + || FAR_major == -1 || FAR_minor == -1) + FAIL(EINVAL); + + block0_words = 0; + if (!FAR_block) { + + offset_in_bits = FAR_pos(FAR_row, FAR_major, FAR_minor); + if (offset_in_bits == -1) FAIL(EINVAL); + if (!FAR_row && !FAR_major && !FAR_minor + && u32 > 4*(505+2)*65) + block0_words = 4*(505+2)*65; + else { + block0_words = u32; + if (block0_words % 65) FAIL(EINVAL); + } + padding_frames = 0; + for (i = 0; i < block0_words/65; i++) { + if (i && i+1 == block0_words/65) { + for (j = 0; j < 130; j++) { + if (d[src_off+i*130+j] + != 0xFF) break; + } + // Not sure about the exact logic to + // determine a padding frame. Maybe + // first word all 1? For now we skip + // the frame as a padding frame when + // it's the last frame of a block and + // all-1. + if (j >= 130) + break; + } + if (!FAR_major && !FAR_minor + && (i%507 == 505)) { + for (j = 0; j < 2*130; j++) { + if (d[src_off+i*130+j] + != 0xFF) FAIL(EINVAL); + } + i++; + padding_frames += 2; + continue; + } + memcpy(&cfg->bits[offset_in_bits + + (i-padding_frames)*130], + &d[src_off + i*130], 130); + } + } + if (u32 - block0_words > 0) { + int bram_data_words = 4*144*65 + 896; + if (u32 - block0_words != bram_data_words + 1) FAIL(EINVAL); + offset_in_bits = 4*505*130; + cfg->bram_off = offset_in_bits; + cfg->IOB_off = offset_in_bits + 4*144*65; + memcpy(&cfg->bits[offset_in_bits], + &d[src_off+block0_words*2], + bram_data_words*2); + u16 = __be16_to_cpu(*(uint16_t*)&d[ + (src_off+block0_words+bram_data_words)*2]); + if (u16) FAIL(EINVAL); + } + src_off += 2*u32; + // two CRC words + u32 = __be32_to_cpu(*(uint32_t*)&d[src_off]); + src_off += 4; + } + rc = EINVAL; +fail: + free(cfg->bits); + cfg->bits = 0; + return rc; +success: + *outdelta = src_off - inpos; + return 0; +} + +static int parse_commands(struct fpga_config* cfg, uint8_t* d, + int len, int inpos) +{ + int curpos, cmd_len, first_FAR_off, u16_off, rc; + int packet_hdr_type, packet_hdr_opcode, packet_hdr_register; + int packet_hdr_wordcount, i; + uint32_t u32; + uint16_t u16; + + curpos = inpos; + if (curpos + 5 > len + || d[curpos] != 'e') FAIL(EINVAL); + cmd_len = __be32_to_cpu(*(uint32_t*)&d[curpos + 1]); + curpos += 5; + if (curpos + cmd_len > len) FAIL(EINVAL); + if (curpos + cmd_len < len) { + printf("#W Unexpected continuation after offset " + "%i.\n", curpos + 5 + cmd_len); + } + + if (curpos >= len) FAIL(EINVAL); + if (d[curpos] != 0xAA) { + while (curpos < len && d[curpos] != 0xAA) { + if (d[curpos] != 0xFF) { + printf("#W Expected 0xFF, but got 0x%X at " + "offset %i\n", d[curpos], curpos); + } + curpos++; if (curpos >= len) FAIL(EINVAL); + } + } + if (curpos + 4 > len) FAIL(EINVAL); + u32 = __be32_to_cpu(*(uint32_t*)&d[curpos]); + curpos += 4; + if (u32 != 0xAA995566) { + fprintf(stderr, "#E Unexpected sync word 0x%x.\n", u32); + FAIL(EINVAL); + } + first_FAR_off = -1; + while (curpos < len) { + // packet header: ug380, Configuration Packets (p88) + if (curpos + 2 > len) FAIL(EINVAL); + u16 = __be16_to_cpu(*(uint16_t*)&d[curpos]); + u16_off = curpos; curpos += 2; + + // 3 bits: 001 = Type 1; 010 = Type 2 + packet_hdr_type = (u16 & 0xE000) >> 13; + if (packet_hdr_type != 1 && packet_hdr_type != 2) FAIL(EINVAL); + + // 2 bits: 00 = noop; 01 = read; 10 = write; 11 = reserved + packet_hdr_opcode = (u16 & 0x1800) >> 11; + if (packet_hdr_opcode == 3) FAIL(EINVAL); + if (packet_hdr_opcode == 0) { // noop + if (packet_hdr_type != 1 || u16 & 0x07FF) FAIL(EINVAL); + cfg->reg[cfg->num_regs++].reg = REG_NOOP; + continue; + } + + packet_hdr_register = (u16 & 0x07E0) >> 5; + packet_hdr_wordcount = u16 & 0x001F; + if (curpos + packet_hdr_wordcount*2 > len) FAIL(EINVAL); + curpos += packet_hdr_wordcount*2; + + if (packet_hdr_type == 2) { + int outdelta; + + if (packet_hdr_wordcount != 0) { + printf("#W 0x%x=0x%x Unexpected Type 2 " + "wordcount.\n", u16_off, u16); + } + if (packet_hdr_register != FDRI) FAIL(EINVAL); + if (curpos + 4 > len) FAIL(EINVAL); + u32 = __be32_to_cpu(*(uint32_t*)&d[curpos]); + if (curpos+4+2*u32 > len) FAIL(EINVAL); + if (2*u32 < 130) FAIL(EINVAL); + + curpos += 4; + if (first_FAR_off == -1) FAIL(EINVAL); + + if (cfg->num_regs_before_bits != -1) FAIL(EINVAL); + cfg->num_regs_before_bits = cfg->num_regs; + + rc = read_bits(cfg, d, len, first_FAR_off, &outdelta); + if (rc) FAIL(rc); + curpos = first_FAR_off + outdelta; + continue; + } + + if (packet_hdr_type != 1) FAIL(EINVAL); + if (packet_hdr_register == IDCODE) { + if (packet_hdr_wordcount != 2) FAIL(EINVAL); + + if (cfg->idcode_reg != -1) FAIL(EINVAL); + cfg->idcode_reg = cfg->num_regs; + + cfg->reg[cfg->num_regs].reg = IDCODE; + cfg->reg[cfg->num_regs].int_v = + __be32_to_cpu(*(uint32_t*)&d[u16_off+2]); + cfg->num_regs++; + + if ((cfg->reg[cfg->idcode_reg].int_v == XC6SLX4 + || cfg->reg[cfg->idcode_reg].int_v == XC6SLX9) + && cfg->reg[cfg->FLR_reg].int_v != 896) + printf("#W Unexpected FLR value %i on " + "idcode 0x%X.\n", + cfg->reg[cfg->FLR_reg].int_v, + cfg->reg[cfg->idcode_reg].int_v); + continue; + } + if (packet_hdr_register == FLR) { + if (packet_hdr_wordcount != 1) FAIL(EINVAL); + + if (cfg->FLR_reg != -1) FAIL(EINVAL); + cfg->FLR_reg = cfg->num_regs; + + // + // First come the type 0 frames (clb, bram + // cfg, dsp, etc). Then type 1 (bram data), + // then type 2, the IOB cfg data block. + // FLR is counted in 16-bit words, and there is + // 1 extra dummy 0x0000 after that. + // + + cfg->reg[cfg->num_regs].reg = FLR; + cfg->reg[cfg->num_regs].int_v = + __be16_to_cpu(*(uint16_t*)&d[u16_off+2]); + cfg->num_regs++; + + if ((cfg->reg[cfg->FLR_reg].int_v*2) % 8) + printf("#W FLR*2 should be multiple of " + "8, but modulo 8 is %i\n", + (cfg->reg[cfg->FLR_reg].int_v*2) % 8); + continue; + } + if (packet_hdr_register == FAR_MAJ) { + if (packet_hdr_wordcount != 2) FAIL(EINVAL); + if (first_FAR_off == -1) + first_FAR_off = u16_off; + + cfg->reg[cfg->num_regs].reg = FAR_MAJ; + cfg->reg[cfg->num_regs].far[FAR_MAJ_O] = + __be16_to_cpu(*(uint16_t*)&d[u16_off+2]); + cfg->reg[cfg->num_regs].far[FAR_MIN_O] = + __be16_to_cpu(*(uint16_t*)&d[u16_off+4]); + cfg->num_regs++; + continue; + } + if (packet_hdr_register == MFWR) { + uint32_t first_dword, second_dword; + + if (packet_hdr_wordcount != 4) FAIL(EINVAL); + first_dword = __be32_to_cpu(*(uint32_t*)&d[u16_off+2]); + second_dword = __be32_to_cpu(*(uint32_t*)&d[u16_off+6]); + if (first_dword || second_dword) FAIL(EINVAL); + + cfg->reg[cfg->num_regs++].reg = MFWR; + continue; + } + if (packet_hdr_register == CRC + || packet_hdr_register == EXP_SIGN) { + if (packet_hdr_wordcount != 2) FAIL(EINVAL); + + cfg->reg[cfg->num_regs].reg = packet_hdr_register; + cfg->reg[cfg->num_regs].int_v = + __be32_to_cpu(*(uint32_t*)&d[u16_off+2]); + cfg->num_regs++; + continue; + } + if (packet_hdr_register == CMD + || packet_hdr_register == COR1 + || packet_hdr_register == COR2 + || packet_hdr_register == CTL + || packet_hdr_register == MASK + || packet_hdr_register == PWRDN_REG + || packet_hdr_register == HC_OPT_REG + || packet_hdr_register == PU_GWE + || packet_hdr_register == PU_GTS + || packet_hdr_register == CWDT + || packet_hdr_register == MODE_REG + || packet_hdr_register == CCLK_FREQ + || packet_hdr_register == EYE_MASK + || packet_hdr_register == GENERAL1 + || packet_hdr_register == GENERAL2 + || packet_hdr_register == GENERAL3 + || packet_hdr_register == GENERAL4 + || packet_hdr_register == GENERAL5 + || packet_hdr_register == SEU_OPT) { + if (packet_hdr_wordcount != 1) FAIL(EINVAL); + + cfg->reg[cfg->num_regs].reg = packet_hdr_register; + cfg->reg[cfg->num_regs].int_v = + __be16_to_cpu(*(uint16_t*)&d[u16_off+2]); + cfg->num_regs++; + continue; + } + printf("#W 0x%x=0x%x T1 %i (%u words)", u16_off, u16, + packet_hdr_register, packet_hdr_wordcount); + for (i = 0; (i < 8) && (i < packet_hdr_wordcount); i++) + printf(" 0x%x", __be16_to_cpu(*(uint16_t*) + &d[u16_off+2+i*2])); + printf("\n"); + } + return 0; +fail: + return rc; +} diff --git a/bits.h b/bits.h index aeb391c..1cfc8c7 100644 --- a/bits.h +++ b/bits.h @@ -5,15 +5,84 @@ // For details see the UNLICENSE file at the root of the source tree. // -struct fpga_config -{ - int param1, param2; - uint8_t* bits; - uint8_t* bram_data; +// The highest 4 bits are the binary revision and not +// used when performing IDCODE verification. +// ug380, Configuration Sequence, page 78 +#define IDCODE_MASK 0x0FFFFFFF + +#define XC6SLX4 0x04000093 +#define XC6SLX9 0x04001093 +#define XC6SLX16 0x04002093 +#define XC6SLX25 0x04004093 +#define XC6SLX25T 0x04024093 +#define XC6SLX45 0x04008093 +#define XC6SLX45T 0x04028093 +#define XC6SLX75 0x0400E093 +#define XC6SLX75T 0x0402E093 +#define XC6SLX100 0x04011093 +#define XC6SLX100T 0x04031093 +#define XC6SLX150 0x0401D093 + +// xc6 configuration registers, documentation in ug380, page90 +enum fpga_config_reg { + CRC = 0, FAR_MAJ, FAR_MIN, FDRI, FDRO, CMD, CTL, MASK, STAT, LOUT, COR1, + COR2, PWRDN_REG, FLR, IDCODE, CWDT, HC_OPT_REG, CSBO = 18, + GENERAL1, GENERAL2, GENERAL3, GENERAL4, GENERAL5, MODE_REG, PU_GWE, + PU_GTS, MFWR, CCLK_FREQ, SEU_OPT, EXP_SIGN, RDBK_SIGN, BOOTSTS, + EYE_MASK, CBC_REG }; -// read_bitfile() write_bitfile() -// get_bit() set_bit() +#define REG_NOOP -1 // pseudo register for noops + +#define FAR_MAJ_O 0 +#define FAR_MIN_O 1 + +struct fpga_config_reg_rw +{ + enum fpga_config_reg reg; + union { + int int_v; + int far[2]; // 0 (FAR_MAJ_O) = major, 1 (FAR_MIN_O) = minor + }; +}; + +enum { + CMD_NULL = 0, CMD_WCFG, CMD_MFW, CMD_LFRM, CMD_RCFG, CMD_START, + CMD_RCRC = 7, CMD_AGHIGH, CMD_GRESTORE = 10, CMD_SHUTDOWN, + CMD_DESYNC = 13, CMD_IPROG +}; + +#define MAX_HEADER_STR_LEN 128 +#define MAX_REG_ACTIONS 256 + +#define BRAM_DATA_START (4*505*130) +#define BRAM_DATA_LEN (4*144*130) + +struct fpga_config +{ + char header_str[4][MAX_HEADER_STR_LEN]; + + int num_regs; + struct fpga_config_reg_rw reg[MAX_REG_ACTIONS]; + // indices into reg (initialized to -1) + int num_regs_before_bits; + int idcode_reg; + int FLR_reg; + + int bits_len; + uint8_t* bits; + int bram_off; + int IOB_off; +}; + +int read_bitfile(struct fpga_config* cfg, FILE* f); +int extract_model(struct fpga_config* cfg, struct fpga_model* model); + +#define DUMP_HEADER_STR 0x0001 +#define DUMP_REGS 0x0002 +#define DUMP_BITS 0x0004 +int dump_config(struct fpga_config* cfg, int flags); + +void free_config(struct fpga_config* cfg); -int read_bits(struct fpga_model* model, FILE* f); int write_bits(FILE* f, struct fpga_model* model); diff --git a/control.c b/control.c index 33fdacf..1ebde85 100644 --- a/control.c +++ b/control.c @@ -269,14 +269,14 @@ int fpga_conn_dest(struct fpga_model* model, int y, int x, int i, rc, connpt_i, num_dests, conn_point_dests_o; rc = strarray_find(&model->str, name, &connpt_i); - if (rc) FAIL(); + if (rc) FAIL(rc); tile = YX_TILE(model, y, x); for (i = 0; i < tile->num_conn_point_names; i++) { if (tile->conn_point_names[i*2+1] == connpt_i) break; } - if (i >= tile->num_conn_point_names) - FAIL(); + if (i >= tile->num_conn_point_names) + FAIL(EINVAL); conn_point_dests_o = tile->conn_point_names[i*2]; if (i < tile->num_conn_point_names-1) @@ -330,7 +330,7 @@ int fpga_switch_dest(struct fpga_model* model, int y, int x, int rc, i, connpt_o, from_name_i, dest_idx_counter; rc = strarray_find(&model->str, name, &from_name_i); - if (rc) FAIL(); + if (rc) FAIL(rc); // counts how many switches from the same source (name) // we have already encountered - to find the dest_idx'th @@ -347,7 +347,7 @@ int fpga_switch_dest(struct fpga_model* model, int y, int x, } if (i >= tile->num_switches) return NO_SWITCH; - if (dest_idx_counter > dest_idx) FAIL(); + if (dest_idx_counter > dest_idx) FAIL(EINVAL); return i; fail: return NO_SWITCH; diff --git a/helper.c b/helper.c index c01af5f..0779511 100644 --- a/helper.c +++ b/helper.c @@ -7,21 +7,6 @@ #include "helper.h" -void printf_help(void) -{ - printf("\n" - "bit2txt %s - convert FPGA bitstream to text\n" - "Public domain work by Wolfgang Spraul\n" - "\n" - "bit2txt [options] \n" - " --help print help message\n" - " --version print version number\n" - " --info add extra info to output (marked #I)\n" - " bitstream to print on stdout\n" - " (proposing extension .b2t)\n" - "\n", PROGRAM_REVISION); -} - const char* bitstr(uint32_t value, int digits) { static char str[2 /* "0b" */ + 32 + 1 /* '\0' */]; @@ -103,52 +88,6 @@ void atom_remove(char* bits, const cfg_atom_t* atom) } } -int printf_header(uint8_t* d, int len, int inpos, int* outdelta, int dry_run) -{ - int i, str_len; - - *outdelta = 0; - if (inpos + 13 > len) { - fprintf(stderr, "#E File size %i below minimum of 13 bytes.\n", - len); - return -1; - } - if (!dry_run) { - printf("hex"); - for (i = 0; i < 13; i++) - printf(" %.02x", d[inpos+*outdelta+i]); - printf("\n"); - } - *outdelta += 13; - - // 4 strings 'a' - 'd', 16-bit length - for (i = 'a'; i <= 'd'; i++) { - if (inpos + *outdelta + 3 > len) { - fprintf(stderr, "#E Unexpected EOF at %i.\n", len); - return -1; - } - if (d[inpos + *outdelta] != i) { - fprintf(stderr, "#E Expected string code '%c', got " - "'%c'.\n", i, d[inpos + *outdelta]); - return -1; - } - str_len = __be16_to_cpu(*(uint16_t*)&d[inpos + *outdelta + 1]); - if (inpos + *outdelta + 3 + str_len > len) { - fprintf(stderr, "#E Unexpected EOF at %i.\n", len); - return -1; - } - if (d[inpos + *outdelta + 3 + str_len - 1]) { - fprintf(stderr, "#E z-terminated string ends with %0xh" - ".\n", d[inpos + *outdelta + 3 + str_len - 1]); - return -1; - } - if (!dry_run) - printf("header_str_%c %s\n", i, &d[inpos + *outdelta + 3]); - *outdelta += 3 + str_len; - } - return 0; -} - // for an equivalent schematic, see lut.svg const int lut_base_vars[6] = {0 /* A1 */, 1, 0 /* A3 - not used */, 0, 0, 1 /* A6 */}; diff --git a/helper.h b/helper.h index f3e759d..3a46686 100644 --- a/helper.h +++ b/helper.h @@ -22,11 +22,9 @@ "Internal error in %s:%i\n", __FILE__, __LINE__); exit(1); } #define HERE() fprintf(stderr, "%s:%i\n", __FILE__, __LINE__) -#define FAIL() do { HERE(); goto fail; } while (0) +#define FAIL(code) do { HERE(); rc = (code); goto fail; } while (0) #define XOUT() do { HERE(); goto xout; } while (0) -void printf_help(void); - const char* bitstr(uint32_t value, int digits); void hexdump(int indent, const uint8_t* data, int len); @@ -56,8 +54,6 @@ typedef struct _cfg_atom int atom_found(char* bits, const cfg_atom_t* atom); void atom_remove(char* bits, const cfg_atom_t* atom); -int printf_header(uint8_t* d, int len, int inpos, int* outdelta, int dry_run); - void printf_lut6(const char* cfg); // bits is tested only for 32 and 64 const char* lut2bool(const uint64_t lut, int bits, diff --git a/model.h b/model.h index 75cc817..c745979 100644 --- a/model.h +++ b/model.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "helper.h" diff --git a/model_devices.c b/model_devices.c index 70325cf..85b7f6a 100644 --- a/model_devices.c +++ b/model_devices.c @@ -52,45 +52,43 @@ static int init_iob(struct fpga_model* model, int y, int x, prefix = "LIOB"; else if (x == model->x_width - RIGHT_OUTER_O) prefix = "RIOB"; - else { - rc = -1; - FAIL(); - } + else + FAIL(EINVAL); snprintf(tile->devs[idx].iob.pinw_in_O, sizeof(tile->devs[idx].iob.pinw_in_O), "%s_O%i_PINW", prefix, type_idx); rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_O); - if (rc) FAIL(); + if (rc) FAIL(rc); snprintf(tile->devs[idx].iob.pinw_in_T, sizeof(tile->devs[idx].iob.pinw_in_T), "%s_T%i_PINW", prefix, type_idx); rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_T); - if (rc) FAIL(); + if (rc) FAIL(rc); snprintf(tile->devs[idx].iob.pinw_out_I, sizeof(tile->devs[idx].iob.pinw_out_I), "%s_IBUF%i_PINW", prefix, type_idx); rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_I); - if (rc) FAIL(); + if (rc) FAIL(rc); snprintf(tile->devs[idx].iob.pinw_out_PADOUT, sizeof(tile->devs[idx].iob.pinw_out_PADOUT), "%s_PADOUT%i", prefix, type_idx); rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_PADOUT); - if (rc) FAIL(); + if (rc) FAIL(rc); snprintf(tile->devs[idx].iob.pinw_in_DIFFI_IN, sizeof(tile->devs[idx].iob.pinw_in_DIFFI_IN), "%s_DIFFI_IN%i", prefix, type_idx); rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_DIFFI_IN); - if (rc) FAIL(); + if (rc) FAIL(rc); snprintf(tile->devs[idx].iob.pinw_in_DIFFO_IN, sizeof(tile->devs[idx].iob.pinw_in_DIFFO_IN), "%s_DIFFO_IN%i", prefix, type_idx); rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_DIFFO_IN); - if (rc) FAIL(); + if (rc) FAIL(rc); snprintf(tile->devs[idx].iob.pinw_out_DIFFO_OUT, sizeof(tile->devs[idx].iob.pinw_out_DIFFO_OUT), "%s_DIFFO_OUT%i", prefix, type_idx); rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_DIFFO_OUT); - if (rc) FAIL(); + if (rc) FAIL(rc); if (!x && y == model->center_y - CENTER_TOP_IOB_O && type_idx == 1) strcpy(tile->devs[idx].iob.pinw_out_PCI_RDY, "LIOB_TOP_PCI_RDY0"); @@ -106,7 +104,7 @@ static int init_iob(struct fpga_model* model, int y, int x, "%s_PCI_RDY%i", prefix, type_idx); } rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_PCI_RDY); - if (rc) FAIL(); + if (rc) FAIL(rc); return 0; fail: return rc; @@ -137,7 +135,7 @@ static int add_dev(struct fpga_model* model, tile->devs[new_dev_i].type = type; if (type == DEV_IOB) { rc = init_iob(model, y, x, new_dev_i, subtype); - if (rc) FAIL(); + if (rc) FAIL(rc); } else if (type == DEV_LOGIC) tile->devs[new_dev_i].logic.subtype = subtype; return 0;