diff --git a/autotest.c b/autotest.c index 869b1a9..c718d36 100644 --- a/autotest.c +++ b/autotest.c @@ -43,7 +43,8 @@ int main(int argc, char** argv) { struct fpga_model model; FILE* dest_f; - int rc; + struct fpga_device* dev; + int iob_y, iob_x, iob_idx, rc; printf("\n"); printf("O fpgatools automatic test suite. Be welcome and be " @@ -64,6 +65,15 @@ int main(int argc, char** argv) // todo: pick 2 input IOBs, one output IOB and configure them // todo: pick 1 logic block and configure + rc = fpga_find_iob(&model, "P46", &iob_y, &iob_x, &iob_idx); + EXIT(rc); + + dev = fpga_dev(&model, iob_y, iob_x, DEV_IOB, iob_idx); + EXIT(!dev); + dev->instantiated = 1; + strcpy(dev->iob.istandard, IO_LVCMOS33); + dev->iob.bypass_mux = BYPASS_MUX_I; + dev->iob.imux = IMUX_I; mkdir(AUTOTEST_TMP_DIR, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); dest_f = fopen(AUTOTEST_TMP_DIR "/test_0001.fp", "w"); diff --git a/control.c b/control.c index 803d25f..bc5c2de 100644 --- a/control.c +++ b/control.c @@ -7,3 +7,169 @@ #include "model.h" #include "control.h" + +struct iob_site +{ + int xy; + const char* name[4]; // left and right only use 2, top and bottom 4 +}; + +static const struct iob_site xc6slx9_iob_top[] = +{ + { 5, {"P144", "P143", "P142", "P141"}}, + { 7, {"P140", "P139", "P138", "P137"}}, + {12, {"UNB9", "UNB10", "UNB11", "UNB12"}}, + {14, {"UNB13", "UNB14", "UNB15", "UNB16"}}, + {19, {"UNB17", "UNB18", "UNB19", "UNB20"}}, + {21, {"P134", "P133", "P132", "P131"}}, + {25, {"P127", "P126", "P124", "P123"}}, + {29, {"UNB29", "UNB30", "UNB31", "UNB32"}}, + {31, {"UNB33", "UNB34", "P121", "P120"}}, + {36, {"P119", "P118", "P117", "P116"}}, + {38, {"P115", "P114", "P112", "P111"}}, +}; + +static const struct iob_site xc6slx9_iob_bottom[] = +{ + { 5, {"P38", "P39", "P40", "P41"}}, + { 7, {"UNB140", "UNB139", "P43", "P44"}}, + {12, {"P45", "P46", "P47", "P48"}}, + {14, {"UNB132", "UNB131", "UNB130", "UNB129"}}, + {19, {"UNB128", "UNB127", "UNB126", "UNB125"}}, + {21, {"UNB124", "UNB123", "P50", "P51"}}, + {25, {"P55", "P56", "UNB118", "UNB117"}}, + {29, {"UNB116", "UNB115", "UNB114", "UNB113"}}, + {31, {"P57", "P58", "P59", "P60"}}, + {36, {"P61", "P62", "P64", "P65"}}, + {38, {"P66", "P67", "P69", "P70"}}, +}; + +static const struct iob_site xc6slx9_iob_left[] = +{ + { 3, {"P1", "P2"}}, + { 5, {"UNB198", "UNB197"}}, + { 7, {"UNB196", "UNB195"}}, + { 9, {"UNB194", "UNB193"}}, + { 11, {"P5", "P6"}}, + { 12, {"P7", "P8"}}, + { 13, {"P9", "P10"}}, + { 14, {"P11", "P12"}}, + { 28, {"UNB184", "UNB183"}}, + { 29, {"UNB182", "UNB181"}}, + { 30, {"UNB180", "UNB179"}}, + { 31, {"UNB178", "UNB177"}}, + { 32, {"P14", "P15"}}, + { 33, {"P16", "P17"}}, + { 37, {"P21", "P22"}}, + { 38, {"P23", "P24"}}, + { 39, {"UNB168", "UNB167"}}, + { 42, {"UNB166", "UNB165"}}, + { 46, {"UNB164", "UNB163"}}, + { 49, {"P26", "P27"}}, + { 52, {"P29", "P30"}}, + { 55, {"UNB158", "UNB157"}}, + { 58, {"UNB156", "UNB155"}}, + { 61, {"UNB154", "UNB153"}}, + { 65, {"UNB152", "UNB151"}}, + { 66, {"UNB150", "UNB149"}}, + { 67, {"P32", "P33"}}, + { 68, {"P34", "P35"}}, +}; + +static const struct iob_site xc6slx9_iob_right[] = +{ + { 4, {"P105", "P104"}}, + { 5, {"UNB47", "UNB48"}}, + { 7, {"UNB49", "UNB50"}}, + { 9, {"UNB51", "UNB52"}}, + { 11, {"P102", "P101"}}, + { 12, {"P100", "P99"}}, + { 13, {"P98", "P97"}}, + { 14, {"UNB59", "UNB60"}}, + { 28, {"UNB61", "UNB62"}}, + { 29, {"UNB63", "UNB64"}}, + { 30, {"UNB65", "UNB66"}}, + { 31, {"UNB67", "UNB68"}}, + { 32, {"P95", "P94"}}, + { 33, {"P93", "P92"}}, + { 37, {"P88", "P87"}}, + { 38, {"P85", "P84"}}, + { 39, {"UNB77", "UNB78"}}, + { 42, {"P83", "P82"}}, + { 46, {"P81", "P80"}}, + { 49, {"P79", "P78"}}, + { 52, {"UNB85", "UNB86"}}, + { 55, {"UNB87", "UNB88"}}, + { 58, {"UNB89", "UNB90"}}, + { 61, {"UNB91", "UNB92"}}, + { 65, {"UNB93", "UNB94"}}, + { 66, {"UNB95", "UNB96"}}, + { 67, {"UNB97", "UNB98"}}, + { 68, {"P75", "P74"}}, +}; + +int fpga_find_iob(struct fpga_model* model, const char* sitename, + int* y, int* x, int* idx) +{ + int i, j; + + for (i = 0; i < sizeof(xc6slx9_iob_top)/sizeof(xc6slx9_iob_top[0]); i++) { + for (j = 0; j < 4; j++) { + if (!strcmp(xc6slx9_iob_top[i].name[j], sitename)) { + *y = TOP_OUTER_ROW; + *x = xc6slx9_iob_top[i].xy; + *idx = j; + return 0; + } + } + } + for (i = 0; i < sizeof(xc6slx9_iob_bottom)/sizeof(xc6slx9_iob_bottom[0]); i++) { + for (j = 0; j < 4; j++) { + if (!strcmp(xc6slx9_iob_bottom[i].name[j], sitename)) { + *y = model->y_height-BOT_OUTER_ROW; + *x = xc6slx9_iob_bottom[i].xy; + *idx = j; + return 0; + } + } + } + for (i = 0; i < sizeof(xc6slx9_iob_left)/sizeof(xc6slx9_iob_left[0]); i++) { + for (j = 0; j < 2; j++) { + if (!strcmp(xc6slx9_iob_left[i].name[j], sitename)) { + *y = xc6slx9_iob_left[i].xy; + *x = LEFT_OUTER_COL; + *idx = j; + return 0; + } + } + } + for (i = 0; i < sizeof(xc6slx9_iob_right)/sizeof(xc6slx9_iob_right[0]); i++) { + for (j = 0; j < 2; j++) { + if (!strcmp(xc6slx9_iob_right[i].name[j], sitename)) { + *y = xc6slx9_iob_right[i].xy; + *x = model->x_width-RIGHT_OUTER_O; + *idx = j; + return 0; + } + } + } + return -1; +} + +struct fpga_device* fpga_dev(struct fpga_model* model, + int y, int x, enum fpgadev_type type, int idx) +{ + struct fpga_tile* tile; + int type_count, i; + + tile = YX_TILE(model, y, x); + type_count = 0; + for (i = 0; i < tile->num_devices; i++) { + if (tile->devices[i].type == type) { + if (type_count == idx) + return &tile->devices[i]; + type_count++; + } + } + return 0; +} diff --git a/control.h b/control.h index 0d6562e..8cfd597 100644 --- a/control.h +++ b/control.h @@ -4,3 +4,9 @@ // This is free and unencumbered software released into the public domain. // For details see the UNLICENSE file at the root of the source tree. // + +int fpga_find_iob(struct fpga_model* model, const char* sitename, + int* y, int* x, int* idx); + +struct fpga_device* fpga_dev(struct fpga_model* model, + int y, int x, enum fpgadev_type type, int idx); diff --git a/floorplan.c b/floorplan.c index b421437..3276839 100644 --- a/floorplan.c +++ b/floorplan.c @@ -84,11 +84,9 @@ int printf_devices(FILE* f, struct fpga_model* model, int config_only) case DEV_TIEOFF: fprintf(f, "device y%02i x%02i TIEOFF\n", y, x); break; - case DEV_IOBM: - fprintf(f, "device y%02i x%02i IOBM\n", y, x); - break; - case DEV_IOBS: - fprintf(f, "device y%02i x%02i IOBS\n", y, x); + case DEV_IOB: + fprintf(f, "device y%02i x%02i %s\n", y, x, + tile->devices[i].iob.type == IOBM ? "IOBM" : "IOBS"); break; case DEV_ILOGIC: fprintf(f, "device y%02i x%02i ILOGIC2\n", y, x); @@ -130,7 +128,7 @@ int printf_devices(FILE* f, struct fpga_model* model, int config_only) fprintf(f, "device y%02i x%02i DCM\n", y, x); break; case DEV_PLL: - fprintf(f, "device y%02i x%02i PLL\n", y, x); + fprintf(f, "device y%02i x%02i PLL_ADV\n", y, x); break; case DEV_ICAP: fprintf(f, "device y%02i x%02i ICAP\n", y, x); diff --git a/model.h b/model.h index e9b6fb0..0ce903a 100644 --- a/model.h +++ b/model.h @@ -276,8 +276,7 @@ enum fpgadev_type DEV_LOGIC_X, DEV_TIEOFF, DEV_MACC, - DEV_IOBM, - DEV_IOBS, + DEV_IOB, DEV_ILOGIC, DEV_OLOGIC, DEV_IODELAY, @@ -320,6 +319,7 @@ struct fpgadev_logic_m int c; }; +enum { IOBM = 1, IOBS }; typedef char IOSTANDARD[32]; #define IO_LVCMOS33 "LVCMOS33" enum { BYPASS_MUX_I = 1, BYPASS_MUX_O, BYPASS_MUX_T }; @@ -334,6 +334,7 @@ enum { OTERM_NONE = 1, OTERM_UNTUNED_25, OTERM_UNTUNED_50, struct fpgadev_iob { + int type; IOSTANDARD istandard; IOSTANDARD ostandard; int bypass_mux; diff --git a/model_conns.c b/model_conns.c index ce5da14..d85d488 100644 --- a/model_conns.c +++ b/model_conns.c @@ -760,7 +760,7 @@ static int run_io_wires(struct fpga_model* model) for (x = LEFT_SIDE_WIDTH; x < model->x_width - RIGHT_SIDE_WIDTH; x++) { y = 0; - if (has_device(model, y, x, DEV_IOBM)) { + if (has_device(model, y, x, DEV_IOB)) { for (i = 0; s[i][0]; i++) { struct w_net net1 = { 1, @@ -784,7 +784,7 @@ static int run_io_wires(struct fpga_model* model) } y = model->y_height - BOT_OUTER_ROW; - if (has_device(model, y, x, DEV_IOBM)) { + if (has_device(model, y, x, DEV_IOB)) { for (i = 0; s[i][0]; i++) { struct w_net net1 = { 1, diff --git a/model_devices.c b/model_devices.c index 6d95343..9a790ca 100644 --- a/model_devices.c +++ b/model_devices.c @@ -169,8 +169,10 @@ int init_devices(struct fpga_model* model) for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { if (is_aty(Y_LEFT_WIRED, model, y)) { tile = YX_TILE(model, y, x); - tile->devices[tile->num_devices++].type = DEV_IOBM; - tile->devices[tile->num_devices++].type = DEV_IOBS; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBM; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBS; } } } @@ -178,24 +180,34 @@ int init_devices(struct fpga_model* model) for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { if (is_aty(Y_RIGHT_WIRED, model, y)) { tile = YX_TILE(model, y, x); - tile->devices[tile->num_devices++].type = DEV_IOBM; - tile->devices[tile->num_devices++].type = DEV_IOBS; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBM; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBS; } } } if (is_atx(X_FABRIC_LOGIC_ROUTING_COL|X_CENTER_ROUTING_COL, model, x) && !is_atx(X_ROUTING_NO_IO, model, x)) { tile = YX_TILE(model, TOP_OUTER_ROW, x); - tile->devices[tile->num_devices++].type = DEV_IOBM; - tile->devices[tile->num_devices++].type = DEV_IOBM; - tile->devices[tile->num_devices++].type = DEV_IOBS; - tile->devices[tile->num_devices++].type = DEV_IOBS; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBM; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBS; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBM; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBS; tile = YX_TILE(model, model->y_height-BOT_OUTER_ROW, x); - tile->devices[tile->num_devices++].type = DEV_IOBM; - tile->devices[tile->num_devices++].type = DEV_IOBM; - tile->devices[tile->num_devices++].type = DEV_IOBS; - tile->devices[tile->num_devices++].type = DEV_IOBS; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBM; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBS; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBM; + tile->devices[tile->num_devices].type = DEV_IOB; + tile->devices[tile->num_devices++].iob.type = IOBS; } } diff --git a/model_switches.c b/model_switches.c index e97cef3..c61180a 100644 --- a/model_switches.c +++ b/model_switches.c @@ -580,24 +580,24 @@ static int init_io_switches(struct fpga_model* model) int x, y, rc; for (x = 0; x < model->x_width; x++) { - if (has_device(model, /*y*/ 0, x, DEV_IOBM)) { + if (has_device(model, /*y*/ 0, x, DEV_IOB)) { rc = init_io_tile(model, 0, x); if (rc) goto xout; } if (has_device(model, model->y_height - BOT_OUTER_ROW, x, - DEV_IOBM)) { + DEV_IOB)) { rc = init_io_tile(model, model->y_height-BOT_OUTER_ROW, x); if (rc) goto xout; } } for (y = 0; y < model->y_height; y++) { - if (has_device(model, y, /*x*/ 0, DEV_IOBM)) { + if (has_device(model, y, /*x*/ 0, DEV_IOB)) { rc = init_io_tile(model, y, 0); if (rc) goto xout; } if (has_device(model, y, model->x_width - RIGHT_OUTER_O, - DEV_IOBM)) { + DEV_IOB)) { rc = init_io_tile(model, y, model->x_width - RIGHT_OUTER_O); if (rc) goto xout;