improved iob config
This commit is contained in:
parent
62db4b6911
commit
1621628e6d
127
autotest.c
127
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_<base_name>_<diff_counter>.???
|
||||
|
@ -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=<name>] [--diff=<diff executable>] [--skip=<num>]\n"
|
||||
" %*s [--dry-run]\n"
|
||||
"Usage: %s [--test=<name>] [--skip=<num>] [--dry-run]\n"
|
||||
" %*s [--diff=<diff executable>]\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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
38
libs/parts.h
38
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
|
||||
|
|
Loading…
Reference in New Issue
Block a user