From 1621628e6db4dce8f0c6b0851ceeace15afcf3c7 Mon Sep 17 00:00:00 2001 From: Wolfgang Spraul Date: Sun, 23 Sep 2012 03:10:01 +0200 Subject: [PATCH] improved iob config --- autotest.c | 127 ++++++++++++++++++++++++++- libs/bit_frames.c | 218 ++++++++++++++++++++++++++++++++++++++-------- libs/control.c | 4 +- libs/helper.c | 14 +-- libs/model.h | 1 + libs/parts.c | 9 ++ libs/parts.h | 38 ++++++++ 7 files changed, 366 insertions(+), 45 deletions(-) diff --git a/autotest.c b/autotest.c index 0919e1d..6658f82 100644 --- a/autotest.c +++ b/autotest.c @@ -24,6 +24,7 @@ struct test_state int cmdline_skip; char cmdline_diff_exec[1024]; int dry_run; + int diff_to_null; struct fpga_model* model; // test filenames are: tmp_dir/autotest__.??? @@ -81,7 +82,8 @@ static int diff_printf(struct test_state* tstate) snprintf(path, sizeof(path), "%s/autotest_%s_%06i", tstate->tmp_dir, tstate->base_name, tstate->next_diff_counter); path_base = strlen(path); - if (tstate->next_diff_counter == tstate->cmdline_skip + 1) + if (tstate->diff_to_null + || tstate->next_diff_counter == tstate->cmdline_skip + 1) strcpy(prior_fp, "/dev/null"); else { snprintf(prior_fp, sizeof(prior_fp), "%s/autotest_%s_%06i.fp", @@ -872,6 +874,118 @@ fail: return rc; } +static int test_iob_config(struct test_state* tstate) +{ + int iob_y, iob_x, iob_type_idx, rc; + net_idx_t net_idx; + struct fpga_device* dev; + + tstate->diff_to_null = 1; + + // P45 is an IOBS + rc = fpga_find_iob(tstate->model, "P45", &iob_y, &iob_x, &iob_type_idx); + if (rc) FAIL(rc); + rc = fdev_iob_input(tstate->model, iob_y, iob_x, iob_type_idx); + if (rc) FAIL(rc); + dev = fdev_p(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx); + if (!dev) FAIL(EINVAL); + + if ((rc = diff_printf(tstate))) FAIL(rc); + dev->u.iob.I_mux = IMUX_I_B; + if ((rc = diff_printf(tstate))) FAIL(rc); + + fdev_delete(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx); + + // P46 is an IOBM + rc = fpga_find_iob(tstate->model, "P46", &iob_y, &iob_x, &iob_type_idx); + if (rc) FAIL(rc); + rc = fdev_iob_input(tstate->model, iob_y, iob_x, iob_type_idx); + if (rc) FAIL(rc); + if ((rc = diff_printf(tstate))) FAIL(rc); + fdev_delete(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx); + + // P47 is an IOBS + rc = fpga_find_iob(tstate->model, "P47", &iob_y, &iob_x, &iob_type_idx); + if (rc) FAIL(rc); + rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx); + if (rc) FAIL(rc); + dev = fdev_p(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx); + if (!dev) FAIL(EINVAL); + + // least amount of bits: + dev->u.iob.slew = SLEW_SLOW; + dev->u.iob.drive_strength = 8; + dev->u.iob.suspend = SUSP_3STATE; + + dev->u.iob.suspend = SUSP_3STATE; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.suspend = SUSP_3STATE_OCT_ON; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.suspend = SUSP_3STATE_KEEPER; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.suspend = SUSP_3STATE_PULLUP; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.suspend = SUSP_3STATE_PULLDOWN; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.suspend = SUSP_LAST_VAL; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.suspend = SUSP_3STATE; + + dev->u.iob.drive_strength = 2; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.drive_strength = 4; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.drive_strength = 6; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.drive_strength = 8; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.drive_strength = 12; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.drive_strength = 16; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.drive_strength = 24; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.drive_strength = 8; + + dev->u.iob.slew = SLEW_SLOW; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.slew = SLEW_FAST; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.slew = SLEW_QUIETIO; + rc = diff_printf(tstate); if (rc) FAIL(rc); + dev->u.iob.slew = SLEW_SLOW; + + fdev_delete(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx); + + // P48 is an IOBM + rc = fpga_find_iob(tstate->model, "P48", &iob_y, &iob_x, &iob_type_idx); + if (rc) FAIL(rc); + rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx); + if (rc) FAIL(rc); + dev = fdev_p(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx); + if (!dev) FAIL(EINVAL); + + // least bits + dev->u.iob.slew = SLEW_SLOW; + dev->u.iob.drive_strength = 8; + dev->u.iob.suspend = SUSP_3STATE; + + // new net + rc = fnet_new(tstate->model, &net_idx); + if (rc) FAIL(rc); + + // add iob port + rc = fnet_add_port(tstate->model, net_idx, iob_y, iob_x, + DEV_IOB, iob_type_idx, IOB_IN_O); + if (rc) FAIL(rc); + if ((rc = diff_printf(tstate))) FAIL(rc); + + fdev_delete(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx); + return 0; +fail: + return rc; +} + #define DEFAULT_DIFF_EXEC "./autotest_diff.sh" static void printf_help(const char* argv_0, const char** available_tests) @@ -879,8 +993,8 @@ static void printf_help(const char* argv_0, const char** available_tests) printf( "\n" "fpgatools automatic test suite\n" "\n" - "Usage: %s [--test=] [--diff=] [--skip=]\n" - " %*s [--dry-run]\n" + "Usage: %s [--test=] [--skip=] [--dry-run]\n" + " %*s [--diff=]\n" "Default diff executable: " DEFAULT_DIFF_EXEC "\n", argv_0, (int) strlen(argv_0), ""); if (available_tests) { @@ -902,7 +1016,7 @@ int main(int argc, char** argv) char param[1024], cmdline_test[1024]; int i, param_skip, rc; const char* available_tests[] = - { "logic_cfg", "routing_sw", "io_sw", 0 }; + { "logic_cfg", "routing_sw", "io_sw", "iob_cfg", 0 }; // flush after every line is better for the autotest // output, tee, etc. @@ -923,6 +1037,7 @@ int main(int argc, char** argv) tstate.cmdline_diff_exec[0] = 0; cmdline_test[0] = 0; tstate.dry_run = -1; + tstate.diff_to_null = 0; for (i = 1; i < argc; i++) { memset(param, 0, sizeof(param)); if (sscanf(argv[i], "--test=%1023c", param) == 1) { @@ -1022,6 +1137,10 @@ int main(int argc, char** argv) rc = test_iologic_switches(&tstate); if (rc) FAIL(rc); } + if (!strcmp(cmdline_test, "iob_cfg")) { + rc = test_iob_config(&tstate); + if (rc) FAIL(rc); + } printf("\n"); printf("O Test completed.\n"); diff --git a/libs/bit_frames.c b/libs/bit_frames.c index 0292121..9952ebc 100644 --- a/libs/bit_frames.c +++ b/libs/bit_frames.c @@ -94,11 +94,12 @@ struct extract_state static int write_iobs(struct fpga_bits* bits, struct fpga_model* model) { - int i, y, x, type_idx, part_idx, dev_idx, rc; + int i, y, x, type_idx, part_idx, dev_idx, first_iob, rc; struct fpga_device* dev; - uint32_t* u32_p; + uint64_t u64; const char* name; + first_iob = 0; for (i = 0; (name = fpga_enum_iob(model, i, &y, &x, &type_idx)); i++) { dev_idx = fpga_dev_idx(model, y, x, DEV_IOB, type_idx); if (dev_idx == NO_DEV) FAIL(EINVAL); @@ -112,15 +113,71 @@ static int write_iobs(struct fpga_bits* bits, struct fpga_model* model) continue; } - u32_p = (uint32_t*) - &bits->d[IOB_DATA_START + part_idx*IOB_ENTRY_LEN]; - if (dev->u.iob.O_used) { - u32_p[0] = 0x00000180; - u32_p[1] = 0x06001100; - } else if (dev->u.iob.I_mux == IMUX_I) { - u32_p[0] = 0x00000107; - u32_p[1] = 0x0B002400; + if (!first_iob) { + first_iob = 1; + // todo: is this right on the other sides? + set_bit(bits, /*row*/ 0, get_rightside_major(XC6SLX9), + /*minor*/ 22, 64*15+XC6_HCLK_BITS+4); } + + if (dev->u.iob.istandard[0]) { + if (!dev->u.iob.I_mux + || !dev->u.iob.bypass_mux + || strcmp(dev->u.iob.istandard, IO_LVCMOS33) + || dev->u.iob.ostandard[0]) + HERE(); + + u64 = XC6_IOB_INSTANTIATED; + u64 |= XC6_IOB_INPUT_LVCMOS33; + if (dev->u.iob.I_mux == IMUX_I) + u64 |= XC6_IOB_IMUX_I; + else if (dev->u.iob.I_mux == IMUX_I_B) + u64 |= XC6_IOB_IMUX_I_B; + else HERE(); + + frame_set_u64(&bits->d[IOB_DATA_START + + part_idx*IOB_ENTRY_LEN], u64); + } else if (dev->u.iob.ostandard[0]) { + if (!dev->u.iob.drive_strength + || !dev->u.iob.slew + || !dev->u.iob.suspend + || strcmp(dev->u.iob.ostandard, IO_LVCMOS33) + || dev->u.iob.istandard[0]) + HERE(); + + u64 = XC6_IOB_INSTANTIATED; + // for now we always turn on O_PINW even if no net + // is connected to the pinw + u64 |= XC6_IOB_MASK_O_PINW; + switch (dev->u.iob.drive_strength) { + case 2: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_2; break; + case 4: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_4; break; + case 6: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_6; break; + case 8: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_8; break; + case 12: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_12; break; + case 16: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_16; break; + case 24: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_24; break; + default: HERE(); + } + switch (dev->u.iob.slew) { + case SLEW_SLOW: u64 |= XC6_IOB_SLEW_SLOW; break; + case SLEW_QUIETIO: u64 |= XC6_IOB_SLEW_QUIETIO; break; + case SLEW_FAST: u64 |= XC6_IOB_SLEW_FAST; break; + default: HERE(); + } + switch (dev->u.iob.suspend) { + case SUSP_LAST_VAL: u64 |= XC6_IOB_SUSP_LAST_VAL; break; + case SUSP_3STATE: u64 |= XC6_IOB_SUSP_3STATE; break; + case SUSP_3STATE_PULLUP: u64 |= XC6_IOB_SUSP_3STATE_PULLUP; break; + case SUSP_3STATE_PULLDOWN: u64 |= XC6_IOB_SUSP_3STATE_PULLDOWN; break; + case SUSP_3STATE_KEEPER: u64 |= XC6_IOB_SUSP_3STATE_KEEPER; break; + case SUSP_3STATE_OCT_ON: u64 |= XC6_IOB_SUSP_3STATE_OCT_ON; break; + default: HERE(); + } + + frame_set_u64(&bits->d[IOB_DATA_START + + part_idx*IOB_ENTRY_LEN], u64); + } else HERE(); } return 0; fail: @@ -129,16 +186,18 @@ fail: static int extract_iobs(struct fpga_model* model, struct fpga_bits* bits) { - int i, num_iobs, iob_y, iob_x, iob_idx, dev_idx, rc; - uint32_t* u32_p; + int i, num_iobs, iob_y, iob_x, iob_idx, dev_idx, first_iob, rc; + uint64_t u64; const char* iob_sitename; struct fpga_device* dev; + struct fpgadev_iob cfg; num_iobs = get_num_iobs(XC6SLX9); + first_iob = 0; for (i = 0; i < num_iobs; i++) { - u32_p = (uint32_t*) &bits->d[IOB_DATA_START + i*IOB_ENTRY_LEN]; - if (!u32_p[0] && !u32_p[1]) - continue; + u64 = frame_get_u64(&bits->d[IOB_DATA_START + i*IOB_ENTRY_LEN]); + if (!u64) continue; + iob_sitename = get_iob_sitename(XC6SLX9, i); if (!iob_sitename) { HERE(); @@ -149,27 +208,118 @@ static int extract_iobs(struct fpga_model* model, struct fpga_bits* bits) dev_idx = fpga_dev_idx(model, iob_y, iob_x, DEV_IOB, iob_idx); if (dev_idx == NO_DEV) FAIL(EINVAL); dev = FPGA_DEV(model, iob_y, iob_x, dev_idx); + memset(&cfg, 0, sizeof(cfg)); - // we only support 2 hardcoded types of IOB right now - // todo: bit 7 goes on when out-net connected? - if ((u32_p[0] & 0xFFFFFF7F) == 0x00000100 - && u32_p[1] == 0x06001100) { + if (!first_iob) { + first_iob = 1; + // todo: is this right on the other sides? + if (!get_bit(bits, /*row*/ 0, get_rightside_major(XC6SLX9), + /*minor*/ 22, 64*15+XC6_HCLK_BITS+4)) + HERE(); + clear_bit(bits, /*row*/ 0, get_rightside_major(XC6SLX9), + /*minor*/ 22, 64*15+XC6_HCLK_BITS+4); + } + if ((u64 & XC6_IOB_MASK_INSTANTIATED) == XC6_IOB_INSTANTIATED) + u64 &= ~XC6_IOB_MASK_INSTANTIATED; + else + HERE(); + + switch (u64 & XC6_IOB_MASK_IO) { + case XC6_IOB_INPUT_LVCMOS33: + u64 &= ~XC6_IOB_MASK_IO; + + strcpy(cfg.istandard, IO_LVCMOS33); + cfg.bypass_mux = BYPASS_MUX_I; + + switch (u64 & XC6_IOB_MASK_I_MUX) { + case XC6_IOB_IMUX_I: + u64 &= ~XC6_IOB_MASK_I_MUX; + cfg.I_mux = IMUX_I; + break; + case XC6_IOB_IMUX_I_B: + u64 &= ~XC6_IOB_MASK_I_MUX; + cfg.I_mux = IMUX_I_B; + break; + default: HERE(); + } + break; + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_2: + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_4: + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_6: + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_8: + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_12: + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_16: + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_24: + u64 &= ~XC6_IOB_MASK_IO; + u64 &= ~XC6_IOB_MASK_O_PINW; + + strcpy(cfg.ostandard, IO_LVCMOS33); + cfg.O_used = 1; + switch (u64 & XC6_IOB_MASK_IO) { + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_2: + cfg.drive_strength = 2; break; + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_4: + cfg.drive_strength = 4; break; + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_6: + cfg.drive_strength = 6; break; + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_8: + cfg.drive_strength = 8; break; + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_12: + cfg.drive_strength = 12; break; + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_16: + cfg.drive_strength = 16; break; + case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_24: + cfg.drive_strength = 24; break; + default: HERE(); + } + switch (u64 & XC6_IOB_MASK_SLEW) { + case XC6_IOB_SLEW_SLOW: + u64 &= ~XC6_IOB_MASK_SLEW; + cfg.slew = SLEW_SLOW; + break; + case XC6_IOB_SLEW_QUIETIO: + u64 &= ~XC6_IOB_MASK_SLEW; + cfg.slew = SLEW_QUIETIO; + break; + case XC6_IOB_SLEW_FAST: + u64 &= ~XC6_IOB_MASK_SLEW; + cfg.slew = SLEW_FAST; + break; + default: HERE(); + } + switch (u64 & XC6_IOB_MASK_SUSPEND) { + case XC6_IOB_SUSP_3STATE: + u64 &= ~XC6_IOB_MASK_SUSPEND; + cfg.suspend = SUSP_3STATE; + break; + case XC6_IOB_SUSP_3STATE_OCT_ON: + u64 &= ~XC6_IOB_MASK_SUSPEND; + cfg.suspend = SUSP_3STATE_OCT_ON; + break; + case XC6_IOB_SUSP_3STATE_KEEPER: + u64 &= ~XC6_IOB_MASK_SUSPEND; + cfg.suspend = SUSP_3STATE_KEEPER; + break; + case XC6_IOB_SUSP_3STATE_PULLUP: + u64 &= ~XC6_IOB_MASK_SUSPEND; + cfg.suspend = SUSP_3STATE_PULLUP; + break; + case XC6_IOB_SUSP_3STATE_PULLDOWN: + u64 &= ~XC6_IOB_MASK_SUSPEND; + cfg.suspend = SUSP_3STATE_PULLDOWN; + break; + case XC6_IOB_SUSP_LAST_VAL: + u64 &= ~XC6_IOB_MASK_SUSPEND; + cfg.suspend = SUSP_LAST_VAL; + break; + default: HERE(); + } + break; + default: HERE(); break; + } + if (!u64) { dev->instantiated = 1; - strcpy(dev->u.iob.ostandard, IO_LVCMOS33); - dev->u.iob.drive_strength = 12; - dev->u.iob.O_used = 1; - dev->u.iob.slew = SLEW_SLOW; - dev->u.iob.suspend = SUSP_3STATE; - u32_p[0] = 0; - u32_p[1] = 0; - } else if (u32_p[0] == 0x00000107 - && u32_p[1] == 0x0B002400) { - dev->instantiated = 1; - strcpy(dev->u.iob.istandard, IO_LVCMOS33); - dev->u.iob.bypass_mux = BYPASS_MUX_I; - dev->u.iob.I_mux = IMUX_I; - u32_p[0] = 0; - u32_p[1] = 0; + dev->u.iob = cfg; } else HERE(); } return 0; diff --git a/libs/control.c b/libs/control.c index 06d0d6f..3a2ee1d 100644 --- a/libs/control.c +++ b/libs/control.c @@ -579,9 +579,9 @@ int fdev_iob_output(struct fpga_model* model, int y, int x, int type_idx) if (rc) FAIL(rc); strcpy(dev->u.iob.ostandard, IO_LVCMOS33); - dev->u.iob.drive_strength = 12; + dev->u.iob.drive_strength = 8; dev->u.iob.O_used = 1; - dev->u.iob.slew = SLEW_SLOW; + dev->u.iob.slew = SLEW_QUIETIO; dev->u.iob.suspend = SUSP_3STATE; dev->instantiated = 1; return 0; diff --git a/libs/helper.c b/libs/helper.c index c9f82fb..c47c08e 100644 --- a/libs/helper.c +++ b/libs/helper.c @@ -364,14 +364,18 @@ const char* lut2bool(const uint64_t lut, int bits, int printf_iob(uint8_t* d, int len, int inpos, int num_entries) { int i, j, num_printed; + uint64_t u64; num_printed = 0; for (i = 0; i < num_entries; i++) { - if (*(uint32_t*)&d[inpos+i*8] || *(uint32_t*)&d[inpos+i*8+4]) { - printf("iob i%i", i); - for (j = 0; j < 8; j++) - printf(" %02X", d[inpos+i*8+j]); - printf("\n"); + u64 = frame_get_u64(&d[inpos+i*8]); + if (u64) { + printf("iob i%i 0x%016llX\n", i, + (long long unsigned) u64); + for (j = 0; j < 64; j++) { + if (u64 & (1ULL << j)) + printf("iob i%i b%i\n", i, j); + } num_printed++; } } diff --git a/libs/model.h b/libs/model.h index cc7dd5d..5e0c3b8 100644 --- a/libs/model.h +++ b/libs/model.h @@ -446,6 +446,7 @@ struct fpgadev_logic enum { IOBM = 1, IOBS }; typedef char IOSTANDARD[32]; #define IO_LVCMOS33 "LVCMOS33" +#define IO_SSTL2_I "SSTL2_I" // drive attr and slew not used here? enum { BYPASS_MUX_I = 1, BYPASS_MUX_O, BYPASS_MUX_T }; enum { IMUX_I_B = 1, IMUX_I }; enum { SLEW_SLOW = 1, SLEW_FAST, SLEW_QUIETIO }; diff --git a/libs/parts.c b/libs/parts.c index d123df5..0f3e6a7 100644 --- a/libs/parts.c +++ b/libs/parts.c @@ -150,6 +150,15 @@ enum major_type get_major_type(int idcode, int major) return major_types[major]; } +int get_rightside_major(int idcode) +{ + if ((idcode & IDCODE_MASK) != XC6SLX9) { + HERE(); + return -1; + } + return XC6_SLX9_RIGHTMOST_MAJOR; +} + // // routing switches // diff --git a/libs/parts.h b/libs/parts.h index d908d8c..9ecd02b 100644 --- a/libs/parts.h +++ b/libs/parts.h @@ -38,12 +38,50 @@ #define IOB_ENTRY_LEN 8 #define BITS_LEN (IOB_DATA_START+IOB_DATA_LEN) +#define XC6_HCLK_BYTES 2 +#define XC6_HCLK_BITS (XC6_HCLK_BYTES*8) + +#define XC6_IOB_MASK_INSTANTIATED 0x0000000000000080 +#define XC6_IOB_MASK_IO 0x00FF00FF00000000 +#define XC6_IOB_MASK_O_PINW 0x0000000000000100 +#define XC6_IOB_MASK_I_MUX 0x000000000000E400 +#define XC6_IOB_MASK_SLEW 0x0000000000FF0000 +#define XC6_IOB_MASK_SUSPEND 0x000000000000001F + +#define XC6_IOB_INSTANTIATED 0x0000000000000080 +#define XC6_IOB_INPUT_LVCMOS33 0x00D0024000000000 +#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_2 0x00100B4000000000 +#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_4 0x007006C000000000 +#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_6 0x00300FC000000000 +#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_8 0x0040000000000000 +#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_12 0x0060088000000000 +#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_16 0x00980C6000000000 +#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_24 0x0088072000000000 +#define XC6_IOB_O_PINW 0x0000000000000100 +#define XC6_IOB_IMUX_I 0x000000000000E000 +#define XC6_IOB_IMUX_I_B 0x000000000000E400 +#define XC6_IOB_SLEW_SLOW 0x0000000000000000 +#define XC6_IOB_SLEW_QUIETIO 0x0000000000330000 +#define XC6_IOB_SLEW_FAST 0x0000000000660000 +#define XC6_IOB_SUSP_3STATE 0x0000000000000000 +#define XC6_IOB_SUSP_3STATE_OCT_ON 0x0000000000000001 +#define XC6_IOB_SUSP_3STATE_KEEPER 0x0000000000000002 +#define XC6_IOB_SUSP_3STATE_PULLUP 0x0000000000000004 +#define XC6_IOB_SUSP_3STATE_PULLDOWN 0x0000000000000008 +#define XC6_IOB_SUSP_LAST_VAL 0x0000000000000010 + int get_major_minors(int idcode, int major); enum major_type { MAJ_ZERO, MAJ_LEFT, MAJ_RIGHT, MAJ_CENTER, MAJ_LOGIC_XM, MAJ_LOGIC_XL, MAJ_BRAM, MAJ_MACC }; enum major_type get_major_type(int idcode, int major); +#define XC6_ZERO_MAJOR 0 +#define XC6_LEFTSIDE_MAJOR 1 +#define XC6_SLX9_RIGHTMOST_MAJOR 17 + +int get_rightside_major(int idcode); + int get_num_iobs(int idcode); const char* get_iob_sitename(int idcode, int idx); // returns -1 if sitename not found