From f2a2c5d2b7509711fb668618e63638089ca12b33 Mon Sep 17 00:00:00 2001 From: Wolfgang Spraul Date: Sat, 28 Jul 2012 07:42:31 +0200 Subject: [PATCH] wires left and right --- model.c | 246 +++++++++++++++++++++++++++++++++++++++----------------- model.h | 84 ++++++++++++------- 2 files changed, 229 insertions(+), 101 deletions(-) diff --git a/model.c b/model.c index 99d20de..b4e1e48 100644 --- a/model.c +++ b/model.c @@ -208,7 +208,7 @@ const char* wpref(struct fpga_model* model, int y, int x, const char* wire_name) char* prefix; if (is_aty(Y_CHIP_HORIZ_REGS, model, y)) { - prefix = is_atx(X_CHIP_VERT_REGS, model, x+3) + prefix = is_atx(X_CENTER_REGS_COL, model, x+3) ? "REGC_INT_" : "REGH_"; } else if (is_aty(Y_ROW_HORIZ_AXSYMM, model, y)) prefix = "HCLK_"; @@ -401,7 +401,7 @@ int run_wires(struct fpga_model* model) { struct fpga_tile* tile; char buf[128]; - int x, y, i, rc, row, row_top_y, is_break; + int x, y, i, rc, row, row_top_y, is_break, left_half; rc = -1; // GCLK @@ -413,6 +413,7 @@ int run_wires(struct fpga_model* model) row_top_y = TOP_IO_TILES + (model->cfg_rows-1-row)*(8+1/* middle of row */+8); if (row < (model->cfg_rows/2)) row_top_y++; // center regs + // net that connects the hclk of half the chip together horizontally gclk_net.last_inc = 15; next_net_o = 0; for (x = LEFT_IO_ROUTING;; x++) { @@ -423,7 +424,7 @@ int run_wires(struct fpga_model* model) gclk_net.pts[next_net_o].x = x; if (is_atx(X_ROUTING_COL, model, x)) { gclk_net.pts[next_net_o++].name = "HCLK_GCLK%i_INT"; - } else if (is_atx(X_LOGIC_COL, model, x)) { + } else if (is_atx(X_LOGIC_COL|X_LEFT_IO_DEVS_COL, model, x)) { gclk_net.pts[next_net_o++].name = "HCLK_GCLK%i_CLB"; } else if (is_atx(X_FABRIC_BRAM_MACC_ROUTING_COL, model, x)) { gclk_net.pts[next_net_o++].name = "HCLK_GCLK%i_BRAM_INTER"; @@ -431,7 +432,7 @@ int run_wires(struct fpga_model* model) gclk_net.pts[next_net_o++].name = "HCLK_GCLK%i_BRAM"; } else if (is_atx(X_FABRIC_MACC_COL, model, x)) { gclk_net.pts[next_net_o++].name = "HCLK_GCLK%i_DSP"; - } else if (is_atx(X_CHIP_VERT_REGS, model, x)) { + } else if (is_atx(X_CENTER_REGS_COL, model, x)) { gclk_net.pts[next_net_o++].name = "CLKV_BUFH_LEFT_L%i"; break; } @@ -454,15 +455,19 @@ int run_wires(struct fpga_model* model) if (row < (model->cfg_rows/2)) row_top_y++; // center regs is_break = 0; - if (model->tiles[x].flags & TF_FABRIC_ROUTING_COL) { + if (is_atx(X_LEFT_IO_ROUTING_COL|X_RIGHT_IO_ROUTING_COL, model, x)) { + if (row && row != model->cfg_rows/2) + is_break = 1; + } else { if (row) is_break = 1; else if (is_atx(X_ROUTING_TO_BRAM_COL|X_ROUTING_TO_MACC_COL, model, x)) is_break = 1; - } else if (row && row != model->cfg_rows/2) - is_break = 1; + } - // net inside row + // vertical net inside row, pulling together 16 gclk + // wires across top (8 tiles) and bottom (8 tiles) half + // of the row. for (i = 0; i < 8; i++) { gclk_net.pts[i].name = "GCLK%i"; gclk_net.pts[i].start_count = 0; @@ -478,7 +483,7 @@ int run_wires(struct fpga_model* model) gclk_net.pts[7].name = "GCLK%i_BRK"; if ((rc = add_conn_net(model, NOPREF_BI_F, &gclk_net))) goto xout; - // connection to hclk + // connects gclk of each row tile to hclk tile at the middle of the row for (i = 0; i < 8; i++) { if ((rc = add_conn_range(model, NOPREF_BI_F, row_top_y+i, x, "GCLK%i", 0, 15, @@ -487,9 +492,63 @@ int run_wires(struct fpga_model* model) row_top_y+9+i, x, (i == 7 && is_break) ? "GCLK%i_BRK" : "GCLK%i", 0, 15, row_top_y+8, x, "HCLK_GCLK%i", 0))) goto xout; } + +if (x < model->center_x) { + // long connection to CMT at center of chip + if ((rc = add_conn_range(model, NOPREF_BI_F, + row_top_y+8, x, "HCLK_GCLK%i_INT", 0, 15, + row_top_y+7, model->center_x-1, "HCLK_CMT_GCLK%i_CLB", 0))) goto xout; +} } } } + // wires running horizontally through the center regs, meeting + // in the middle of each half (left and right), and the center + // of the chip. + left_half = 1; + for (x = 0; x < model->tile_x_range; x++) { + const char* fmt; + + if (x == model->left_gclk_sep_x + || x == model->right_gclk_sep_x) + continue; + + if (is_atx(X_OUTER_LEFT, model, x)) { + fmt = "REGL_CLKPLL%i"; + } else if (is_atx(X_INNER_LEFT, model, x)) { + fmt = "REGL_LTERM_CLKPLL%i"; + } else if (is_atx(X_FABRIC_ROUTING_COL|X_LEFT_IO_ROUTING_COL|X_RIGHT_IO_ROUTING_COL, model, x)) { + fmt = "INT_CLKPLL%i"; + } else if (is_atx(X_LEFT_IO_DEVS_COL|X_FABRIC_BRAM_MACC_ROUTING_COL|X_FABRIC_LOGIC_COL|X_RIGHT_IO_DEVS_COL, model, x)) { + fmt = "CLE_CLKPLL%i"; + } else if (is_atx(X_FABRIC_MACC_COL, model, x)) { + fmt = "DSP_CLKPLL%i"; + } else if (is_atx(X_CENTER_ROUTING_COL, model, x)) { + fmt = "REGC_INT_CLKPLL_IO_RT%i"; + } else if (is_atx(X_CENTER_LOGIC_COL, model, x)) { + fmt = "REGC_CLECLKPLL_IO_LT%i"; + } else if (is_atx(X_CENTER_CMTPLL_COL, model, x)) { + fmt = left_half ? "REGC_CLKPLL_IO_LT%i" : "REGC_CLKPLL_IO_RT%i"; + } else if (is_atx(X_CENTER_REGS_COL, model, x)) { + fmt = "CLKC_PLL_IO_RT%i"; + } else if (is_atx(X_INNER_RIGHT, model, x)) { + fmt = "REGR_RTERM_CLKPLL%i"; + } else if (is_atx(X_OUTER_RIGHT, model, x)) { + fmt = "REGR_CLKPLL%i"; + } else continue; + + if ((rc = add_conn_range(model, NOPREF_BI_F, + model->center_y, x, fmt, 0, 1, + model->center_y, left_half ? model->left_gclk_sep_x : model->right_gclk_sep_x, + "INT_CLKPLL%i", 0))) goto xout; + + if (left_half && is_atx(X_CENTER_CMTPLL_COL, model, x)) { + left_half = 0; + // x-- to redo the cmtpll col and wire + // it up with the right side as well + x--; + } + } } for (y = 0; y < model->tile_y_range; y++) { @@ -576,7 +635,7 @@ int run_wires(struct fpga_model* model) } } } - if (is_atx(X_CHIP_VERT_REGS, model, x+3)) { + if (is_atx(X_CENTER_REGS_COL, model, x+3)) { if (tile[2].flags & (TF_PLL_DEV|TF_DCM_DEV)) { const char* prefix = (tile[2].flags & TF_PLL_DEV) ? "PLL_CLB2" : "DCM_CLB2"; @@ -807,23 +866,42 @@ xout: return rc; } +static char next_non_whitespace(const char* s) +{ + int i; + for (i = 0; s[i] == ' '; i++); + return s[i]; +} + +static char last_major(const char* str, int cur_o) +{ + for (; cur_o; cur_o--) { + if (str[cur_o-1] >= 'A' && str[cur_o-1] <= 'Z') + return str[cur_o-1]; + } + return 0; +} + int init_tiles(struct fpga_model* model) { - int tile_rows, tile_columns, i, j, k, l, row_top_y, center_row, left_side; - int start, end; + int tile_rows, tile_columns, i, j, k, l, row_top_y, left_side; + int start, end, no_io; + char cur_cfgcol, last_col; struct fpga_tile* tile_i0; tile_rows = 1 /* middle */ + (8+1+8)*model->cfg_rows + 2+2 /* two extra tiles at top and bottom */; tile_columns = 5 /* left */ + 5 /* right */; for (i = 0; model->cfg_columns[i] != 0; i++) { - tile_columns += 2; // 2 for logic blocks L/M and minimum for others - if (model->cfg_columns[i] == 'B' || model->cfg_columns[i] == 'D') - tile_columns++; // 3 for bram or macc + if (model->cfg_columns[i] == 'L' || model->cfg_columns[i] == 'M') + tile_columns += 2; // 2 for logic blocks L/M + else if (model->cfg_columns[i] == 'B' || model->cfg_columns[i] == 'D') + tile_columns += 3; // 3 for bram or macc else if (model->cfg_columns[i] == 'R') - tile_columns+=2; // 2+2 for middle IO+logic+PLL/DCM + tile_columns += 2+2; // 2+2 for middle IO+logic+PLL/DCM } model->tile_x_range = tile_columns; model->tile_y_range = tile_rows; + model->center_x = -1; model->tiles = calloc(tile_columns * tile_rows, sizeof(struct fpga_tile)); if (!model->tiles) { fprintf(stderr, "%i: Out of memory.\n", __LINE__); @@ -833,7 +911,7 @@ int init_tiles(struct fpga_model* model) model->tiles[i].type = NA; if (!(tile_rows % 2)) fprintf(stderr, "Unexpected even number of tile rows (%i).\n", tile_rows); - center_row = 2 /* top IO files */ + (model->cfg_rows/2)*(8+1/*middle of row clock*/+8); + model->center_y = 2 /* top IO files */ + (model->cfg_rows/2)*(8+1/*middle of row clock*/+8); // // top, bottom, center: @@ -843,25 +921,29 @@ int init_tiles(struct fpga_model* model) left_side = 1; // turn off (=right side) when reaching the 'R' middle column i = 5; // skip left IO columns for (j = 0; model->cfg_columns[j]; j++) { - switch (model->cfg_columns[j]) { + cur_cfgcol = model->cfg_columns[j]; + switch (cur_cfgcol) { case 'L': case 'l': case 'M': case 'm': + no_io = (next_non_whitespace(&model->cfg_columns[j+1]) == 'n'); + last_col = last_major(model->cfg_columns, j); + model->tiles[i].flags |= TF_FABRIC_ROUTING_COL; model->tiles[i+1].flags |= TF_FABRIC_LOGIC_COL; for (k = model->cfg_rows-1; k >= 0; k--) { row_top_y = 2 /* top IO tiles */ + (model->cfg_rows-1-k)*(8+1/*middle of row clock*/+8); if (k<(model->cfg_rows/2)) row_top_y++; // middle system tiles (center row) - start = ((k == model->cfg_rows-1 && (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'M')) ? 2 : 0); - end = ((k == 0 && (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'M')) ? 14 : 16); + start = ((k == model->cfg_rows-1 && !no_io) ? 2 : 0); + end = ((k == 0 && !no_io) ? 14 : 16); for (l = start; l < end; l++) { tile_i0 = &model->tiles[(row_top_y+(l<8?l:l+1))*tile_columns + i]; - if (l < 15 || (!k && (model->cfg_columns[j] == 'l' || model->cfg_columns[j] == 'm'))) + if (l < 15 || (!k && no_io)) tile_i0->type = ROUTING; else tile_i0->type = ROUTING_BRK; - if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'l') { + if (cur_cfgcol == 'L') { tile_i0[1].flags |= TF_LOGIC_XL_DEV; tile_i0[1].type = LOGIC_XL; } else { @@ -869,7 +951,7 @@ int init_tiles(struct fpga_model* model) tile_i0[1].type = LOGIC_XM; } } - if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'l') { + if (cur_cfgcol == 'L') { model->tiles[(row_top_y+8)*tile_columns + i].type = HCLK_ROUTING_XL; model->tiles[(row_top_y+8)*tile_columns + i + 1].type = HCLK_LOGIC_XL; } else { @@ -878,17 +960,17 @@ int init_tiles(struct fpga_model* model) } } - if (j && model->cfg_columns[j-1] == 'R') { + if (last_col == 'R') { model->tiles[tile_columns + i].type = IO_BUFPLL_TERM_T; model->tiles[(tile_rows-2)*tile_columns + i].type = IO_BUFPLL_TERM_B; } else { model->tiles[tile_columns + i].type = IO_TERM_T; - if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'M') + if (!no_io) model->tiles[(tile_rows-2)*tile_columns + i].type = IO_TERM_B; else model->tiles[(tile_rows-2)*tile_columns + i].type = LOGIC_ROUTING_TERM_B; } - if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'M') { + if (!no_io) { model->tiles[i].type = IO_T; model->tiles[(tile_rows-1)*tile_columns + i].type = IO_B; model->tiles[2*tile_columns + i].type = IO_ROUTING; @@ -897,17 +979,17 @@ int init_tiles(struct fpga_model* model) model->tiles[(tile_rows-3)*tile_columns + i].type = IO_ROUTING; } - if (j && model->cfg_columns[j-1] == 'R') { + if (last_col == 'R') { model->tiles[tile_columns + i + 1].type = IO_LOGIC_REG_TERM_T; model->tiles[(tile_rows-2)*tile_columns + i + 1].type = IO_LOGIC_REG_TERM_B; } else { model->tiles[tile_columns + i + 1].type = IO_LOGIC_TERM_T; - if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'M') + if (!no_io) model->tiles[(tile_rows-2)*tile_columns + i + 1].type = IO_LOGIC_TERM_B; else model->tiles[(tile_rows-2)*tile_columns + i + 1].type = LOGIC_NOIO_TERM_B; } - if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'M') { + if (!no_io) { model->tiles[2*tile_columns + i + 1].type = IO_OUTER_T; model->tiles[2*tile_columns + i + 1].flags |= TF_IOLOGIC_DELAY_DEV; model->tiles[3*tile_columns + i + 1].type = IO_INNER_T; @@ -918,16 +1000,22 @@ int init_tiles(struct fpga_model* model) model->tiles[(tile_rows-3)*tile_columns + i + 1].flags |= TF_IOLOGIC_DELAY_DEV; } - if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'l') { - model->tiles[center_row*tile_columns + i].type = REGH_ROUTING_XL; - model->tiles[center_row*tile_columns + i + 1].type = REGH_LOGIC_XL; + if (cur_cfgcol == 'L') { + model->tiles[model->center_y*tile_columns + i].type = REGH_ROUTING_XL; + model->tiles[model->center_y*tile_columns + i + 1].type = REGH_LOGIC_XL; } else { - model->tiles[center_row*tile_columns + i].type = REGH_ROUTING_XM; - model->tiles[center_row*tile_columns + i + 1].type = REGH_LOGIC_XM; + model->tiles[model->center_y*tile_columns + i].type = REGH_ROUTING_XM; + model->tiles[model->center_y*tile_columns + i + 1].type = REGH_LOGIC_XM; } i += 2; break; case 'B': + if (next_non_whitespace(&model->cfg_columns[j+1]) == 'g') { + if (left_side) + model->left_gclk_sep_x = i+2; + else + model->right_gclk_sep_x = i+2; + } model->tiles[i].flags |= TF_FABRIC_ROUTING_COL; model->tiles[i+1].flags |= TF_FABRIC_BRAM_MACC_ROUTING_COL; model->tiles[i+2].flags |= TF_FABRIC_BRAM_COL; @@ -958,9 +1046,9 @@ int init_tiles(struct fpga_model* model) model->tiles[tile_columns + i + 2].type = left_side ? BRAM_TERM_LT : BRAM_TERM_RT; model->tiles[(tile_rows-2)*tile_columns + i + 2].type = left_side ? BRAM_TERM_LB : BRAM_TERM_RB; - model->tiles[center_row*tile_columns + i].type = REGH_BRAM_ROUTING; - model->tiles[center_row*tile_columns + i + 1].type = REGH_BRAM_ROUTING_VIA; - model->tiles[center_row*tile_columns + i + 2].type = left_side ? REGH_BRAM_L : REGH_BRAM_R; + model->tiles[model->center_y*tile_columns + i].type = REGH_BRAM_ROUTING; + model->tiles[model->center_y*tile_columns + i + 1].type = REGH_BRAM_ROUTING_VIA; + model->tiles[model->center_y*tile_columns + i + 2].type = left_side ? REGH_BRAM_L : REGH_BRAM_R; i += 3; break; case 'D': @@ -994,21 +1082,18 @@ int init_tiles(struct fpga_model* model) model->tiles[tile_columns + i + 2].type = left_side ? MACC_TERM_TL : MACC_TERM_TR; model->tiles[(tile_rows-2)*tile_columns + i + 2].type = left_side ? MACC_TERM_BL : MACC_TERM_BR; - model->tiles[center_row*tile_columns + i].type = REGH_MACC_ROUTING; - model->tiles[center_row*tile_columns + i + 1].type = REGH_MACC_ROUTING_VIA; - model->tiles[center_row*tile_columns + i + 2].type = REGH_MACC_L; + model->tiles[model->center_y*tile_columns + i].type = REGH_MACC_ROUTING; + model->tiles[model->center_y*tile_columns + i + 1].type = REGH_MACC_ROUTING_VIA; + model->tiles[model->center_y*tile_columns + i + 2].type = REGH_MACC_L; i += 3; break; case 'R': - if (model->cfg_columns[j+1] != 'M') { + if (next_non_whitespace(&model->cfg_columns[j+1]) != 'M') { // We expect a LOGIC_XM column to follow the center for // the top and bottom bufpll and reg routing. fprintf(stderr, "Expecting LOGIC_XM after center but found '%c'\n", model->cfg_columns[j+1]); } - - model->tiles[i].flags |= TF_FABRIC_ROUTING_COL; - model->tiles[i+1].flags |= TF_FABRIC_LOGIC_COL; - model->tiles[i+3].flags |= TF_CHIP_VERT_REGS; + model->center_x = i+3; left_side = 0; for (k = model->cfg_rows-1; k >= 0; k--) { @@ -1096,16 +1181,20 @@ int init_tiles(struct fpga_model* model) model->tiles[tile_columns + i + 3].type = REGV_TERM_T; model->tiles[(tile_rows-2)*tile_columns + i + 3].type = REGV_TERM_B; - model->tiles[center_row*tile_columns + i].type = REGC_ROUTING; - model->tiles[center_row*tile_columns + i + 1].type = REGC_LOGIC; - model->tiles[center_row*tile_columns + i + 2].type = REGC_CMT; - model->tiles[center_row*tile_columns + i + 3].type = CENTER; + model->tiles[model->center_y*tile_columns + i].type = REGC_ROUTING; + model->tiles[model->center_y*tile_columns + i + 1].type = REGC_LOGIC; + model->tiles[model->center_y*tile_columns + i + 2].type = REGC_CMT; + model->tiles[model->center_y*tile_columns + i + 3].type = CENTER; i += 4; break; + case ' ': // space used to make string more readable only + case 'g': // global clock separator + case 'n': // noio for logic blocks + break; default: - fprintf(stderr, "Unexpected column identifier '%c'\n", model->cfg_columns[j]); - break; + fprintf(stderr, "Ignoring unexpected column identifier '%c'\n", cur_cfgcol); + break; } } @@ -1192,22 +1281,22 @@ int init_tiles(struct fpga_model* model) model->tiles[(row_top_y+8)*tile_columns + 4].type = HCLK_MCB; } - model->tiles[(center_row-3)*tile_columns].type = IO_PCI_L; - model->tiles[(center_row-2)*tile_columns].type = IO_PCI_CONN_L; - model->tiles[(center_row-1)*tile_columns].type = IO_PCI_CONN_L; - model->tiles[center_row*tile_columns].type = REG_L; - model->tiles[(center_row+1)*tile_columns].type = IO_RDY_L; + model->tiles[(model->center_y-3)*tile_columns].type = IO_PCI_L; + model->tiles[(model->center_y-2)*tile_columns].type = IO_PCI_CONN_L; + model->tiles[(model->center_y-1)*tile_columns].type = IO_PCI_CONN_L; + model->tiles[model->center_y*tile_columns].type = REG_L; + model->tiles[(model->center_y+1)*tile_columns].type = IO_RDY_L; - model->tiles[center_row*tile_columns + 1].type = REGH_IO_TERM_L; + model->tiles[model->center_y*tile_columns + 1].type = REGH_IO_TERM_L; model->tiles[tile_columns + 2].type = CORNER_TERM_T; model->tiles[(tile_rows-2)*tile_columns + 2].type = CORNER_TERM_B; - model->tiles[center_row*tile_columns + 2].type = REGH_ROUTING_IO_L; + model->tiles[model->center_y*tile_columns + 2].type = REGH_ROUTING_IO_L; model->tiles[tile_columns + 3].type = ROUTING_IO_PCI_CE_L; model->tiles[(tile_rows-2)*tile_columns + 3].type = ROUTING_IO_PCI_CE_L; - model->tiles[center_row*tile_columns + 3].type = REGH_IO_L; - model->tiles[center_row*tile_columns + 4].type = REGH_MCB; + model->tiles[model->center_y*tile_columns + 3].type = REGH_IO_L; + model->tiles[model->center_y*tile_columns + 4].type = REGH_MCB; // // right IO @@ -1308,11 +1397,11 @@ int init_tiles(struct fpga_model* model) model->tiles[(tile_rows-2)*tile_columns + tile_columns - 5].type = CORNER_TERM_B; model->tiles[tile_columns + tile_columns - 4].type = ROUTING_IO_PCI_CE_R; model->tiles[(tile_rows-2)*tile_columns + tile_columns - 4].type = ROUTING_IO_PCI_CE_R; - model->tiles[center_row*tile_columns + tile_columns - 1].type = REG_R; - model->tiles[center_row*tile_columns + tile_columns - 2].type = REGH_IO_TERM_R; - model->tiles[center_row*tile_columns + tile_columns - 3].type = REGH_MCB; - model->tiles[center_row*tile_columns + tile_columns - 4].type = REGH_IO_R; - model->tiles[center_row*tile_columns + tile_columns - 5].type = REGH_ROUTING_IO_R; + model->tiles[model->center_y*tile_columns + tile_columns - 1].type = REG_R; + model->tiles[model->center_y*tile_columns + tile_columns - 2].type = REGH_IO_TERM_R; + model->tiles[model->center_y*tile_columns + tile_columns - 3].type = REGH_MCB; + model->tiles[model->center_y*tile_columns + tile_columns - 4].type = REGH_IO_R; + model->tiles[model->center_y*tile_columns + tile_columns - 5].type = REGH_ROUTING_IO_R; return 0; } @@ -1342,10 +1431,7 @@ int is_aty(int check, struct fpga_model* model, int y) if (y < 0) return 0; if (check & Y_INNER_TOP && y == 1) return 1; if (check & Y_INNER_BOTTOM && y == model->tile_y_range-2) return 1; - if (check & Y_CHIP_HORIZ_REGS) { - int center_tile = 2 /* top IO files */ + (model->cfg_rows/2)*(8+1/*middle of row clock*/+8); - if (y == center_tile) return 1; - } + if (check & Y_CHIP_HORIZ_REGS && y == model->center_y) return 1; if (check & (Y_ROW_HORIZ_AXSYMM|Y_BOTTOM_OF_ROW)) { int row_pos; if (is_in_row(model, y, &row_pos)) { @@ -1359,12 +1445,14 @@ int is_aty(int check, struct fpga_model* model, int y) int is_atx(int check, struct fpga_model* model, int x) { if (x < 0) return 0; + if (check & X_OUTER_LEFT && !x) return 1; if (check & X_INNER_LEFT && x == 1) return 1; if (check & X_INNER_RIGHT && x == model->tile_x_range-2) return 1; - if (check & X_CHIP_VERT_REGS && model->tiles[x].flags & TF_CHIP_VERT_REGS) return 1; + if (check & X_OUTER_RIGHT && x == model->tile_x_range-1) return 1; if (check & X_ROUTING_COL && (model->tiles[x].flags & TF_FABRIC_ROUTING_COL - || x == 2 || x == model->tile_x_range-5)) return 1; + || x == LEFT_IO_ROUTING || x == model->tile_x_range-5 + || x == model->center_x-3)) return 1; if (model->tiles[x].flags & TF_FABRIC_ROUTING_COL) { if (check & X_ROUTING_TO_BRAM_COL && model->tiles[x+1].flags & TF_FABRIC_BRAM_MACC_ROUTING_COL @@ -1375,10 +1463,21 @@ int is_atx(int check, struct fpga_model* model, int x) } if (check & X_LOGIC_COL && (model->tiles[x].flags & TF_FABRIC_LOGIC_COL - || x == 3)) return 1; + || x == model->center_x-2)) return 1; + if (check & X_FABRIC_ROUTING_COL && model->tiles[x].flags & TF_FABRIC_ROUTING_COL) return 1; + if (check & X_FABRIC_LOGIC_COL && model->tiles[x].flags & TF_FABRIC_LOGIC_COL) return 1; if (check & X_FABRIC_BRAM_MACC_ROUTING_COL && model->tiles[x].flags & TF_FABRIC_BRAM_MACC_ROUTING_COL) return 1; if (check & X_FABRIC_BRAM_COL && model->tiles[x].flags & TF_FABRIC_BRAM_COL) return 1; if (check & X_FABRIC_MACC_COL && model->tiles[x].flags & TF_FABRIC_MACC_COL) return 1; + if (check & X_CENTER_ROUTING_COL && x == model->center_x-3) return 1; + if (check & X_CENTER_LOGIC_COL && x == model->center_x-2) return 1; + if (check & X_CENTER_CMTPLL_COL && x == model->center_x-1) return 1; + if (check & X_CENTER_REGS_COL && x == model->center_x) return 1; + if (check & X_LEFT_IO_ROUTING_COL && x == LEFT_IO_ROUTING) return 1; + if (check & X_LEFT_IO_DEVS_COL && x == LEFT_IO_DEVS) return 1; + if (check & X_RIGHT_IO_ROUTING_COL && x == model->tile_x_range-5) return 1; + if (check & X_RIGHT_IO_DEVS_COL && x == model->tile_x_range-4) return 1; + if (check & X_LEFT_SIDE && x < model->center_x) return 1; return 0; } @@ -1387,7 +1486,8 @@ int is_atyx(int check, struct fpga_model* model, int y, int x) if (y < 0 || x < 0) return 0; if (check & YX_ROUTING_TILE && (model->tiles[x].flags & TF_FABRIC_ROUTING_COL - || x == 2 || x == model->tile_x_range-5)) { + || x == LEFT_IO_ROUTING || x == model->tile_x_range-5 + || x == model->center_x-3)) { int row_pos; if (is_in_row(model, y, &row_pos) && row_pos != 8) return 1; } diff --git a/model.h b/model.h index 48e6777..08e43ec 100644 --- a/model.h +++ b/model.h @@ -27,21 +27,30 @@ struct hashed_strarray int bin_len[1024]; // points behind the last zero-termination }; +// // columns // 'L' = X+L logic block -// 'l' = X+L logic block without IO at top and bottom // 'M' = X+M logic block -// 'm' = X+M logic block without IO at top and bottom // 'B' = block ram // 'D' = dsp (macc) // 'R' = registers and center IO/logic column // +// 'n' = noio - can follow L or M to designate a logic +// column without IO at top or bottom +// 'g' = gclk - can follow LlMmBD to designate exactly one +// place on the left and right side of the chip where +// the global clock is separated into left and right +// half (on each side of the chip, for a total of 4 +// vertical clock separations). +// // wiring on the left and right side is described with 16 -// characters for each row - 'W' = wired, 'U' = unwired -// order is top-down +// characters for each row, order is top-down +// 'W' = wired +// 'U' = unwired +// #define XC6SLX9_ROWS 4 -#define XC6SLX9_COLUMNS "MLBMLDMRMlMLBML" +#define XC6SLX9_COLUMNS "M L Bg M L D M R M Ln M L Bg M L" #define XC6SLX9_LEFT_WIRING \ /* row 3 */ "UWUWUWUW" "WWWWUUUU" \ /* row 2 */ "UUUUUUUU" "WWWWWWUU" \ @@ -60,6 +69,13 @@ struct fpga_model char cfg_left_wiring[1024], cfg_right_wiring[1024]; int tile_x_range, tile_y_range; + int center_x; + int center_y; + // Left and right gclk separators will be located on + // the device column (+1 or +2) of the logic or dsp/macc + // column as indicated in the chip's cfg_columns with a 'g'. + int left_gclk_sep_x, right_gclk_sep_x; + struct fpga_tile* tiles; struct hashed_strarray str; }; @@ -122,23 +138,23 @@ enum fpga_tile_type // Some constant to make the core more readable #define LEFT_IO_ROUTING 2 +#define LEFT_IO_DEVS 3 #define TOP_IO_TILES 2 // tile flags -#define TF_CHIP_VERT_REGS 0x00000001 // only set in y==0 -#define TF_FABRIC_ROUTING_COL 0x00000002 // only set in y==0, not for left and right IO routing -#define TF_FABRIC_LOGIC_COL 0x00000004 // only set in y==0 -#define TF_FABRIC_BRAM_MACC_ROUTING_COL 0x00000008 // only set in y==0 -#define TF_FABRIC_BRAM_COL 0x00000010 // only set in y==0 -#define TF_FABRIC_MACC_COL 0x00000020 // only set in y==0 -#define TF_BRAM_DEV 0x00000040 -#define TF_MACC_DEV 0x00000080 -#define TF_LOGIC_XL_DEV 0x00000100 -#define TF_LOGIC_XM_DEV 0x00000200 -#define TF_IOLOGIC_DELAY_DEV 0x00000400 -#define TF_DCM_DEV 0x00000800 -#define TF_PLL_DEV 0x00001000 +#define TF_FABRIC_ROUTING_COL 0x00000001 // only set in y==0, not for left and right IO routing or center +#define TF_FABRIC_LOGIC_COL 0x00000002 // only set in y==0 +#define TF_FABRIC_BRAM_MACC_ROUTING_COL 0x00000004 // only set in y==0 +#define TF_FABRIC_BRAM_COL 0x00000008 // only set in y==0 +#define TF_FABRIC_MACC_COL 0x00000010 // only set in y==0 +#define TF_BRAM_DEV 0x00000020 +#define TF_MACC_DEV 0x00000040 +#define TF_LOGIC_XL_DEV 0x00000080 +#define TF_LOGIC_XM_DEV 0x00000100 +#define TF_IOLOGIC_DELAY_DEV 0x00000200 +#define TF_DCM_DEV 0x00000400 +#define TF_PLL_DEV 0x00000800 #define Y_INNER_TOP 0x0001 #define Y_INNER_BOTTOM 0x0002 @@ -149,16 +165,28 @@ enum fpga_tile_type // multiple checks are combined with OR logic int is_aty(int check, struct fpga_model* model, int y); -#define X_INNER_LEFT 0x0001 -#define X_INNER_RIGHT 0x0002 -#define X_CHIP_VERT_REGS 0x0004 -#define X_ROUTING_COL 0x0008 // includes routing col in left and right IO -#define X_ROUTING_TO_BRAM_COL 0x0010 -#define X_ROUTING_TO_MACC_COL 0x0020 -#define X_LOGIC_COL 0x0040 // includes the logic col in left IO -#define X_FABRIC_BRAM_MACC_ROUTING_COL 0x0080 -#define X_FABRIC_BRAM_COL 0x0100 -#define X_FABRIC_MACC_COL 0x0200 +#define X_OUTER_LEFT 0x00000001 +#define X_INNER_LEFT 0x00000002 +#define X_INNER_RIGHT 0x00000004 +#define X_OUTER_RIGHT 0x00000008 +#define X_ROUTING_COL 0x00000010 // includes routing col in left and right IO and center +#define X_ROUTING_TO_BRAM_COL 0x00000020 +#define X_ROUTING_TO_MACC_COL 0x00000040 +#define X_LOGIC_COL 0x00000080 // includes the center logic col +#define X_FABRIC_ROUTING_COL 0x00000100 +#define X_FABRIC_LOGIC_COL 0x00000200 +#define X_FABRIC_BRAM_MACC_ROUTING_COL 0x00000400 +#define X_FABRIC_BRAM_COL 0x00000800 +#define X_FABRIC_MACC_COL 0x00001000 +#define X_CENTER_ROUTING_COL 0x00002000 +#define X_CENTER_LOGIC_COL 0x00004000 +#define X_CENTER_CMTPLL_COL 0x00008000 +#define X_CENTER_REGS_COL 0x00010000 +#define X_LEFT_IO_ROUTING_COL 0x00020000 +#define X_LEFT_IO_DEVS_COL 0x00040000 +#define X_RIGHT_IO_ROUTING_COL 0x00080000 +#define X_RIGHT_IO_DEVS_COL 0x00100000 +#define X_LEFT_SIDE 0x00200000 // true for anything left of the center (not including center) // multiple checks are combined with OR logic int is_atx(int check, struct fpga_model* model, int x);