From f26b3d05c93d4726d6659b49f29ca6aa4809178a Mon Sep 17 00:00:00 2001 From: Wolfgang Spraul Date: Fri, 7 Sep 2012 14:21:36 +0200 Subject: [PATCH] started with routing switches --- autotest.c | 4 +- bit.h | 1 + bit2fp.c | 28 +++- bit_frames.c | 427 +++++++++++++++++++++++++++++++++++++++++++++-- control.c | 32 +++- control.h | 3 + model.h | 106 ++++++++++-- model_devices.c | 34 ++-- model_main.c | 2 + model_switches.c | 63 +------ 10 files changed, 579 insertions(+), 121 deletions(-) diff --git a/autotest.c b/autotest.c index 7219d6f..abbc449 100644 --- a/autotest.c +++ b/autotest.c @@ -636,7 +636,7 @@ int main(int argc, char** argv) P46_dev_idx, IOB_OUT_I); if (rc) FAIL(rc); rc = fpga_net_add_port(&model, P46_net, /*y*/ 68, /*x*/ 13, - logic_dev_idx, LOGIC_IN_D3); + logic_dev_idx, LI_D3); if (rc) FAIL(rc); switch_to.yx_req = YX_DEV_ILOGIC; @@ -691,7 +691,7 @@ int main(int argc, char** argv) struct sw_chain c = { .model = &model, .y = switch_to.dest_y, .x = switch_to.dest_x+1, - .start_switch = logic_dev->pinw[LOGIC_IN_D3], + .start_switch = logic_dev->pinw[LI_D3], .from_to = SW_TO, .max_depth = SW_SET_SIZE, .block_list = 0 }; diff --git a/bit.h b/bit.h index 4f5620f..9afd97e 100644 --- a/bit.h +++ b/bit.h @@ -92,4 +92,5 @@ void free_config(struct fpga_config* cfg); int write_bitfile(FILE* f, struct fpga_model* model); int extract_model(struct fpga_model* model, struct fpga_bits* bits); +int printf_routing_mips(struct fpga_model* model); int write_model(struct fpga_bits* bits, struct fpga_model* model); diff --git a/bit2fp.c b/bit2fp.c index 9bb1ac7..01c5295 100644 --- a/bit2fp.c +++ b/bit2fp.c @@ -12,7 +12,8 @@ int main(int argc, char** argv) { struct fpga_model model; - int bit_header, bit_regs, fp_header, pull_model, file_arg, flags, rc = -1; + int bit_header, bit_regs, fp_header, pull_model, file_arg, flags; + int dump_routing_mips, rc = -1; struct fpga_config config; // parameters @@ -20,8 +21,9 @@ int main(int argc, char** argv) fprintf(stderr, "\n" "%s - bitstream to floorplan\n" - "Usage: %s [--bit-header] [--bit-regs] [--no-model] [--no-fp-header] \n" - "\n", argv[0], argv[0]); + "Usage: %s [--bit-header] [--bit-regs] [--no-model] [--no-fp-header]\n" + " %*s [--dump-routing-mips] \n" + "\n", argv[0], argv[0], (int) strlen(argv[0]), ""); goto fail; } bit_header = 0; @@ -29,7 +31,9 @@ int main(int argc, char** argv) pull_model = 1; fp_header = 1; file_arg = 1; - while (!strncmp(argv[file_arg], "--", 2)) { + dump_routing_mips = 0; + while (file_arg < argc + && !strncmp(argv[file_arg], "--", 2)) { if (!strcmp(argv[file_arg], "--bit-header")) bit_header = 1; else if (!strcmp(argv[file_arg], "--bit-regs")) @@ -38,10 +42,22 @@ int main(int argc, char** argv) pull_model = 0; else if (!strcmp(argv[file_arg], "--no-fp-header")) fp_header = 0; + else if (!strcmp(argv[file_arg], "--dump-routing-mips")) + dump_routing_mips = 1; else break; file_arg++; } + // build model + if ((rc = fpga_build_model(&model, XC6SLX9_ROWS, XC6SLX9_COLUMNS, + XC6SLX9_LEFT_WIRING, XC6SLX9_RIGHT_WIRING))) FAIL(rc); + + if (dump_routing_mips) { + rc = printf_routing_mips(&model); + if (rc) FAIL(rc); + return 0; + } + // read bitstream file { FILE* fbits = fopen(argv[file_arg], "r"); @@ -54,9 +70,7 @@ int main(int argc, char** argv) if (rc) FAIL(rc); } - // build model and fill from bitstream - if ((rc = fpga_build_model(&model, XC6SLX9_ROWS, XC6SLX9_COLUMNS, - XC6SLX9_LEFT_WIRING, XC6SLX9_RIGHT_WIRING))) FAIL(rc); + // fill model from bitstream if (pull_model) if ((rc = extract_model(&model, &config.bits))) FAIL(rc); diff --git a/bit_frames.c b/bit_frames.c index e336480..087c4d9 100644 --- a/bit_frames.c +++ b/bit_frames.c @@ -73,23 +73,46 @@ static struct bit_pos s_default_bits[] = { { 0, 1, 23, 1039 }, { 2, 0, 3, 66 }}; -int extract_model(struct fpga_model* model, struct fpga_bits* bits) +// swpos_mip is relative to a tile, i.e. major (x) and +// row/v64_i (y) are defined outside. +struct swpos_mip { - int i, num_iobs, iob_y, iob_x, iob_idx, dev_idx, row, row_pos, rc; - int x, y, byte_off; + int mip; // 0-18, even only + int two_bits_o; // 0-127, even only + int two_bits_val; // 0-3 + int one_bit_o; // 0-127, 1-6 bits up or down from two-bit val + swidx_t uni_dir; + swidx_t rev_dir; // NO_SWITCH for unidirectional switches +}; + +struct swpos_yx +{ + int y; + int x; + swidx_t idx; +}; + +#define MAX_YX_SWITCHES 1024 + +struct extract_state +{ + struct fpga_model* model; + struct fpga_bits* bits; + int num_mips; + struct swpos_mip mip[MAX_SWITCHBOX_SIZE]; + // yx switches are fully extracted ones pointing into the + // model, stored here for later processing into nets. + int num_sw_yx; + struct swpos_yx sw_yx[MAX_YX_SWITCHES]; // needs to be dynamically alloced... +}; + +static int extract_iobs(struct fpga_model* model, struct fpga_bits* bits) +{ + int i, num_iobs, iob_y, iob_x, iob_idx, dev_idx, rc; uint32_t* u32_p; - uint8_t* u8_p; - uint64_t u64; - const char* iob_sitename, *lut_str; + const char* iob_sitename; struct fpga_device* dev; - for (i = 0; i < sizeof(s_default_bits)/sizeof(s_default_bits[0]); i++) { - if (!get_bitp(bits, &s_default_bits[i])) - FAIL(EINVAL); - clear_bitp(bits, &s_default_bits[i]); - } - - // IOBs num_iobs = get_num_iobs(XC6SLX9); for (i = 0; i < num_iobs; i++) { u32_p = (uint32_t*) &bits->d[IOB_DATA_START + i*IOB_ENTRY_LEN]; @@ -128,8 +151,19 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits) u32_p[1] = 0; } else HERE(); } + return 0; +fail: + return rc; +} + +static int extract_logic(struct fpga_model* model, struct fpga_bits* bits) +{ + int dev_idx, row, row_pos, rc; + int x, y, byte_off; + uint8_t* u8_p; + uint64_t u64; + const char* lut_str; - // logic for (x = LEFT_SIDE_WIDTH; x < model->x_width-RIGHT_SIDE_WIDTH; x++) { if (!is_atx(X_FABRIC_LOGIC_COL|X_CENTER_LOGIC_COL, model, x)) continue; @@ -150,7 +184,6 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits) // M device dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGM); if (dev_idx == NO_DEV) FAIL(EINVAL); - dev = FPGA_DEV(model, y, x, dev_idx); // A6_LUT if (frame_get_u32(u8_p + 24*FRAME_SIZE + byte_off + 4) @@ -230,7 +263,6 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits) dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGX); if (dev_idx == NO_DEV) FAIL(EINVAL); - dev = FPGA_DEV(model, y, x, dev_idx); *(uint64_t*)(u8_p+26*FRAME_SIZE+byte_off) = 0; // A6_LUT @@ -282,6 +314,369 @@ fail: return rc; } +static int mip_is_set(struct extract_state* es, int y, int x, + struct swpos_mip* swpos, int* is_set) +{ + int row_num, row_pos, start_in_frame, two_bits_val, rc; + + *is_set = 0; + is_in_row(es->model, y, &row_num, &row_pos); + if (row_num == -1 || row_pos == -1 + || row_pos == HCLK_POS) FAIL(EINVAL); + if (row_pos > HCLK_POS) + start_in_frame = (row_pos-1)*64 + 16; + else + start_in_frame = row_pos*64; + + two_bits_val = + (get_bit(es->bits, row_num, es->model->x_major[x], swpos->mip, + start_in_frame + swpos->two_bits_o/2) << 1) + | (get_bit(es->bits, row_num, es->model->x_major[x], swpos->mip+1, + start_in_frame + swpos->two_bits_o/2) << 2); + if (two_bits_val != swpos->two_bits_val) + return 0; + + if (!get_bit(es->bits, row_num, es->model->x_major[x], + swpos->mip + (swpos->one_bit_o&1), + start_in_frame + swpos->one_bit_o/2)) + return 0; + *is_set = 1; + return 0; +fail: + return rc; +} + +static int mip_clear_bits(struct extract_state* es, int y, int x, + struct swpos_mip* swpos) +{ + int row_num, row_pos, start_in_frame, rc; + + is_in_row(es->model, y, &row_num, &row_pos); + if (row_num == -1 || row_pos == -1 + || row_pos == HCLK_POS) FAIL(EINVAL); + if (row_pos > HCLK_POS) + start_in_frame = (row_pos-1)*64 + 16; + else + start_in_frame = row_pos*64; + + clear_bit(es->bits, row_num, es->model->x_major[x], swpos->mip, + start_in_frame + swpos->two_bits_o/2); + clear_bit(es->bits, row_num, es->model->x_major[x], swpos->mip + 1, + start_in_frame + swpos->two_bits_o/2); + clear_bit(es->bits, row_num, es->model->x_major[x], swpos->mip + (swpos->one_bit_o&1), + start_in_frame + swpos->one_bit_o/2); + + return 0; +fail: + return rc; +} + +static int extract_routing_switches(struct extract_state* es, int y, int x) +{ + struct fpga_tile* tile; + int i, is_set, rc; + + tile = YX_TILE(es->model, y, x); +if (y != 68 || x != 12) return 0; + + // build tile-relative model of all routing switches and + // store in the extract state + if (!es->num_mips) { + } + + for (i = 0; i < es->num_mips; i++) { + rc = mip_is_set(es, y, x, &es->mip[i], &is_set); + if (rc) FAIL(rc); + if (!is_set) continue; + + if (tile->switches[es->mip[i].uni_dir] & SWITCH_BIDIRECTIONAL) + HERE(); + if (tile->switches[es->mip[i].uni_dir] & SWITCH_USED) + HERE(); + if (es->num_sw_yx >= MAX_YX_SWITCHES) + { FAIL(ENOTSUP); } + es->sw_yx[es->num_sw_yx].y = y; + es->sw_yx[es->num_sw_yx].x = x; + es->sw_yx[es->num_sw_yx].idx = es->mip[i].uni_dir; + es->num_sw_yx++; + rc = mip_clear_bits(es, y, x, &es->mip[i]); + if (rc) FAIL(rc); + } + return 0; +fail: + return rc; +} + +static int extract_switches(struct extract_state* es) +{ + int x, y, rc; + + // go through all tiles, look for one with switches + // go through each switch, lookup device, is_enabled() -> enable + for (x = 0; x < es->model->x_width; x++) { + for (y = 0; y < es->model->y_height; y++) { + if (is_atx(X_ROUTING_COL, es->model, x) + && y >= TOP_IO_TILES + && y < es->model->y_height-BOT_IO_TILES + && !is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, + es->model, y)) { + rc = extract_routing_switches(es, y, x); + if (rc) FAIL(rc); + } +#if 0 +// when all switches are supported, we can turn this +// on to make the model more robust + if (tile->num_switches) + fprintf(stderr, "%i unsupported switches in y%02i x%02i\n", + tile->num_switches, y, x); +#endif + } + } + return 0; +fail: + return rc; +} + +// these are roughly ordered in rows and columns as they are wired +// up in the routing switchbox. + +#define DIRBEG_ROW 12 +static const int dirbeg_matrix[] = +{ + W_WW4, W_NW4, W_NN4, W_NE4, W_NW2, W_NN2, W_NE2, W_EE2, W_WR1, W_NL1, W_EL1, W_NR1, + W_SS4, W_SW4, W_EE4, W_SE4, W_WW2, W_SW2, W_SS2, W_SE2, W_SR1, W_WL1, W_SL1, W_ER1 +}; + +static const int dirbeg_matrix_topnum[] = +{ + 3, 3, 3, 3, 3, 3, 3, 3, /*WR1*/ 0, /*NL1*/ 2, /*EL1*/ 2, /*NR1*/ 3, + 3, 3, 3, 3, 3, 3, 3, 3, /*SR1*/ 0, /*WL1*/ 2, /*SL1*/ 3, /*ER1*/ 0 +}; + +#define LOGOUT_ROW 6 +static const int logicout_matrix[] = +{ + M_BMUX, M_DQ, M_D, X_BMUX, X_DQ, X_D, + M_AMUX, M_CQ, M_C, X_AMUX, X_CQ, X_C, + M_DMUX, M_BQ, M_B, X_DMUX, X_BQ, X_B, + M_CMUX, M_AQ, M_A, X_CMUX, X_AQ, X_A +}; + +#define LOGIN_ROW 8 +static const int logicin_matrix[] = +{ + /*mip 12*/ /*mip 14*/ /*mip 16*/ /*mip 18*/ + /* 000 */ M_C6, X_D6, X_C1, X_DX, M_B3, X_A3, X_B2, FAN_B, + /* 016 */ M_B1, M_DI, M_A3, X_B3, M_C2, M_DX, M_D6, X_C6, + /* 032 */ M_C5, X_D5, M_CX, M_D2, M_B4, X_A4, M_A1, M_CE, + /* 048 */ M_CI, X_A2, M_A4, X_B4, X_CX, X_D1, M_D5, X_C5, + /* 064 */ M_C4, X_D4, M_D1, X_BX, M_B5, X_A5, M_A2, M_BI, + /* 080 */ X_A1, X_CE, M_A5, X_B5, M_BX, X_D2, M_D4, X_C4, + /* 096 */ M_C3, X_D3, M_AX, X_C2, M_B6, X_A6, M_AI, X_B1, + /* 112 */ M_B2, M_WE, M_A6, X_B6, M_C1, X_AX, M_D3, X_C3 +}; + +static int mod4_calc(int a, int b) +{ + return (unsigned int) (a+b)%4; +} + +static int construct_extract_state(struct extract_state* es, struct fpga_model* model) +{ + char from_str[MAX_WIRENAME_LEN], to_str[MAX_WIRENAME_LEN]; + int i, j, k, l, cur_mip, cur_two_bits_o, cur_two_bits_val, rc; + int logicin_i; + + memset(es, 0, sizeof(*es)); + es->model = model; + if (model->first_routing_y == -1) + FAIL(EINVAL); + + // switches from logicout to dirwires (6*2*2*4*6=576 switches) + for (i = 0; i < DIRBEG_ROW; i++) { + cur_mip = (i/2)*2; + for (j = 0; j <= 3; j++) { // 4 wires for each dirwire + for (k = 0; k <= 1; k++) { // two dirbeg rows + cur_two_bits_o = j*32 + k*16; + if (i%2) cur_two_bits_o += 14; + cur_two_bits_val = ((i%2)^k) ? 1 : 2; + for (l = 0; l < LOGOUT_ROW; l++) { + es->mip[es->num_mips].mip = cur_mip; + es->mip[es->num_mips].two_bits_o = cur_two_bits_o; + es->mip[es->num_mips].two_bits_val = cur_two_bits_val; + + es->mip[es->num_mips].one_bit_o = j*32+k*16+2+l*2; + if (!((i%2)^k)) // right side (second minor) + es->mip[es->num_mips].one_bit_o++; + + snprintf(from_str, sizeof(from_str), "LOGICOUT%i", logicout_matrix[j*LOGOUT_ROW + (k?5-l:l)]); + snprintf(to_str, sizeof(to_str), "%sB%i", + wire_base(dirbeg_matrix[k*DIRBEG_ROW+i]), mod4_calc(dirbeg_matrix_topnum[k*DIRBEG_ROW+i], -j)); + es->mip[es->num_mips].uni_dir = fpga_switch_lookup(es->model, + es->model->first_routing_y, es->model->first_routing_x, + strarray_find(&es->model->str, from_str), + strarray_find(&es->model->str, to_str)); + if (es->mip[es->num_mips].uni_dir == NO_SWITCH) { + fprintf(stderr, "#E routing switch %s -> %s not in model\n", + from_str, to_str); + FAIL(EINVAL); + } + + es->mip[es->num_mips].rev_dir = NO_SWITCH; + es->num_mips++; + } + } + } + } + + // VCC (32 switches) and GFAN (32 switches +4 bidir) + for (i = 12; i <= 18; i+=2) { // mip12/14/16/18 + for (j = 0; j <= 3; j++) { // 4 rows + for (k = 0; k <= 1; k++) { // two switch destinations + + // VCC + es->mip[es->num_mips].mip = i; + es->mip[es->num_mips].two_bits_o = 32*j + (k?14:0); + es->mip[es->num_mips].two_bits_val = 3; + es->mip[es->num_mips].one_bit_o = 32*j+2; + logicin_i = j*2*LOGIN_ROW + i-12 + k; + + if (i == 14 || i == 18) { + es->mip[es->num_mips].two_bits_o += 16; + es->mip[es->num_mips].one_bit_o += 16; + es->mip[es->num_mips].one_bit_o += !k; + logicin_i += LOGIN_ROW; + } else + es->mip[es->num_mips].one_bit_o += k; + + snprintf(to_str, sizeof(to_str), "LOGICIN_B%i", logicin_matrix[logicin_i]); + es->mip[es->num_mips].uni_dir = fpga_switch_lookup(es->model, + es->model->first_routing_y, es->model->first_routing_x, + strarray_find(&es->model->str, "VCC_WIRE"), + strarray_find(&es->model->str, to_str)); + if (es->mip[es->num_mips].uni_dir == NO_SWITCH) { + fprintf(stderr, "#E routing switch VCC_WIRE -> %s not in model\n", + to_str); + FAIL(EINVAL); + } + es->mip[es->num_mips].rev_dir = NO_SWITCH; + es->mip[es->num_mips+1] = es->mip[es->num_mips]; + es->num_mips++; + + // GFAN + if (i == 14 || i == 18) { + es->mip[es->num_mips].two_bits_o -= 16; + es->mip[es->num_mips].one_bit_o -= 16; + logicin_i -= LOGIN_ROW; + } else { // 12 or 16 + es->mip[es->num_mips].two_bits_o += 16; + es->mip[es->num_mips].one_bit_o += 16; + logicin_i += LOGIN_ROW; + } + snprintf(from_str, sizeof(from_str), "GFAN%i", j<2?1:0); + if (logicin_matrix[logicin_i] == FAN_B) + strcpy(to_str, "FAN_B"); + else + snprintf(to_str, sizeof(to_str), "LOGICIN_B%i", logicin_matrix[logicin_i]); + es->mip[es->num_mips].uni_dir = fpga_switch_lookup(es->model, + es->model->first_routing_y, es->model->first_routing_x, + strarray_find(&es->model->str, from_str), + strarray_find(&es->model->str, to_str)); + if (es->mip[es->num_mips].uni_dir == NO_SWITCH) { + fprintf(stderr, "#E routing switch %s -> %s not in model\n", + from_str, to_str); + FAIL(EINVAL); + } + // two bidir switches from and to GFAN0 (6 and 35), + // two from and to GFAN1 (51 and 53) + if (logicin_matrix[logicin_i] == 6 + || logicin_matrix[logicin_i] == 35 + || logicin_matrix[logicin_i] == 51 + || logicin_matrix[logicin_i] == 53) { + es->mip[es->num_mips].rev_dir = fpga_switch_lookup(es->model, + es->model->first_routing_y, es->model->first_routing_x, + strarray_find(&es->model->str, to_str), + strarray_find(&es->model->str, from_str)); + if (es->mip[es->num_mips].rev_dir == NO_SWITCH) { + fprintf(stderr, "#E rev routing switch %s -> %s not in model\n", + to_str, from_str); + FAIL(EINVAL); + } + } else + es->mip[es->num_mips].rev_dir = NO_SWITCH; + es->num_mips++; + } + } + } + return 0; +fail: + return rc; +} + +int extract_model(struct fpga_model* model, struct fpga_bits* bits) +{ + struct extract_state es; + net_idx_t net_idx; + int i, rc; + + rc = construct_extract_state(&es, model); + if (rc) FAIL(rc); + es.bits = bits; + for (i = 0; i < sizeof(s_default_bits)/sizeof(s_default_bits[0]); i++) { + if (!get_bitp(bits, &s_default_bits[i])) + FAIL(EINVAL); + clear_bitp(bits, &s_default_bits[i]); + } + + rc = extract_iobs(model, bits); + if (rc) FAIL(rc); + rc = extract_logic(model, bits); + if (rc) FAIL(rc); + rc = extract_switches(&es); + if (rc) FAIL(rc); + + // turn switches into nets + if (model->nets) + HERE(); // should be empty here + for (i = 0; i < es.num_sw_yx; i++) { + rc = fpga_net_new(model, &net_idx); + if (rc) FAIL(rc); + rc = fpga_net_add_switch(model, net_idx, es.sw_yx[i].y, es.sw_yx[i].x, es.sw_yx[i].idx); + if (rc) FAIL(rc); + } + return 0; +fail: + return rc; +} + +int printf_routing_mips(struct fpga_model* model) +{ + struct extract_state es; + char bit_str[129]; + int i, j, rc; + + rc = construct_extract_state(&es, model); + if (rc) FAIL(rc); + bit_str[128] = 0; + for (i = 0; i < es.num_mips; i++) { + for (j = 0; j < 128; j++) + bit_str[j] = '0'; + if (es.mip[i].two_bits_val & 2) + bit_str[es.mip[i].two_bits_o] = '1'; + if (es.mip[i].two_bits_val & 1) + bit_str[es.mip[i].two_bits_o+1] = '1'; + bit_str[es.mip[i].one_bit_o] = '1'; + printf("mip%02i %s %s %s %s\n", es.mip[i].mip, + fpga_switch_str(model, model->first_routing_y, model->first_routing_x, es.mip[i].uni_dir, SW_TO), + bit_str, + fpga_switch_str(model, model->first_routing_y, model->first_routing_x, es.mip[i].uni_dir, SW_FROM), + es.mip[i].rev_dir != NO_SWITCH ? "<->" : "->"); + } + return 0; +fail: + return rc; +} + int write_model(struct fpga_bits* bits, struct fpga_model* model) { int i; diff --git a/control.c b/control.c index 15b799f..fbdff6a 100644 --- a/control.c +++ b/control.c @@ -312,6 +312,28 @@ const char* fdev_pinw_idx2str(int devtype, pinw_idx_t idx) return 0; } +const char* fdev_logic_pinstr(pinw_idx_t idx, int ld1_type) +{ + enum { NUM_BUFS = 16, BUF_SIZE = 16 }; + static char buf[NUM_BUFS][BUF_SIZE]; + static int last_buf = 0; + + last_buf = (last_buf+1)%NUM_BUFS; + if (ld1_type == LOGIC_M) + snprintf(buf[last_buf], sizeof(*buf), "%s%s", + (idx & LD1) ? "M_" : "X_", + logic_pinw_str[idx&(~LD1)]); + else if (ld1_type == LOGIC_L) + snprintf(buf[last_buf], sizeof(*buf), "%s%s", + (idx & LD1) ? "L_" : "XX_", + logic_pinw_str[idx&(~LD1)]); + else { + HERE(); + buf[last_buf][0] = 0; + } + return buf[last_buf]; +} + static int reset_required_pins(struct fpga_device* dev) { int rc; @@ -453,13 +475,13 @@ int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type, if (rc) FAIL(rc); if (type == DEV_LOGIC) { if (dev->u.logic.A_used) - add_req_outpin(dev, LOGIC_OUT_A); + add_req_outpin(dev, LO_A); if (dev->u.logic.B_used) - add_req_outpin(dev, LOGIC_OUT_B); + add_req_outpin(dev, LO_B); if (dev->u.logic.C_used) - add_req_outpin(dev, LOGIC_OUT_C); + add_req_outpin(dev, LO_C); if (dev->u.logic.D_used) - add_req_outpin(dev, LOGIC_OUT_D); + add_req_outpin(dev, LO_D); for (i = 0; i < sizeof(dev->u.logic.luts) /sizeof(dev->u.logic.luts[0]); i++) { if (!dev->u.logic.luts[i]) continue; @@ -468,7 +490,7 @@ int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type, // i/2 because luts order is A5-A6 B5-B6, etc. if (digits[j]) add_req_inpin(dev, - LOGIC_IN_A1+(i/2)*6+j); + LI_A1+(i/2)*6+j); } } } diff --git a/control.h b/control.h index c113f76..61fadeb 100644 --- a/control.h +++ b/control.h @@ -38,6 +38,9 @@ dev_type_idx_t fdev_typeidx(struct fpga_model* model, int y, int x, pinw_idx_t fdev_pinw_str2idx(int devtype, const char* str, int len); // returns 0 when idx not found for the given devtype const char* fdev_pinw_idx2str(int devtype, pinw_idx_t idx); +// ld1_type can be LOGIC_M or LOGIC_L to specify whether +// we are in a XM or XL column. +const char* fdev_logic_pinstr(pinw_idx_t idx, int ld1_type); int fdev_logic_set_lut(struct fpga_model* model, int y, int x, int type_idx, int which_lut, const char* lut_str, int lut_len); diff --git a/model.h b/model.h index ea65419..aaecb78 100644 --- a/model.h +++ b/model.h @@ -72,6 +72,8 @@ struct fpga_model // 'majors' in the bitstream. int x_major[512]; + int first_routing_y, first_routing_x; + struct fpga_tile* tiles; struct hashed_strarray str; @@ -347,31 +349,37 @@ typedef int dev_type_idx_t; // data can safely be initialized to 0 meaning unconfigured. enum { LOGIC_M = 1, LOGIC_L, LOGIC_X }; + +// LD1 stands for logic device 1 and can be OR'ed to the LI_A1 +// or LO_A values to indicate the second logic device in a tile, +// either an M or L device. +#define LD1 0x100 + // All LOGICIN_IN A..D sequences must be exactly sequential as // here to match initialization in model_devices.c:init_logic() // and control.c:fdev_set_required_pins(). 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, - LOGIC_IN_C6, - LOGIC_IN_D1, LOGIC_IN_D2, LOGIC_IN_D3, LOGIC_IN_D4, LOGIC_IN_D5, - LOGIC_IN_D6, - LOGIC_IN_AX, LOGIC_IN_BX, LOGIC_IN_CX, LOGIC_IN_DX, - LOGIC_IN_CLK, LOGIC_IN_CE, LOGIC_IN_SR, + LI_A1 = 0, + LI_A2, LI_A3, LI_A4, LI_A5, LI_A6, + LI_B1, LI_B2, LI_B3, LI_B4, LI_B5, + LI_B6, + LI_C1, LI_C2, LI_C3, LI_C4, LI_C5, + LI_C6, + LI_D1, LI_D2, LI_D3, LI_D4, LI_D5, + LI_D6, + LI_AX, LI_BX, LI_CX, LI_DX, + LI_CLK, LI_CE, LI_SR, // only for L and M: - LOGIC_IN_CIN, // only some L and M devs have this + LI_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, + LI_WE, LI_AI, LI_BI, LI_CI, LI_DI, // 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 -#define LOGIC_LAST_INPUT_PINW LOGIC_IN_DI -#define LOGIC_LAST_OUTPUT_PINW LOGIC_OUT_COUT + LO_A, LO_B, LO_C, LO_D, + LO_AMUX, LO_BMUX, LO_CMUX, LO_DMUX, + LO_AQ, LO_BQ, LO_CQ, LO_DQ, + LO_COUT }; // only some L and M devs have this +#define LOGIC_LAST_INPUT_PINW LI_DI +#define LOGIC_LAST_OUTPUT_PINW LO_COUT #define LOGIC_PINW_STR \ { "A1", "A2", "A3", "A4", "A5", "A6", \ "B1", "B2", "B3", "B4", "B5", "B6", \ @@ -629,6 +637,8 @@ struct seed_data void seed_strx(struct fpga_model* model, struct seed_data* data); +#define MAX_WIRENAME_LEN 64 + // The LWF flags are OR'ed into the logic_wire enum #define LWF_SOUTH0 0x0100 #define LWF_NORTH3 0x0200 @@ -636,6 +646,10 @@ void seed_strx(struct fpga_model* model, struct seed_data* data); #define LWF_FAN_B 0x0800 #define LWF_WIRE_MASK 0x00FF // namespace for the enums +// ordered to match the LOGICIN_B?? enumeration +// todo: both enums logicin_wire and logicout_wire are not really +// ideal for supporting L_ and XX_ variants, maybe use pinwires +// and LD1 instead? enum logicin_wire { /* 0 */ X_A1 = 0, X_A2, X_A3, X_A4, X_A5, X_A6, X_AX, @@ -649,6 +663,7 @@ enum logicin_wire { /* 62 */ M_WE }; +// ordered to match the LOGICOUT_B?? enumeration enum logicout_wire { /* 0 */ X_A = 0, X_AMUX, X_AQ, X_B, X_BMUX, X_BQ, @@ -680,3 +695,58 @@ enum extra_wires { LOGICIN_S44, LOGICIN_S62 }; + +// The wires are ordered clockwise. Order is important for +// wire_to_NESW4(). +enum wire_type +{ + FIRST_LEN1 = 1, + W_NL1 = FIRST_LEN1, + W_NR1, + W_EL1, + W_ER1, + W_SL1, + W_SR1, + W_WL1, + W_WR1, + LAST_LEN1 = W_WR1, + + FIRST_LEN2, + W_NN2 = FIRST_LEN2, + W_NE2, + W_EE2, + W_SE2, + W_SS2, + W_SW2, + W_WW2, + W_NW2, + LAST_LEN2 = W_NW2, + + FIRST_LEN4, + W_NN4 = FIRST_LEN4, + W_NE4, + W_EE4, + W_SE4, + W_SS4, + W_SW4, + W_WW4, + W_NW4, + LAST_LEN4 = W_NW4 +}; + +#define W_CLOCKWISE(w) rotate_wire((w), 1) +#define W_CLOCKWISE_2(w) rotate_wire((w), 2) +#define W_COUNTER_CLOCKWISE(w) rotate_wire((w), -1) +#define W_COUNTER_CLOCKWISE_2(w) rotate_wire((w), -2) + +#define W_IS_LEN1(w) ((w) >= FIRST_LEN1 && (w) <= LAST_LEN1) +#define W_IS_LEN2(w) ((w) >= FIRST_LEN2 && (w) <= LAST_LEN2) +#define W_IS_LEN4(w) ((w) >= FIRST_LEN4 && (w) <= LAST_LEN4) + +#define W_TO_LEN1(w) wire_to_len(w, FIRST_LEN1) +#define W_TO_LEN2(w) wire_to_len(w, FIRST_LEN2) +#define W_TO_LEN4(w) wire_to_len(w, FIRST_LEN4) + +const char* wire_base(enum wire_type w); +enum wire_type rotate_wire(enum wire_type cur, int off); +enum wire_type wire_to_len(enum wire_type w, int first_len); diff --git a/model_devices.c b/model_devices.c index a3a385f..771c6af 100644 --- a/model_devices.c +++ b/model_devices.c @@ -463,52 +463,52 @@ static int init_logic(struct fpga_model* model, int y, int x, int idx) 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[LOGIC_IN_A1+i*6+j], 0); + &tile->devs[idx].pinw[LI_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[LOGIC_IN_AX+i], 0); + &tile->devs[idx].pinw[LI_AX+i], 0); if (rc) FAIL(rc); if (tile->devs[idx].subtype == LOGIC_M) { rc = add_connpt_name(model, y, x, pf("%s%cI", pre, 'A'+i), /*dup_warn*/ 1, - &tile->devs[idx].pinw[LOGIC_IN_AI+i], 0); + &tile->devs[idx].pinw[LI_AI+i], 0); if (rc) FAIL(rc); } else - tile->devs[idx].pinw[LOGIC_IN_AI+i] = STRIDX_NO_ENTRY; + tile->devs[idx].pinw[LI_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[LOGIC_OUT_A+i], 0); + &tile->devs[idx].pinw[LO_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[LOGIC_OUT_AMUX+i], 0); + &tile->devs[idx].pinw[LO_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[LOGIC_OUT_AQ+i], 0); + &tile->devs[idx].pinw[LO_AQ+i], 0); if (rc) FAIL(rc); } rc = add_connpt_name(model, y, x, pf("%sCLK", pre), /*dup_warn*/ 1, - &tile->devs[idx].pinw[LOGIC_IN_CLK], 0); + &tile->devs[idx].pinw[LI_CLK], 0); if (rc) FAIL(rc); rc = add_connpt_name(model, y, x, pf("%sCE", pre), /*dup_warn*/ 1, - &tile->devs[idx].pinw[LOGIC_IN_CE], 0); + &tile->devs[idx].pinw[LI_CE], 0); if (rc) FAIL(rc); rc = add_connpt_name(model, y, x, pf("%sSR", pre), /*dup_warn*/ 1, - &tile->devs[idx].pinw[LOGIC_IN_SR], 0); + &tile->devs[idx].pinw[LI_SR], 0); if (rc) FAIL(rc); if (tile->devs[idx].subtype == LOGIC_M) { rc = add_connpt_name(model, y, x, pf("%sWE", pre), /*dup_warn*/ 1, - &tile->devs[idx].pinw[LOGIC_IN_WE], 0); + &tile->devs[idx].pinw[LI_WE], 0); if (rc) FAIL(rc); } else - tile->devs[idx].pinw[LOGIC_IN_WE] = STRIDX_NO_ENTRY; + tile->devs[idx].pinw[LI_WE] = STRIDX_NO_ENTRY; if (tile->devs[idx].subtype != LOGIC_X && ((is_atx(X_ROUTING_NO_IO, model, x-1) && is_aty(Y_INNER_BOTTOM, model, y+1)) @@ -516,22 +516,22 @@ static int init_logic(struct fpga_model* model, int y, int x, int idx) && 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[LOGIC_IN_CIN], 0); + &tile->devs[idx].pinw[LI_CIN], 0); if (rc) FAIL(rc); } else - tile->devs[idx].pinw[LOGIC_IN_CIN] = STRIDX_NO_ENTRY; + tile->devs[idx].pinw[LI_CIN] = STRIDX_NO_ENTRY; if (tile->devs[idx].subtype == LOGIC_M) { rc = add_connpt_name(model, y, x, "M_COUT", /*dup_warn*/ 1, - &tile->devs[idx].pinw[LOGIC_OUT_COUT], 0); + &tile->devs[idx].pinw[LO_COUT], 0); if (rc) FAIL(rc); } else if (tile->devs[idx].subtype == LOGIC_L) { rc = add_connpt_name(model, y, x, "XL_COUT", /*dup_warn*/ 1, - &tile->devs[idx].pinw[LOGIC_OUT_COUT], 0); + &tile->devs[idx].pinw[LO_COUT], 0); if (rc) FAIL(rc); } else - tile->devs[idx].pinw[LOGIC_OUT_COUT] = STRIDX_NO_ENTRY; + tile->devs[idx].pinw[LO_COUT] = STRIDX_NO_ENTRY; return 0; fail: diff --git a/model_main.c b/model_main.c index 62a5b0d..37c3cd3 100644 --- a/model_main.c +++ b/model_main.c @@ -23,6 +23,8 @@ int fpga_build_model(struct fpga_model* model, int fpga_rows, strncpy(model->cfg_right_wiring, right_wiring, sizeof(model->cfg_right_wiring)-1); strarray_init(&model->str, STRIDX_64K); + model->first_routing_y = -1; + model->first_routing_x = -1; // The order of tiles, then devices, then ports, then // connections and finally switches is important so diff --git a/model_switches.c b/model_switches.c index 1c0924f..0afad3c 100644 --- a/model_switches.c +++ b/model_switches.c @@ -874,62 +874,7 @@ xout: return rc; } -// The wires are ordered clockwise. Order is important for -// wire_to_NESW4(). -enum wire_type -{ - FIRST_LEN1 = 1, - W_NL1 = FIRST_LEN1, - W_NR1, - W_EL1, - W_ER1, - W_SL1, - W_SR1, - W_WL1, - W_WR1, - LAST_LEN1 = W_WR1, - - FIRST_LEN2, - W_NN2 = FIRST_LEN2, - W_NE2, - W_EE2, - W_SE2, - W_SS2, - W_SW2, - W_WW2, - W_NW2, - LAST_LEN2 = W_NW2, - - FIRST_LEN4, - W_NN4 = FIRST_LEN4, - W_NE4, - W_EE4, - W_SE4, - W_SS4, - W_SW4, - W_WW4, - W_NW4, - LAST_LEN4 = W_NW4 -}; - -#define W_CLOCKWISE(w) rotate_wire((w), 1) -#define W_CLOCKWISE_2(w) rotate_wire((w), 2) -#define W_COUNTER_CLOCKWISE(w) rotate_wire((w), -1) -#define W_COUNTER_CLOCKWISE_2(w) rotate_wire((w), -2) - -#define W_IS_LEN1(w) ((w) >= FIRST_LEN1 && (w) <= LAST_LEN1) -#define W_IS_LEN2(w) ((w) >= FIRST_LEN2 && (w) <= LAST_LEN2) -#define W_IS_LEN4(w) ((w) >= FIRST_LEN4 && (w) <= LAST_LEN4) - -#define W_TO_LEN1(w) wire_to_len(w, FIRST_LEN1) -#define W_TO_LEN2(w) wire_to_len(w, FIRST_LEN2) -#define W_TO_LEN4(w) wire_to_len(w, FIRST_LEN4) - -static const char* wire_base(enum wire_type w); -static enum wire_type rotate_wire(enum wire_type cur, int off); -static enum wire_type wire_to_len(enum wire_type w, int first_len); - -static const char* wire_base(enum wire_type w) +const char* wire_base(enum wire_type w) { switch (w) { case W_NL1: return "NL1"; @@ -1683,6 +1628,12 @@ static int init_routing_tile(struct fpga_model* model, int y, int x) const char* gfan_s, *gclk_s; tile = YX_TILE(model, y, x); + if (model->first_routing_y == -1 + && tile->type != IO_ROUTING && tile->type != ROUTING_IO_L + && tile->type != ROUTING_BRK && tile->type != BRAM_ROUTING_BRK) { + model->first_routing_y = y; + model->first_routing_x = x; + } routing_io = (tile->type == IO_ROUTING || tile->type == ROUTING_IO_L); gfan_s = routing_io ? "INT_IOI_GFAN%i" : "GFAN%i";