diff --git a/Makefile b/Makefile index 2a1fc3b..7a168e3 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ xc6slx9_empty.fp: new_fp xc6slx9.svg: draw_svg_tiles ./draw_svg_tiles | xmllint --pretty 1 - > $@ -compare_all: compare.tiles compare.devices compare.conns compare.ports compare.sw +compare_all: compare.tiles compare.devs compare.conns compare.ports compare.sw compare.%: xc6slx9_empty.% @comm -1 -2 $< compare_other.$* > compare_$*_matching.txt @@ -92,11 +92,11 @@ compare.%: xc6slx9_empty.% %.tiles: %.fp @cat $<|awk '{if ($$1=="tile" && $$4=="name") printf "%s %s %s\n",$$2,$$3,$$5}'|sort >$@ -%.devices: %.fp - @cat $<|awk '{if ($$1=="device") printf "%s %s %s\n",$$2,$$3,$$4}'|sort >$@ +%.devs: %.fp + @cat $<|awk '{if ($$1=="dev") {if ($$6=="type") printf "%s %s %s %s\n",$$2,$$3,$$4,$$7; else printf "%s %s %s\n",$$2,$$3,$$4; }}'|sort >$@ %.nets: %.fp pair2net - cat $<|awk '{if ($$1=="static_conn") printf "%s-%s-%s %s-%s-%s\n",$$2,$$3,$$4,$$5,$$6,$$7}' |./pair2net -|sort >$@ + cat $<|awk '{if ($$1=="conn") printf "%s-%s-%s %s-%s-%s\n",$$2,$$3,$$4,$$5,$$6,$$7}' |./pair2net -|sort >$@ @echo Number of nets: @cat $@|wc -l @echo Number of connection points: @@ -105,13 +105,13 @@ compare.%: xc6slx9_empty.% @cat $@|awk '{if (NF>max) max=NF} END {print max}' %.conns: %.fp sort_seq merge_seq - @cat $<|awk '{if ($$1=="static_conn") printf "%s %s %s %s %s %s\n",$$2,$$3,$$5,$$6,$$4,$$7}'|sort|./sort_seq -|./merge_seq -|awk '{printf "%s %s %s %s %s %s\n",$$1,$$2,$$5,$$3,$$4,$$6}'|sort >$@ + @cat $<|awk '{if ($$1=="conn") printf "%s %s %s %s %s %s\n",$$2,$$3,$$5,$$6,$$4,$$7}'|sort|./sort_seq -|./merge_seq -|awk '{printf "%s %s %s %s %s %s\n",$$1,$$2,$$5,$$3,$$4,$$6}'|sort >$@ %.ports: %.fp @cat $<|awk '{if ($$1=="port") printf "%s %s %s\n",$$2,$$3,$$4}'|sort >$@ %.sw: %.fp - @cat $<|awk '{if ($$1=="switch") printf "%s %s %s %s %s\n",$$2,$$3,$$4,$$5,$$6}'|sort >$@ + @cat $<|awk '{if ($$1=="sw") printf "%s %s %s %s %s\n",$$2,$$3,$$4,$$5,$$6}'|sort >$@ clean: rm -f bit2txt bit2txt.o \ @@ -122,12 +122,12 @@ clean: merge_seq merge_seq.o \ autotest.o control.o floorplan.o \ xc6slx9_empty.fp xc6slx9.svg \ - xc6slx9_empty.tiles xc6slx9_empty.devices xc6slx9_empty.conns \ + xc6slx9_empty.tiles xc6slx9_empty.devs xc6slx9_empty.conns \ xc6slx9_empty.ports xc6slx9_empty.sw xc6slx9_empty.nets \ - compare_other.tiles compare_other.devices compare_other.conns compare_other.ports \ + compare_other.tiles compare_other.devs compare_other.conns compare_other.ports \ compare_other.sw compare_other.nets \ compare_tiles_matching.txt compare_tiles_diff.txt compare_tiles_extra.txt \ - compare_devices_matching.txt compare_devices_diff.txt compare_devices_extra.txt \ + compare_devs_matching.txt compare_devs_diff.txt compare_devs_extra.txt \ compare_conns_matching.txt compare_conns_diff.txt compare_conns_extra.txt \ compare_ports_matching.txt compare_ports_diff.txt compare_ports_extra.txt \ compare_sw_matching.txt compare_sw_diff.txt compare_sw_extra.txt \ diff --git a/autotest.c b/autotest.c index c718d36..af6ffe0 100644 --- a/autotest.c +++ b/autotest.c @@ -63,17 +63,29 @@ int main(int argc, char** argv) printf("O Done\n"); TIME_AND_MEM(); - // todo: pick 2 input IOBs, one output IOB and configure them - // todo: pick 1 logic block and configure + // configure P46 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; + dev->iob.I_mux = IMUX_I; + + // configure P48 + rc = fpga_find_iob(&model, "P48", &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.ostandard, IO_LVCMOS33); + dev->iob.drive_strength = 12; + dev->iob.O_used = 1; + dev->iob.slew = SLEW_SLOW; + dev->iob.suspend = SUSP_3STATE; + + // todo: configure logic 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 bc5c2de..ea5595f 100644 --- a/control.c +++ b/control.c @@ -164,10 +164,10 @@ struct fpga_device* fpga_dev(struct fpga_model* model, tile = YX_TILE(model, y, x); type_count = 0; - for (i = 0; i < tile->num_devices; i++) { - if (tile->devices[i].type == type) { + for (i = 0; i < tile->num_devs; i++) { + if (tile->devs[i].type == type) { if (type_count == idx) - return &tile->devices[i]; + return &tile->devs[i]; type_count++; } } diff --git a/floorplan.c b/floorplan.c index 3276839..fd4b82a 100644 --- a/floorplan.c +++ b/floorplan.c @@ -5,6 +5,8 @@ // For details see the UNLICENSE file at the root of the source tree. // +#include + #include "model.h" #include "floorplan.h" @@ -57,105 +59,288 @@ int printf_tiles(FILE* f, struct fpga_model* model) return 0; } +static void printf_wrap(FILE* f, char* line, int prefix_len, + const char* fmt, ...) +{ + va_list list; + int i; + + va_start(list, fmt); + i = strlen(line); + if (i >= 80) { + line[i] = '\n'; + line[i+1] = 0; + fprintf(f, line); + line[prefix_len] = 0; + i = prefix_len; + } + line[i] = ' '; + vsnprintf(&line[i+1], 256, fmt, list); + va_end(list); +} + +static int printf_IOB(FILE* f, struct fpga_model* model, + int y, int x, int config_only) +{ + struct fpga_tile* tile; + char line[1024]; + int type_count, plen, i; + + tile = YX_TILE(model, y, x); + type_count = 0; + for (i = 0; i < tile->num_devs; i++) { + if (tile->devs[i].type != DEV_IOB) + continue; + if (config_only && !(tile->devs[i].instantiated)) { + type_count++; + continue; + } + snprintf(line, sizeof(line), "dev y%02i x%02i IOB %i", + y, x, type_count); + type_count++; + plen = strlen(line); + + printf_wrap(f, line, plen, "type %s", + tile->devs[i].iob.subtype == IOBM + ? "M" : "S"); + if (tile->devs[i].iob.istandard[0]) + printf_wrap(f, line, plen, "istd %s", + tile->devs[i].iob.istandard); + if (tile->devs[i].iob.ostandard[0]) + printf_wrap(f, line, plen, "ostd %s", + tile->devs[i].iob.ostandard); + switch (tile->devs[i].iob.bypass_mux) { + case BYPASS_MUX_I: + printf_wrap(f, line, plen, "bypass_mux I"); + break; + case BYPASS_MUX_O: + printf_wrap(f, line, plen, "bypass_mux O"); + break; + case BYPASS_MUX_T: + printf_wrap(f, line, plen, "bypass_mux T"); + break; + case 0: break; default: EXIT(1); + } + switch (tile->devs[i].iob.I_mux) { + case IMUX_I_B: + printf_wrap(f, line, plen, "imux I_B"); + break; + case IMUX_I: + printf_wrap(f, line, plen, "imux I"); + break; + case 0: break; default: EXIT(1); + } + if (tile->devs[i].iob.drive_strength) + printf_wrap(f, line, plen, "strength %i", + tile->devs[i].iob.drive_strength); + switch (tile->devs[i].iob.slew) { + case SLEW_SLOW: + printf_wrap(f, line, plen, "slew SLOW"); + break; + case SLEW_FAST: + printf_wrap(f, line, plen, "slew FAST"); + break; + case SLEW_QUIETIO: + printf_wrap(f, line, plen, "slew QUIETIO"); + break; + case 0: break; default: EXIT(1); + } + if (tile->devs[i].iob.O_used) + printf_wrap(f, line, plen, "o_used"); + switch (tile->devs[i].iob.suspend) { + case SUSP_LAST_VAL: + printf_wrap(f, line, plen, "suspend DRIVE_LAST_VALUE"); + break; + case SUSP_3STATE: + printf_wrap(f, line, plen, "suspend 3STATE"); + break; + case SUSP_3STATE_PULLUP: + printf_wrap(f, line, plen, "suspend 3STATE_PULLUP"); + break; + case SUSP_3STATE_PULLDOWN: + printf_wrap(f, line, plen, "suspend 3STATE_PULLDOWN"); + break; + case SUSP_3STATE_KEEPER: + printf_wrap(f, line, plen, "suspend 3STATE_KEEPER"); + break; + case SUSP_3STATE_OCT_ON: + printf_wrap(f, line, plen, "suspend 3STATE_OCT_ON"); + break; + case 0: break; default: EXIT(1); + } + switch (tile->devs[i].iob.in_term) { + case ITERM_NONE: + printf_wrap(f, line, plen, "in_term NONE"); + break; + case ITERM_UNTUNED_25: + printf_wrap(f, line, plen, "in_term UNTUNED_SPLIT_25"); + break; + case ITERM_UNTUNED_50: + printf_wrap(f, line, plen, "in_term UNTUNED_SPLIT_50"); + break; + case ITERM_UNTUNED_75: + printf_wrap(f, line, plen, "in_term UNTUNED_SPLIT_75"); + break; + case 0: break; default: EXIT(1); + } + switch (tile->devs[i].iob.out_term) { + case OTERM_NONE: + printf_wrap(f, line, plen, "out_term NONE"); + break; + case OTERM_UNTUNED_25: + printf_wrap(f, line, plen, "out_term UNTUNED_25"); + break; + case OTERM_UNTUNED_50: + printf_wrap(f, line, plen, "out_term UNTUNED_50"); + break; + case OTERM_UNTUNED_75: + printf_wrap(f, line, plen, "out_term UNTUNED_75"); + break; + case 0: break; default: EXIT(1); + } + strcat(line, "\n"); + fprintf(f, line); + } + return 0; +} + +static int printf_LOGIC(FILE* f, struct fpga_model* model, + int y, int x, int config_only) +{ + struct fpga_tile* tile; + char line[1024]; + int type_count, plen, i; + + tile = YX_TILE(model, y, x); + type_count = 0; + for (i = 0; i < tile->num_devs; i++) { + if (tile->devs[i].type != DEV_LOGIC) + continue; + if (config_only && !(tile->devs[i].instantiated)) { + type_count++; + continue; + } + snprintf(line, sizeof(line), "dev y%02i x%02i LOGIC %i", + y, x, type_count); + type_count++; + plen = strlen(line); + + switch (tile->devs[i].logic.subtype) { + case LOGIC_X: + printf_wrap(f, line, plen, "type X"); + break; + case LOGIC_L: + printf_wrap(f, line, plen, "type L"); + break; + case LOGIC_M: + printf_wrap(f, line, plen, "type M"); + break; + default: EXIT(1); + } + strcat(line, "\n"); + fprintf(f, line); + } + return 0; +} + int printf_devices(FILE* f, struct fpga_model* model, int config_only) { - int x, y, i; + int x, y, i, rc; struct fpga_tile* tile; for (x = 0; x < model->x_width; x++) { for (y = 0; y < model->y_height; y++) { + + rc = printf_IOB(f, model, y, x, config_only); + if (rc) goto fail; + rc = printf_LOGIC(f, model, y, x, config_only); + if (rc) goto fail; + tile = YX_TILE(model, y, x); - for (i = 0; i < tile->num_devices; i++) { - if (config_only && !(tile->devices[i].instantiated)) + for (i = 0; i < tile->num_devs; i++) { + if (config_only && !(tile->devs[i].instantiated)) continue; - switch (tile->devices[i].type) { - case DEV_LOGIC_M: - fprintf(f, "device y%02i x%02i SLICEM\n", y, x); - break; - case DEV_LOGIC_L: - fprintf(f, "device y%02i x%02i SLICEL\n", y, x); - break; - case DEV_LOGIC_X: - fprintf(f, "device y%02i x%02i SLICEX\n", y, x); - break; + switch (tile->devs[i].type) { case DEV_MACC: - fprintf(f, "device y%02i x%02i DSP48A1\n", y, x); + fprintf(f, "dev y%02i x%02i DSP48A1\n", y, x); break; case DEV_TIEOFF: - fprintf(f, "device y%02i x%02i TIEOFF\n", y, x); - break; - case DEV_IOB: - fprintf(f, "device y%02i x%02i %s\n", y, x, - tile->devices[i].iob.type == IOBM ? "IOBM" : "IOBS"); + fprintf(f, "dev y%02i x%02i TIEOFF\n", y, x); break; case DEV_ILOGIC: - fprintf(f, "device y%02i x%02i ILOGIC2\n", y, x); + fprintf(f, "dev y%02i x%02i ILOGIC\n", y, x); break; case DEV_OLOGIC: - fprintf(f, "device y%02i x%02i OLOGIC2\n", y, x); + fprintf(f, "dev y%02i x%02i OLOGIC\n", y, x); break; case DEV_IODELAY: - fprintf(f, "device y%02i x%02i IODELAY2\n", y, x); + fprintf(f, "dev y%02i x%02i IODELAY\n", y, x); break; case DEV_BRAM16: - fprintf(f, "device y%02i x%02i RAMB16BWER\n", y, x); + fprintf(f, "dev y%02i x%02i RAMB16\n", y, x); break; case DEV_BRAM8: - fprintf(f, "device y%02i x%02i RAMB8BWER\n", y, x); + fprintf(f, "dev y%02i x%02i RAMB8\n", y, x); break; case DEV_BUFH: - fprintf(f, "device y%02i x%02i BUFH\n", y, x); + fprintf(f, "dev y%02i x%02i BUFH\n", y, x); break; case DEV_BUFIO: - fprintf(f, "device y%02i x%02i BUFIO2\n", y, x); + fprintf(f, "dev y%02i x%02i BUFIO2\n", y, x); break; case DEV_BUFIO_FB: - fprintf(f, "device y%02i x%02i BUFIO2FB\n", y, x); + fprintf(f, "dev y%02i x%02i BUFIO2FB\n", y, x); break; case DEV_BUFPLL: - fprintf(f, "device y%02i x%02i BUFPLL\n", y, x); + fprintf(f, "dev y%02i x%02i BUFPLL\n", y, x); break; case DEV_BUFPLL_MCB: - fprintf(f, "device y%02i x%02i BUFPLL_MCB\n", y, x); + fprintf(f, "dev y%02i x%02i BUFPLL_MCB\n", y, x); break; case DEV_BUFGMUX: - fprintf(f, "device y%02i x%02i BUFGMUX\n", y, x); + fprintf(f, "dev y%02i x%02i BUFGMUX\n", y, x); break; case DEV_BSCAN: - fprintf(f, "device y%02i x%02i BSCAN\n", y, x); + fprintf(f, "dev y%02i x%02i BSCAN\n", y, x); break; case DEV_DCM: - fprintf(f, "device y%02i x%02i DCM\n", y, x); + fprintf(f, "dev y%02i x%02i DCM\n", y, x); break; case DEV_PLL: - fprintf(f, "device y%02i x%02i PLL_ADV\n", y, x); + fprintf(f, "dev y%02i x%02i PLL\n", y, x); break; case DEV_ICAP: - fprintf(f, "device y%02i x%02i ICAP\n", y, x); + fprintf(f, "dev y%02i x%02i ICAP\n", y, x); break; case DEV_POST_CRC_INTERNAL: - fprintf(f, "device y%02i x%02i POST_CRC_INTERNAL\n", y, x); + fprintf(f, "dev y%02i x%02i POST_CRC_INTERNAL\n", y, x); break; case DEV_STARTUP: - fprintf(f, "device y%02i x%02i STARTUP\n", y, x); + fprintf(f, "dev y%02i x%02i STARTUP\n", y, x); break; case DEV_SLAVE_SPI: - fprintf(f, "device y%02i x%02i SLAVE_SPI\n", y, x); + fprintf(f, "dev y%02i x%02i SLAVE_SPI\n", y, x); break; case DEV_SUSPEND_SYNC: - fprintf(f, "device y%02i x%02i SUSPEND_SYNC\n", y, x); + fprintf(f, "dev y%02i x%02i SUSPEND_SYNC\n", y, x); break; case DEV_OCT_CALIBRATE: - fprintf(f, "device y%02i x%02i OCT_CALIBRATE\n", y, x); + fprintf(f, "dev y%02i x%02i OCT_CALIBRATE\n", y, x); break; case DEV_SPI_ACCESS: - fprintf(f, "device y%02i x%02i SPI_ACCESS\n", y, x); + fprintf(f, "dev y%02i x%02i SPI_ACCESS\n", y, x); + break; + case DEV_IOB: + case DEV_LOGIC: + // to suppress compiler warning break; } } } } return 0; +fail: + return rc; } int printf_ports(FILE* f, struct fpga_model* model) @@ -241,7 +426,7 @@ int printf_conns(FILE* f, struct fpga_model* model) first_conn_printed = 1; fprintf(f, "\n"); } - sprintf(tmp_line, "static_conn y%02i x%02i %s ", + sprintf(tmp_line, "conn y%02i x%02i %s ", y, x, conn_point_name_src); k = strlen(tmp_line); while (k < 45) @@ -290,7 +475,7 @@ int printf_switches(FILE* f, struct fpga_model* model, int enabled_only) first_switch_printed = 1; fprintf(f, "\n"); } - fprintf(f, "switch y%02i x%02i %s %s %s\n", + fprintf(f, "sw y%02i x%02i %s %s %s\n", y, x, from_str, is_bidirectional ? "<->" : "->", to_str); } diff --git a/model.h b/model.h index 0ce903a..faa0414 100644 --- a/model.h +++ b/model.h @@ -271,9 +271,7 @@ const char* logicin_s(int wire, int routing_io); enum fpgadev_type { - DEV_LOGIC_M, - DEV_LOGIC_L, - DEV_LOGIC_X, + DEV_LOGIC, DEV_TIEOFF, DEV_MACC, DEV_IOB, @@ -304,19 +302,13 @@ enum fpgadev_type // 0 is never a valid configured setting. That way all config // data can safely be initialized to 0 meaning unconfigured. -struct fpgadev_logic_x -{ - int a; -}; +enum { LOGIC_M = 1, LOGIC_L, LOGIC_X }; -struct fpgadev_logic_l +struct fpgadev_logic { - int b; -}; - -struct fpgadev_logic_m -{ - int c; + int subtype; // LOGIC_M, LOGIC_L or LOGIC_X + int A_used, B_used, C_used, D_used; + char* A6_lut, *B6_lut, *C6_lut, *D6_lut; }; enum { IOBM = 1, IOBS }; @@ -334,14 +326,14 @@ enum { OTERM_NONE = 1, OTERM_UNTUNED_25, OTERM_UNTUNED_50, struct fpgadev_iob { - int type; + int subtype; // IOBM or IOBS IOSTANDARD istandard; IOSTANDARD ostandard; int bypass_mux; - int imux; + int I_mux; int drive_strength; // supports 2,4,6,8,12,16 and 24 int slew; - int o_used; + int O_used; int suspend; int in_term; int out_term; @@ -352,9 +344,7 @@ struct fpga_device enum fpgadev_type type; int instantiated; union { - struct fpgadev_logic_m log_m; - struct fpgadev_logic_l log_l; - struct fpgadev_logic_x log_x; + struct fpgadev_logic logic; struct fpgadev_iob iob; }; }; @@ -368,9 +358,9 @@ struct fpga_tile enum fpga_tile_type type; int flags; - // we currently support a maximum of 32 devices per tile - int num_devices; - struct fpga_device devices[32]; + // expect up to 64 devices per tile + int num_devs; + struct fpga_device* devs; // expect up to 5k connection point names per tile // 2*16 bit per entry @@ -407,6 +397,7 @@ int init_tiles(struct fpga_model* model); int init_conns(struct fpga_model* model); int init_ports(struct fpga_model* model); int init_devices(struct fpga_model* model); +void free_devices(struct fpga_model* model); int init_switches(struct fpga_model* model); const char* pf(const char* fmt, ...); @@ -417,6 +408,7 @@ int has_connpt(struct fpga_model* model, int y, int x, const char* name); int add_connpt_name(struct fpga_model* model, int y, int x, const char* connpt_name); int has_device(struct fpga_model* model, int y, int x, int dev); +int has_device_type(struct fpga_model* model, int y, int x, int dev, int subtype); int add_connpt_2(struct fpga_model* model, int y, int x, const char* connpt_name, const char* suffix1, const char* suffix2); diff --git a/model_conns.c b/model_conns.c index d85d488..1dc05eb 100644 --- a/model_conns.c +++ b/model_conns.c @@ -61,9 +61,9 @@ static int connect_logic_carry(struct fpga_model* model) for (x = 0; x < model->x_width; x++) { if (is_atx(X_LOGIC_COL, model, x)) { for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { - if (has_device(model, y, x, DEV_LOGIC_M)) { + if (has_device_type(model, y, x, DEV_LOGIC, LOGIC_M)) { if (is_aty(Y_CHIP_HORIZ_REGS, model, y-1) - && has_device(model, y-2, x, DEV_LOGIC_M)) { + && has_device_type(model, y-2, x, DEV_LOGIC, LOGIC_M)) { struct w_net net = { 0, {{ "M_CIN", 0, y-2, x }, @@ -72,7 +72,7 @@ static int connect_logic_carry(struct fpga_model* model) { "" }}}; if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) goto xout; } else if (is_aty(Y_ROW_HORIZ_AXSYMM, model, y-1) - && has_device(model, y-2, x, DEV_LOGIC_M)) { + && has_device_type(model, y-2, x, DEV_LOGIC, LOGIC_M)) { struct w_net net = { 0, {{ "M_CIN", 0, y-2, x }, @@ -80,7 +80,7 @@ static int connect_logic_carry(struct fpga_model* model) { "M_COUT_N", 0, y, x }, { "" }}}; if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) goto xout; - } else if (has_device(model, y-1, x, DEV_LOGIC_M)) { + } else if (has_device_type(model, y-1, x, DEV_LOGIC, LOGIC_M)) { if ((rc = add_conn_bi(model, y, x, "M_COUT_N", y-1, x, "M_CIN"))) goto xout; } } @@ -120,13 +120,13 @@ static int connect_clk_sr(struct fpga_model* model, const char* clk_sr) } if (is_atx(X_FABRIC_LOGIC_ROUTING_COL|X_CENTER_ROUTING_COL, model, x)) { for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { - if (has_device(model, y, x+1, DEV_LOGIC_M)) { + if (has_device_type(model, y, x+1, DEV_LOGIC, LOGIC_M)) { if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, pf("%s%%i", clk_sr), 0, 1, y, x+1, pf("CLEXM_%s%%i", clk_sr), 0))) goto xout; - } else if (has_device(model, y, x+1, DEV_LOGIC_L)) { + } else if (has_device_type(model, y, x+1, DEV_LOGIC, LOGIC_L)) { if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, pf("%s%%i", clk_sr), 0, 1, diff --git a/model_devices.c b/model_devices.c index 9a790ca..05a6832 100644 --- a/model_devices.c +++ b/model_devices.c @@ -8,241 +8,297 @@ #include #include "model.h" +void free_devices(struct fpga_model* model) +{ + int i, j; + for (i = 0; i < model->x_width * model->y_height; i++) { + if (!model->tiles[i].num_devs) + continue; + EXIT(!model->tiles[i].devs); + for (j = 0; j < model->tiles[i].num_devs; j++) { + if (model->tiles[i].devs[j].type != DEV_LOGIC) + continue; + free(model->tiles[i].devs[i].logic.A6_lut); + model->tiles[i].devs[i].logic.A6_lut = 0; + free(model->tiles[i].devs[i].logic.B6_lut); + model->tiles[i].devs[i].logic.B6_lut = 0; + free(model->tiles[i].devs[i].logic.C6_lut); + model->tiles[i].devs[i].logic.C6_lut = 0; + free(model->tiles[i].devs[i].logic.D6_lut); + model->tiles[i].devs[i].logic.D6_lut = 0; + } + free(model->tiles[i].devs); + model->tiles[i].devs = 0; + model->tiles[i].num_devs = 0; + } +} + +#define DEV_INCREMENT 8 + +static int add_dev(struct fpga_model* model, + int y, int x, int type, int subtype) +{ + struct fpga_tile* tile = YX_TILE(model, y, x); + if (!(tile->num_devs % DEV_INCREMENT)) { + void* new_ptr = realloc(tile->devs, + (tile->num_devs+DEV_INCREMENT)*sizeof(*tile->devs)); + EXIT(!new_ptr); + memset(new_ptr + tile->num_devs * sizeof(*tile->devs), 0, DEV_INCREMENT*sizeof(*tile->devs)); + tile->devs = new_ptr; + } + tile->devs[tile->num_devs].type = type; + if (type == DEV_IOB) + tile->devs[tile->num_devs].iob.subtype = subtype; + else if (type == DEV_LOGIC) + tile->devs[tile->num_devs].logic.subtype = subtype; + tile->num_devs++; + return 0; +} + int init_devices(struct fpga_model* model) { - int x, y, i, j; - struct fpga_tile* tile; + int x, y, i, j, rc; - // DCM, PLL_ADV + // DCM, PLL for (i = 0; i < model->cfg_rows; i++) { - y = TOP_IO_TILES + HALF_ROW + i*ROW_SIZE; + y = TOP_IO_TILES + HALF_ROW-1 + i*ROW_SIZE; if (y > model->center_y) y++; // central regs - tile = YX_TILE(model, y-1, model->center_x-CENTER_CMTPLL_O); + x = model->center_x-CENTER_CMTPLL_O; if (i%2) { - tile->devices[tile->num_devices++].type = DEV_DCM; - tile->devices[tile->num_devices++].type = DEV_DCM; + if ((rc = add_dev(model, y, x, DEV_DCM, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_DCM, 0))) goto fail; } else - tile->devices[tile->num_devices++].type = DEV_PLL; + if ((rc = add_dev(model, y, x, DEV_PLL, 0))) goto fail; } // BSCAN - tile = YX_TILE(model, TOP_IO_TILES, model->x_width-RIGHT_IO_DEVS_O); - tile->devices[tile->num_devices++].type = DEV_BSCAN; - tile->devices[tile->num_devices++].type = DEV_BSCAN; + y = TOP_IO_TILES; + x = model->x_width-RIGHT_IO_DEVS_O; + if ((rc = add_dev(model, y, x, DEV_BSCAN, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BSCAN, 0))) goto fail; // BSCAN, OCT_CALIBRATE - tile = YX_TILE(model, TOP_IO_TILES+1, model->x_width-RIGHT_IO_DEVS_O); - tile->devices[tile->num_devices++].type = DEV_BSCAN; - tile->devices[tile->num_devices++].type = DEV_BSCAN; - tile->devices[tile->num_devices++].type = DEV_OCT_CALIBRATE; + y = TOP_IO_TILES+1; + x = model->x_width-RIGHT_IO_DEVS_O; + if ((rc = add_dev(model, y, x, DEV_BSCAN, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BSCAN, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_OCT_CALIBRATE, 0))) goto fail; // ICAP, SPI_ACCESS, OCT_CALIBRATE - tile = YX_TILE(model, model->y_height-BOT_IO_TILES-1, - model->x_width-RIGHT_IO_DEVS_O); - tile->devices[tile->num_devices++].type = DEV_ICAP; - tile->devices[tile->num_devices++].type = DEV_SPI_ACCESS; - tile->devices[tile->num_devices++].type = DEV_OCT_CALIBRATE; + y = model->y_height-BOT_IO_TILES-1; + x = model->x_width-RIGHT_IO_DEVS_O; + if ((rc = add_dev(model, y, x, DEV_ICAP, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_SPI_ACCESS, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_OCT_CALIBRATE, 0))) goto fail; // STARTUP, POST_CRC_INTERNAL, SLAVE_SPI, SUSPEND_SYNC - tile = YX_TILE(model, model->y_height-BOT_IO_TILES-2, - model->x_width-RIGHT_IO_DEVS_O); - tile->devices[tile->num_devices++].type = DEV_STARTUP; - tile->devices[tile->num_devices++].type = DEV_POST_CRC_INTERNAL; - tile->devices[tile->num_devices++].type = DEV_SLAVE_SPI; - tile->devices[tile->num_devices++].type = DEV_SUSPEND_SYNC; + y = model->y_height-BOT_IO_TILES-2; + x = model->x_width-RIGHT_IO_DEVS_O; + if ((rc = add_dev(model, y, x, DEV_STARTUP, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_POST_CRC_INTERNAL, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_SLAVE_SPI, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_SUSPEND_SYNC, 0))) goto fail; // BUFGMUX - tile = YX_TILE(model, model->center_y, model->center_x); + y = model->center_y; + x = model->center_x; for (i = 0; i < 16; i++) - tile->devices[tile->num_devices++].type = DEV_BUFGMUX; + if ((rc = add_dev(model, y, x, DEV_BUFGMUX, 0))) goto fail; // BUFIO, BUFIO_FB, BUFPLL, BUFPLL_MCB - tile = YX_TILE(model, TOP_OUTER_ROW, model->center_x-CENTER_CMTPLL_O); - tile->devices[tile->num_devices++].type = DEV_BUFPLL; - tile->devices[tile->num_devices++].type = DEV_BUFPLL; - tile->devices[tile->num_devices++].type = DEV_BUFPLL_MCB; + y = TOP_OUTER_ROW; + x = model->center_x-CENTER_CMTPLL_O; + if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFPLL_MCB, 0))) goto fail; for (j = 0; j < 8; j++) { - tile->devices[tile->num_devices++].type = DEV_BUFIO; - tile->devices[tile->num_devices++].type = DEV_BUFIO_FB; + if ((rc = add_dev(model, y, x, DEV_BUFIO, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFIO_FB, 0))) goto fail; } - tile = YX_TILE(model, model->center_y, LEFT_OUTER_COL); - tile->devices[tile->num_devices++].type = DEV_BUFPLL; - tile->devices[tile->num_devices++].type = DEV_BUFPLL; - tile->devices[tile->num_devices++].type = DEV_BUFPLL_MCB; + y = model->center_y; + x = LEFT_OUTER_COL; + if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFPLL_MCB, 0))) goto fail; for (j = 0; j < 8; j++) { - tile->devices[tile->num_devices++].type = DEV_BUFIO; - tile->devices[tile->num_devices++].type = DEV_BUFIO_FB; + if ((rc = add_dev(model, y, x, DEV_BUFIO, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFIO_FB, 0))) goto fail; } - tile = YX_TILE(model, model->center_y, model->x_width - RIGHT_OUTER_O); - tile->devices[tile->num_devices++].type = DEV_BUFPLL; - tile->devices[tile->num_devices++].type = DEV_BUFPLL; - tile->devices[tile->num_devices++].type = DEV_BUFPLL_MCB; + y = model->center_y; + x = model->x_width - RIGHT_OUTER_O; + if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFPLL_MCB, 0))) goto fail; for (j = 0; j < 8; j++) { - tile->devices[tile->num_devices++].type = DEV_BUFIO; - tile->devices[tile->num_devices++].type = DEV_BUFIO_FB; + if ((rc = add_dev(model, y, x, DEV_BUFIO, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFIO_FB, 0))) goto fail; } - tile = YX_TILE(model, model->y_height - BOT_OUTER_ROW, model->center_x-CENTER_CMTPLL_O); - tile->devices[tile->num_devices++].type = DEV_BUFPLL; - tile->devices[tile->num_devices++].type = DEV_BUFPLL; - tile->devices[tile->num_devices++].type = DEV_BUFPLL_MCB; + y = model->y_height - BOT_OUTER_ROW; + x = model->center_x-CENTER_CMTPLL_O; + if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFPLL_MCB, 0))) goto fail; for (j = 0; j < 8; j++) { - tile->devices[tile->num_devices++].type = DEV_BUFIO; - tile->devices[tile->num_devices++].type = DEV_BUFIO_FB; + if ((rc = add_dev(model, y, x, DEV_BUFIO, 0))) goto fail; + if ((rc = add_dev(model, y, x, DEV_BUFIO_FB, 0))) goto fail; } // BUFH for (i = 0; i < model->cfg_rows; i++) { y = TOP_IO_TILES + HALF_ROW + i*ROW_SIZE; if (y > model->center_y) y++; // central regs - tile = YX_TILE(model, y, model->center_x); + x = model->center_x; for (j = 0; j < 32; j++) - tile->devices[tile->num_devices++].type = DEV_BUFH; + if ((rc = add_dev(model, y, x, DEV_BUFH, 0))) goto fail; } // BRAM for (x = 0; x < model->x_width; x++) { - if (is_atx(X_FABRIC_BRAM_COL, model, x)) { - for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { - tile = YX_TILE(model, y, x); - if (tile->flags & TF_BRAM_DEV) { - tile->devices[tile->num_devices++].type = DEV_BRAM16; - tile->devices[tile->num_devices++].type = DEV_BRAM8; - tile->devices[tile->num_devices++].type = DEV_BRAM8; - } - } + if (!is_atx(X_FABRIC_BRAM_COL, model, x)) + continue; + for (y = TOP_IO_TILES; y < model->y_height-BOT_IO_TILES; y++) { + if (!(YX_TILE(model, y, x)->flags & TF_BRAM_DEV)) + continue; + if ((rc = add_dev(model, y, x, DEV_BRAM16, 0))) + goto fail; + if ((rc = add_dev(model, y, x, DEV_BRAM8, 0))) + goto fail; + if ((rc = add_dev(model, y, x, DEV_BRAM8, 0))) + goto fail; } } // MACC for (x = 0; x < model->x_width; x++) { - if (is_atx(X_FABRIC_MACC_COL, model, x)) { - for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { - tile = YX_TILE(model, y, x); - if (tile->flags & TF_MACC_DEV) - tile->devices[tile->num_devices++].type = DEV_MACC; - } + if (!is_atx(X_FABRIC_MACC_COL, model, x)) + continue; + for (y = TOP_IO_TILES; y < model->y_height-BOT_IO_TILES; y++) { + if (!(YX_TILE(model, y, x)->flags & TF_MACC_DEV)) + continue; + if ((rc = add_dev(model, y, x, DEV_MACC, 0))) goto fail; } } // ILOGIC/OLOGIC/IODELAY for (x = LEFT_SIDE_WIDTH; x < model->x_width - RIGHT_SIDE_WIDTH; x++) { - if (is_atx(X_LOGIC_COL, model, x) - && !is_atx(X_ROUTING_NO_IO, model, x-1)) { - for (i = 0; i <= 1; i++) { - tile = YX_TILE(model, TOP_IO_TILES+i, x); - for (j = 0; j <= 1; j++) { - tile->devices[tile->num_devices++].type = DEV_ILOGIC; - tile->devices[tile->num_devices++].type = DEV_OLOGIC; - tile->devices[tile->num_devices++].type = DEV_IODELAY; - } - tile = YX_TILE(model, model->y_height-BOT_IO_TILES-i-1, x); - for (j = 0; j <= 1; j++) { - tile->devices[tile->num_devices++].type = DEV_ILOGIC; - tile->devices[tile->num_devices++].type = DEV_OLOGIC; - tile->devices[tile->num_devices++].type = DEV_IODELAY; - } + if (!is_atx(X_LOGIC_COL, model, x) + || is_atx(X_ROUTING_NO_IO, model, x-1)) + continue; + for (i = 0; i <= 1; i++) { + y = TOP_IO_TILES+i; + for (j = 0; j <= 1; j++) { + if ((rc = add_dev(model, y, x, DEV_ILOGIC, 0))) + goto fail; + if ((rc = add_dev(model, y, x, DEV_OLOGIC, 0))) + goto fail; + if ((rc = add_dev(model, y, x, DEV_IODELAY, 0))) + goto fail; + } + y = model->y_height-BOT_IO_TILES-i-1; + for (j = 0; j <= 1; j++) { + if ((rc = add_dev(model, y, x, DEV_ILOGIC, 0))) + goto fail; + if ((rc = add_dev(model, y, x, DEV_OLOGIC, 0))) + goto fail; + if ((rc = add_dev(model, y, x, DEV_IODELAY, 0))) + goto fail; } } } 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, LEFT_IO_DEVS); + x = LEFT_IO_DEVS; for (j = 0; j <= 1; j++) { - tile->devices[tile->num_devices++].type = DEV_ILOGIC; - tile->devices[tile->num_devices++].type = DEV_OLOGIC; - tile->devices[tile->num_devices++].type = DEV_IODELAY; + if ((rc = add_dev(model, y, x, DEV_ILOGIC, 0))) + goto fail; + if ((rc = add_dev(model, y, x, DEV_OLOGIC, 0))) + goto fail; + if ((rc = add_dev(model, y, x, DEV_IODELAY, 0))) + goto fail; } } if (is_aty(Y_RIGHT_WIRED, model, y)) { - tile = YX_TILE(model, y, model->x_width-RIGHT_IO_DEVS_O); + x = model->x_width-RIGHT_IO_DEVS_O; for (j = 0; j <= 1; j++) { - tile->devices[tile->num_devices++].type = DEV_ILOGIC; - tile->devices[tile->num_devices++].type = DEV_OLOGIC; - tile->devices[tile->num_devices++].type = DEV_IODELAY; + if ((rc = add_dev(model, y, x, DEV_ILOGIC, 0))) + goto fail; + if ((rc = add_dev(model, y, x, DEV_OLOGIC, 0))) + goto fail; + if ((rc = add_dev(model, y, x, DEV_IODELAY, 0))) + goto fail; } } } - // IOB for (x = 0; x < model->x_width; x++) { + // Note that the order of sub-types IOBM and IOBS must match + // the order in the control.c sitename arrays. if (is_atx(X_OUTER_LEFT, model, x)) { 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_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_aty(Y_LEFT_WIRED, model, y)) + continue; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail; } } if (is_atx(X_OUTER_RIGHT, model, x)) { 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_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_aty(Y_RIGHT_WIRED, model, y)) + continue; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail; } } 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_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; + y = TOP_OUTER_ROW; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail; - tile = YX_TILE(model, model->y_height-BOT_OUTER_ROW, x); - 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; + y = model->y_height-BOT_OUTER_ROW; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail; } } // TIEOFF - tile = YX_TILE(model, model->center_y, LEFT_OUTER_COL); - tile->devices[tile->num_devices++].type = DEV_TIEOFF; - tile = YX_TILE(model, model->center_y, model->x_width-RIGHT_OUTER_O); - tile->devices[tile->num_devices++].type = DEV_TIEOFF; - tile = YX_TILE(model, TOP_OUTER_ROW, model->center_x-1); - tile->devices[tile->num_devices++].type = DEV_TIEOFF; - tile = YX_TILE(model, model->y_height-BOT_OUTER_ROW, model->center_x-CENTER_CMTPLL_O); - tile->devices[tile->num_devices++].type = DEV_TIEOFF; + y = model->center_y; + x = LEFT_OUTER_COL; + if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail; + y = model->center_y; + x = model->x_width-RIGHT_OUTER_O; + if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail; + y = TOP_OUTER_ROW; + x = model->center_x-1; + if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail; + y = model->y_height-BOT_OUTER_ROW; + x = model->center_x-CENTER_CMTPLL_O; + if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail; for (x = 0; x < model->x_width; x++) { if (is_atx(X_LEFT_IO_DEVS_COL, model, x)) { 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_TIEOFF; - } + if (!is_aty(Y_LEFT_WIRED, model, y)) + continue; + if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail; } } if (is_atx(X_RIGHT_IO_DEVS_COL, model, x)) { 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_TIEOFF; - } + if (!is_aty(Y_RIGHT_WIRED, model, y)) + continue; + if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail; } } if (is_atx(X_CENTER_CMTPLL_COL, model, x)) { for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { - tile = YX_TILE(model, y, x); - if (tile->flags & TF_PLL_DEV) - tile->devices[tile->num_devices++].type = DEV_TIEOFF; + if (!(YX_TILE(model, y, x)->flags & TF_PLL_DEV)) + continue; + if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail; } } @@ -251,35 +307,35 @@ int init_devices(struct fpga_model* model) if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, model, y)) continue; - tile = YX_TILE(model, y, x); - tile->devices[tile->num_devices++].type = DEV_TIEOFF; + if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail; } } if (is_atx(X_LOGIC_COL, model, x) && !is_atx(X_ROUTING_NO_IO, model, x-1)) { for (i = 0; i <= 1; i++) { - tile = YX_TILE(model, TOP_IO_TILES+i, x); - tile->devices[tile->num_devices++].type = DEV_TIEOFF; - tile = YX_TILE(model, model->y_height-BOT_IO_TILES-i-1, x); - tile->devices[tile->num_devices++].type = DEV_TIEOFF; + y = TOP_IO_TILES+i; + if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail; + y = model->y_height-BOT_IO_TILES-i-1; + if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail; } } } // LOGIC for (x = 0; x < model->x_width; x++) { - if (is_atx(X_LOGIC_COL, model, x)) { - for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { - tile = YX_TILE(model, y, x); - if (tile->flags & TF_LOGIC_XM_DEV) { - tile->devices[tile->num_devices++].type = DEV_LOGIC_X; - tile->devices[tile->num_devices++].type = DEV_LOGIC_M; - } - if (tile->flags & TF_LOGIC_XL_DEV) { - tile->devices[tile->num_devices++].type = DEV_LOGIC_X; - tile->devices[tile->num_devices++].type = DEV_LOGIC_L; - } + if (!is_atx(X_LOGIC_COL, model, x)) + continue; + for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { + if (YX_TILE(model, y, x)->flags & TF_LOGIC_XM_DEV) { + if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_X))) goto fail; + if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_M))) goto fail; + } + if (YX_TILE(model, y, x)->flags & TF_LOGIC_XL_DEV) { + if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_X))) goto fail; + if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_L))) goto fail; } } } return 0; +fail: + return rc; } diff --git a/model_helper.c b/model_helper.c index be31f5a..7c6f32b 100644 --- a/model_helper.c +++ b/model_helper.c @@ -137,13 +137,36 @@ int has_device(struct fpga_model* model, int y, int x, int dev) struct fpga_tile* tile = YX_TILE(model, y, x); int i; - for (i = 0; i < tile->num_devices; i++) { - if (tile->devices[i].type == dev) + for (i = 0; i < tile->num_devs; i++) { + if (tile->devs[i].type == dev) return 1; } return 0; } +int has_device_type(struct fpga_model* model, int y, int x, int dev, int subtype) +{ + struct fpga_tile* tile = YX_TILE(model, y, x); + int i; + + for (i = 0; i < tile->num_devs; i++) { + if (tile->devs[i].type == dev) { + switch (dev) { + case DEV_LOGIC: + if (tile->devs[i].logic.subtype == subtype) + return 1; + break; + case DEV_IOB: + if (tile->devs[i].iob.subtype == subtype) + return 1; + break; + default: EXIT(1); + } + } + } + return 0; +} + int add_connpt_2(struct fpga_model* model, int y, int x, const char* connpt_name, const char* suffix1, const char* suffix2) { diff --git a/model_main.c b/model_main.c index 48c8a9d..55f0093 100644 --- a/model_main.c +++ b/model_main.c @@ -49,6 +49,7 @@ int fpga_build_model(struct fpga_model* model, int fpga_rows, const char* column void fpga_free_model(struct fpga_model* model) { if (!model) return; + free_devices(model); free(model->tmp_str); strarray_free(&model->str); free(model->tiles); diff --git a/model_switches.c b/model_switches.c index c61180a..36412c7 100644 --- a/model_switches.c +++ b/model_switches.c @@ -46,14 +46,13 @@ static int init_logic_tile(struct fpga_model* model, int y, int x) int rc, i, j, ml; const char* xp; - if (has_device(model, y, x, DEV_LOGIC_M)) { + if (has_device_type(model, y, x, DEV_LOGIC, LOGIC_M)) { ml = 'M'; xp = "X"; - } else if (has_device(model, y, x, DEV_LOGIC_L)) { + } else if (has_device_type(model, y, x, DEV_LOGIC, LOGIC_L)) { ml = 'L'; xp = "XX"; - } else - EXIT(1); + } else EXIT(1); if ((rc = add_switch(model, y, x, pf("CLEX%c_CLK0", ml), pf("%s_CLK", xp), 0 /* bidir */))) goto xout; @@ -137,8 +136,7 @@ static int init_logic_switches(struct fpga_model* model) if (!is_atx(X_LOGIC_COL, model, x)) continue; for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { - if (has_device(model, y, x, DEV_LOGIC_M) - || has_device(model, y, x, DEV_LOGIC_L)) { + if (has_device(model, y, x, DEV_LOGIC)) { rc = init_logic_tile(model, y, x); if (rc) goto xout; }