diff --git a/Makefile b/Makefile index 1aed6d1..bb04f67 100644 --- a/Makefile +++ b/Makefile @@ -150,7 +150,7 @@ compare_%.ftest: compare_%.fcr @if test ! -e test.gold/$(*F).fco; then echo Gold test.gold/$(*F).fco does not exist, aborting.; false; fi; @diff -u test.gold/$(*F).fco $< >$@ || true -%.fce: %.fco +%.fce: %.fcd @cat $< | grep ^+[^+] >$@ || true compare_%_tiles.fco: compare_%.fp diff --git a/libs/floorplan.c b/libs/floorplan.c index fc5c186..c5d1f33 100644 --- a/libs/floorplan.c +++ b/libs/floorplan.c @@ -762,7 +762,7 @@ static int printf_BUFIO(FILE* f, struct fpga_model* model, type_count++; continue; } - snprintf(pref, sizeof(pref), "dev y%02i x%02i BUFGMUX %i", + snprintf(pref, sizeof(pref), "dev y%02i x%02i BUFIO %i", y, x, type_count++); if (!config_only) fprintf(f, "%s\n", pref); @@ -841,7 +841,7 @@ static int printf_BSCAN(FILE* f, struct fpga_model* model, type_count++; continue; } - snprintf(pref, sizeof(pref), "dev y%02i x%02i BUFGMUX %i", + snprintf(pref, sizeof(pref), "dev y%02i x%02i BSCAN %i", y, x, type_count++); if (!config_only) fprintf(f, "%s\n", pref); diff --git a/libs/model.h b/libs/model.h index 7152fcf..24525e7 100644 --- a/libs/model.h +++ b/libs/model.h @@ -317,7 +317,8 @@ enum fpgadev_type DEV_BUFH, DEV_BUFIO, DEV_BUFIO_FB, DEV_BUFPLL, DEV_BUFPLL_MCB, DEV_BUFGMUX, DEV_BSCAN, DEV_DCM, DEV_PLL, DEV_ICAP, DEV_POST_CRC_INTERNAL, DEV_STARTUP, DEV_SLAVE_SPI, - DEV_SUSPEND_SYNC, DEV_OCT_CALIBRATE, DEV_SPI_ACCESS }; + DEV_SUSPEND_SYNC, DEV_OCT_CALIBRATE, DEV_SPI_ACCESS, + DEV_DNA, DEV_PMV, DEV_PCILOGIC_SE }; #define FPGA_DEV_STR \ { 0, \ "LOGIC", "TIEOFF", "MACC", "IOB", \ @@ -325,7 +326,8 @@ enum fpgadev_type "BUFH", "BUFIO", "BUFIO_FB", "BUFPLL", "BUFPLL_MCB", \ "BUFGMUX", "BSCAN", "DCM", "PLL", "ICAP", \ "POST_CRC_INTERNAL", "STARTUP", "SLAVE_SPI", \ - "SUSPEND_SYNC", "OCT_CALIBRATE", "SPI_ACCESS" } + "SUSPEND_SYNC", "OCT_CALIBRATE", "SPI_ACCESS", \ + "DNA", "PMV", "PCILOGIC_SE" } // We use two types of device indices, one is a flat index // into the tile->devs array (dev_idx_t), the other @@ -534,6 +536,133 @@ struct fpgadev_bscan int jtag_test; }; +// +// DEV_BRAM +// + +// B8_0 or B8_1 can be or'ed into the BI/BO values +// to designate the first and second BRAM8 device, +// instead of the default BRAM16 device. +#define B8_0 0x100 +#define B8_1 0x200 +#define BW_FLAGS (B8_0|B8_1) + +enum { + // input: + BI_FIRST = 0, + + // port A + BI_ADDRA0 = BI_FIRST, BI_ADDRA1, BI_ADDRA2, BI_ADDRA3, BI_ADDRA4, BI_ADDRA5, + BI_ADDRA6, BI_ADDRA7, BI_ADDRA8, BI_ADDRA9, BI_ADDRA10, BI_ADDRA11, + BI_ADDRA12, BI_ADDRA13, + + BI_DIA0, BI_DIA1, BI_DIA2, BI_DIA3, BI_DIA4, BI_DIA5, + BI_DIA6, BI_DIA7, BI_DIA8, BI_DIA9, BI_DIA10, BI_DIA11, + BI_DIA12, BI_DIA13, BI_DIA14, BI_DIA15, BI_DIA16, BI_DIA17, + BI_DIA18, BI_DIA19, BI_DIA20, BI_DIA21, BI_DIA22, BI_DIA23, + BI_DIA24, BI_DIA25, BI_DIA26, BI_DIA27, BI_DIA28, BI_DIA29, + BI_DIA30, BI_DIA31, + + BI_DIPA0, BI_DIPA1, BI_DIPA2, BI_DIPA3, + BI_WEA0, BI_WEA1, BI_WEA2, BI_WEA3, + BI_REGCEA, + BI_ENA, + + // port B + BI_ADDRB0, BI_ADDRB1, BI_ADDRB2, BI_ADDRB3, BI_ADDRB4, BI_ADDRB5, + BI_ADDRB6, BI_ADDRB7, BI_ADDRB8, BI_ADDRB9, BI_ADDRB10, BI_ADDRB11, + BI_ADDRB12, BI_ADDRB13, + + BI_DIB0, BI_DIB1, BI_DIB2, BI_DIB3, BI_DIB4, BI_DIB5, + BI_DIB6, BI_DIB7, BI_DIB8, BI_DIB9, BI_DIB10, BI_DIB11, + BI_DIB12, BI_DIB13, BI_DIB14, BI_DIB15, BI_DIB16, BI_DIB17, + BI_DIB18, BI_DIB19, BI_DIB20, BI_DIB21, BI_DIB22, BI_DIB23, + BI_DIB24, BI_DIB25, BI_DIB26, BI_DIB27, BI_DIB28, BI_DIB29, + BI_DIB30, BI_DIB31, + + BI_DIPB0, BI_DIPB1, BI_DIPB2, BI_DIPB3, + BI_WEB0, BI_WEB1, BI_WEB2, BI_WEB3, + BI_REGCEB, + BI_ENB, + + BI_LAST = BI_ENB, + + // output: + BO_FIRST, + + // port A + BO_DOA0 = BO_FIRST, BO_DOA1, BO_DOA2, BO_DOA3, BO_DOA4, BO_DOA5, + BO_DOA6, BO_DOA7, BO_DOA8, BO_DOA9, BO_DOA10, BO_DOA11, + BO_DOA12, BO_DOA13, BO_DOA14, BO_DOA15, BO_DOA16, BO_DOA17, + BO_DOA18, BO_DOA19, BO_DOA20, BO_DOA21, BO_DOA22, BO_DOA23, + BO_DOA24, BO_DOA25, BO_DOA26, BO_DOA27, BO_DOA28, BO_DOA29, + BO_DOA30, BO_DOA31, + + BO_DOPA0, BO_DOPA1, BO_DOPA2, BO_DOPA3, + + // port B + BO_DOB0, BO_DOB1, BO_DOB2, BO_DOB3, BO_DOB4, BO_DOB5, + BO_DOB6, BO_DOB7, BO_DOB8, BO_DOB9, BO_DOB10, BO_DOB11, + BO_DOB12, BO_DOB13, BO_DOB14, BO_DOB15, BO_DOB16, BO_DOB17, + BO_DOB18, BO_DOB19, BO_DOB20, BO_DOB21, BO_DOB22, BO_DOB23, + BO_DOB24, BO_DOB25, BO_DOB26, BO_DOB27, BO_DOB28, BO_DOB29, + BO_DOB30, BO_DOB31, + + BO_DOPB0, BO_DOPB1, BO_DOPB2, BO_DOPB3, + + BO_LAST = BO_DOPB3 +}; + +// +// DEV_MACC +// + +enum { + // input: + MI_FIRST = 0, + + MI_CEA = MI_FIRST, MI_CEB, MI_CEC, MI_CED, MI_CEM, MI_CEP, + MI_CE_OPMODE, MI_CE_CARRYIN, + MI_OPMODE0, MI_OPMODE1, MI_OPMODE2, MI_OPMODE3, + MI_OPMODE4, MI_OPMODE5, MI_OPMODE6, MI_OPMODE7, + MI_A0, MI_A1, MI_A2, MI_A3, MI_A4, MI_A5, MI_A6, MI_A7, + MI_A8, MI_A9, MI_A10, MI_A11, MI_A12, MI_A13, MI_A14, MI_A15, + MI_A16, MI_A17, + MI_B0, MI_B1, MI_B2, MI_B3, MI_B4, MI_B5, MI_B6, MI_B7, + MI_B8, MI_B9, MI_B10, MI_B11, MI_B12, MI_B13, MI_B14, MI_B15, + MI_B16, MI_B17, + MI_C0, MI_C1, MI_C2, MI_C3, MI_C4, MI_C5, MI_C6, MI_C7, + MI_C8, MI_C9, MI_C10, MI_C11, MI_C12, MI_C13, MI_C14, MI_C15, + MI_C16, MI_C17, MI_C18, MI_C19, MI_C20, MI_C21, MI_C22, MI_C23, + MI_C24, MI_C25, MI_C26, MI_C27, MI_C28, MI_C29, MI_C30, MI_C31, + MI_C32, MI_C33, MI_C34, MI_C35, MI_C36, MI_C37, MI_C38, MI_C39, + MI_C40, MI_C41, MI_C42, MI_C43, MI_C44, MI_C45, MI_C46, MI_C47, + MI_D0, MI_D1, MI_D2, MI_D3, MI_D4, MI_D5, MI_D6, MI_D7, + MI_D8, MI_D9, MI_D10, MI_D11, MI_D12, MI_D13, MI_D14, MI_D15, + MI_D16, MI_D17, + + MI_LAST = MI_D17, + + // output: + MO_FIRST, + + MO_CARRYOUT = MO_FIRST, + MO_P0, MO_P1, MO_P2, MO_P3, MO_P4, MO_P5, MO_P6, MO_P7, + MO_P8, MO_P9, MO_P10, MO_P11, MO_P12, MO_P13, MO_P14, MO_P15, + MO_P16, MO_P17, MO_P18, MO_P19, MO_P20, MO_P21, MO_P22, MO_P23, + MO_P24, MO_P25, MO_P26, MO_P27, MO_P28, MO_P29, MO_P30, MO_P31, + MO_P32, MO_P33, MO_P34, MO_P35, MO_P36, MO_P37, MO_P38, MO_P39, + MO_P40, MO_P41, MO_P42, MO_P43, MO_P44, MO_P45, MO_P46, MO_P47, + + MO_M0, MO_M1, MO_M2, MO_M3, MO_M4, MO_M5, MO_M6, MO_M7, + MO_M8, MO_M9, MO_M10, MO_M11, MO_M12, MO_M13, MO_M14, MO_M15, + MO_M16, MO_M17, MO_M18, MO_M19, MO_M20, MO_M21, MO_M22, MO_M23, + MO_M24, MO_M25, MO_M26, MO_M27, MO_M28, MO_M29, MO_M30, MO_M31, + MO_M32, MO_M33, MO_M34, MO_M35, + + MO_LAST = MO_M35 +}; + // // fpga_device // @@ -851,10 +980,10 @@ enum extra_wires { FAN_B, GFAN0, GFAN1, - CLK0, - CLK1, - SR0, - SR1, + CLK0, // == clka for bram + CLK1, // == clkb for bram + SR0, // == rsta for bram + SR1, // == rstb for bram LOGICIN20, LOGICIN21, LOGICIN44, @@ -883,7 +1012,15 @@ enum extra_wires { LW, // logic wires are encoded here as LOGIC_BEG+LI_A1. LD1 (0x100) // can be OR'ed to the LI or LO value. - LW_LAST = 1999 + LW_LAST = 1999, + + // bram wires are BW + (BI_/BO_, ORed with B8_0(0x100) or B8_1(0x200)) + BW, + BW_LAST = 2999, + + // macc wires are MW + MI_/MO_ + MW, + MW_LAST = 3499, }; const char* fpga_wire2str(enum extra_wires wire); @@ -891,3 +1028,13 @@ str16_t fpga_wire2str_i(struct fpga_model* model, enum extra_wires wire); enum extra_wires fpga_str2wire(const char* str); int fdev_logic_inbit(pinw_idx_t idx); int fdev_logic_outbit(pinw_idx_t idx); + +// physically, tile3 is at the top, tile0 at the bottom +// errors are returned as -1 in tile0_to_3 +void fdev_bram_inbit(enum extra_wires wire, int* tile0_to_3, int* wire0_to_62); +void fdev_bram_outbit(enum extra_wires wire, int* tile0_to_3, int* wire0_to_23); +int fdev_is_bram8_inwire(int bi_wire); // direct BI_ value +int fdev_is_bram8_outwire(int bo_wire); // direct BO_ value + +void fdev_macc_inbit(enum extra_wires wire, int* tile0_to_3, int* wire0_to_62); +void fdev_macc_outbit(enum extra_wires wire, int* tile0_to_3, int* wire0_to_23); diff --git a/libs/model_conns.c b/libs/model_conns.c index dc9ee73..7d2e35a 100644 --- a/libs/model_conns.c +++ b/libs/model_conns.c @@ -84,6 +84,49 @@ static int connect_logic_carry(struct fpga_model* model) if ((rc = add_conn_bi(model, y, x, "M_COUT_N", y-1, x, "M_CIN"))) goto xout; } } + else if (has_device_type(model, y, x, DEV_LOGIC, LOGIC_L)) { + if (is_aty(Y_CHIP_HORIZ_REGS, model, y-1)) { + if (x == model->center_x - CENTER_LOGIC_O) { + struct w_net net = { + 0, + {{ "L_CIN", 0, y-3, x }, + { "INT_INTERFACE_COUT", 0, y-2, x }, + { "REGC_CLE_COUT", 0, y-1, x }, + { "XL_COUT_N", 0, y, x }, + { "" }}}; + if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) goto xout; + } else { + struct w_net net = { + 0, + {{ "L_CIN", 0, y-2, x }, + { "REGH_CLEXL_COUT", 0, y-1, x }, + { "XL_COUT_N", 0, y, x }, + { "" }}}; + if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) goto xout; + } + } else if (is_aty(Y_ROW_HORIZ_AXSYMM, model, y-1)) { + struct w_net net = { + 0, + {{ "L_CIN", 0, y-2, x }, + { "HCLK_CLEXL_COUT", 0, y-1, x }, + { "XL_COUT_N", 0, y, x }, + { "" }}}; + if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) goto xout; + } else if (is_aty(Y_ROW_HORIZ_AXSYMM, model, y-2) + && (x == model->center_x - CENTER_LOGIC_O)) { + struct w_net net = { + 0, + {{ "L_CIN", 0, y-4, x }, + { "INT_INTERFACE_COUT", 0, y-3, x }, + { "HCLK_CLEXL_COUT", 0, y-2, x }, + { "INT_INTERFACE_COUT_BOT", 0, y-1, x }, + { "XL_COUT_N", 0, y, x }, + { "" }}}; + if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) goto xout; + } else if (has_device_type(model, y-1, x, DEV_LOGIC, LOGIC_L)) { + if ((rc = add_conn_bi(model, y, x, "XL_COUT_N", y-1, x, "L_CIN"))) goto xout; + } + } } } } diff --git a/libs/model_devices.c b/libs/model_devices.c index 1be89cd..e1d423e 100644 --- a/libs/model_devices.c +++ b/libs/model_devices.c @@ -58,6 +58,29 @@ int init_devices(struct fpga_model* model) 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; + // OCT_CALIBRATE + x = LEFT_IO_DEVS; + if ((rc = add_dev(model, TOP_IO_TILES, x, DEV_OCT_CALIBRATE, 0))) + FAIL(rc); + if ((rc = add_dev(model, TOP_IO_TILES, x, DEV_OCT_CALIBRATE, 0))) + FAIL(rc); + if ((rc = add_dev(model, model->y_height-BOT_IO_TILES-1, x, + DEV_OCT_CALIBRATE, 0))) FAIL(rc); + if ((rc = add_dev(model, model->y_height-BOT_IO_TILES-1, x, + DEV_OCT_CALIBRATE, 0))) FAIL(rc); + + // DNA, PMV + x = LEFT_IO_DEVS; + y = TOP_IO_TILES; + if ((rc = add_dev(model, y, x, DEV_DNA, 0))) FAIL(rc); + if ((rc = add_dev(model, y, x, DEV_PMV, 0))) FAIL(rc); + + // PCILOGIC_SE + if ((rc = add_dev(model, model->center_y, LEFT_IO_ROUTING, + DEV_PCILOGIC_SE, 0))) FAIL(rc); + if ((rc = add_dev(model, model->center_y, model->x_width + - RIGHT_IO_DEVS_O, DEV_PCILOGIC_SE, 0))) FAIL(rc); + // BUFGMUX y = model->center_y; x = model->center_x; diff --git a/libs/model_helper.c b/libs/model_helper.c index be4d538..7583aeb 100644 --- a/libs/model_helper.c +++ b/libs/model_helper.c @@ -749,6 +749,7 @@ const char* fpga_wire2str(enum extra_wires wire) enum { NUM_BUFS = 8, BUF_SIZE = 64 }; static char buf[NUM_BUFS][BUF_SIZE]; static int last_buf = 0; + int flags; switch (wire) { case GFAN0: return "GFAN0"; @@ -781,7 +782,6 @@ const char* fpga_wire2str(enum extra_wires wire) snprintf(buf[last_buf], sizeof(buf[0]), "GCLK%i", wire-GCLK0); else if (wire >= DW && wire <= DW_LAST) { char beg_end; - int flags; wire -= DW; flags = wire & DIR_FLAGS; @@ -804,7 +804,92 @@ const char* fpga_wire2str(enum extra_wires wire) else if ((wire&(~LD1)) >= LO_FIRST && (wire&(~LD1)) <= LO_LAST) snprintf(buf[last_buf], sizeof(buf[0]), "LOGICOUT%i", fdev_logic_outbit(wire)); else HERE(); + } else if (wire >= BW && wire <= BW_LAST) { + const char* bram_pref; + int bram_w; + + wire -= BW; + flags = wire & BW_FLAGS; + bram_w = wire & ~BW_FLAGS; + if (flags & B8_0) + bram_pref = "RAMB8BWER_0_"; + else if (flags & B8_1) + bram_pref = "RAMB8BWER_1_"; + else + bram_pref = "RAMB16BWER_"; + + if (bram_w >= BI_ADDRA0 && bram_w <= BI_ADDRA13) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sADDRA%i", bram_pref, bram_w-BI_ADDRA0); + } else if (bram_w >= BI_ADDRB0 && bram_w <= BI_ADDRB13) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sADDRB%i", bram_pref, bram_w-BI_ADDRB0); + } else if (bram_w >= BI_DIA0 && bram_w <= BI_DIA31) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sDIA%i", bram_pref, bram_w-BI_DIA0); + } else if (bram_w >= BI_DIB0 && bram_w <= BI_DIB31) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sDIB%i", bram_pref, bram_w-BI_DIB0); + } else if (bram_w >= BI_DIPA0 && bram_w <= BI_DIPA3) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sDIPA%i", bram_pref, bram_w-BI_DIPA0); + } else if (bram_w >= BI_DIPB0 && bram_w <= BI_DIPB3) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sDIPB%i", bram_pref, bram_w-BI_DIPB0); + + } else if (bram_w >= BO_DOA0 && bram_w <= BO_DOA31) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sDOA%i", bram_pref, bram_w-BO_DOA0); + } else if (bram_w >= BO_DOB0 && bram_w <= BO_DOB31) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sDOB%i", bram_pref, bram_w-BO_DOB0); + } else if (bram_w >= BO_DOPA0 && bram_w <= BO_DOPA3) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sDOPA%i", bram_pref, bram_w-BO_DOPA0); + } else if (bram_w >= BO_DOPB0 && bram_w <= BO_DOPB3) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sDOPB%i", bram_pref, bram_w-BO_DOPB0); + + } else if (bram_w >= BI_WEA0 && bram_w <= BI_WEA3) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sWEA%i", bram_pref, bram_w-BI_WEA0); + } else if (bram_w >= BI_WEB0 && bram_w <= BI_WEB3) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sWEB%i", bram_pref, bram_w-BI_WEB0); + } else if (bram_w == BI_REGCEA) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sREGCEA", bram_pref); + } else if (bram_w == BI_REGCEB) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sREGCEB", bram_pref); + } else if (bram_w == BI_ENA) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sENA", bram_pref); + } else if (bram_w == BI_ENB) { + snprintf(buf[last_buf], sizeof(buf[0]), "%sENB", bram_pref); + } else HERE(); + } else if (wire >= MW && wire <= MW_LAST) { + int macc_w = wire - MW; + if (macc_w >= MI_A0 && macc_w <= MI_A17) + snprintf(buf[last_buf], sizeof(buf[0]), "A%i_DSP48A1_SITE", macc_w-MI_A0); + else if (macc_w >= MI_B0 && macc_w <= MI_B17) + snprintf(buf[last_buf], sizeof(buf[0]), "B%i_DSP48A1_SITE", macc_w-MI_B0); + else if (macc_w >= MI_C0 && macc_w <= MI_C47) + snprintf(buf[last_buf], sizeof(buf[0]), "C%i_DSP48A1_SITE", macc_w-MI_C0); + else if (macc_w >= MI_D0 && macc_w <= MI_D17) + snprintf(buf[last_buf], sizeof(buf[0]), "D%i_DSP48A1_SITE", macc_w-MI_D0); + else if (macc_w >= MI_OPMODE0 && macc_w <= MI_OPMODE7) + snprintf(buf[last_buf], sizeof(buf[0]), "OPMODE%i_DSP48A1_SITE", macc_w-MI_OPMODE0); + else if (macc_w >= MO_P0 && macc_w <= MO_P47) + snprintf(buf[last_buf], sizeof(buf[0]), "P%i_DSP48A1_SITE", macc_w-MO_P0); + else if (macc_w >= MO_M0 && macc_w <= MO_M35) + snprintf(buf[last_buf], sizeof(buf[0]), "M%i_DSP48A1_SITE", macc_w-MO_M0); + else if (macc_w == MI_CEA) + snprintf(buf[last_buf], sizeof(buf[0]), "CEA_DSP48A1_SITE"); + else if (macc_w == MI_CEB) + snprintf(buf[last_buf], sizeof(buf[0]), "CEB_DSP48A1_SITE"); + else if (macc_w == MI_CEC) + snprintf(buf[last_buf], sizeof(buf[0]), "CEC_DSP48A1_SITE"); + else if (macc_w == MI_CED) + snprintf(buf[last_buf], sizeof(buf[0]), "CED_DSP48A1_SITE"); + else if (macc_w == MI_CEM) + snprintf(buf[last_buf], sizeof(buf[0]), "CEM_DSP48A1_SITE"); + else if (macc_w == MI_CEP) + snprintf(buf[last_buf], sizeof(buf[0]), "CEP_DSP48A1_SITE"); + else if (macc_w == MI_CE_OPMODE) + snprintf(buf[last_buf], sizeof(buf[0]), "CEOPMODE_DSP48A1_SITE"); + else if (macc_w == MI_CE_CARRYIN) + snprintf(buf[last_buf], sizeof(buf[0]), "CECARRYIN_DSP48A1_SITE"); + else if (macc_w == MO_CARRYOUT) + snprintf(buf[last_buf], sizeof(buf[0]), "CARRYOUTF_DSP48A1_SITE"); + else HERE(); } else HERE(); + return buf[last_buf]; } @@ -1064,3 +1149,432 @@ int fdev_logic_outbit(pinw_idx_t idx) HERE(); return -1; } + +void fdev_bram_inbit(enum extra_wires wire, int* tile0_to_3, int* wire0_to_62) +{ + const int ramb16_map[4*63] = { + // tile #3 (topmost) + /* 0*/ 0, BW+BI_DIB25, 0, BW+BI_DIB24, + /* 4*/ BW+BI_DIB22, 0, 0, 0, + /* 8*/ BW+BI_DIB31, BW+BI_DIB29, BW+BI_WEA0, 0, + /*12*/ 0, 0, 0, 0, + /*16*/ 0, 0, 0, BW+BI_DIB26, + /*20*/ 0, 0, 0, BW+BI_DIB19, + /*24*/ BW+BI_ADDRB13, BW+BI_REGCEB, BW+BI_DIPB2, BW+BI_DIB27, + /*28*/ 0, 0, BW+BI_WEA1, 0, + /*32*/ 0, 0, 0, 0, + /*36*/ 0, 0, BW+BI_DIB18, BW+BI_DIB30, + /*40*/ 0, BW+BI_DIPB3, 0, 0, + /*44*/ BW+BI_WEA3, 0, 0, BW+BI_DIB17, + /*48*/ 0, 0, 0, 0, + /*52*/ 0, 0, BW+BI_DIB20, BW+BI_DIB23, + /*56*/ 0, BW+BI_DIB21, BW+BI_WEA2, BW+BI_DIB28, + /*60*/ 0, 0, BW+BI_DIB16, + + // tile #2 + /* 0*/ 0, 0, 0, BW+BI_DIA27, + /* 4*/ BW+BI_ADDRB10, BW+BI_ADDRB2, 0, BW+BI_DIA17, + /* 8*/ 0, BW+BI_DIA31, BW+BI_ADDRB12, 0, + /*12*/ BW+BI_ADDRB3, 0, 0, BW+BI_DIA16, + /*16*/ BW+BI_DIA19, BW+BI_ADDRB7, 0, BW+BI_DIA28, + /*20*/ BW+BI_DIA20, 0, 0, BW+BI_DIA22, + /*24*/ BW+BI_ADDRB0, BW+BI_ADDRB9, BW+BI_DIA24, BW+BI_DIA30, + /*28*/ BW+BI_DIA29, 0, BW+BI_DIA25, 0, + /*32*/ BW+BI_REGCEA, 0, 0, 0, + /*36*/ BW+BI_DIA18, 0, BW+BI_DIA21, 0, + /*40*/ 0, BW+BI_DIA26, BW+BI_ADDRB1, 0, + /*44*/ BW+BI_DIPA2, BW+BI_ADDRB6, 0, BW+BI_ADDRB5, + /*48*/ BW+BI_DIA23, 0, 0, 0, + /*52*/ 0, 0, BW+BI_ENB, BW+BI_DIPA3, + /*56*/ 0, BW+BI_ADDRB8, BW+BI_ADDRB11, 0, + /*60*/ 0, 0, BW+BI_ADDRB4, + + // tile #1 + /* 0*/ 0, BW+BI_ADDRA5, BW+BI_DIB13, BW+BI_DIB8, + /* 4*/ BW+BI_DIB5, 0, 0, 0, + /* 8*/ BW+BI_ADDRA11, BW+BI_ADDRA8, BW+BI_ADDRA3, 0, + /*12*/ BW+BI_DIB0, 0, BW+BI_DIB14, 0, + /*16*/ 0, 0, 0, BW+BI_DIB9, + /*20*/ 0, 0, 0, BW+BI_DIB3, + /*24*/ 0, 0, BW+BI_DIB7, BW+BI_ADDRA6, + /*28*/ BW+BI_DIB10, BW+BI_DIB11, BW+BI_DIPB1, BW+BI_ADDRA12, + /*32*/ BW+BI_ADDRA7, 0, BW+BI_ADDRA0, 0, + /*36*/ 0, BW+BI_DIB15, BW+BI_DIB2, BW+BI_ADDRA10, + /*40*/ 0, BW+BI_DIPB0, 0, 0, + /*44*/ BW+BI_ADDRA2, 0, 0, BW+BI_DIB1, + /*48*/ BW+BI_ENA, 0, 0, 0, + /*52*/ BW+BI_ADDRA9, 0, BW+BI_ADDRA1, BW+BI_DIB6, + /*56*/ 0, BW+BI_DIB4, BW+BI_ADDRA4, BW+BI_DIB12, + /*60*/ 0, 0, 0, + + // tile #0 (bottommost) + /* 0*/ 0, 0, 0, BW+BI_DIA11, + /* 4*/ BW+BI_WEB0, 0, 0, BW+BI_DIA1, + /* 8*/ 0, BW+BI_DIA15, BW+BI_DIA10, 0, + /*12*/ 0, 0, 0, BW+BI_DIA0, + /*16*/ BW+BI_DIA3, 0, 0, BW+BI_DIA12, + /*20*/ BW+BI_DIA4, 0, 0, BW+BI_DIA6, + /*24*/ 0, BW+BI_WEB1, BW+BI_DIA8, BW+BI_DIA13, + /*28*/ 0, 0, BW+BI_DIA9, BW+BI_ADDRA13, + /*32*/ BW+BI_DIA14, 0, BW+BI_WEB3, 0, + /*36*/ BW+BI_DIA2, 0, BW+BI_DIA5, 0, + /*40*/ 0, 0, 0, 0, + /*44*/ 0, 0, 0, 0, + /*48*/ BW+BI_DIA7, 0, 0, 0, + /*52*/ 0, 0, BW+BI_WEB2, BW+BI_DIPA1, + /*56*/ 0, BW+BI_DIPA0, 0, 0, + /*60*/ 0, 0, 0 }; + + const int ramb8_map[4*63] = { + // tile #3 (topmost) + /* 0*/ 0, BW+(B8_1|BI_DIB9), 0, BW+(B8_1|BI_DIB8), + /* 4*/ BW+(B8_1|BI_DIB6), BW+(B8_1|BI_ADDRB4), 0, BW+(B8_1|BI_ADDRB2), + /* 8*/ BW+(B8_1|BI_DIB15), BW+(B8_1|BI_DIB13), BW+(B8_0|BI_WEA0), 0, + /*12*/ BW+(B8_1|BI_ADDRB6), 0, 0, BW+(B8_1|BI_ADDRB1), + /*16*/ BW+(B8_1|BI_ADDRB8), BW+(B8_1|BI_ADDRB10), 0, BW+(B8_1|BI_DIB10), + /*20*/ BW+(B8_1|BI_ADDRB7), 0, 0, BW+(B8_1|BI_DIB3), + /*24*/ BW+(B8_1|BI_ADDRB0), BW+(B8_0|BI_REGCEB), BW+(B8_1|BI_DIPB0), BW+(B8_1|BI_DIB11), + /*28*/ 0, 0, BW+(B8_0|BI_WEA1), 0, + /*32*/ 0, 0, BW+(B8_1|BI_ADDRB11), 0, + /*36*/ BW+(B8_1|BI_ADDRB5), 0, BW+(B8_1|BI_DIB2), BW+(B8_1|BI_DIB14), + /*40*/ 0, BW+(B8_1|BI_DIPB1), BW+(B8_1|BI_ADDRB3), 0, + /*44*/ BW+(B8_1|BI_WEA1), BW+(B8_1|BI_ADDRB9), 0, BW+(B8_1|BI_DIB1), + /*48*/ BW+(B8_1|BI_ADDRB12), 0, 0, 0, + /*52*/ 0, 0, BW+(B8_1|BI_DIB4), BW+(B8_1|BI_DIB7), + /*56*/ 0, BW+(B8_1|BI_DIB5), BW+(B8_1|BI_WEA0), BW+(B8_1|BI_DIB12), + /*60*/ 0, 0, BW+(B8_1|BI_DIB0), + + // tile #2 + /* 0*/ 0, 0, 0, BW+(B8_1|BI_DIA11), + /* 4*/ BW+(B8_0|BI_ADDRB10), BW+(B8_0|BI_ADDRB2), 0, BW+(B8_1|BI_DIA1), + /* 8*/ 0, BW+(B8_1|BI_DIA15), BW+(B8_0|BI_ADDRB12), 0, + /*12*/ BW+(B8_0|BI_ADDRB3), 0, 0, BW+(B8_1|BI_DIA0), + /*16*/ BW+(B8_1|BI_DIA3), BW+(B8_0|BI_ADDRB7), 0, BW+(B8_1|BI_DIA12), + /*20*/ BW+(B8_1|BI_DIA4), 0, 0, BW+(B8_1|BI_DIA6), + /*24*/ BW+(B8_0|BI_ADDRB0), BW+(B8_0|BI_ADDRB9), BW+(B8_1|BI_DIA8), BW+(B8_1|BI_DIA14), + /*28*/ BW+(B8_1|BI_DIA13), BW+(B8_1|BI_REGCEA), BW+(B8_1|BI_DIA9), 0, + /*32*/ BW+(B8_0|BI_REGCEA), 0, BW+(B8_1|BI_ENB), 0, + /*36*/ BW+(B8_1|BI_DIA2), 0, BW+(B8_1|BI_DIA5), 0, + /*40*/ 0, BW+(B8_1|BI_DIA10), BW+(B8_0|BI_ADDRB1), 0, + /*44*/ BW+(B8_1|BI_DIPA0), BW+(B8_0|BI_ADDRB6), 0, BW+(B8_0|BI_ADDRB5), + /*48*/ BW+(B8_1|BI_DIA7), 0, 0, 0, + /*52*/ 0, 0, BW+(B8_0|BI_ENB), BW+(B8_1|BI_DIPA1), + /*56*/ 0, BW+(B8_0|BI_ADDRB8), BW+(B8_0|BI_ADDRB11), BW+(B8_1|BI_REGCEB), + /*60*/ 0, 0, BW+(B8_0|BI_ADDRB4), + + // tile #1 + /* 0*/ 0, BW+(B8_0|BI_ADDRA5), BW+(B8_0|BI_DIB13), BW+(B8_0|BI_DIB8), + /* 4*/ BW+(B8_0|BI_DIB5), 0, 0, 0, + /* 8*/ BW+(B8_0|BI_ADDRA11), BW+(B8_0|BI_ADDRA8), BW+(B8_0|BI_ADDRA3), 0, + /*12*/ BW+(B8_0|BI_DIB0), 0, BW+(B8_0|BI_DIB14), 0, + /*16*/ 0, 0, 0, BW+(B8_0|BI_DIB9), + /*20*/ 0, 0, 0, BW+(B8_0|BI_DIB3), + /*24*/ 0, BW+(B8_1|BI_ENA), BW+(B8_0|BI_DIB7), BW+(B8_0|BI_ADDRA6), + /*28*/ BW+(B8_0|BI_DIB10), BW+(B8_0|BI_DIB11), BW+(B8_0|BI_DIPB1), BW+(B8_0|BI_ADDRA12), + /*32*/ BW+(B8_0|BI_ADDRA7), 0, BW+(B8_0|BI_ADDRA0), 0, + /*36*/ 0, BW+(B8_0|BI_DIB15), BW+(B8_0|BI_DIB2), BW+(B8_0|BI_ADDRA10), + /*40*/ 0, BW+(B8_0|BI_DIPB0), 0, 0, + /*44*/ BW+(B8_0|BI_ADDRA2), 0, 0, BW+(B8_0|BI_DIB1), + /*48*/ BW+(B8_0|BI_ENA), 0, 0, 0, + /*52*/ BW+(B8_0|BI_ADDRA9), 0, BW+(B8_0|BI_ADDRA1), BW+(B8_0|BI_DIB6), + /*56*/ 0, BW+(B8_0|BI_DIB4), BW+(B8_0|BI_ADDRA4), BW+(B8_0|BI_DIB12), + /*60*/ 0, 0, 0, + + // tile #0 (bottommost) + /* 0*/ 0, BW+(B8_1|BI_ADDRA3), BW+(B8_1|BI_ADDRA8), BW+(B8_0|BI_DIA11), + /* 4*/ BW+(B8_0|BI_WEB0), 0, 0, BW+(B8_0|BI_DIA1), + /* 8*/ BW+(B8_1|BI_ADDRA12), BW+(B8_0|BI_DIA15), BW+(B8_0|BI_DIA10), 0, + /*12*/ 0, 0, BW+(B8_1|BI_ADDRA9), BW+(B8_0|BI_DIA0), + /*16*/ BW+(B8_0|BI_DIA3), 0, 0, BW+(B8_0|BI_DIA12), + /*20*/ BW+(B8_0|BI_DIA4), 0, 0, BW+(B8_0|BI_DIA6), + /*24*/ 0, BW+(B8_0|BI_WEB1), BW+(B8_0|BI_DIA8), BW+(B8_0|BI_DIA13), + /*28*/ BW+(B8_1|BI_ADDRA4), BW+(B8_1|BI_ADDRA5), BW+(B8_0|BI_DIA9), BW+(B8_1|BI_ADDRA0), + /*32*/ BW+(B8_0|BI_DIA14), 0, BW+(B8_1|BI_WEB1), 0, + /*36*/ BW+(B8_0|BI_DIA2), BW+(B8_1|BI_ADDRA11), BW+(B8_0|BI_DIA5), BW+(B8_1|BI_ADDRA10), + /*40*/ 0, BW+(B8_1|BI_ADDRA1), 0, 0, + /*44*/ 0, 0, 0, 0, + /*48*/ BW+(B8_0|BI_DIA7), 0, 0, 0, + /*52*/ BW+(B8_1|BI_ADDRA7), 0, BW+(B8_1|BI_WEB0), BW+(B8_0|BI_DIPA1), + /*56*/ 0, BW+(B8_0|BI_DIPA0), BW+(B8_1|BI_ADDRA2), BW+(B8_1|BI_ADDRA6), + /*60*/ 0, 0, 0 }; + + const int *search_map; + int i; + + if (wire < BW || wire > BW_LAST) { + HERE(); + *tile0_to_3 = -1; + return; + } + search_map = ((wire-BW) & BW_FLAGS) ? ramb8_map : ramb16_map; + for (i = 0; i < 4*63; i++) { + if (search_map[i] == wire) { + *tile0_to_3 = 3-(i/63); + *wire0_to_62 = i%63; + return; + } + } + fprintf(stderr, "#E %s:%i unknown wire %i\n", + __FILE__, __LINE__, wire); + *tile0_to_3 = -1; +} + +void fdev_bram_outbit(enum extra_wires wire, int* tile0_to_3, int* wire0_to_23) +{ + const int ramb16_map[4*24] = { + // tile #3 (topmost) + /* 0*/ 0, BW+BO_DOPB3, 0, BW+BO_DOB27, + /* 4*/ BW+BO_DOA29, BW+BO_DOA25, BW+BO_DOB29, BW+BO_DOA24, + /* 8*/ BW+BO_DOPA3, BW+BO_DOB31, BW+BO_DOB25, BW+BO_DOA31, + /*12*/ BW+BO_DOB24, 0, 0, BW+BO_DOA27, + /*16*/ BW+BO_DOA30, BW+BO_DOA26, BW+BO_DOA28, 0, + /*20*/ BW+BO_DOB28, BW+BO_DOB30, BW+BO_DOB26, 0, + + // tile #2 + /* 0*/ BW+BO_DOA18, BW+BO_DOB20, BW+BO_DOA16, BW+BO_DOPB2, + /* 4*/ BW+BO_DOA23, BW+BO_DOB18, BW+BO_DOB22, 0, + /* 8*/ BW+BO_DOA20, 0, BW+BO_DOA19, 0, + /*12*/ BW+BO_DOB17, BW+BO_DOA22, BW+BO_DOA17, 0, + /*16*/ BW+BO_DOB23, BW+BO_DOB19, BW+BO_DOA21, BW+BO_DOB16, + /*20*/ BW+BO_DOB21, 0, BW+BO_DOPA2, 0, + + // tile #1 + /* 0*/ BW+BO_DOB8, BW+BO_DOPA1, 0, BW+BO_DOA11, + /* 4*/ BW+BO_DOB13, BW+BO_DOA9, BW+BO_DOA13, 0, + /* 8*/ BW+BO_DOB11, BW+BO_DOB15, BW+BO_DOB9, BW+BO_DOA15, + /*12*/ BW+BO_DOA8, BW+BO_DOB12, 0, 0, + /*16*/ BW+BO_DOA14, BW+BO_DOA10, BW+BO_DOPB1, 0, + /*20*/ BW+BO_DOA12, BW+BO_DOB14, BW+BO_DOB10, 0, + + // tile #0 (bottommost) + /* 0*/ BW+BO_DOA2, BW+BO_DOB4, BW+BO_DOA0, BW+BO_DOPB0, + /* 4*/ BW+BO_DOB6, BW+BO_DOB2, BW+BO_DOA6, BW+BO_DOA1, + /* 8*/ BW+BO_DOA4, 0, BW+BO_DOA3, 0, + /*12*/ BW+BO_DOB1, BW+BO_DOB5, BW+BO_DOB0, BW+BO_DOPA0, + /*16*/ BW+BO_DOA7, BW+BO_DOB3, BW+BO_DOA5, 0, + /*20*/ 0, BW+BO_DOB7, 0, 0 + }; + const int ramb8_map[4*24] = { + // tile #3 (topmost) + /* 0*/ 0, BW+(BO_DOPB1|B8_1), 0, BW+(BO_DOB11|B8_1), + /* 4*/ BW+(BO_DOA13|B8_1), BW+(BO_DOA9|B8_1), BW+(BO_DOB13|B8_1), BW+(BO_DOA8|B8_1), + /* 8*/ BW+(BO_DOPA1|B8_1), BW+(BO_DOB15|B8_1), BW+(BO_DOB9|B8_1), BW+(BO_DOA15|B8_1), + /*12*/ BW+(BO_DOB8|B8_1), 0, 0, BW+(BO_DOA11|B8_1), + /*16*/ BW+(BO_DOA14|B8_1), BW+(BO_DOA10|B8_1), BW+(BO_DOA12|B8_1), 0, + /*20*/ BW+(BO_DOB12|B8_1), BW+(BO_DOB14|B8_1), BW+(BO_DOB10|B8_1), 0, + + // tile #2 + /* 0*/ BW+(BO_DOA2|B8_1), BW+(BO_DOB4|B8_1), BW+(BO_DOA0|B8_1), BW+(BO_DOPB0|B8_1), + /* 4*/ BW+(BO_DOA7|B8_1), BW+(BO_DOB2|B8_1), BW+(BO_DOB6|B8_1), 0, + /* 8*/ BW+(BO_DOA4|B8_1), 0, BW+(BO_DOA3|B8_1), 0, + /*12*/ BW+(BO_DOB1|B8_1), BW+(BO_DOA6|B8_1), BW+(BO_DOA1|B8_1), 0, + /*16*/ BW+(BO_DOB7|B8_1), BW+(BO_DOB3|B8_1), BW+(BO_DOA5|B8_1), BW+(BO_DOB0|B8_1), + /*20*/ BW+(BO_DOB5|B8_1), 0, BW+(BO_DOPA0|B8_1), 0, + + // tile #1 + /* 0*/ BW+(BO_DOB8|B8_0), BW+(BO_DOPA1|B8_0), 0, BW+(BO_DOA11|B8_0), + /* 4*/ BW+(BO_DOB13|B8_0), BW+(BO_DOA9|B8_0), BW+(BO_DOA13|B8_0), 0, + /* 8*/ BW+(BO_DOB11|B8_0), BW+(BO_DOB15|B8_0), BW+(BO_DOB9|B8_0), BW+(BO_DOA15|B8_0), + /*12*/ BW+(BO_DOA8|B8_0), BW+(BO_DOB12|B8_0), 0, 0, + /*16*/ BW+(BO_DOA14|B8_0), BW+(BO_DOA10|B8_0), BW+(BO_DOPB1|B8_0), 0, + /*20*/ BW+(BO_DOA12|B8_0), BW+(BO_DOB14|B8_0), BW+(BO_DOB10|B8_0), 0, + + // tile #0 (bottommost) + /* 0*/ BW+(BO_DOA2|B8_0), BW+(BO_DOB4|B8_0), BW+(BO_DOA0|B8_0), BW+(BO_DOPB0|B8_0), + /* 4*/ BW+(BO_DOB6|B8_0), BW+(BO_DOB2|B8_0), BW+(BO_DOA6|B8_0), BW+(BO_DOA1|B8_0), + /* 8*/ BW+(BO_DOA4|B8_0), 0, BW+(BO_DOA3|B8_0), 0, + /*12*/ BW+(BO_DOB1|B8_0), BW+(BO_DOB5|B8_0), BW+(BO_DOB0|B8_0), BW+(BO_DOPA0|B8_0), + /*16*/ BW+(BO_DOA7|B8_0), BW+(BO_DOB3|B8_0), BW+(BO_DOA5|B8_0), 0, + /*20*/ 0, BW+(BO_DOB7|B8_0), 0, 0 + }; + + const int *search_map; + int i; + + if (wire < BW || wire > BW_LAST) { + HERE(); + *tile0_to_3 = -1; + return; + } + search_map = ((wire-BW) & BW_FLAGS) ? ramb8_map : ramb16_map; + for (i = 0; i < 4*24; i++) { + if (search_map[i] == wire) { + *tile0_to_3 = 3-(i/24); + *wire0_to_23 = i%24; + return; + } + } + fprintf(stderr, "#E %s:%i unknown wire %i\n", + __FILE__, __LINE__, wire); + *tile0_to_3 = -1; +} + +int fdev_is_bram8_inwire(int bi_wire) +{ + if (bi_wire == BI_ADDRA13 || bi_wire == BI_ADDRB13) + return 0; + if (bi_wire == BI_WEA2 || bi_wire == BI_WEA3 + || bi_wire == BI_WEB2 || bi_wire == BI_WEB3) + return 0; + if (bi_wire == BI_DIPA2 || bi_wire == BI_DIPA3 + || bi_wire == BI_DIPB2 || bi_wire == BI_DIPB3) + return 0; + if ((bi_wire >= BI_DIA16 && bi_wire <= BI_DIA31) + || (bi_wire >= BI_DIB16 && bi_wire <= BI_DIB31)) + return 0; + return 1; +} + +int fdev_is_bram8_outwire(int bo_wire) +{ + if (bo_wire == BO_DOPA2 || bo_wire == BO_DOPA3 + || bo_wire == BO_DOPB2 || bo_wire == BO_DOPB3) + return 0; + if ((bo_wire >= BO_DOA16 && bo_wire <= BO_DOA31) + || (bo_wire >= BO_DOB16 && bo_wire <= BO_DOB31)) + return 0; + return 1; +} + +void fdev_macc_inbit(enum extra_wires wire, int* tile0_to_3, int* wire0_to_62) +{ + const int map[4*63] = { + // tile #3 (topmost) + /* 0*/ 0, MW+MI_A12, 0, MW+MI_C43, + /* 4*/ MW+MI_C40, 0, 0, MW+MI_A6, + /* 8*/ MW+MI_A17, 0, MW+MI_C42, 0, + /*12*/ 0, 0, MW+MI_A16, MW+MI_A5, + /*16*/ MW+MI_A7, MW+MI_C38, 0, MW+MI_A13, + /*20*/ 0, 0, 0, MW+MI_A8, + /*24*/ 0, 0, MW+MI_A10, MW+MI_C44, + /*28*/ 0, MW+MI_A14, MW+MI_A11, 0, + /*32*/ MW+MI_C45, 0, 0, 0, + /*36*/ MW+MI_C36, MW+MI_C47, 0, MW+MI_C46, + /*40*/ 0, 0, 0, 0, + /*44*/ MW+MI_A9, 0, 0, MW+MI_C37, + /*48*/ 0, 0, 0, 0, + /*52*/ MW+MI_A15, 0, 0, MW+MI_C41, + /*56*/ 0, MW+MI_C39, 0, 0, + /*60*/ 0, 0, 0, + + // tile #2 + /* 0*/ 0, 0, 0, MW+MI_C31, + /* 4*/ MW+MI_C28, 0, 0, MW+MI_D16, + /* 8*/ MW+MI_A4, 0, MW+MI_C30, 0, + /*12*/ MW+MI_D17, 0, MW+MI_C34, MW+MI_OPMODE3, + /*16*/ MW+MI_C24, MW+MI_CED, 0, MW+MI_A0, + /*20*/ MW+MI_C25, 0, 0, MW+MI_C26, + /*24*/ MW+MI_OPMODE7, 0, MW+MI_C29, MW+MI_C32, + /*28*/ 0, MW+MI_A1, MW+MI_CEA, MW+MI_C35, + /*32*/ 0, 0, MW+MI_CE_CARRYIN, 0, + /*36*/ MW+MI_B16, 0, 0, MW+MI_A3, + /*40*/ 0, MW+MI_CEB, MW+MI_OPMODE2, 0, + /*44*/ MW+MI_CEP, 0, 0, MW+MI_B17, + /*48*/ MW+MI_C27, 0, 0, 0, + /*52*/ MW+MI_A2, 0, 0, MW+MI_CE_OPMODE, + /*56*/ 0, MW+MI_CEC, MW+MI_CEM, MW+MI_C33, + /*60*/ 0, 0, MW+MI_OPMODE5, + + // tile #1 + /* 0*/ 0, MW+MI_B12, MW+MI_D14, 0, + /* 4*/ MW+MI_D11, MW+MI_OPMODE4, 0, 0, + /* 8*/ MW+MI_OPMODE1, MW+MI_C23, MW+MI_D12, 0, + /*12*/ 0, 0, MW+MI_D15, MW+MI_C12, + /*16*/ MW+MI_OPMODE6, MW+MI_C15, 0, MW+MI_C21, + /*20*/ 0, 0, 0, MW+MI_D10, + /*24*/ 0, 0, MW+MI_C18, MW+MI_B13, + /*28*/ MW+MI_D13, 0, 0, MW+MI_OPMODE0, + /*32*/ MW+MI_C22, 0, MW+MI_B9, 0, + /*36*/ MW+MI_C13, 0, 0, MW+MI_B15, + /*40*/ 0, MW+MI_C19, 0, 0, + /*44*/ MW+MI_C17, MW+MI_D9, 0, MW+MI_C14, + /*48*/ MW+MI_C16, 0, 0, 0, + /*52*/ MW+MI_B14, 0, 0, MW+MI_B11, + /*56*/ 0, MW+MI_B10, MW+MI_C20, 0, + /*60*/ 0, 0, 0, + + // tile #0 (bottommost) + /* 0*/ 0, MW+MI_D5, 0, MW+MI_C8, + /* 4*/ MW+MI_C5, 0, 0, MW+MI_D0, + /* 8*/ MW+MI_D8, 0, 0, 0, + /*12*/ 0, 0, MW+MI_C11, MW+MI_C0, + /*16*/ 0, MW+MI_C3, 0, 0, + /*20*/ MW+MI_C2, 0, 0, MW+MI_C4, + /*24*/ 0, MW+MI_D2, MW+MI_D4, 0, + /*28*/ MW+MI_C9, MW+MI_B6, MW+MI_B4, MW+MI_B8, + /*32*/ MW+MI_C10, 0, MW+MI_B2, 0, + /*36*/ 0, MW+MI_B7, MW+MI_B1, MW+MI_D7, + /*40*/ 0, MW+MI_C7, MW+MI_B0, 0, + /*44*/ MW+MI_B3, 0, 0, MW+MI_D1, + /*48*/ 0, 0, 0, 0, + /*52*/ 0, 0, 0, MW+MI_C6, + /*56*/ 0, MW+MI_D3, MW+MI_B5, MW+MI_D6, + /*60*/ 0, 0, MW+MI_C1 }; + int i; + + if (wire < MW || wire > MW_LAST) { + HERE(); + *tile0_to_3 = -1; + return; + } + for (i = 0; i < 4*63; i++) { + if (map[i] == wire) { + *tile0_to_3 = 3-(i/63); + *wire0_to_62 = i%63; + return; + } + } + fprintf(stderr, "#E %s:%i unknown wire %i\n", + __FILE__, __LINE__, wire); + *tile0_to_3 = -1; +} + +void fdev_macc_outbit(enum extra_wires wire, int* tile0_to_3, int* wire0_to_23) +{ + const int map[4*24] = { + // tile #3 (topmost) + /* 0*/ MW+MO_P37, MW+MO_M33, MW+MO_P35, MW+MO_P41, + /* 4*/ MW+MO_M34, MW+MO_P38, MW+MO_P44, MW+MO_M29, + /* 8*/ MW+MO_M32, MW+MO_CARRYOUT, MW+MO_M30, MW+MO_P47, + /*12*/ MW+MO_P36, 0, 0, MW+MO_P40, + /*16*/ MW+MO_M35, MW+MO_M31, MW+MO_P42, MW+MO_M28, + /*20*/ MW+MO_P43, MW+MO_P45, MW+MO_P39, MW+MO_P46, + // tile #2 + /* 0*/ MW+MO_M21, MW+MO_P29, MW+MO_M18, MW+MO_M23, + /* 4*/ MW+MO_P32, 0, MW+MO_P31, MW+MO_P24, + /* 8*/ MW+MO_P28, MW+MO_P34, MW+MO_P25, MW+MO_M27, + /*12*/ MW+MO_M20, MW+MO_M25, MW+MO_M19, MW+MO_M22, + /*16*/ 0, MW+MO_P26, MW+MO_P30, 0, + /*20*/ MW+MO_M24, MW+MO_P33, MW+MO_P27, MW+MO_M26, + // tile #1 + /* 0*/ MW+MO_M11, MW+MO_P19, MW+MO_P12, MW+MO_M14, + /* 4*/ MW+MO_P21, MW+MO_M12, 0, MW+MO_P13, + /* 8*/ MW+MO_P18, 0, MW+MO_P15, MW+MO_P23, + /*12*/ MW+MO_P14, MW+MO_P20, MW+MO_M9, MW+MO_M13, + /*16*/ MW+MO_P22, MW+MO_P16, MW+MO_M15, MW+MO_M10, + /*20*/ MW+MO_M16, 0, MW+MO_P17, MW+MO_M17, + // tile #0 (bottommost) + /* 0*/ MW+MO_P2, MW+MO_P6, 0, MW+MO_M3, + /* 4*/ MW+MO_P9, MW+MO_P3, MW+MO_M6, MW+MO_P1, + /* 8*/ MW+MO_M4, MW+MO_P11, MW+MO_M1, 0, + /*12*/ MW+MO_M0, MW+MO_M5, MW+MO_P0, MW+MO_P5, + /*16*/ MW+MO_P10, MW+MO_M2, MW+MO_P7, 0, + /*20*/ MW+MO_P8, MW+MO_M7, MW+MO_P4, MW+MO_M8 }; + int i; + + if (wire < MW || wire > MW_LAST) { + HERE(); + *tile0_to_3 = -1; + return; + } + for (i = 0; i < 4*24; i++) { + if (map[i] == wire) { + *tile0_to_3 = 3-(i/24); + *wire0_to_23 = i%24; + return; + } + } + fprintf(stderr, "#E %s:%i unknown wire %i\n", + __FILE__, __LINE__, wire); + *tile0_to_3 = -1; +} diff --git a/libs/model_switches.c b/libs/model_switches.c index 0df5826..af97f05 100644 --- a/libs/model_switches.c +++ b/libs/model_switches.c @@ -15,6 +15,11 @@ static int init_routing_switches(struct fpga_model* model); static int init_north_south_dirwire_term(struct fpga_model* model); static int init_iologic_switches(struct fpga_model* model); static int init_logic_switches(struct fpga_model* model); +static int init_center_switches(struct fpga_model* model); +static int init_hclk_switches(struct fpga_model* model); +static int init_logicout_fw_switches(struct fpga_model* model); +static int init_bram_switches(struct fpga_model* model); +static int init_macc_switches(struct fpga_model* model); int init_switches(struct fpga_model* model, int routing_sw) { @@ -22,26 +27,41 @@ int init_switches(struct fpga_model* model, int routing_sw) if (routing_sw) { rc = init_routing_switches(model); - if (rc) goto xout; + if (rc) FAIL(rc); } rc = init_logic_switches(model); - if (rc) goto xout; + if (rc) FAIL(rc); rc = init_iologic_switches(model); - if (rc) goto xout; + if (rc) FAIL(rc); rc = init_north_south_dirwire_term(model); - if (rc) goto xout; + if (rc) FAIL(rc); rc = init_ce_clk_switches(model); - if (rc) goto xout; + if (rc) FAIL(rc); rc = init_io_switches(model); - if (rc) goto xout; + if (rc) FAIL(rc); + + rc = init_center_switches(model); + if (rc) FAIL(rc); + + rc = init_hclk_switches(model); + if (rc) FAIL(rc); + + rc = init_logicout_fw_switches(model); + if (rc) FAIL(rc); + + rc = init_bram_switches(model); + if (rc) FAIL(rc); + + rc = init_macc_switches(model); + if (rc) FAIL(rc); return 0; -xout: +fail: return rc; } @@ -1142,3 +1162,340 @@ int replicate_routing_switches(struct fpga_model* model) fail: return rc; } + +static int init_center_switches(struct fpga_model* model) +{ + int i, j, rc; + + { const char* pairs[] = + { "CLKC_CKLR%i", "CLKC_GCLK%i", + "CLKC_CKTB%i", "CLKC_GCLK%i", + "CLKC_PLL_L%i", "CLKC_GCLK%i", + "CLKC_PLL_U%i", "CLKC_GCLK%i", + "CLKC_SEL%i_PLL", "S_GCLK_SITE%i", + "I0_GCLK_SITE%i", "O_GCLK_SITE%i", + "O_GCLK_SITE%i", "CLKC_GCLK_MAIN%i" }; + int i_dest[2][16] = + {{ 0,1,2,4,3,5,6,7,8,9,10,12,11,13,14,15 }, + { 1,0,3,5,2,4,7,6,9,8,11,13,10,12,15,14 }}; + + for (i = 0; i < sizeof(pairs)/sizeof(*pairs)/2; i++) { + for (j = 0; j <= 15; j++) { + if ((rc = add_switch(model, model->center_y, model->center_x, + pf(pairs[i*2], j), pf(pairs[i*2+1], j), + /*bidir*/ 0))) FAIL(rc); + } + } + for (j = 0; j <= 15; j++) { + if ((rc = add_switch(model, model->center_y, model->center_x, + pf("CLKC_GCLK%i", j), pf("I0_GCLK_SITE%i", i_dest[0][j]), + /*bidir*/ 0))) FAIL(rc); + if ((rc = add_switch(model, model->center_y, model->center_x, + pf("CLKC_GCLK%i", j), pf("I1_GCLK_SITE%i", i_dest[1][j]), + /*bidir*/ 0))) FAIL(rc); + }} + + { const char *to[] = { + "CLK_PLL_LOCK_LT0", "CLK_PLL_LOCK_LT1", + "CLK_PLL_LOCK_RT0", "CLK_PLL_LOCK_RT1" }; + const char *from[] = { + "PLL_LOCK_BOT0", "PLL_LOCK_BOT1", + "PLL_LOCK_TOP0", "PLL_LOCK_TOP1" }; + for (i = 0; i < sizeof(to)/sizeof(*to); i++) { + for (j = 0; j < sizeof(from)/sizeof(*from); j++) { + if ((rc = add_switch(model, model->center_y, + model->center_x-CENTER_CMTPLL_O, + from[j], to[i], /*bidir*/ 0))) FAIL(rc); + } + }} + + { const char* pairs[] = { + "PLL_LOCK_BOT0", "PLL_LOCK_TOP2", + "PLL_LOCK_BOT1", "PLL_LOCK_TOP2", + "PLL_LOCK_TOP0", "PLL_LOCK_BOT2", + "PLL_LOCK_TOP1", "PLL_LOCK_BOT2" }; + + for (i = 0; i < sizeof(pairs)/sizeof(*pairs)/2; i++) { + if ((rc = add_switch(model, model->center_y, + model->center_x-CENTER_CMTPLL_O, + pairs[i*2], pairs[i*2+1], + /*bidir*/ 0))) FAIL(rc); + }} + + { const char *to[] = { + "REGC_CLKPLL_IO_LT0", "REGC_CLKPLL_IO_LT1", + "REGC_CLKPLL_IO_RT0", "REGC_CLKPLL_IO_RT1", + "REGC_PLLCLK_UP_OUT0", "REGC_PLLCLK_UP_OUT1" }; + for (i = 0; i <= 3; i++) { + for (j = 0; j < sizeof(to)/sizeof(*to); j++) { + if ((rc = add_switch(model, model->center_y, + model->center_x-CENTER_CMTPLL_O, + pf("REGC_PLLCLK_DN_IN%i", i), to[j], + /*bidir*/ 0))) FAIL(rc); + } + }} + { const char *to[] = { + "REGC_CLKPLL_IO_LT0", "REGC_CLKPLL_IO_LT1", + "REGC_CLKPLL_IO_RT0", "REGC_CLKPLL_IO_RT1", + "REGC_PLLCLK_DN_OUT0", "REGC_PLLCLK_DN_OUT1" }; + for (i = 0; i <= 3; i++) { + for (j = 0; j < sizeof(to)/sizeof(*to); j++) { + if ((rc = add_switch(model, model->center_y, + model->center_x-CENTER_CMTPLL_O, + pf("REGC_PLLCLK_UP_IN%i", i), to[j], + /*bidir*/ 0))) FAIL(rc); + } + }} + return 0; +fail: + return rc; +} + +static int init_hclk_switches(struct fpga_model* model) +{ + int x, y, i, rc; + + for (x = 0; x < model->x_width; x++) { + if (!is_atx(X_ROUTING_COL, model, x)) + continue; + for (y = TOP_IO_TILES; y < model->y_height-BOT_IO_TILES; y++) { + if (!is_aty(Y_ROW_HORIZ_AXSYMM, model, y)) + continue; + for (i = 0; i <= 15; i++) { + if ((rc = add_switch(model, y, x, + pf("HCLK_GCLK%i_INT", i), pf("HCLK_GCLK%i", i), + /*bidir*/ 0))) FAIL(rc); + if ((rc = add_switch(model, y, x, + pf("HCLK_GCLK%i_INT", i), pf("HCLK_GCLK_UP%i", i), + /*bidir*/ 0))) FAIL(rc); + } + } + } + return 0; +fail: + return rc; +} + +static int init_logicout_fw_switches(struct fpga_model *model) +{ + int i, x, y, rc; + + for (x = 0; x < model->x_width; x++) { + if (is_atx(X_FABRIC_BRAM_VIA_COL|X_FABRIC_MACC_VIA_COL, model, x)) { + for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { + if (is_aty(Y_CHIP_HORIZ_REGS|Y_ROW_HORIZ_AXSYMM, model, y)) + continue; + for (i = 0; i <= 23; i++) { + if ((rc = add_switch(model, y, x, + pf("INT_INTERFACE_LOGICOUT_%i", i), pf("INT_INTERFACE_LOGICOUT%i", i), + /*bidir*/ 0))) FAIL(rc); + } + } + continue; + } + if (is_atx(X_CENTER_ROUTING_COL, model, x)) { + for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { + if (!is_aty(Y_ROW_HORIZ_AXSYMM, model, y)) + continue; + for (i = 0; i <= 23; i++) { + if ((rc = add_switch(model, y-1, model->center_x-CENTER_LOGIC_O, + pf("INT_INTERFACE_LOGICOUT_%i", i), pf("INT_INTERFACE_LOGICOUT%i", i), + /*bidir*/ 0))) FAIL(rc); + if ((rc = add_switch(model, y+1, model->center_x-CENTER_LOGIC_O, + pf("INT_INTERFACE_LOGICOUT_%i", i), pf("INT_INTERFACE_LOGICOUT%i", i), + /*bidir*/ 0))) FAIL(rc); + } + } + continue; + } + 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_CHIP_HORIZ_REGS|Y_ROW_HORIZ_AXSYMM, model, y) + || has_device(model, y, LEFT_IO_DEVS, DEV_ILOGIC)) + continue; + if (has_device(model, y, LEFT_IO_DEVS, DEV_OCT_CALIBRATE)) { + for (i = 0; i <= 23; i++) { + if ((rc = add_switch(model, y, x, + pf("INT_INTERFACE_LOCAL_LOGICOUT_%i", i), pf("INT_INTERFACE_LOCAL_LOGICOUT%i", i), + /*bidir*/ 0))) FAIL(rc); + } + continue; + } + // todo: this is probably not right... + if (y == model->center_y-1 || y == model->center_y-2 + || y < TOP_IO_TILES + HALF_ROW + || y == model->y_height-BOT_INNER_IO) + continue; + for (i = 0; i <= 23; i++) { + if ((rc = add_switch(model, y, x, + pf("INT_INTERFACE_LOGICOUT_%i", i), pf("INT_INTERFACE_LOGICOUT%i", i), + /*bidir*/ 0))) FAIL(rc); + } + } + continue; + } + 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_CHIP_HORIZ_REGS|Y_ROW_HORIZ_AXSYMM, model, y) + || has_device(model, y, model->x_width-RIGHT_IO_DEVS_O, DEV_ILOGIC)) + continue; + if (has_device(model, y, model->x_width-RIGHT_IO_DEVS_O, DEV_BSCAN) + || has_device(model, y, model->x_width-RIGHT_IO_DEVS_O, DEV_ICAP) + || has_device(model, y, model->x_width-RIGHT_IO_DEVS_O, DEV_SLAVE_SPI)) { + for (i = 0; i <= 23; i++) { + if ((rc = add_switch(model, y, x, + pf("INT_INTERFACE_LOCAL_LOGICOUT_%i", i), pf("INT_INTERFACE_LOCAL_LOGICOUT%i", i), + /*bidir*/ 0))) FAIL(rc); + } + continue; + } + // todo: this is probably not right... + if (y == model->center_y-1 || y == model->center_y-2 + || y < TOP_IO_TILES + HALF_ROW) + continue; + for (i = 0; i <= 23; i++) { + if ((rc = add_switch(model, y, x, + pf("INT_INTERFACE_LOGICOUT_%i", i), pf("INT_INTERFACE_LOGICOUT%i", i), + /*bidir*/ 0))) FAIL(rc); + } + } + continue; + } + } + return 0; +fail: + return rc; +} + +static int init_bram_switches(struct fpga_model* model) +{ + int i, x, y, tile0_to_3, wire_num, rc; + + for (x = 0; x < model->x_width; x++) { + if (!is_atx(X_FABRIC_BRAM_COL, model, x)) + continue; + for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { + if (!has_device(model, y, x, DEV_BRAM16)) + continue; + { const char* pairs[] = { + "BRAM_CLK%c_INT1", "RAMB16BWER_CLK%c", + "BRAM_CLK%c_INT1", "RAMB8BWER_0_CLK%c", + "BRAM_CLK%c_INT2", "RAMB8BWER_1_CLK%c" }; + for (i = 0; i < sizeof(pairs)/sizeof(*pairs)/2; i++) { + if ((rc = add_switch(model, y, x, + pf(pairs[i*2], '0'+0), pf(pairs[i*2+1], 'A'+0), + /*bidir*/ 0))) FAIL(rc); + if ((rc = add_switch(model, y, x, + pf(pairs[i*2], '0'+1), pf(pairs[i*2+1], 'A'+1), + /*bidir*/ 0))) FAIL(rc); + }} + { const char *s[] = { + "BRAM_SR0_INT1", "RAMB16BWER_RSTA", + "BRAM_SR0_INT1", "RAMB8BWER_0_RSTA", + "BRAM_SR0_INT2", "RAMB8BWER_1_RSTA", + "BRAM_SR1_INT1", "RAMB16BWER_RSTB", + "BRAM_SR1_INT1", "RAMB8BWER_0_RSTB", + "BRAM_SR1_INT2", "RAMB8BWER_1_RSTB" }; + for (i = 0; i < sizeof(s)/sizeof(*s)/2; i++) { + if ((rc = add_switch(model, y, x, s[i*2], + s[i*2+1], /*bidir*/ 0))) FAIL(rc); + }} + for (i = BI_FIRST; i <= BI_LAST; i++) { + fdev_bram_inbit(BW+i, &tile0_to_3, &wire_num); + if (tile0_to_3 == -1) { HERE(); continue; } + if ((rc = add_switch(model, y, x, + pf("BRAM_LOGICINB%i_INT%i", wire_num, tile0_to_3), + fpga_wire2str(BW+i), + /*bidir*/ 0))) FAIL(rc); + if (fdev_is_bram8_inwire(i)) { + fdev_bram_inbit(BW+(B8_0|i), &tile0_to_3, &wire_num); + if (tile0_to_3 == -1) { HERE(); continue; } + if ((rc = add_switch(model, y, x, + pf("BRAM_LOGICINB%i_INT%i", wire_num, tile0_to_3), + fpga_wire2str(BW+(B8_0|i)), + /*bidir*/ 0))) FAIL(rc); + + fdev_bram_inbit(BW+(B8_1|i), &tile0_to_3, &wire_num); + if (tile0_to_3 == -1) { HERE(); continue; } + if ((rc = add_switch(model, y, x, + pf("BRAM_LOGICINB%i_INT%i", wire_num, tile0_to_3), + fpga_wire2str(BW+(B8_1|i)), + /*bidir*/ 0))) FAIL(rc); + } + } + for (i = BO_FIRST; i <= BO_LAST; i++) { + fdev_bram_outbit(BW+i, &tile0_to_3, &wire_num); + if (tile0_to_3 == -1) { HERE(); continue; } + if ((rc = add_switch(model, y, x, + fpga_wire2str(BW+i), + pf("BRAM_LOGICOUT%i_INT%i", wire_num, tile0_to_3), + /*bidir*/ 0))) FAIL(rc); + if (fdev_is_bram8_outwire(i)) { + fdev_bram_outbit(BW+(B8_0|i), &tile0_to_3, &wire_num); + if (tile0_to_3 == -1) { HERE(); continue; } + if ((rc = add_switch(model, y, x, + fpga_wire2str(BW+(B8_0|i)), + pf("BRAM_LOGICOUT%i_INT%i", wire_num, tile0_to_3), + /*bidir*/ 0))) FAIL(rc); + + fdev_bram_outbit(BW+(B8_1|i), &tile0_to_3, &wire_num); + if (tile0_to_3 == -1) { HERE(); continue; } + if ((rc = add_switch(model, y, x, + fpga_wire2str(BW+(B8_1|i)), + pf("BRAM_LOGICOUT%i_INT%i", wire_num, tile0_to_3), + /*bidir*/ 0))) FAIL(rc); + } + } + } + } + return 0; +fail: + return rc; +} + +static int init_macc_switches(struct fpga_model* model) +{ + int i, x, y, tile0_to_3, wire_num, rc; + + for (x = 0; x < model->x_width; x++) { + if (!is_atx(X_FABRIC_MACC_COL, model, x)) + continue; + for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { + if (!has_device(model, y, x, DEV_MACC)) + continue; + { const char *s[] = { + "MACC_SR0_INT0", "RSTD_DSP48A1_SITE", + "MACC_SR0_INT1", "RSTP_DSP48A1_SITE", + "MACC_SR0_INT2", "RSTC_DSP48A1_SITE", + "MACC_SR0_INT3", "RSTA_DSP48A1_SITE", + "MACC_SR1_INT0", "RSTCARRYIN_DSP48A1_SITE", + "MACC_SR1_INT1", "RSTOPMODE_DSP48A1_SITE", + "MACC_SR1_INT2", "RSTM_DSP48A1_SITE", + "MACC_SR1_INT3", "RSTB_DSP48A1_SITE", + "MACC_CLK0_INT2", "CLK_DSP48A1_SITE" }; + for (i = 0; i < sizeof(s)/sizeof(*s)/2; i++) { + if ((rc = add_switch(model, y, x, s[i*2], + s[i*2+1], /*bidir*/ 0))) FAIL(rc); + }} + for (i = MI_FIRST; i <= MI_LAST; i++) { + fdev_macc_inbit(MW+i, &tile0_to_3, &wire_num); + if (tile0_to_3 == -1) { HERE(); continue; } + if ((rc = add_switch(model, y, x, + pf("MACC_LOGICINB%i_INT%i", wire_num, tile0_to_3), + fpga_wire2str(MW+i), + /*bidir*/ 0))) FAIL(rc); + } + for (i = MO_FIRST; i <= MO_LAST; i++) { + fdev_macc_outbit(MW+i, &tile0_to_3, &wire_num); + if (tile0_to_3 == -1) { HERE(); continue; } + if ((rc = add_switch(model, y, x, + fpga_wire2str(MW+i), + pf("MACC_LOGICOUT%i_INT%i", wire_num, tile0_to_3), + /*bidir*/ 0))) FAIL(rc); + } + } + } + return 0; +fail: + return rc; +}