wires left and right

This commit is contained in:
Wolfgang Spraul 2012-07-28 07:42:31 +02:00
parent 1dadb4c381
commit f2a2c5d2b7
2 changed files with 229 additions and 101 deletions

246
model.c
View File

@ -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;
}

84
model.h
View File

@ -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);