From b25f9daa4ae9b223741b35a119aecdba965ba1eb Mon Sep 17 00:00:00 2001 From: Wolfgang Spraul Date: Sun, 14 Oct 2012 05:24:21 +0200 Subject: [PATCH] more work in iologic switches, minor fixes --- README | 12 +- libs/bit_frames.c | 329 ++++++++++++++++++++++++++++++++------------ libs/bit_regs.c | 203 +++++++++++++-------------- libs/helper.c | 53 +++++-- libs/helper.h | 4 +- libs/model_helper.c | 4 +- libs/parts.c | 278 +++++++++++++++++++++++++++++++++++++ libs/parts.h | 46 +++++++ 8 files changed, 709 insertions(+), 220 deletions(-) diff --git a/README b/README index b85ead3..65003fa 100644 --- a/README +++ b/README @@ -1,11 +1,10 @@ Introduction fpgatools is a toolchain to program field-programmable gate arrays - (FPGAs). The only supported chip at this time is the xc6slx9, a cheap - (ca. 7 USD) but powerful 45nm-generation chip with 5720 6-input LUTs, - block ram and multiply-accumulate devices. - The long-term goals of fpgatools are: + (FPGAs). The only supported chip at this time is the xc6slx9, a + 7 USD 45nm-generation fpga with 5720 6-input LUTs, block ram and + multiply-accumulate devices. - *) reach maximum physical chip performance + *) maximize chip performance *) fast development cycles *) independent toolchain that only depends on other free software *) reconfigure on-chip @@ -31,6 +30,7 @@ Libraries Design Utilities - hello_world outputs an AND gate floorplan to stdout +- blinking_led outputs blinking led design to stdout - new_fp creates empty .fp floorplan file - fp2bit converts .fp floorplan into .bit bitstream - bit2fp converts .bit bitstream into .fp floorplan @@ -38,7 +38,7 @@ Design Utilities fpgatools Development Utilities -- autotest executes test suite +- autotest test suite - sort_seq sorts line-based text file by sequence numbers in strings - merge_seq merges a pre-sorted text file into wire sequences - pair2net reads the first two words per line and builds nets diff --git a/libs/bit_frames.c b/libs/bit_frames.c index a8f6284..9546d2e 100644 --- a/libs/bit_frames.c +++ b/libs/bit_frames.c @@ -95,7 +95,7 @@ struct extract_state static int find_es_switch(struct extract_state* es, int y, int x, swidx_t sw) { int i; - if (sw == NO_CONN) { HERE(); return 0; } + if (sw == NO_SWITCH) { HERE(); return 0; } for (i = 0; i < es->num_yx_pos; i++) { if (es->yx_pos[i].y == y && es->yx_pos[i].x == x @@ -1311,10 +1311,28 @@ static int extract_logic(struct extract_state* es) // todo: ff5_srinit // todo: 5Q ff also needs clock/sync check } - // todo: - // if (lut_a->out_mux == xor || lut_a->ff_mux == xor - // || lut_a->acy0 != 0) && !precyinit && !cin_switch - // -> precyinit = precyinit_0 + + // Check whether we should default to PRECYINIT_0 + if (!cfg_ml.precyinit + && (cfg_ml.a2d[LUT_A].out_mux == MUX_XOR + || cfg_ml.a2d[LUT_A].ff_mux == MUX_XOR + || cfg_ml.a2d[LUT_A].cy0)) { + int connpt_dests_o, num_dests, cout_y, cout_x; + str16_t cout_str; + + if ((fpga_connpt_find(es->model, y, x, + dev_ml->pinw[LI_CIN], &connpt_dests_o, + &num_dests) == NO_CONN) + || num_dests != 1) { + HERE(); + } else { + fpga_conn_dest(es->model, y, x, connpt_dests_o, + &cout_y, &cout_x, &cout_str); + if (find_es_switch(es, cout_y, cout_x,fpga_switch_first( + es->model, cout_y, cout_x, cout_str, SW_TO))) + cfg_ml.precyinit = PRECYINIT_0; + } + } // // Step 8: @@ -1559,6 +1577,216 @@ fail: return rc; } +#define MAX_IOLOGIC_SWBLOCK 4 +#define MAX_IOLOGIC_BITS 4 +struct iologic_sw_pos +{ + const char* to[MAX_IOLOGIC_SWBLOCK]; + const char* from[MAX_IOLOGIC_SWBLOCK]; + int minor[MAX_IOLOGIC_BITS]; + int b64[MAX_IOLOGIC_BITS]; +}; + +// todo: can we assume the maximum range for iologic +// minors to be 21..29? that would be a total of +// 9*64=675 bits for ilogic/ologic/iodelay? +struct iologic_sw_pos s_left_io_swpos[] = { {{0}} }; +struct iologic_sw_pos s_right_io_swpos[] = { {{0}} }; +struct iologic_sw_pos s_top_outer_io_swpos[] = { {{0}} }; +struct iologic_sw_pos s_top_inner_io_swpos[] = { {{0}} }; + +struct iologic_sw_pos s_bot_inner_io_swpos[] = +{ + // input + {{"D_ILOGIC_IDATAIN_IODELAY_S"}, + {"BIOI_INNER_IBUF0"}, + {23, 23, -1}, + {28, 29}}, + + {{"D_ILOGIC_SITE"}, + {"D_ILOGIC_IDATAIN_IODELAY"}, + {26, -1}, + {20}}, + + {{"D_ILOGIC_SITE_S"}, + {"D_ILOGIC_IDATAIN_IODELAY_S"}, + {26, -1}, + {23}}, + + {{"DFB_ILOGIC_SITE"}, + {"D_ILOGIC_SITE"}, + {28, -1}, + {63}}, + + {{"DFB_ILOGIC_SITE_S"}, + {"D_ILOGIC_SITE_S"}, + {28, -1}, + {0}}, + + {{"FABRICOUT_ILOGIC_SITE"}, + {"D_ILOGIC_SITE"}, + {29, -1}, + {49}}, + + {{"FABRICOUT_ILOGIC_SITE_S"}, + {"D_ILOGIC_SITE_S"}, + {29, -1}, + {14}}, + + // output + {{"OQ_OLOGIC_SITE", "BIOI_INNER_O0"}, + {"D1_OLOGIC_SITE", "OQ_OLOGIC_SITE"}, + {26, 27, 28, -1}, + {40, 21, 57}}, + + {{"OQ_OLOGIC_SITE_S", "BIOI_INNER_O1"}, + {"D1_OLOGIC_SITE_S", "OQ_OLOGIC_SITE_S"}, + {26, 27, 28, -1}, + {43, 56, 6}}, + + {{"IOI_LOGICOUT0"}, {"IOI_INTER_LOGICOUT0"}, {-1}}, + {{"IOI_LOGICOUT7"}, {"IOI_INTER_LOGICOUT7"}, {-1}}, + {{"IOI_INTER_LOGICOUT0"}, {"FABRICOUT_ILOGIC_SITE"}, {-1}}, + {{"IOI_INTER_LOGICOUT7"}, {"FABRICOUT_ILOGIC_SITE_S"}, {-1}}, + {{"D_ILOGIC_IDATAIN_IODELAY"}, {"BIOI_INNER_IBUF0"}, {-1}}, + {{"D_ILOGIC_IDATAIN_IODELAY_S"}, {"BIOI_INNER_IBUF1"}, {-1}}, + {{"D1_OLOGIC_SITE"}, {"IOI_LOGICINB31"}, {-1}}, + {{0}} +}; + +struct iologic_sw_pos s_bot_outer_io_swpos[] = +{ + // input + {{"D_ILOGIC_IDATAIN_IODELAY_S"}, + {"BIOI_OUTER_IBUF0"}, + {23, 23, -1}, + {28, 29}}, + + {{"D_ILOGIC_SITE"}, + {"D_ILOGIC_IDATAIN_IODELAY"}, + {26, -1}, + {20}}, + + {{"D_ILOGIC_SITE_S"}, + {"D_ILOGIC_IDATAIN_IODELAY_S"}, + {26, -1}, + {23}}, + + {{"DFB_ILOGIC_SITE"}, + {"D_ILOGIC_SITE"}, + {28, -1}, + {63}}, + + {{"DFB_ILOGIC_SITE_S"}, + {"D_ILOGIC_SITE_S"}, + {28, -1}, + {0}}, + + {{"FABRICOUT_ILOGIC_SITE"}, + {"D_ILOGIC_SITE"}, + {29, -1}, + {49}}, + + {{"FABRICOUT_ILOGIC_SITE_S"}, + {"D_ILOGIC_SITE_S"}, + {29, -1}, + {14}}, + + // output + {{"OQ_OLOGIC_SITE", "BIOI_OUTER_O0"}, + {"D1_OLOGIC_SITE", "OQ_OLOGIC_SITE"}, + {26, 27, 28, -1}, + {40, 21, 57}}, + + {{"OQ_OLOGIC_SITE_S", "BIOI_OUTER_O1"}, + {"D1_OLOGIC_SITE_S", "OQ_OLOGIC_SITE_S"}, + {26, 27, 28, -1}, + {43, 56, 6}}, + + {{"IOI_LOGICOUT0"}, {"IOI_INTER_LOGICOUT0"}, {-1}}, + {{"IOI_LOGICOUT7"}, {"IOI_INTER_LOGICOUT7"}, {-1}}, + {{"IOI_INTER_LOGICOUT0"}, {"FABRICOUT_ILOGIC_SITE"}, {-1}}, + {{"IOI_INTER_LOGICOUT7"}, {"FABRICOUT_ILOGIC_SITE_S"}, {-1}}, + {{"D_ILOGIC_IDATAIN_IODELAY"}, {"BIOI_INNER_IBUF0"}, {-1}}, + {{"D_ILOGIC_IDATAIN_IODELAY_S"}, {"BIOI_INNER_IBUF1"}, {-1}}, + {{"D1_OLOGIC_SITE"}, {"IOI_LOGICINB31"}, {-1}}, + {{0}} +}; + +static int extract_iologic_switches(struct extract_state* es, int y, int x) +{ + int row_num, row_pos, bit_in_frame, i, j, rc; + uint8_t* minor0_p; + struct iologic_sw_pos* sw_pos; + str16_t from_str_i, to_str_i; + swidx_t sw_idx; + + // From y/x coordinate, determine major, row, bit offset + // in frame (v64_i) and pointer to first minor. + is_in_row(es->model, y, &row_num, &row_pos); + if (row_num == -1 || row_pos == -1 + || row_pos == HCLK_POS) FAIL(EINVAL); + if (row_pos > HCLK_POS) + bit_in_frame = (row_pos-1)*64 + XC6_HCLK_BITS; + else + bit_in_frame = row_pos*64; + minor0_p = get_first_minor(es->bits, row_num, es->model->x_major[x]); + + if (x < LEFT_SIDE_WIDTH) { + if (x != LEFT_IO_DEVS) FAIL(EINVAL); + sw_pos = s_left_io_swpos; + } else if (x >= es->model->x_width-RIGHT_SIDE_WIDTH) { + if (x != es->model->x_width - RIGHT_IO_DEVS_O) FAIL(EINVAL); + sw_pos = s_right_io_swpos; + } else if (y == TOP_OUTER_IO) + sw_pos = s_top_outer_io_swpos; + else if (y == TOP_INNER_IO) + sw_pos = s_top_inner_io_swpos; + else if (y == es->model->y_height-BOT_INNER_IO) + sw_pos = s_bot_inner_io_swpos; + else if (y == es->model->y_height-BOT_OUTER_IO) + sw_pos = s_bot_outer_io_swpos; + else FAIL(EINVAL); + + // Go through switches + for (i = 0; sw_pos[i].to[0]; i++) { + for (j = 0; sw_pos[i].minor[j] != -1; j++) { + if (!frame_get_bit(&minor0_p[sw_pos[i].minor[j] + *FRAME_SIZE], bit_in_frame+sw_pos[i].b64[j])) + break; + } + if (!j || sw_pos[i].minor[j] != -1) + continue; + for (j = 0; j < MAX_IOLOGIC_SWBLOCK && sw_pos[i].to[j]; j++) { + from_str_i = strarray_find(&es->model->str, sw_pos[i].from[j]); + to_str_i = strarray_find(&es->model->str, sw_pos[i].to[j]); + if (from_str_i == STRIDX_NO_ENTRY + || to_str_i == STRIDX_NO_ENTRY) + FAIL(EINVAL); + sw_idx = fpga_switch_lookup(es->model, y, x, + from_str_i, to_str_i); + if (sw_idx == NO_SWITCH) FAIL(EINVAL); + + if (es->num_yx_pos >= MAX_YX_SWITCHES) + { FAIL(ENOTSUP); } + es->yx_pos[es->num_yx_pos].y = y; + es->yx_pos[es->num_yx_pos].x = x; + es->yx_pos[es->num_yx_pos].idx = sw_idx; + es->num_yx_pos++; + } + for (j = 0; sw_pos[i].minor[j] != -1; j++) + frame_clear_bit(&minor0_p[sw_pos[i].minor[j] + *FRAME_SIZE], bit_in_frame+sw_pos[i].b64[j]); + } + // todo: we could implement an all-or-nothing system where + // the device bits are first copied into an u64 array, + // and switches rewound by resetting num_yx_pos - unless + // all bits have been processed... + return 0; +fail: + return rc; +} + static int extract_switches(struct extract_state* es) { int x, y, rc; @@ -1579,6 +1807,11 @@ static int extract_switches(struct extract_state* es) rc = extract_logic_switches(es, y, x); if (rc) FAIL(rc); } + // iologic switches + if (has_device(es->model, y, x, DEV_ILOGIC)) { + rc = extract_iologic_switches(es, y, x); + if (rc) FAIL(rc); + } } } return 0; @@ -1714,92 +1947,6 @@ fail: return rc; } -#define MAX_IOLOGIC_SWBLOCK 4 -#define MAX_IOLOGIC_BITS 4 -struct iologic_sw_pos -{ - const char* to[MAX_IOLOGIC_SWBLOCK]; - const char* from[MAX_IOLOGIC_SWBLOCK]; - int minor[MAX_IOLOGIC_BITS]; - int b64[MAX_IOLOGIC_BITS]; -}; - -struct iologic_sw_pos s_left_io_swpos[] = { {{0}} }; -struct iologic_sw_pos s_right_io_swpos[] = { {{0}} }; -struct iologic_sw_pos s_top_outer_io_swpos[] = { {{0}} }; -struct iologic_sw_pos s_top_inner_io_swpos[] = { {{0}} }; - -struct iologic_sw_pos s_bot_inner_io_swpos[] = -{ - // input - {{"D_ILOGIC_IDATAIN_IODELAY_S"}, {"BIOI_INNER_IBUF0"}, - {23, 23, -1}, - {28, 29}}, - {{"D_ILOGIC_SITE"}, {"D_ILOGIC_IDATAIN_IODELAY"}, {26, -1}, {20}}, - {{"D_ILOGIC_SITE_S"}, {"D_ILOGIC_IDATAIN_IODELAY_S"}, {26, -1}, {23}}, - {{"DFB_ILOGIC_SITE"}, {"D_ILOGIC_SITE"}, {28, -1}, {63}}, - {{"DFB_ILOGIC_SITE_S"}, {"D_ILOGIC_SITE_S"}, {28, -1}, {0}}, - {{"FABRICOUT_ILOGIC_SITE"}, {"D_ILOGIC_SITE"}, {29, -1}, {49}}, - {{"FABRICOUT_ILOGIC_SITE_S"}, {"D_ILOGIC_SITE_S"}, {29, -1}, {14}}, - - // output - {{"OQ_OLOGIC_SITE", "BIOI_INNER_O0"}, - {"D1_OLOGIC_SITE", "OQ_OLOGIC_SITE"}, - {26, 27, 28, -1}, - {40, 21, 57}}, - {{"OQ_OLOGIC_SITE_S", "BIOI_INNER_O1"}, - {"D1_OLOGIC_SITE_S", "OQ_OLOGIC_SITE_S"}, - {26, 27, 28, -1}, - {43, 56, 6}}, - - {{"IOI_LOGICOUT0"}, {"IOI_INTER_LOGICOUT0"}, {-1}}, - {{"IOI_LOGICOUT7"}, {"IOI_INTER_LOGICOUT7"}, {-1}}, - {{"IOI_INTER_LOGICOUT0"}, {"FABRICOUT_ILOGIC_SITE"}, {-1}}, - {{"IOI_INTER_LOGICOUT7"}, {"FABRICOUT_ILOGIC_SITE_S"}, {-1}}, - {{"D_ILOGIC_IDATAIN_IODELAY"}, {"BIOI_INNER_IBUF0"}, {-1}}, - {{"D_ILOGIC_IDATAIN_IODELAY_S"}, {"BIOI_INNER_IBUF1"}, {-1}}, - {{"D1_OLOGIC_SITE"}, {"IOI_LOGICINB31"}, {-1}}, - {{0}} -}; - -struct iologic_sw_pos s_bot_outer_io_swpos[] = -{ - // input - {{"D_ILOGIC_IDATAIN_IODELAY_S"}, {"BIOI_OUTER_IBUF0"}, - {23, 23, -1}, - {28, 29}}, - {{"D_ILOGIC_SITE"}, {"D_ILOGIC_IDATAIN_IODELAY"}, {26, -1}, {20}}, - {{"D_ILOGIC_SITE_S"}, {"D_ILOGIC_IDATAIN_IODELAY_S"}, {26, -1}, {23}}, - {{"DFB_ILOGIC_SITE"}, {"D_ILOGIC_SITE"}, {28, -1}, {63}}, - {{"DFB_ILOGIC_SITE_S"}, {"D_ILOGIC_SITE_S"}, {28, -1}, {0}}, - {{"FABRICOUT_ILOGIC_SITE"}, {"D_ILOGIC_SITE"}, {29, -1}, {49}}, - {{"FABRICOUT_ILOGIC_SITE_S"}, {"D_ILOGIC_SITE_S"}, {29, -1}, {14}}, - - // output - {{"OQ_OLOGIC_SITE", "BIOI_OUTER_O0"}, - {"D1_OLOGIC_SITE", "OQ_OLOGIC_SITE"}, - {26, 27, 28, -1}, - {40, 21, 57}}, - {{"OQ_OLOGIC_SITE_S", "BIOI_OUTER_O1"}, - {"D1_OLOGIC_SITE_S", "OQ_OLOGIC_SITE_S"}, - {26, 27, 28, -1}, - {43, 56, 6}}, - - {{"OQ_OLOGIC_SITE", "BIOI_OUTER_O0"}, - {"D1_OLOGIC_SITE", "OQ_OLOGIC_SITE"}, - {26, 27, 28, -1}, - {40, 21, 57}}, - - {{"IOI_LOGICOUT0"}, {"IOI_INTER_LOGICOUT0"}, {-1}}, - {{"IOI_LOGICOUT7"}, {"IOI_INTER_LOGICOUT7"}, {-1}}, - {{"IOI_INTER_LOGICOUT0"}, {"FABRICOUT_ILOGIC_SITE"}, {-1}}, - {{"IOI_INTER_LOGICOUT7"}, {"FABRICOUT_ILOGIC_SITE_S"}, {-1}}, - {{"D_ILOGIC_IDATAIN_IODELAY"}, {"BIOI_INNER_IBUF0"}, {-1}}, - {{"D_ILOGIC_IDATAIN_IODELAY_S"}, {"BIOI_INNER_IBUF1"}, {-1}}, - {{"D1_OLOGIC_SITE"}, {"IOI_LOGICINB31"}, {-1}}, - {{0}} -}; - struct str_sw { const char* from_str; diff --git a/libs/bit_regs.c b/libs/bit_regs.c index e291e02..b859735 100644 --- a/libs/bit_regs.c +++ b/libs/bit_regs.c @@ -762,6 +762,8 @@ static void printf_v64_mi20(const uint8_t* bits, int row, int major) if (u64 & (1ULL << i)) num_bits_on++; } + // this is most helpful for bits 24:39 which are + // part of logic device configuration if (num_bits_on < 5) { for (i = 0; i < 64; i++) { if (!(u64 & (1ULL << i))) @@ -841,13 +843,12 @@ static int dump_maj_right(const uint8_t* bits, int row, int major) return 0; } -static int dump_maj_center(const uint8_t* bits, int row, int major) +static int dump_maj_logic(const uint8_t* bits, int row, int major) { - int minor, i; + const struct xc_info* xci = xc_info(XC6SLX9); + int minor, i, logdev_start, logdev_end; - if (get_major_minors(XC6SLX9, major) != 31) HERE(); - - for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++) + for (minor = 0; minor < xci->majors[major].minors; minor++) printf_clock(&bits[minor*FRAME_SIZE], row, major, minor); // 0:19 routing minor pairs @@ -857,102 +858,89 @@ static int dump_maj_center(const uint8_t* bits, int row, int major) // mi20 as 64-char 0/1 string printf_v64_mi20(&bits[20*FRAME_SIZE], row, major); - // L devices - for (i = 0; i < 16; i++) { - printf_lut(bits, row, major, 21, i*2); - printf_lut(bits, row, major, 23, i*2); - printf_lut(bits, row, major, 21, i*2+1); - printf_lut(bits, row, major, 23, i*2+1); - } - printf_frames(&bits[25*FRAME_SIZE], /*max_frames*/ 1, - row, major, 25, /*print_empty*/ 0, /*no_clock*/ 1); - // X devices - for (i = 0; i < 16; i++) { - printf_lut(bits, row, major, 26, i*2); - printf_lut(bits, row, major, 28, i*2); - printf_lut(bits, row, major, 26, i*2+1); - printf_lut(bits, row, major, 28, i*2+1); - } - printf_frames(&bits[30*FRAME_SIZE], /*max_frames*/ 1, - row, major, 30, /*print_empty*/ 0, /*no_clock*/ 1); - return 0; -} - -static int dump_maj_logic_xm(const uint8_t* bits, int row, int major) -{ - int minor, i; - - if (get_major_minors(XC6SLX9, major) != 31) HERE(); - - for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++) - printf_clock(&bits[minor*FRAME_SIZE], row, major, minor); - - // 0:19 routing minor pairs - for (i = 0; i < 10; i++) - printf_routing_2minors(&bits[i*2*FRAME_SIZE], row, major, i*2); - - // mi20 as 64-char 0/1 string - printf_v64_mi20(&bits[20*FRAME_SIZE], row, major); - - // todo: some logic device configuration bits are also in mi20 - // todo: the top and bottom two luts should be skipped in !no_io cols - - // M devices - for (i = 0; i < 16; i++) { - printf_lut(bits, row, major, 21, i*2); - printf_lut(bits, row, major, 21, i*2+1); - } - printf_frames(&bits[23*FRAME_SIZE], /*max_frames*/ 1, - row, major, 23, /*print_empty*/ 0, /*no_clock*/ 1); - for (i = 0; i < 16; i++) { - printf_lut(bits, row, major, 24, i*2); - printf_lut(bits, row, major, 24, i*2+1); + logdev_start = 0; + logdev_end = 15; + if (xci->majors[major].flags & XC_MAJ_TOP_BOT_IO) { + if (row == xc_info(XC6SLX9)->num_rows-1) + logdev_start += TOPBOT_IO_ROWS; + else if (!row) + logdev_end -= TOPBOT_IO_ROWS; } - // X devices - printf_frames(&bits[26*FRAME_SIZE], /*max_frames*/ 1, - row, major, 26, /*print_empty*/ 0, /*no_clock*/ 1); - for (i = 0; i < 16; i++) { - printf_lut(bits, row, major, 27, i*2); - printf_lut(bits, row, major, 29, i*2); - printf_lut(bits, row, major, 27, i*2+1); - printf_lut(bits, row, major, 29, i*2+1); - } - return 0; -} + if (xci->majors[major].flags & XC_MAJ_XM) { + if (xci->majors[major].minors != 31) HERE(); -static int dump_maj_logic_xl(const uint8_t* bits, int row, int major) -{ - int minor, i; + // M devices + if (logdev_start) + printf_extrabits(bits, 21, 2, 0, logdev_start*64, row, major); + for (i = logdev_start; i <= logdev_end; i++) { + printf_lut(bits, row, major, 21, i*2); + printf_lut(bits, row, major, 21, i*2+1); + } + if (logdev_end < 15) + printf_extrabits(bits, 21, 2, i*64 + XC6_HCLK_BITS, (15-logdev_end)*64, row, major); + printf_frames(&bits[23*FRAME_SIZE], /*max_frames*/ 1, + row, major, 23, /*print_empty*/ 0, /*no_clock*/ 1); + if (logdev_start) + printf_extrabits(bits, 24, 2, 0, logdev_start*64, row, major); + for (i = logdev_start; i <= logdev_end; i++) { + printf_lut(bits, row, major, 24, i*2); + printf_lut(bits, row, major, 24, i*2+1); + } + if (logdev_end < 15) + printf_extrabits(bits, 24, 2, i*64 + XC6_HCLK_BITS, (15-logdev_end)*64, row, major); - if (get_major_minors(XC6SLX9, major) != 30) HERE(); + // X devices + printf_frames(&bits[26*FRAME_SIZE], /*max_frames*/ 1, + row, major, 26, /*print_empty*/ 0, /*no_clock*/ 1); + if (logdev_start) + printf_extrabits(bits, 27, 4, 0, logdev_start*64, row, major); + for (i = logdev_start; i <= logdev_end; i++) { + printf_lut(bits, row, major, 27, i*2); + printf_lut(bits, row, major, 29, i*2); + printf_lut(bits, row, major, 27, i*2+1); + printf_lut(bits, row, major, 29, i*2+1); + } + if (logdev_end < 15) + printf_extrabits(bits, 27, 4, i*64 + XC6_HCLK_BITS, (15-logdev_end)*64, row, major); + } else if (xci->majors[major].flags & (XC_MAJ_XL|XC_MAJ_CENTER)) { - for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++) - printf_clock(&bits[minor*FRAME_SIZE], row, major, minor); + // L devices + if (logdev_start) + printf_extrabits(bits, 21, 4, 0, logdev_start*64, row, major); + for (i = logdev_start; i <= logdev_end; i++) { + printf_lut(bits, row, major, 21, i*2); + printf_lut(bits, row, major, 23, i*2); + printf_lut(bits, row, major, 21, i*2+1); + printf_lut(bits, row, major, 23, i*2+1); + } + if (logdev_end < 15) + printf_extrabits(bits, 21, 4, i*64 + XC6_HCLK_BITS, (15-logdev_end)*64, row, major); + printf_frames(&bits[25*FRAME_SIZE], /*max_frames*/ 1, + row, major, 25, /*print_empty*/ 0, /*no_clock*/ 1); + // X devices + if (logdev_start) + printf_extrabits(bits, 26, 4, 0, logdev_start*64, row, major); + for (i = logdev_start; i <= logdev_end; i++) { + printf_lut(bits, row, major, 26, i*2); + printf_lut(bits, row, major, 28, i*2); + printf_lut(bits, row, major, 26, i*2+1); + printf_lut(bits, row, major, 28, i*2+1); + } + if (logdev_end < 15) + printf_extrabits(bits, 26, 4, i*64 + XC6_HCLK_BITS, (15-logdev_end)*64, row, major); - // 0:19 routing minor pairs - for (i = 0; i < 10; i++) - printf_routing_2minors(&bits[i*2*FRAME_SIZE], row, major, i*2); + // one extra minor in the center major + if (xci->majors[major].flags & XC_MAJ_CENTER) { + if (xci->majors[major].minors != 31) HERE(); + printf_frames(&bits[30*FRAME_SIZE], /*max_frames*/ 1, + row, major, 30, /*print_empty*/ 0, /*no_clock*/ 1); + } else { // XL + if (xci->majors[major].minors != 30) HERE(); + } + } else + HERE(); - // mi20 as 64-char 0/1 string - printf_v64_mi20(&bits[20*FRAME_SIZE], row, major); - - // L devices - for (i = 0; i < 16; i++) { - printf_lut(bits, row, major, 21, i*2); - printf_lut(bits, row, major, 23, i*2); - printf_lut(bits, row, major, 21, i*2+1); - printf_lut(bits, row, major, 23, i*2+1); - } - printf_frames(&bits[25*FRAME_SIZE], /*max_frames*/ 1, - row, major, 25, /*print_empty*/ 0, /*no_clock*/ 1); - // X devices - for (i = 0; i < 16; i++) { - printf_lut(bits, row, major, 26, i*2); - printf_lut(bits, row, major, 28, i*2); - printf_lut(bits, row, major, 26, i*2+1); - printf_lut(bits, row, major, 28, i*2+1); - } return 0; } @@ -1022,13 +1010,18 @@ static int dump_maj_macc(const uint8_t* bits, int row, int major) static int dump_bits(struct fpga_config* cfg) { - int row, major, off, rc; + int idcode, num_rows, row, major, off, rc; + + if (cfg->idcode_reg == -1) FAIL(EINVAL); + idcode = cfg->reg[cfg->idcode_reg].int_v; + num_rows = xc_num_rows(idcode); + if (num_rows < 1) FAIL(EINVAL); // type0 - for (major = 0; major <= get_rightside_major(XC6SLX9); major++) { - for (row = 3; row >= 0; row--) { - off = (row*get_frames_per_row(XC6SLX9) + get_major_framestart(XC6SLX9, major)) * FRAME_SIZE; - switch (get_major_type(cfg->reg[cfg->idcode_reg].int_v, major)) { + for (major = 0; major <= get_rightside_major(idcode); major++) { + for (row = num_rows-1; row >= 0; row--) { + off = (row*get_frames_per_row(idcode) + get_major_framestart(idcode, major)) * FRAME_SIZE; + switch (get_major_type(idcode, major)) { case MAJ_ZERO: rc = dump_maj_zero(&cfg->bits.d[off], row, major); if (rc) FAIL(rc); @@ -1041,16 +1034,10 @@ static int dump_bits(struct fpga_config* cfg) rc = dump_maj_right(&cfg->bits.d[off], row, major); if (rc) FAIL(rc); break; - case MAJ_CENTER: - rc = dump_maj_center(&cfg->bits.d[off], row, major); - if (rc) FAIL(rc); - break; case MAJ_LOGIC_XM: - rc = dump_maj_logic_xm(&cfg->bits.d[off], row, major); - if (rc) FAIL(rc); - break; case MAJ_LOGIC_XL: - rc = dump_maj_logic_xl(&cfg->bits.d[off], row, major); + case MAJ_CENTER: + rc = dump_maj_logic(&cfg->bits.d[off], row, major); if (rc) FAIL(rc); break; case MAJ_BRAM: @@ -1113,7 +1100,7 @@ int dump_config(struct fpga_config* cfg, int flags) if (rc) FAIL(rc); rc = dump_bram(cfg); if (rc) FAIL(rc); - printf_iob(cfg->bits.d, cfg->bits.len, + printf_type2(cfg->bits.d, cfg->bits.len, BRAM_DATA_START + BRAM_DATA_LEN, 896*2/8); if (flags & DUMP_CRC) printf("auto-crc 0x%X\n", cfg->auto_crc); diff --git a/libs/helper.c b/libs/helper.c index 79427a8..b073a49 100644 --- a/libs/helper.c +++ b/libs/helper.c @@ -7,7 +7,7 @@ #include #include -#include "helper.h" +#include "model.h" #include "parts.h" const char* bitstr(uint32_t value, int digits) @@ -230,16 +230,22 @@ const char* bool_bits2str(uint64_t u64, int num_bits) int str_end, first_op, bit_width; static char str[2048]; - if (num_bits == 64) + if (!u64) return "0"; + if (num_bits == 64) { + if (u64 == 0xFFFFFFFFFFFFFFFFULL) return "1"; bit_width = 6; - else if (num_bits == 32) + } else if (num_bits == 32) { + if (u64 & 0xFFFFFFFF00000000ULL) { + // upper 32 bits should be 0 + HERE(); + return "0"; + } + if (u64 == 0x00000000FFFFFFFFULL) return "1"; bit_width = 5; - else { + } else { HERE(); return "0"; } - if (!u64) return "0"; - if (u64 == 0xFFFFFFFFFFFFFFFFULL) return "1"; memset(mt, 0, sizeof(mt)); memset(mt_size, 0, sizeof(mt_size)); @@ -350,7 +356,7 @@ int parse_boolexpr(const char* expr, uint64_t* lut) return 0; } -int printf_iob(uint8_t* d, int len, int inpos, int num_entries) +int printf_type2(uint8_t* d, int len, int inpos, int num_entries) { int i, num_printed; uint64_t u64; @@ -359,7 +365,7 @@ int printf_iob(uint8_t* d, int len, int inpos, int num_entries) for (i = 0; i < num_entries; i++) { u64 = frame_get_u64(&d[inpos+i*8]); if (u64) { - printf("iob i%i 0x%016lX\n", i, u64); + printf("type2 i%i 0x%016lX\n", i, u64); num_printed++; } } @@ -681,13 +687,19 @@ int clb_empty(uint8_t* maj_bits, int idx) void printf_extrabits(const uint8_t* maj_bits, int start_minor, int num_minors, int start_bit, int num_bits, int row, int major) { - int minor, bit; + int minor, bit, bit_no_clk; for (minor = start_minor; minor < start_minor + num_minors; minor++) { for (bit = start_bit; bit < start_bit + num_bits; bit++) { - if (frame_get_bit(&maj_bits[minor*130], bit)) - printf("r%i ma%i extra mi%i bit %i\n", - row, major, minor, bit); + if (frame_get_bit(&maj_bits[minor*FRAME_SIZE], bit)) { + bit_no_clk = bit; + if (bit_no_clk >= 528) + bit_no_clk -= XC6_HCLK_BITS; + printf("r%i ma%i mi%i bit %i 64*%i+%i 256*%i+%i\n", + row, major, minor, bit, + bit_no_clk/64, bit_no_clk%64, + bit_no_clk/256, bit_no_clk%256); + } } } } @@ -1049,3 +1061,20 @@ void strarray_free(struct hashed_strarray* array) free(array->index_to_bin); array->index_to_bin = 0; } + +int row_pos_to_y(int num_rows, int row, int pos) +{ + int y; + + if (row >= num_rows) { + HERE(); + return -1; + } + y = TOP_IO_TILES; + if (row < num_rows/2) + y++; // below center + y += num_rows - row - 1; // hclk in full rows from top + if (pos >= HALF_ROW) + y++; // hclk in row + return y; +} diff --git a/libs/helper.h b/libs/helper.h index 942a79e..a3682de 100644 --- a/libs/helper.h +++ b/libs/helper.h @@ -64,7 +64,7 @@ const char* bool_bits2str(uint64_t u64, int num_bits); int parse_boolexpr(const char* expr, uint64_t* lut); -int printf_iob(uint8_t* d, int len, int inpos, int num_entries); +int printf_type2(uint8_t* d, int len, int inpos, int num_entries); void printf_ramb16_data(uint8_t* bits, int inpos); int is_empty(const uint8_t* d, int l); @@ -151,3 +151,5 @@ int strarray_add(struct hashed_strarray* array, const char* str, int* idx); // anymore, only strarray_lookup(). int strarray_stash(struct hashed_strarray* array, const char* str, int idx); int strarray_used_slots(struct hashed_strarray* array); + +int row_pos_to_y(int num_rows, int row, int pos); diff --git a/libs/model_helper.c b/libs/model_helper.c index ca6525e..be4d538 100644 --- a/libs/model_helper.c +++ b/libs/model_helper.c @@ -602,9 +602,9 @@ void is_in_row(const struct fpga_model* model, int y, if (row_num) *row_num = -1; if (row_pos) *row_pos = -1; - if (y < 2) return; + if (y < TOP_IO_TILES) return; // normalize y to beginning of rows - y -= 2; + y -= TOP_IO_TILES; // calculate distance to center and check // that y is not pointing to the center diff --git a/libs/parts.c b/libs/parts.c index 75df611..51ea5ea 100644 --- a/libs/parts.c +++ b/libs/parts.c @@ -91,6 +91,284 @@ int find_iob_sitename(int idcode, const char* name) return -1; } +int xc_num_rows(int idcode) +{ + if ((idcode & IDCODE_MASK) != XC6SLX9) { + HERE(); + return -1; + } + return NUM_ROWS; +} + +const struct xc_info* xc_info(int idcode) +{ + static const struct xc_info xc6slx9_info = { + .num_rows = 4, + .left_wiring = + /* row 3 */ "UWUWUWUW" "WWWWUUUU" \ + /* row 2 */ "UUUUUUUU" "WWWWWWUU" \ + /* row 1 */ "WWWUUWUU" "WUUWUUWU" \ + /* row 0 */ "UWUUWUUW" "UUWWWWUU", + .right_wiring = + /* row 3 */ "UUWWUWUW" "WWWWUUUU" \ + /* row 2 */ "UUUUUUUU" "WWWWWWUU" \ + /* row 1 */ "WWWUUWUU" "WUUWUUWU" \ + /* row 0 */ "UWUUWUUW" "UUWWWWUU", + .major_str = "M L Bg M L D M R M Ln M L Bg M L", + .num_majors = 18, + .majors = { + // maj_zero: 505 bytes = extra 8-bit for each minor? + [0] = { XC_MAJ_ZERO, 4 }, + [1] = { XC_MAJ_LEFT, 30 }, + [2] = { XC_MAJ_XM | XC_MAJ_TOP_BOT_IO, 31 }, + [3] = { XC_MAJ_XL | XC_MAJ_TOP_BOT_IO, 30 }, + [4] = { XC_MAJ_BRAM | XC_MAJ_GCLK_SEP, 25 }, + [5] = { XC_MAJ_XM | XC_MAJ_TOP_BOT_IO, 31 }, + [6] = { XC_MAJ_XL | XC_MAJ_TOP_BOT_IO, 30 }, + [7] = { XC_MAJ_MACC, 24 }, + [8] = { XC_MAJ_XM | XC_MAJ_TOP_BOT_IO, 31 }, + [9] = { XC_MAJ_CENTER | XC_MAJ_TOP_BOT_IO, 31 }, + [10] = { XC_MAJ_XM | XC_MAJ_TOP_BOT_IO, 31 }, + [11] = { XC_MAJ_XL, 30 }, + [12] = { XC_MAJ_XM | XC_MAJ_TOP_BOT_IO, 31 }, + [13] = { XC_MAJ_XL | XC_MAJ_TOP_BOT_IO, 30 }, + [14] = { XC_MAJ_BRAM | XC_MAJ_GCLK_SEP, 25 }, + [15] = { XC_MAJ_XM | XC_MAJ_TOP_BOT_IO, 31 }, + [16] = { XC_MAJ_XL | XC_MAJ_TOP_BOT_IO, 30 }, + [17] = { XC_MAJ_RIGHT, 30 }}, + .num_type2 = 224, + .type2 = { + [0] = { XC_T2_IOB_PAD, 70 }, + [1] = { XC_T2_IOB_PAD, 69 }, + [2] = { XC_T2_IOB_PAD, 67 }, + [3] = { XC_T2_IOB_PAD, 66 }, + [4] = { XC_T2_IOB_PAD, 65 }, + [5] = { XC_T2_IOB_PAD, 64 }, + [6] = { XC_T2_IOB_PAD, 62 }, + [7] = { XC_T2_IOB_PAD, 61 }, + [8] = { XC_T2_IOB_PAD, 60 }, + [9] = { XC_T2_IOB_PAD, 59 }, + [10] = { XC_T2_IOB_PAD, 58 }, + [11] = { XC_T2_IOB_PAD, 57 }, + [12] = { XC_T2_IOB_UNBONDED, 113 }, + [13] = { XC_T2_IOB_UNBONDED, 114 }, + [14] = { XC_T2_IOB_UNBONDED, 115 }, + [15] = { XC_T2_IOB_UNBONDED, 116 }, + [16] = { XC_T2_IOB_UNBONDED, 117 }, + [17] = { XC_T2_IOB_UNBONDED, 118 }, + [18] = { XC_T2_IOB_PAD, 56 }, + [19] = { XC_T2_IOB_PAD, 55 }, + [20] = { XC_T2_CENTER }, + [21] = { XC_T2_CENTER }, + [22] = { XC_T2_CENTER }, + [23] = { XC_T2_CENTER }, + [24] = { XC_T2_CENTER }, + [25] = { XC_T2_CENTER }, + [26] = { XC_T2_IOB_PAD, 51 }, + [27] = { XC_T2_IOB_PAD, 50 }, + [28] = { XC_T2_IOB_UNBONDED, 123 }, + [29] = { XC_T2_IOB_UNBONDED, 124 }, + [30] = { XC_T2_IOB_UNBONDED, 125 }, + [31] = { XC_T2_IOB_UNBONDED, 126 }, + [32] = { XC_T2_IOB_UNBONDED, 127 }, + [33] = { XC_T2_IOB_UNBONDED, 128 }, + [34] = { XC_T2_IOB_UNBONDED, 129 }, + [35] = { XC_T2_IOB_UNBONDED, 130 }, + [36] = { XC_T2_IOB_UNBONDED, 131 }, + [37] = { XC_T2_IOB_UNBONDED, 132 }, + [38] = { XC_T2_IOB_PAD, 48 }, + [39] = { XC_T2_IOB_PAD, 47 }, + [40] = { XC_T2_IOB_PAD, 46 }, + [41] = { XC_T2_IOB_PAD, 45 }, + [42] = { XC_T2_IOB_PAD, 44 }, + [43] = { XC_T2_IOB_PAD, 43 }, + [44] = { XC_T2_IOB_UNBONDED, 139 }, + [45] = { XC_T2_IOB_UNBONDED, 140 }, + [46] = { XC_T2_IOB_PAD, 41 }, + [47] = { XC_T2_IOB_PAD, 40 }, + [48] = { XC_T2_IOB_PAD, 39 }, + [49] = { XC_T2_IOB_PAD, 38 }, + [50] = { XC_T2_IOB_PAD, 35 }, + [51] = { XC_T2_IOB_PAD, 34 }, + [52] = { XC_T2_IOB_PAD, 33 }, + [53] = { XC_T2_IOB_PAD, 32 }, + [54] = { XC_T2_IOB_UNBONDED, 149 }, + [55] = { XC_T2_IOB_UNBONDED, 150 }, + [56] = { XC_T2_IOB_UNBONDED, 151 }, + [57] = { XC_T2_IOB_UNBONDED, 152 }, + [58] = { XC_T2_IOB_UNBONDED, 153 }, + [59] = { XC_T2_IOB_UNBONDED, 154 }, + [60] = { XC_T2_IOB_UNBONDED, 155 }, + [61] = { XC_T2_IOB_UNBONDED, 156 }, + [62] = { XC_T2_IOB_UNBONDED, 157 }, + [63] = { XC_T2_IOB_UNBONDED, 158 }, + [64] = { XC_T2_IOB_PAD, 30 }, + [65] = { XC_T2_IOB_PAD, 29 }, + [66] = { XC_T2_IOB_PAD, 27 }, + [67] = { XC_T2_IOB_PAD, 26 }, + [68] = { XC_T2_IOB_UNBONDED, 163 }, + [69] = { XC_T2_IOB_UNBONDED, 164 }, + [70] = { XC_T2_IOB_UNBONDED, 165 }, + [71] = { XC_T2_IOB_UNBONDED, 166 }, + [72] = { XC_T2_IOB_UNBONDED, 167 }, + [73] = { XC_T2_IOB_UNBONDED, 168 }, + [74] = { XC_T2_IOB_PAD, 24 }, + [75] = { XC_T2_IOB_PAD, 23 }, + [76] = { XC_T2_IOB_PAD, 22 }, + [77] = { XC_T2_IOB_PAD, 21 }, + [78] = { XC_T2_CENTER }, + [79] = { XC_T2_CENTER }, + [80] = { XC_T2_CENTER }, + [81] = { XC_T2_CENTER }, + [82] = { XC_T2_CENTER }, + [83] = { XC_T2_CENTER }, + [84] = { XC_T2_IOB_PAD, 17 }, + [85] = { XC_T2_IOB_PAD, 16 }, + [86] = { XC_T2_IOB_PAD, 15 }, + [87] = { XC_T2_IOB_PAD, 14 }, + [88] = { XC_T2_IOB_UNBONDED, 177 }, + [89] = { XC_T2_IOB_UNBONDED, 178 }, + [90] = { XC_T2_IOB_UNBONDED, 179 }, + [91] = { XC_T2_IOB_UNBONDED, 180 }, + [92] = { XC_T2_IOB_UNBONDED, 181 }, + [93] = { XC_T2_IOB_UNBONDED, 182 }, + [94] = { XC_T2_IOB_UNBONDED, 183 }, + [95] = { XC_T2_IOB_UNBONDED, 184 }, + [96] = { XC_T2_IOB_PAD, 12 }, + [97] = { XC_T2_IOB_PAD, 11 }, + [98] = { XC_T2_IOB_PAD, 10 }, + [99] = { XC_T2_IOB_PAD, 9 }, + [100] = { XC_T2_IOB_PAD, 8 }, + [101] = { XC_T2_IOB_PAD, 7 }, + [102] = { XC_T2_IOB_PAD, 6 }, + [103] = { XC_T2_IOB_PAD, 5 }, + [104] = { XC_T2_IOB_UNBONDED, 193 }, + [105] = { XC_T2_IOB_UNBONDED, 194 }, + [106] = { XC_T2_IOB_UNBONDED, 195 }, + [107] = { XC_T2_IOB_UNBONDED, 196 }, + [108] = { XC_T2_IOB_UNBONDED, 197 }, + [109] = { XC_T2_IOB_UNBONDED, 198 }, + [110] = { XC_T2_IOB_PAD, 2 }, + [111] = { XC_T2_IOB_PAD, 1 }, + [112] = { XC_T2_IOB_PAD, 144 }, + [113] = { XC_T2_IOB_PAD, 143 }, + [114] = { XC_T2_IOB_PAD, 142 }, + [115] = { XC_T2_IOB_PAD, 141 }, + [116] = { XC_T2_IOB_PAD, 140 }, + [117] = { XC_T2_IOB_PAD, 139 }, + [118] = { XC_T2_IOB_PAD, 138 }, + [119] = { XC_T2_IOB_PAD, 137 }, + [120] = { XC_T2_IOB_UNBONDED, 9 }, + [121] = { XC_T2_IOB_UNBONDED, 10 }, + [122] = { XC_T2_IOB_UNBONDED, 11 }, + [123] = { XC_T2_IOB_UNBONDED, 12 }, + [124] = { XC_T2_IOB_UNBONDED, 13 }, + [125] = { XC_T2_IOB_UNBONDED, 14 }, + [126] = { XC_T2_IOB_UNBONDED, 15 }, + [127] = { XC_T2_IOB_UNBONDED, 16 }, + [128] = { XC_T2_IOB_UNBONDED, 17 }, + [129] = { XC_T2_IOB_UNBONDED, 18 }, + [130] = { XC_T2_IOB_UNBONDED, 19 }, + [131] = { XC_T2_IOB_UNBONDED, 20 }, + [132] = { XC_T2_IOB_PAD, 134 }, + [133] = { XC_T2_IOB_PAD, 133 }, + [134] = { XC_T2_IOB_PAD, 132 }, + [135] = { XC_T2_IOB_PAD, 131 }, + [136] = { XC_T2_CENTER }, + [137] = { XC_T2_CENTER }, + [138] = { XC_T2_CENTER }, + [139] = { XC_T2_CENTER }, + [140] = { XC_T2_CENTER }, + [141] = { XC_T2_CENTER }, + [142] = { XC_T2_IOB_PAD, 127 }, + [143] = { XC_T2_IOB_PAD, 126 }, + [144] = { XC_T2_IOB_PAD, 124 }, + [145] = { XC_T2_IOB_PAD, 123 }, + [146] = { XC_T2_IOB_UNBONDED, 29 }, + [147] = { XC_T2_IOB_UNBONDED, 30 }, + [148] = { XC_T2_IOB_UNBONDED, 31 }, + [149] = { XC_T2_IOB_UNBONDED, 32 }, + [150] = { XC_T2_IOB_UNBONDED, 33 }, + [151] = { XC_T2_IOB_UNBONDED, 34 }, + [152] = { XC_T2_IOB_PAD, 121 }, + [153] = { XC_T2_IOB_PAD, 120 }, + [154] = { XC_T2_IOB_PAD, 119 }, + [155] = { XC_T2_IOB_PAD, 118 }, + [156] = { XC_T2_IOB_PAD, 117 }, + [157] = { XC_T2_IOB_PAD, 116 }, + [158] = { XC_T2_IOB_PAD, 115 }, + [159] = { XC_T2_IOB_PAD, 114 }, + [160] = { XC_T2_IOB_PAD, 112 }, + [161] = { XC_T2_IOB_PAD, 111 }, + [162] = { XC_T2_IOB_PAD, 105 }, + [163] = { XC_T2_IOB_PAD, 104 }, + [164] = { XC_T2_IOB_UNBONDED, 47 }, + [165] = { XC_T2_IOB_UNBONDED, 48 }, + [166] = { XC_T2_IOB_UNBONDED, 49 }, + [167] = { XC_T2_IOB_UNBONDED, 50 }, + [168] = { XC_T2_IOB_UNBONDED, 51 }, + [169] = { XC_T2_IOB_UNBONDED, 52 }, + [170] = { XC_T2_IOB_PAD, 102 }, + [171] = { XC_T2_IOB_PAD, 101 }, + [172] = { XC_T2_IOB_PAD, 100 }, + [173] = { XC_T2_IOB_PAD, 99 }, + [174] = { XC_T2_IOB_PAD, 98 }, + [175] = { XC_T2_IOB_PAD, 97 }, + [176] = { XC_T2_IOB_UNBONDED, 59 }, + [177] = { XC_T2_IOB_UNBONDED, 60 }, + [178] = { XC_T2_IOB_UNBONDED, 61 }, + [179] = { XC_T2_IOB_UNBONDED, 62 }, + [180] = { XC_T2_IOB_UNBONDED, 63 }, + [181] = { XC_T2_IOB_UNBONDED, 64 }, + [182] = { XC_T2_IOB_UNBONDED, 65 }, + [183] = { XC_T2_IOB_UNBONDED, 66 }, + [184] = { XC_T2_IOB_UNBONDED, 67 }, + [185] = { XC_T2_IOB_UNBONDED, 68 }, + [186] = { XC_T2_IOB_PAD, 95 }, + [187] = { XC_T2_IOB_PAD, 94 }, + [188] = { XC_T2_IOB_PAD, 93 }, + [189] = { XC_T2_IOB_PAD, 92 }, + [190] = { XC_T2_CENTER }, + [191] = { XC_T2_CENTER }, + [192] = { XC_T2_CENTER }, + [193] = { XC_T2_CENTER }, + [194] = { XC_T2_CENTER }, + [195] = { XC_T2_CENTER }, + [196] = { XC_T2_IOB_PAD, 88 }, + [197] = { XC_T2_IOB_PAD, 87 }, + [198] = { XC_T2_IOB_PAD, 85 }, + [199] = { XC_T2_IOB_PAD, 84 }, + [200] = { XC_T2_IOB_UNBONDED, 77 }, + [201] = { XC_T2_IOB_UNBONDED, 78 }, + [202] = { XC_T2_IOB_PAD, 83 }, + [203] = { XC_T2_IOB_PAD, 82 }, + [204] = { XC_T2_IOB_PAD, 81 }, + [205] = { XC_T2_IOB_PAD, 80 }, + [206] = { XC_T2_IOB_PAD, 79 }, + [207] = { XC_T2_IOB_PAD, 78 }, + [208] = { XC_T2_IOB_UNBONDED, 85 }, + [209] = { XC_T2_IOB_UNBONDED, 86 }, + [210] = { XC_T2_IOB_UNBONDED, 87 }, + [211] = { XC_T2_IOB_UNBONDED, 88 }, + [212] = { XC_T2_IOB_UNBONDED, 89 }, + [213] = { XC_T2_IOB_UNBONDED, 90 }, + [214] = { XC_T2_IOB_UNBONDED, 91 }, + [215] = { XC_T2_IOB_UNBONDED, 92 }, + [216] = { XC_T2_IOB_UNBONDED, 93 }, + [217] = { XC_T2_IOB_UNBONDED, 94 }, + [218] = { XC_T2_IOB_UNBONDED, 95 }, + [219] = { XC_T2_IOB_UNBONDED, 96 }, + [220] = { XC_T2_IOB_UNBONDED, 97 }, + [221] = { XC_T2_IOB_UNBONDED, 98 }, + [222] = { XC_T2_IOB_PAD, 75 }, + [223] = { XC_T2_IOB_PAD, 74 }}}; + switch (idcode & IDCODE_MASK) { + case XC6SLX9: return &xc6slx9_info; + } + HERE(); + return 0; +} + int get_major_minors(int idcode, int major) { static const int minors_per_major[] = // for slx9 diff --git a/libs/parts.h b/libs/parts.h index 3f127bc..3d0dca0 100644 --- a/libs/parts.h +++ b/libs/parts.h @@ -23,6 +23,50 @@ #define XC6SLX100T 0x04031093 #define XC6SLX150 0x0401D093 +#define XC_MAX_MAJORS 400 +#define XC_MAX_TYPE2_ENTRIES 2000 + +#define XC_MAJ_ZERO 0x00000001 +#define XC_MAJ_LEFT 0x00000002 +#define XC_MAJ_CENTER 0x00000004 +#define XC_MAJ_RIGHT 0x00000008 +#define XC_MAJ_XM 0x00000010 +#define XC_MAJ_XL 0x00000020 +#define XC_MAJ_BRAM 0x00000040 +#define XC_MAJ_MACC 0x00000080 +#define XC_MAJ_TOP_BOT_IO 0x00000100 +#define XC_MAJ_GCLK_SEP 0x00000200 + +struct xc_major_info +{ + int flags; + int minors; +}; + +#define XC_T2_IOB_PAD 0x00000001 +#define XC_T2_IOB_UNBONDED 0x00000002 +#define XC_T2_CENTER 0x00000004 + +struct xc_type2_info +{ + int flags; + int val; +}; + +struct xc_info +{ + int num_rows; + const char* left_wiring; + const char* right_wiring; + const char* major_str; + int num_majors; + struct xc_major_info majors[XC_MAX_MAJORS]; + int num_type2; + struct xc_type2_info type2[XC_MAX_TYPE2_ENTRIES]; +}; + +const struct xc_info* xc_info(int idcode); + #define FRAME_SIZE 130 #define FRAMES_PER_ROW 505 // for slx4 and slx9 #define PADDING_FRAMES_PER_ROW 2 @@ -130,6 +174,8 @@ const char* get_iob_sitename(int idcode, int idx); // returns -1 if sitename not found int find_iob_sitename(int idcode, const char* name); +int xc_num_rows(int idcode); + // The routing bitpos is relative to a tile, i.e. major (x) // and row/v64_i (y) are defined outside. struct xc6_routing_bitpos