diff --git a/autotest.c b/autotest.c index 009e3db..8f34602 100644 --- a/autotest.c +++ b/autotest.c @@ -167,14 +167,14 @@ int main(int argc, char** argv) rc = diff_printf(&tstate); if (rc) FAIL(rc); -printf("P46 I pinw %s\n", strarray_lookup(&model.str, P46_dev->pinw_out[IOB_OUT_I])); +printf("P46 I pinw %s\n", strarray_lookup(&model.str, P46_dev->pinw[IOB_OUT_I])); switch_to.yx_req = YX_DEV_ILOGIC; switch_to.flags = SWTO_YX_DEF; switch_to.model = &model; switch_to.y = P46_y; switch_to.x = P46_x; - switch_to.start_switch = P46_dev->pinw_out[IOB_OUT_I]; + switch_to.start_switch = P46_dev->pinw[IOB_OUT_I]; rc = fpga_switch_to_yx(&switch_to); if (rc) FAIL(rc); rc = fpga_switch_set_enable(&model, switch_to.y, switch_to.x, &switch_to.set); @@ -216,7 +216,7 @@ printf(" %s\n", fmt_swset(&model, switch_to.y, switch_to.x, &switch_to.set, SW_F struct sw_chain c = { .model = &model, .y = switch_to.dest_y, .x = switch_to.dest_x+1, - .start_switch = logic_dev->pinw_in[LOGIC_IN_D3], + .start_switch = logic_dev->pinw[LOGIC_IN_D3], .from_to = SW_TO, .max_chain_size = MAX_SW_DEPTH }; if (fpga_switch_chain(&c) == NO_CONN) FAIL(EINVAL); if (c.set.len == 0) { HERE(); FAIL(EINVAL); } @@ -248,7 +248,7 @@ printf(" %s\n", fmt_swset(&model, c.y, c.x, &c.set, SW_FROM)); if (rc) FAIL(rc); printf("\n"); - printf("P48 O pinw %s\n", strarray_lookup(&model.str, P48_dev->pinw_in[IOB_IN_O])); + printf("P48 O pinw %s\n", strarray_lookup(&model.str, P48_dev->pinw[IOB_IN_O])); printf("\n"); printf("O Test suite completed.\n"); diff --git a/control.c b/control.c index b035100..5c330df 100644 --- a/control.c +++ b/control.c @@ -423,7 +423,7 @@ int fpga_switch_is_bidir(struct fpga_model* model, int y, int x, return (YX_TILE(model, y, x)->switches[swidx] & SWITCH_BIDIRECTIONAL) != 0; } -int fpga_switch_is_enabled(struct fpga_model* model, int y, int x, +int fpga_switch_is_used(struct fpga_model* model, int y, int x, swidx_t swidx) { return (YX_TILE(model, y, x)->switches[swidx] & SWITCH_USED) != 0; @@ -461,7 +461,7 @@ const char* fmt_sw(struct fpga_model* model, int y, int x, swidx_t sw, int from_ last_buf = (last_buf+1)%NUM_SW_BUFS; - strcpy(midstr, fpga_switch_is_enabled(model, y, x, sw) ? "on:" : ""); + strcpy(midstr, fpga_switch_is_used(model, y, x, sw) ? "on:" : ""); if (fpga_switch_is_bidir(model, y, x, sw)) strcat(midstr, "<->"); else { diff --git a/control.h b/control.h index 7e64ba7..7776464 100644 --- a/control.h +++ b/control.h @@ -66,7 +66,7 @@ str16_t fpga_switch_str_i(struct fpga_model* model, int y, int x, swidx_t swidx, int from_to); int fpga_switch_is_bidir(struct fpga_model* model, int y, int x, swidx_t swidx); -int fpga_switch_is_enabled(struct fpga_model* model, int y, int x, +int fpga_switch_is_used(struct fpga_model* model, int y, int x, swidx_t swidx); void fpga_switch_enable(struct fpga_model* model, int y, int x, swidx_t swidx); diff --git a/floorplan.c b/floorplan.c index 73e1674..714a373 100644 --- a/floorplan.c +++ b/floorplan.c @@ -761,7 +761,7 @@ static void read_sw_line(struct fpga_model* model, const char* line, int start) HERE(); return; } - if (fpga_switch_is_enabled(model, y_coord, x_coord, sw_idx)) + if (fpga_switch_is_used(model, y_coord, x_coord, sw_idx)) HERE(); if (is_on) fpga_switch_enable(model, y_coord, x_coord, sw_idx); diff --git a/model.h b/model.h index 86a285a..9e4c85b 100644 --- a/model.h +++ b/model.h @@ -344,8 +344,9 @@ enum fpgadev_type enum { LOGIC_M = 1, LOGIC_L, LOGIC_X }; // All LOGICIN_IN A..D sequences must be exactly sequential as // here to match initialization in model_device:init_logic(). -enum { LOGIC_IN_A1 = 0, LOGIC_IN_A2, LOGIC_IN_A3, LOGIC_IN_A4, LOGIC_IN_A5, - LOGIC_IN_A6, +enum { // input: + LOGIC_IN_A1 = 0, + LOGIC_IN_A2, LOGIC_IN_A3, LOGIC_IN_A4, LOGIC_IN_A5, LOGIC_IN_A6, LOGIC_IN_B1, LOGIC_IN_B2, LOGIC_IN_B3, LOGIC_IN_B4, LOGIC_IN_B5, LOGIC_IN_B6, LOGIC_IN_C1, LOGIC_IN_C2, LOGIC_IN_C3, LOGIC_IN_C4, LOGIC_IN_C5, @@ -358,12 +359,26 @@ enum { LOGIC_IN_A1 = 0, LOGIC_IN_A2, LOGIC_IN_A3, LOGIC_IN_A4, LOGIC_IN_A5, LOGIC_IN_CIN, // only some L and M devs have this // only for M: LOGIC_IN_WE, LOGIC_IN_AI, LOGIC_IN_BI, LOGIC_IN_CI, LOGIC_IN_DI, - LOGIC_NUM_PINW_IN }; -enum { LOGIC_OUT_A = 0, LOGIC_OUT_B, LOGIC_OUT_C, LOGIC_OUT_D, + // output: + LOGIC_OUT_A, LOGIC_OUT_B, LOGIC_OUT_C, LOGIC_OUT_D, LOGIC_OUT_AMUX, LOGIC_OUT_BMUX, LOGIC_OUT_CMUX, LOGIC_OUT_DMUX, LOGIC_OUT_AQ, LOGIC_OUT_BQ, LOGIC_OUT_CQ, LOGIC_OUT_DQ, - LOGIC_OUT_COUT, // only some L and M devs have this - LOGIC_NUM_PINW_OUT }; + LOGIC_OUT_COUT }; // only some L and M devs have this +#define LOGIC_LAST_INPUT_PINW LOGIC_IN_DI +#define LOGIC_LAST_OUTPUT_PINW LOGIC_OUT_COUT +#define LOGIC_PINW_STR \ + { "A1", "A2", "A3", "A4", "A5", "A6", \ + "B1", "B2", "B3", "B4", "B5", "B6", \ + "C1", "C2", "C3", "C4", "C5", "C6", \ + "D1", "D2", "D3", "D4", "D5", "D6", \ + "AX", "BX", "CX", "DX", \ + "CLK", "CE", "SR", \ + "CIN", \ + "WE", "AI", "BI", "CI", "DI", \ + "A", "B", "C", "D", \ + "AMUX", "BMUX", "CMUX", "DMUX", \ + "AQ", "BQ", "CQ", "DQ", \ + "COUT" } struct fpgadev_logic { @@ -385,10 +400,15 @@ enum { ITERM_NONE = 1, ITERM_UNTUNED_25, ITERM_UNTUNED_50, enum { OTERM_NONE = 1, OTERM_UNTUNED_25, OTERM_UNTUNED_50, OTERM_UNTUNED_75 }; -enum { IOB_IN_O = 0, IOB_IN_T, IOB_IN_DIFFI_IN, IOB_IN_DIFFO_IN, - IOB_NUM_PINW_IN }; -enum { IOB_OUT_I = 0, IOB_OUT_PADOUT, IOB_OUT_PCI_RDY, IOB_OUT_DIFFO_OUT, - IOB_NUM_PINW_OUT }; +enum { // input: + IOB_IN_O = 0, IOB_IN_T, IOB_IN_DIFFI_IN, IOB_IN_DIFFO_IN, + // output: + IOB_OUT_I, IOB_OUT_PADOUT, IOB_OUT_PCI_RDY, IOB_OUT_DIFFO_OUT }; +#define IOB_LAST_INPUT_PINW IOB_IN_DIFFO_IN +#define IOB_LAST_OUTPUT_PINW IOB_OUT_DIFFO_OUT +#define IOB_PINW_STR \ + { "O", "T", "DIFFI_IN", "DIFFO_IN", \ + "I", "PADOUT", "PCI_RDY", "DIFFO_OUT" } struct fpgadev_iob { @@ -405,19 +425,20 @@ struct fpgadev_iob int out_term; }; -#define MAX_PINW_IN 64 -#define MAX_PINW_OUT 32 +typedef int pinw_idx_t; // index into pinw array struct fpga_device { enum fpgadev_type type; int instantiated; - int num_in_wires, num_out_wires; - // pinwires that are within the type-range of a device, but - // don't exist for that particular instance, will be set to - // STRIDX_NO_ENTRY - str16_t pinw_in[MAX_PINW_IN]; - str16_t pinw_out[MAX_PINW_OUT]; + + // A bram dev has about 190 pinwires (input and output + // combined), macc about 350, mcb about 1200. + int num_pinw_total, num_pinw_in; + // The array holds first the input wires, then the output wires. + // Unused members are set to STRIDX_NO_ENTRY. + str16_t* pinw; + union { struct fpgadev_logic logic; struct fpgadev_iob iob; @@ -481,8 +502,14 @@ void fpga_free_model(struct fpga_model* model); const char* fpga_tiletype_str(enum fpga_tile_type type); int init_tiles(struct fpga_model* model); + int init_devices(struct fpga_model* model); void free_devices(struct fpga_model* model); +#define PINW_NO_IDX -1 +pinw_idx_t fpgadev_pinw_str2idx(int devtype, const char* str); +// returns 0 when idx not found for the given devtype +const char* fpgadev_pinw_idx2str(int devtype, pinw_idx_t idx); + int init_ports(struct fpga_model* model, int dup_warn); int init_conns(struct fpga_model* model); diff --git a/model_devices.c b/model_devices.c index 85a857c..00f9930 100644 --- a/model_devices.c +++ b/model_devices.c @@ -310,8 +310,14 @@ void free_devices(struct fpga_model* model) continue; EXIT(!model->tiles[i].devs); for (j = 0; j < model->tiles[i].num_devs; j++) { + free(model->tiles[i].devs[j].pinw); + model->tiles[i].devs[j].pinw = 0; + model->tiles[i].devs[j].num_pinw_total = 0; + model->tiles[i].devs[j].num_pinw_in = 0; + 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); @@ -326,6 +332,52 @@ void free_devices(struct fpga_model* model) model->tiles[i].num_devs = 0; } } + +static const char* iob_pinw_str[] = IOB_PINW_STR; +static const char* logic_pinw_str[] = LOGIC_PINW_STR; + +pinw_idx_t fpgadev_pinw_str2idx(int devtype, const char* str) +{ + int i; + if (devtype == DEV_IOB) { + for (i = 0; i < sizeof(iob_pinw_str)/sizeof(*iob_pinw_str); i++) { + if (!strcmp(iob_pinw_str[i], str)) + return i; + } + HERE(); + return PINW_NO_IDX; + } + if (devtype == DEV_LOGIC) { + for (i = 0; i < sizeof(logic_pinw_str)/sizeof(*logic_pinw_str); i++) { + if (!strcmp(logic_pinw_str[i], str)) + return i; + } + HERE(); + return PINW_NO_IDX; + } + HERE(); + return PINW_NO_IDX; +} + +const char* fpgadev_pinw_idx2str(int devtype, pinw_idx_t idx) +{ + if (devtype == DEV_IOB) { + if (idx < 0 || idx >= sizeof(iob_pinw_str)/sizeof(*iob_pinw_str)) { + HERE(); + return 0; + } + return iob_pinw_str[idx]; + } + if (devtype == DEV_LOGIC) { + if (idx < 0 || idx >= sizeof(logic_pinw_str)/sizeof(*logic_pinw_str)) { + HERE(); + return 0; + } + return logic_pinw_str[idx]; + } + HERE(); + return 0; +} #define DEV_INCREMENT 4 @@ -384,35 +436,40 @@ static int init_iob(struct fpga_model* model, int y, int x, else FAIL(EINVAL); + tile->devs[idx].pinw = calloc((IOB_LAST_OUTPUT_PINW+1) + *sizeof(tile->devs[idx].pinw[0]), /*elsize*/ 1); + if (!tile->devs[idx].pinw) FAIL(ENOMEM); + tile->devs[idx].num_pinw_total = IOB_LAST_OUTPUT_PINW+1; + tile->devs[idx].num_pinw_in = IOB_LAST_INPUT_PINW+1; + snprintf(tmp_str, sizeof(tmp_str), "%s_O%i_PINW", prefix, type_idx); rc = add_connpt_name(model, y, x, tmp_str, /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[IOB_IN_O], 0); + &tile->devs[idx].pinw[IOB_IN_O], 0); if (rc) FAIL(rc); snprintf(tmp_str, sizeof(tmp_str), "%s_T%i_PINW", prefix, type_idx); rc = add_connpt_name(model, y, x, tmp_str, /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[IOB_IN_T], 0); + &tile->devs[idx].pinw[IOB_IN_T], 0); if (rc) FAIL(rc); snprintf(tmp_str, sizeof(tmp_str), "%s_DIFFI_IN%i", prefix, type_idx); rc = add_connpt_name(model, y, x, tmp_str, /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[IOB_IN_DIFFI_IN], 0); + &tile->devs[idx].pinw[IOB_IN_DIFFI_IN], 0); if (rc) FAIL(rc); snprintf(tmp_str, sizeof(tmp_str), "%s_DIFFO_IN%i", prefix, type_idx); rc = add_connpt_name(model, y, x, tmp_str, /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[IOB_IN_DIFFO_IN], 0); + &tile->devs[idx].pinw[IOB_IN_DIFFO_IN], 0); if (rc) FAIL(rc); - tile->devs[idx].num_in_wires = IOB_NUM_PINW_IN; snprintf(tmp_str, sizeof(tmp_str), "%s_IBUF%i_PINW", prefix, type_idx); rc = add_connpt_name(model, y, x, tmp_str, /*dup_warn*/ 1, - &tile->devs[idx].pinw_out[IOB_OUT_I], 0); + &tile->devs[idx].pinw[IOB_OUT_I], 0); if (rc) FAIL(rc); snprintf(tmp_str, sizeof(tmp_str), "%s_PADOUT%i", prefix, type_idx); rc = add_connpt_name(model, y, x, tmp_str, /*dup_warn*/ 1, - &tile->devs[idx].pinw_out[IOB_OUT_PADOUT], 0); + &tile->devs[idx].pinw[IOB_OUT_PADOUT], 0); if (rc) FAIL(rc); snprintf(tmp_str, sizeof(tmp_str), "%s_DIFFO_OUT%i", prefix, type_idx); rc = add_connpt_name(model, y, x, tmp_str, /*dup_warn*/ 1, - &tile->devs[idx].pinw_out[IOB_OUT_DIFFO_OUT], 0); + &tile->devs[idx].pinw[IOB_OUT_DIFFO_OUT], 0); if (rc) FAIL(rc); if (!x && y == model->center_y - CENTER_TOP_IOB_O && type_idx == 1) @@ -428,9 +485,8 @@ static int init_iob(struct fpga_model* model, int y, int x, "%s_PCI_RDY%i", prefix, type_idx); } rc = add_connpt_name(model, y, x, tmp_str, /*dup_warn*/ 1, - &tile->devs[idx].pinw_out[IOB_OUT_PCI_RDY], 0); + &tile->devs[idx].pinw[IOB_OUT_PCI_RDY], 0); if (rc) FAIL(rc); - tile->devs[idx].num_out_wires = IOB_NUM_PINW_OUT; return 0; fail: return rc; @@ -454,56 +510,62 @@ static int init_logic(struct fpga_model* model, int y, int x, ? "XX_" : "X_"; } else FAIL(EINVAL); + tile->devs[idx].pinw = calloc((LOGIC_LAST_OUTPUT_PINW+1) + *sizeof(tile->devs[idx].pinw[0]), /*elsize*/ 1); + if (!tile->devs[idx].pinw) FAIL(ENOMEM); + tile->devs[idx].num_pinw_total = LOGIC_LAST_OUTPUT_PINW+1; + tile->devs[idx].num_pinw_in = LOGIC_LAST_INPUT_PINW+1; + for (i = 0; i < 4; i++) { // 'A' to 'D' for (j = 0; j < 6; j++) { rc = add_connpt_name(model, y, x, pf("%s%c%i", pre, 'A'+i, j+1), /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[LOGIC_IN_A1+i*6+j], 0); + &tile->devs[idx].pinw[LOGIC_IN_A1+i*6+j], 0); if (rc) FAIL(rc); } rc = add_connpt_name(model, y, x, pf("%s%cX", pre, 'A'+i), /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[LOGIC_IN_AX+i], 0); + &tile->devs[idx].pinw[LOGIC_IN_AX+i], 0); if (rc) FAIL(rc); if (subtype == LOGIC_M) { rc = add_connpt_name(model, y, x, pf("%s%cI", pre, 'A'+i), /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[LOGIC_IN_AI+i], 0); + &tile->devs[idx].pinw[LOGIC_IN_AI+i], 0); if (rc) FAIL(rc); } else - tile->devs[idx].pinw_in[LOGIC_IN_AI+i] = STRIDX_NO_ENTRY; + tile->devs[idx].pinw[LOGIC_IN_AI+i] = STRIDX_NO_ENTRY; rc = add_connpt_name(model, y, x, pf("%s%c", pre, 'A'+i), /*dup_warn*/ 1, - &tile->devs[idx].pinw_out[LOGIC_OUT_A+i], 0); + &tile->devs[idx].pinw[LOGIC_OUT_A+i], 0); if (rc) FAIL(rc); rc = add_connpt_name(model, y, x, pf("%s%cMUX", pre, 'A'+i), /*dup_warn*/ 1, - &tile->devs[idx].pinw_out[LOGIC_OUT_AMUX+i], 0); + &tile->devs[idx].pinw[LOGIC_OUT_AMUX+i], 0); if (rc) FAIL(rc); rc = add_connpt_name(model, y, x, pf("%s%cQ", pre, 'A'+i), /*dup_warn*/ 1, - &tile->devs[idx].pinw_out[LOGIC_OUT_AQ+i], 0); + &tile->devs[idx].pinw[LOGIC_OUT_AQ+i], 0); if (rc) FAIL(rc); } rc = add_connpt_name(model, y, x, pf("%sCLK", pre), /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[LOGIC_IN_CLK], 0); + &tile->devs[idx].pinw[LOGIC_IN_CLK], 0); if (rc) FAIL(rc); rc = add_connpt_name(model, y, x, pf("%sCE", pre), /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[LOGIC_IN_CE], 0); + &tile->devs[idx].pinw[LOGIC_IN_CE], 0); if (rc) FAIL(rc); rc = add_connpt_name(model, y, x, pf("%sSR", pre), /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[LOGIC_IN_SR], 0); + &tile->devs[idx].pinw[LOGIC_IN_SR], 0); if (rc) FAIL(rc); if (subtype == LOGIC_M) { rc = add_connpt_name(model, y, x, pf("%sWE", pre), /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[LOGIC_IN_WE], 0); + &tile->devs[idx].pinw[LOGIC_IN_WE], 0); if (rc) FAIL(rc); } else - tile->devs[idx].pinw_in[LOGIC_IN_WE] = STRIDX_NO_ENTRY; + tile->devs[idx].pinw[LOGIC_IN_WE] = STRIDX_NO_ENTRY; if (subtype != LOGIC_X && ((is_atx(X_ROUTING_NO_IO, model, x-1) && is_aty(Y_INNER_BOTTOM, model, y+1)) @@ -511,25 +573,23 @@ static int init_logic(struct fpga_model* model, int y, int x, && is_aty(Y_BOT_INNER_IO, model, y+1)))) { rc = add_connpt_name(model, y, x, pf("%sCIN", pre), /*dup_warn*/ 1, - &tile->devs[idx].pinw_in[LOGIC_IN_CIN], 0); + &tile->devs[idx].pinw[LOGIC_IN_CIN], 0); if (rc) FAIL(rc); } else - tile->devs[idx].pinw_in[LOGIC_IN_CIN] = STRIDX_NO_ENTRY; + tile->devs[idx].pinw[LOGIC_IN_CIN] = STRIDX_NO_ENTRY; if (subtype == LOGIC_M) { rc = add_connpt_name(model, y, x, "M_COUT", /*dup_warn*/ 1, - &tile->devs[idx].pinw_out[LOGIC_OUT_COUT], 0); + &tile->devs[idx].pinw[LOGIC_OUT_COUT], 0); if (rc) FAIL(rc); } else if (subtype == LOGIC_L) { rc = add_connpt_name(model, y, x, "XL_COUT", /*dup_warn*/ 1, - &tile->devs[idx].pinw_out[LOGIC_OUT_COUT], 0); + &tile->devs[idx].pinw[LOGIC_OUT_COUT], 0); if (rc) FAIL(rc); } else - tile->devs[idx].pinw_out[LOGIC_OUT_COUT] = STRIDX_NO_ENTRY; + tile->devs[idx].pinw[LOGIC_OUT_COUT] = STRIDX_NO_ENTRY; - tile->devs[idx].num_in_wires = LOGIC_NUM_PINW_IN; - tile->devs[idx].num_out_wires = LOGIC_NUM_PINW_OUT; return 0; fail: return rc;