more wires

This commit is contained in:
Wolfgang Spraul 2012-11-11 07:40:39 +01:00
parent 865dbfbb73
commit c88c46b80d
4 changed files with 698 additions and 287 deletions

6
README
View File

@ -53,7 +53,7 @@ Design Principles
- automatic test suite
- public domain software
TODO (as of October, 2012)
TODO (as of November, 2012)
short-term (1 month):
* example: blinking_led
@ -65,7 +65,7 @@ short-term (1 month):
mid-term (6 months):
* support chips other than xc6slx9, maybe an ftg256 or fgg484-packaged
xc6 or the xc7a100
* more cases in switches (98% done) and inter-tile connections (15% done)
* more cases in switches (98% done) and inter-tile connections (70% done)
* more cases in logic block configuration
* configuration of bram and macc blocks, bram initialization data
* write standard design elements for libfpga-stdlib library
@ -85,7 +85,7 @@ long-term (>6 months):
* support lm32 or openrisc core, either via libfpga or iverilog backend
* ipv6 or vnc in hardware?
* iverilog fpga backend
* design fpga 'core' that uses high-speed icap/reconfig to process data
* design fpga core that uses high-speed icap/reconfig to process data
ChangeLog

View File

@ -256,6 +256,10 @@ int is_aty(int check, struct fpga_model* model, int y);
|X_CENTER_ROUTING_COL \
|X_LEFT_IO_ROUTING_COL \
|X_RIGHT_IO_ROUTING_COL)
#define X_CENTER_MAJOR (X_CENTER_ROUTING_COL \
|X_CENTER_LOGIC_COL \
|X_CENTER_CMTPLL_COL \
|X_CENTER_REGS_COL)
// todo and realizations:
// * maybe the center_logic and routing cols can also be
@ -887,8 +891,8 @@ struct seed_data
const char* str;
};
void seed_strx(struct fpga_model *model, struct seed_data *data);
void seed_stry(struct fpga_model *model, struct seed_data *data);
void seed_strx(struct fpga_model *model, const struct seed_data *data);
void seed_stry(struct fpga_model *model, const struct seed_data *data);
#define MAX_WIRENAME_LEN 64
@ -1026,6 +1030,9 @@ enum extra_wires {
IOCLK,
PLLCE,
PLLCLK,
CKPIN,
CLK_FEEDBACK,
CLK_INDIRECT,
VCC_WIRE = 150,
GND_WIRE,
GCLK0 = 200, GCLK1, GCLK2, GCLK3, GCLK4, GCLK5, GCLK6, GCLK7,

View File

@ -15,7 +15,7 @@ static int term_to_io(struct fpga_model *model, enum extra_wires wire);
static int pcice(struct fpga_model *model);
static int clkpll(struct fpga_model *model);
static int ckpin(struct fpga_model *model);
static int clkindirect_feedback(struct fpga_model *model);
static int clkindirect_feedback(struct fpga_model *model, enum extra_wires wire);
static int run_gclk(struct fpga_model *model);
static int run_gclk_horiz_regs(struct fpga_model *model);
static int run_gclk_vert_regs(struct fpga_model *model);
@ -40,7 +40,8 @@ int init_conns(struct fpga_model *model)
if ((rc = clkpll(model))) FAIL(rc);
if ((rc = ckpin(model))) FAIL(rc);
if ((rc = clkindirect_feedback(model))) FAIL(rc);
if ((rc = clkindirect_feedback(model, CLK_INDIRECT))) FAIL(rc);
if ((rc = clkindirect_feedback(model, CLK_FEEDBACK))) FAIL(rc);
if ((rc = pcice(model))) FAIL(rc);
if ((rc = run_gclk(model))) FAIL(rc);
@ -581,11 +582,11 @@ fail:
return rc;
}
static int term_to_io(struct fpga_model *model, enum extra_wires wire)
static int net_up_down(struct fpga_model *model, int hclk_y, int up_down_x,
enum extra_wires wire, struct w_net *up_net, struct w_net *down_net)
{
struct w_net up_net, down_net;
const char *s1;
int last_inc, y, i, rc;
int last_inc, i, rc;
if (wire == IOCE) {
s1 = "IOCE";
@ -601,7 +602,82 @@ static int term_to_io(struct fpga_model *model, enum extra_wires wire)
last_inc = 1;
} else FAIL(EINVAL);
up_net->last_inc = last_inc;
up_net->pt[0].name = pf("HCLK_IOIL_%s%%i_UP", s1);
up_net->pt[0].start_count = 0;
up_net->pt[0].y = hclk_y;
up_net->pt[0].x = up_down_x;
up_net->num_pts = 1;
down_net->last_inc = last_inc;
down_net->pt[0].name = pf("HCLK_IOIL_%s%%i_DOWN", s1);
down_net->pt[0].start_count = 0;
down_net->pt[0].y = hclk_y;
down_net->pt[0].x = up_down_x;
down_net->num_pts = 1;
for (i = 0; i < HALF_ROW; i++) {
if (has_device(model, hclk_y-1-i, up_down_x, DEV_IODELAY)) {
while (up_net->pt[up_net->num_pts-1].y > hclk_y-1-i+1) {
up_net->pt[up_net->num_pts].name = pf("INT_INTERFACE_%s%%i", s1);
up_net->pt[up_net->num_pts].start_count = 0;
up_net->pt[up_net->num_pts].y = up_net->pt[up_net->num_pts-1].y-1;
up_net->pt[up_net->num_pts].x = up_down_x;
up_net->num_pts++;
}
up_net->pt[up_net->num_pts].name = pf("%s_%s%%i",
up_down_x < model->center_x ? "IOI" : "RIOI", s1);
up_net->pt[up_net->num_pts].start_count = 0;
up_net->pt[up_net->num_pts].y = hclk_y-1-i;
up_net->pt[up_net->num_pts].x = up_down_x;
up_net->num_pts++;
}
if (has_device(model, hclk_y+1+i, up_down_x, DEV_IODELAY)) {
while (down_net->pt[down_net->num_pts-1].y < hclk_y+1+i-1) {
down_net->pt[down_net->num_pts].name = pf("INT_INTERFACE_%s%%i", s1);
down_net->pt[down_net->num_pts].start_count = 0;
down_net->pt[down_net->num_pts].y = down_net->pt[down_net->num_pts-1].y+1;
down_net->pt[down_net->num_pts].x = up_down_x;
down_net->num_pts++;
}
down_net->pt[down_net->num_pts].name = pf("%s_%s%%i",
up_down_x < model->center_x ? "IOI" : "RIOI", s1);
down_net->pt[down_net->num_pts].start_count = 0;
down_net->pt[down_net->num_pts].y = hclk_y+1+i;
down_net->pt[down_net->num_pts].x = up_down_x;
down_net->num_pts++;
}
}
return 0;
fail:
return rc;
}
static int term_to_io(struct fpga_model *model, enum extra_wires wire)
{
struct w_net up_net, down_net, net;
const char *s1;
int last_inc, y, i, rc;
// from termination into fabric via hclk
if (wire == IOCE) {
s1 = "IOCE";
last_inc = 3;
} else if (wire == IOCLK) {
s1 = "IOCLK";
last_inc = 3;
} else if (wire == PLLCE) {
s1 = "PLLCE";
last_inc = 1;
} else if (wire == PLLCLK) {
s1 = "PLLCLK";
last_inc = 1;
} else FAIL(EINVAL);
//
// left
//
for (y = TOP_FIRST_REGULAR; y <= model->y_height - BOT_LAST_REGULAR_O; y++) {
if (!is_aty(Y_ROW_HORIZ_AXSYMM, model, y))
continue;
@ -643,48 +719,56 @@ static int term_to_io(struct fpga_model *model, enum extra_wires wire)
if ((rc = add_conn_net(model, NOPREF_BI_F, &n))) FAIL(rc); }
// wire up and down the row (8 each) to reach all io devices
up_net.last_inc = last_inc;
up_net.pt[0].name = pf("HCLK_IOIL_%s%%i_UP", s1);
up_net.pt[0].start_count = 0;
up_net.pt[0].y = y;
up_net.pt[0].x = LEFT_IO_DEVS;
up_net.num_pts = 1;
down_net.last_inc = last_inc;
down_net.pt[0].name = pf("HCLK_IOIL_%s%%i_DOWN", s1);
down_net.pt[0].start_count = 0;
down_net.pt[0].y = y;
down_net.pt[0].x = LEFT_IO_DEVS;
down_net.num_pts = 1;
for (i = 0; i < HALF_ROW; i++) {
if (has_device(model, y-1-i, LEFT_IO_DEVS, DEV_IODELAY)) {
while (up_net.pt[up_net.num_pts-1].y > y-1-i+1) {
up_net.pt[up_net.num_pts].name = pf("INT_INTERFACE_%s%%i", s1);
up_net.pt[up_net.num_pts].start_count = 0;
up_net.pt[up_net.num_pts].y = up_net.pt[up_net.num_pts-1].y-1;
up_net.pt[up_net.num_pts].x = LEFT_IO_DEVS;
up_net.num_pts++;
if ((rc = net_up_down(model, y, LEFT_IO_DEVS,
wire, &up_net, &down_net))) FAIL(rc);
if (up_net.num_pts > 1
&& (rc = add_conn_net(model, NOPREF_BI_F, &up_net))) FAIL(rc);
if (down_net.num_pts > 1
&& (rc = add_conn_net(model, NOPREF_BI_F, &down_net))) FAIL(rc);
}
up_net.pt[up_net.num_pts].name = pf("IOI_%s%%i", s1);
up_net.pt[up_net.num_pts].start_count = 0;
up_net.pt[up_net.num_pts].y = y-1-i;
up_net.pt[up_net.num_pts].x = LEFT_IO_DEVS;
up_net.num_pts++;
}
if (has_device(model, y+1+i, LEFT_IO_DEVS, DEV_IODELAY)) {
while (down_net.pt[down_net.num_pts-1].y < y+1+i-1) {
down_net.pt[down_net.num_pts].name = pf("INT_INTERFACE_%s%%i", s1);
down_net.pt[down_net.num_pts].start_count = 0;
down_net.pt[down_net.num_pts].y = down_net.pt[down_net.num_pts-1].y+1;
down_net.pt[down_net.num_pts].x = LEFT_IO_DEVS;
down_net.num_pts++;
}
down_net.pt[down_net.num_pts].name = pf("IOI_%s%%i", s1);
down_net.pt[down_net.num_pts].start_count = 0;
down_net.pt[down_net.num_pts].y = y+1+i;
down_net.pt[down_net.num_pts].x = LEFT_IO_DEVS;
down_net.num_pts++;
//
// right
//
for (y = TOP_FIRST_REGULAR; y <= model->y_height - BOT_LAST_REGULAR_O; y++) {
if (!is_aty(Y_ROW_HORIZ_AXSYMM, model, y))
continue;
if (wire == IOCE || wire == IOCLK) {
net.last_inc = 0;
net.num_pts = 3;
for (i = 0; i <= 3; i++) {
net.pt[0].name = pf("HCLK_IOI_RTERM_%s%i_W", s1, i);
net.pt[0].start_count = 0;
net.pt[0].y = y;
net.pt[0].x = model->x_width - RIGHT_INNER_O;
net.pt[1].name = pf("HCLK_MCB_%s%i_W", s1, i);
net.pt[1].start_count = 0;
net.pt[1].y = y;
net.pt[1].x = model->x_width - RIGHT_MCB_O;
net.pt[2].name = pf("HCLK_IOIL_%s%i", s1, 3-i);
net.pt[2].start_count = 0;
net.pt[2].y = y;
net.pt[2].x = model->x_width - RIGHT_IO_DEVS_O;
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
}
} else { // PLLCE/PLLCLK
struct w_net n = {
.last_inc = last_inc, .num_pts = 3, .pt =
{{ wire == PLLCE ? "HCLK_IOI_RTERM_PLLCEOUT%i_W"
: "HCLK_IOI_RTERM_PLLCLKOUT%i_W",
0, y, model->x_width - RIGHT_INNER_O },
{ wire == PLLCE ? "HCLK_MCB_PLLCEOUT%i_W"
: "HCLK_MCB_PLLCLKOUT%i_W",
0, y, model->x_width - RIGHT_MCB_O },
{ pf("HCLK_IOIL_%s%%i", s1), 0, y, model->x_width - RIGHT_IO_DEVS_O }}};
if ((rc = add_conn_net(model, NOPREF_BI_F, &n))) FAIL(rc);
}
// wire up and down the row (8 each) to reach all io devices
if ((rc = net_up_down(model, y, model->x_width - RIGHT_IO_DEVS_O,
wire, &up_net, &down_net))) FAIL(rc);
if (up_net.num_pts > 1
&& (rc = add_conn_net(model, NOPREF_BI_F, &up_net))) FAIL(rc);
if (down_net.num_pts > 1
@ -796,19 +880,22 @@ fail:
static int clkpll(struct fpga_model *model)
{
int x, rc, left_half;
int x, rc;
struct w_net net;
//
// clk pll 0:1
//
{
struct seed_data clkpll_seeds[] = {
// two nets - one for left side, one for right side
{ struct seed_data seeds[] = {
{ X_OUTER_LEFT, "REGL_CLKPLL%i" },
{ X_INNER_LEFT, "REGL_LTERM_CLKPLL%i" },
{ X_LEFT_MCB | X_RIGHT_MCB, "MCB_CLKPLL%i" },
{ X_FABRIC_ROUTING_COL
| X_LEFT_IO_ROUTING_COL
| X_RIGHT_IO_ROUTING_COL, "INT_CLKPLL%i" },
| X_RIGHT_IO_ROUTING_COL
| X_FABRIC_BRAM_COL, "INT_CLKPLL%i" },
{ X_LEFT_IO_DEVS_COL
| X_FABRIC_BRAM_VIA_COL
| X_FABRIC_MACC_VIA_COL
@ -817,50 +904,52 @@ static int clkpll(struct fpga_model *model)
{ X_FABRIC_MACC_COL, "DSP_CLKPLL%i" },
{ X_CENTER_ROUTING_COL, "REGC_INT_CLKPLL_IO_RT%i" },
{ X_CENTER_LOGIC_COL, "REGC_CLECLKPLL_IO_LT%i" },
{ X_CENTER_CMTPLL_COL, "REGC_CLKPLL_IO_LT%i" },
{ X_CENTER_REGS_COL, "CLKC_PLL_IO_RT%i" },
{ X_INNER_RIGHT, "REGR_RTERM_CLKPLL%i" },
{ X_OUTER_RIGHT, "REGR_CLKPLL%i" },
{ 0 }};
left_half = 1;
seed_strx(model, clkpll_seeds);
seed_strx(model, seeds);
net.last_inc = 1;
net.num_pts = 0;
for (x = 0; x < model->x_width; x++) {
if (x == model->left_gclk_sep_x
|| x == model->right_gclk_sep_x)
continue;
ASSERT(model->tmp_str[x]);
ASSERT(net.num_pts < sizeof(net.pt)/sizeof(net.pt[0]));
if (is_atx(X_CENTER_CMTPLL_COL, model, x))
model->tmp_str[x] = left_half
? "REGC_CLKPLL_IO_LT%i"
: "REGC_CLKPLL_IO_RT%i";
if (!model->tmp_str[x])
continue;
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].x = x;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].name = model->tmp_str[x];
net.num_pts++;
if ((rc = add_conn_range(model, NOPREF_BI_F,
model->center_y, x, model->tmp_str[x], 0, 1,
model->center_y,
left_half ? model->left_gclk_sep_x
: model->right_gclk_sep_x,
"INT_CLKPLL%i", 0))) FAIL(rc);
if (left_half && is_atx(X_CENTER_CMTPLL_COL, model, x)) {
left_half = 0;
x--; // wire up cmtpll col on right side as well
}
if (is_atx(X_CENTER_CMTPLL_COL, model, x)) {
// left-side net
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
// start right side
net.pt[0].start_count = 0;
net.pt[0].x = x;
net.pt[0].y = model->center_y;
net.pt[0].name = "REGC_CLKPLL_IO_RT%i";
net.num_pts = 1;
}
}
// right-side net
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc); }
//
// clk pll lock 0:1
//
{
struct seed_data clkpll_lock_seeds[] = {
// two nets - one for left side, one for right side
{ struct seed_data seeds[] = {
{ X_OUTER_LEFT, "REGL_LOCKED%i" },
{ X_INNER_LEFT, "REGH_LTERM_LOCKED%i" },
{ X_LEFT_MCB | X_RIGHT_MCB, "MCB_CLKPLL_LOCK%i" },
{ X_FABRIC_ROUTING_COL
| X_LEFT_IO_ROUTING_COL
| X_RIGHT_IO_ROUTING_COL, "INT_CLKPLL_LOCK%i" },
| X_RIGHT_IO_ROUTING_COL
| X_FABRIC_BRAM_COL, "INT_CLKPLL_LOCK%i" },
{ X_LEFT_IO_DEVS_COL
| X_FABRIC_BRAM_VIA_COL
| X_FABRIC_MACC_VIA_COL
@ -869,38 +958,38 @@ static int clkpll(struct fpga_model *model)
{ X_FABRIC_MACC_COL, "DSP_CLKPLL_LOCK%i" },
{ X_CENTER_ROUTING_COL, "REGC_INT_CLKPLL_LOCK_RT%i" },
{ X_CENTER_LOGIC_COL, "REGC_CLECLKPLL_LOCK_LT%i" },
{ X_CENTER_CMTPLL_COL, "CLK_PLL_LOCK_LT%i" },
{ X_CENTER_REGS_COL, "CLKC_PLL_LOCK_RT%i" },
{ X_INNER_RIGHT, "REGH_RTERM_LOCKED%i" },
{ X_OUTER_RIGHT, "REGR_LOCKED%i" },
{ 0 }};
left_half = 1;
seed_strx(model, clkpll_lock_seeds);
seed_strx(model, seeds);
net.last_inc = 1;
net.num_pts = 0;
for (x = 0; x < model->x_width; x++) {
if (x == model->left_gclk_sep_x
|| x == model->right_gclk_sep_x)
continue;
ASSERT(model->tmp_str[x]);
ASSERT(net.num_pts < sizeof(net.pt)/sizeof(net.pt[0]));
if (is_atx(X_CENTER_CMTPLL_COL, model, x))
model->tmp_str[x] = left_half
? "CLK_PLL_LOCK_LT%i"
: "CLK_PLL_LOCK_RT%i";
if (!model->tmp_str[x])
continue;
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].x = x;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].name = model->tmp_str[x];
net.num_pts++;
if ((rc = add_conn_range(model, NOPREF_BI_F,
model->center_y, x, model->tmp_str[x], 0, 1,
model->center_y,
left_half ? model->left_gclk_sep_x
: model->right_gclk_sep_x,
"INT_CLKPLL_LOCK%i", 0))) FAIL(rc);
if (left_half && is_atx(X_CENTER_CMTPLL_COL, model, x)) {
left_half = 0;
x--; // wire up cmtpll col on right side as well
}
if (is_atx(X_CENTER_CMTPLL_COL, model, x)) {
// left-side net
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
// start right side
net.pt[0].start_count = 0;
net.pt[0].x = x;
net.pt[0].y = model->center_y;
net.pt[0].name = "CLK_PLL_LOCK_RT%i";
net.num_pts = 1;
}
}
// right-side net
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc); }
return 0;
fail:
return rc;
@ -908,19 +997,103 @@ fail:
static int ckpin(struct fpga_model *model)
{
int x, rc, left_half, gclk_sep_pos, start1;
int y, x, rc;
struct w_net net;
//
// ckpin 0:7
// ckpin is made out of 8 nets.
//
// 4 vertical through center_x:
// 1. top edge to top midbuf
// 2. top midbuf to center
// 3. center to bottom midbuf
// 4. bottom midbuf to bottom edge
// 4 horizontal through center_y:
// 1. left edge to left_gclk_sep_x
// 2. left_gclk_sep_x to center
// 3. center to right_gclk_sep_x
// 4. right_gclk_sep_x to right edge
//
{
struct seed_data ckpin_seeds[] = {
// vertical
{ struct seed_data y_seeds[] = {
{ Y_INNER_TOP, "REGV_TTERM_CKPIN%i" },
{ Y_ROW_HORIZ_AXSYMM, "CLKV_HCLK_CKPIN%i" },
{ Y_CHIP_HORIZ_REGS, "CLKC_CKTB%i" },
{ Y_INNER_BOTTOM, "REGV_BTERM_CKPIN%i" },
{ Y_REGULAR_ROW, "CLKV_CKPIN%i" },
{ 0 }};
seed_stry(model, y_seeds);
net.last_inc = 7;
net.pt[0].start_count = 0;
net.pt[0].x = model->center_x-CENTER_CMTPLL_O;
net.pt[0].y = TOP_OUTER_ROW;
net.pt[0].name = "REGT_CKPIN%i";
net.pt[1].start_count = 0;
net.pt[1].x = model->center_x-CENTER_CMTPLL_O;
net.pt[1].y = TOP_INNER_ROW;
net.pt[1].name = "REGT_TTERM_CKPIN%i";
net.num_pts = 2;
for (y = TOP_INNER_ROW; y <= model->y_height - BOT_INNER_ROW; y++) {
ASSERT(model->tmp_str[y]);
ASSERT(net.num_pts < sizeof(net.pt)/sizeof(net.pt[0]));
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].x = model->center_x;
net.pt[net.num_pts].y = y;
net.pt[net.num_pts].name = model->tmp_str[y];
net.num_pts++;
if (y < model->center_y
&& YX_TILE(model, y+1, model->center_x)->flags & TF_CENTER_MIDBUF) {
net.pt[net.num_pts-1].name = "CLKV_CKPIN_BUF%i";
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
net.pt[0].start_count = 0;
net.pt[0].x = model->center_x;
net.pt[0].y = y;
net.pt[0].name = "CLKV_MIDBUF_TOP_CKPIN%i";
net.num_pts = 1;
} else if (is_aty(Y_CHIP_HORIZ_REGS, model, y)) {
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
net.pt[0].start_count = 8;
net.pt[0].x = model->center_x;
net.pt[0].y = y;
net.pt[0].name = "CLKC_CKTB%i";
net.num_pts = 1;
} else if (y > model->center_y
&& YX_TILE(model, y-1, model->center_x)->flags & TF_CENTER_MIDBUF) {
net.pt[net.num_pts-1].name = "CLKV_CKPIN_BOT_BUF%i";
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
net.pt[0].start_count = 0;
net.pt[0].x = model->center_x;
net.pt[0].y = y;
net.pt[0].name = "CLKV_MIDBUF_BOT_CKPIN%i";
net.num_pts = 1;
}
}
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].x = model->center_x-CENTER_CMTPLL_O;
net.pt[net.num_pts].y = model->y_height-BOT_INNER_ROW;
net.pt[net.num_pts].name = "REGB_BTERM_CKPIN%i";
net.num_pts++;
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].x = model->center_x-CENTER_CMTPLL_O;
net.pt[net.num_pts].y = model->y_height-BOT_OUTER_ROW;
net.pt[net.num_pts].name = "REGB_CKPIN%i";
net.num_pts++;
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc); }
// horizontal
{ struct seed_data x_seeds[] = {
{ X_OUTER_LEFT, "REGL_CKPIN%i" },
{ X_INNER_LEFT, "REGH_LTERM_CKPIN%i" },
{ X_LEFT_MCB | X_RIGHT_MCB, "MCB_REGH_CKPIN%i" },
{ X_FABRIC_ROUTING_COL
| X_LEFT_IO_ROUTING_COL
| X_RIGHT_IO_ROUTING_COL, "REGH_CKPIN%i_INT" },
| X_RIGHT_IO_ROUTING_COL
| X_FABRIC_BRAM_COL, "REGH_CKPIN%i_INT" },
{ X_LEFT_IO_DEVS_COL
| X_FABRIC_BRAM_VIA_COL
| X_FABRIC_MACC_VIA_COL
@ -934,60 +1107,62 @@ static int ckpin(struct fpga_model *model)
{ X_INNER_RIGHT, "REGH_RTERM_CKPIN%i" },
{ X_OUTER_RIGHT, "REGR_CKPIN%i" },
{ 0 }};
char* gclk_sep_str;
seed_strx(model, x_seeds);
left_half = 1;
seed_strx(model, ckpin_seeds);
net.last_inc = 7;
net.num_pts = 0;
for (x = 0; x < model->x_width; x++) {
if (x == model->left_gclk_sep_x
|| x == model->right_gclk_sep_x)
continue;
if (!model->tmp_str[x])
continue;
ASSERT(model->tmp_str[x]);
ASSERT(net.num_pts < sizeof(net.pt)/sizeof(net.pt[0]));
if (is_atx(X_CENTER_ROUTING_COL|X_CENTER_LOGIC_COL|X_CENTER_CMTPLL_COL, model, x))
start1 = 8;
else if (is_atx(X_CENTER_REGS_COL, model, x))
start1 = left_half ? 8 : 0;
else
start1 = 0;
net.pt[net.num_pts].start_count =
is_atx(X_CENTER_MAJOR, model, x) ? 8 : 0;
net.pt[net.num_pts].x = x;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].name = model->tmp_str[x];
net.num_pts++;
gclk_sep_pos = left_half ? model->left_gclk_sep_x : model->right_gclk_sep_x;
gclk_sep_str = ((x > gclk_sep_pos) ^ left_half) ? "REGH_DSP_IN_CKPIN%i" : "REGH_DSP_OUT_CKPIN%i";
if ((rc = add_conn_range(model, NOPREF_BI_F,
model->center_y, x, model->tmp_str[x], start1, start1+7,
model->center_y, gclk_sep_pos,
gclk_sep_str, 0))) FAIL(rc);
// In this loop we tie around the CENTER_REGS_COL, not the
// CENTER_CMTPLL_COL as before.
if (left_half && is_atx(X_CENTER_REGS_COL, model, x)) {
left_half = 0;
x--; // wire up center regs col on right side as well
}
if (x == model->left_gclk_sep_x) {
net.pt[net.num_pts-1].name = "REGH_DSP_IN_CKPIN%i";
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
net.pt[0].start_count = 0;
net.pt[0].x = x;
net.pt[0].y = model->center_y;
net.pt[0].name = "REGH_DSP_OUT_CKPIN%i";
net.num_pts = 1;
} else if (x == model->center_x) {
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
net.pt[0].start_count = 0;
net.pt[0].x = x;
net.pt[0].y = model->center_y;
net.pt[0].name = "CLKC_CKLR%i";
net.num_pts = 1;
} else if (x == model->right_gclk_sep_x) {
net.pt[net.num_pts-1].name = "REGH_DSP_OUT_CKPIN%i";
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
net.pt[0].start_count = 0;
net.pt[0].x = x;
net.pt[0].y = model->center_y;
net.pt[0].name = "REGH_DSP_IN_CKPIN%i";
net.num_pts = 1;
}
}
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc); }
return 0;
fail:
return rc;
}
static int clkindirect_feedback(struct fpga_model *model)
static int clkindirect_feedback(struct fpga_model *model, enum extra_wires wire)
{
int x, i, rc, left_half, start1, last1, start2;
//
// clk indirect 0:7
// clk feedback 0:7
//
{
struct seed_data clk_indirect_seeds[] = {
const struct seed_data clk_indirect_seeds[] = {
{ X_OUTER_LEFT, "REGL_CLK_INDIRECT%i" },
{ X_INNER_LEFT, "REGH_LTERM_CLKINDIRECT%i" },
{ X_LEFT_MCB | X_RIGHT_MCB, "MCB_REGH_CLKINDIRECT_LR%i" },
{ X_FABRIC_ROUTING_COL
| X_LEFT_IO_ROUTING_COL
| X_RIGHT_IO_ROUTING_COL, "REGH_CLKINDIRECT_LR%i_INT" },
| X_RIGHT_IO_ROUTING_COL
| X_FABRIC_BRAM_COL, "REGH_CLKINDIRECT_LR%i_INT" },
{ X_LEFT_IO_DEVS_COL
| X_FABRIC_BRAM_VIA_COL
| X_FABRIC_MACC_VIA_COL
@ -1001,12 +1176,14 @@ static int clkindirect_feedback(struct fpga_model *model)
{ X_INNER_RIGHT, "REGH_RTERM_CLKINDIRECT%i" },
{ X_OUTER_RIGHT, "REGR_CLK_INDIRECT%i" },
{ 0 }};
struct seed_data clk_feedback_seeds[] = {
const struct seed_data clk_feedback_seeds[] = {
{ X_OUTER_LEFT, "REGL_CLK_FEEDBACK%i" },
{ X_INNER_LEFT, "REGH_LTERM_CLKFEEDBACK%i" },
{ X_LEFT_MCB | X_RIGHT_MCB, "MCB_REGH_CLKFEEDBACK_LR%i" },
{ X_FABRIC_ROUTING_COL
| X_LEFT_IO_ROUTING_COL
| X_RIGHT_IO_ROUTING_COL, "REGH_CLKFEEDBACK_LR%i_INT" },
| X_RIGHT_IO_ROUTING_COL
| X_FABRIC_BRAM_COL, "REGH_CLKFEEDBACK_LR%i_INT" },
{ X_LEFT_IO_DEVS_COL
| X_FABRIC_BRAM_VIA_COL
| X_FABRIC_MACC_VIA_COL
@ -1020,66 +1197,293 @@ static int clkindirect_feedback(struct fpga_model *model)
{ X_INNER_RIGHT, "REGH_RTERM_CLKFEEDBACK%i" },
{ X_OUTER_RIGHT, "REGR_CLK_FEEDBACK%i" },
{ 0 }};
struct seed_data* seeds[2] = {clk_indirect_seeds, clk_feedback_seeds};
const char* gclk_sep_str[2] = {"REGH_CLKINDIRECT_LR%i_INT", "REGH_CLKFEEDBACK_LR%i_INT"};
int y, x, i, top_pll_y, top_dcm_y, bot_pll_y, bot_dcm_y;
int regular_pts, rc;
const char *wstr;
struct w_net net;
for (i = 0; i <= 1; i++) { // indirect and feedback
left_half = 1;
seed_strx(model, seeds[i]);
for (x = 0; x < model->x_width; x++) {
if (x == model->left_gclk_sep_x
|| x == model->right_gclk_sep_x)
//
// clk_indirect and clk_feedback have 6 nets:
//
// 2 small nets - one for the top side, one for the bottom side, that
// connect the pll and dcm devices on each side to their termination
// tiles.
//
// Then 4 larger nets each covering one quarter of the chip (bottom-left,
// bottom-right, top-left and top-right). They connect together 4 wires
// of the dcm and pll devices on one side to the entire center_y row
// (separately for left and right columns). The bottom pll/dcm go to
// center row 0:3, the top pll/dcm go to center row 4:7.
//
if (wire == CLK_INDIRECT) {
seed_strx(model, clk_indirect_seeds);
wstr = "INDIRECT";
} else if (wire == CLK_FEEDBACK) {
seed_strx(model, clk_feedback_seeds);
wstr = "FEEDBACK";
} else FAIL(EINVAL);
//
// 2 termination to pll/dcm nets (top and bottom side)
//
top_pll_y = -1;
top_dcm_y = -1;
bot_pll_y = -1;
bot_dcm_y = -1;
net.last_inc = 7;
net.pt[0].name = pf("REGT_CLK_%s%%i", wstr);
net.pt[0].start_count = 0;
net.pt[0].y = TOP_OUTER_ROW;
net.pt[0].x = model->center_x - CENTER_CMTPLL_O;
net.pt[1].name = pf("REGT_TTERM_CLK%s%%i", wstr);
net.pt[1].start_count = 0;
net.pt[1].y = TOP_INNER_ROW;
net.pt[1].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts = 2;
for (y = TOP_FIRST_REGULAR; y <= model->y_height - BOT_LAST_REGULAR_O; y++) {
if (y < model->center_y
&& has_device(model, y, model->center_x-CENTER_CMTPLL_O, DEV_PLL)) {
top_pll_y = y;
net.pt[net.num_pts].name = pf("PLL_CLK_%s_TB%%i", wstr);
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
} else if (y < model->center_y
&& has_device(model, y, model->center_x-CENTER_CMTPLL_O, DEV_DCM)) {
top_dcm_y = y;
net.pt[net.num_pts].name = pf("DCM_CLK_%s_LR_TOP%%i", wstr);
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
} else if (y == model->center_y) {
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
// start bottom side net
net.num_pts = 0;
} else if (y > model->center_y
&& has_device(model, y, model->center_x-CENTER_CMTPLL_O, DEV_PLL)) {
bot_pll_y = y;
net.pt[net.num_pts].name = pf("CMT_PLL_CLK_%s_LRBOT%%i", wstr);
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
} else if (y > model->center_y
&& has_device(model, y, model->center_x-CENTER_CMTPLL_O, DEV_DCM)) {
bot_dcm_y = y;
net.pt[net.num_pts].name = pf("DCM_CLK_%s_TB_BOT%%i", wstr);
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
}
}
net.pt[net.num_pts].name = pf("REGB_BTERM_CLK%s%%i", wstr);
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = model->y_height - BOT_INNER_ROW;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
net.pt[net.num_pts].name = pf("REGB_CLK_%s%%i", wstr);
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = model->y_height - BOT_OUTER_ROW;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
// todo: this function doesn't support more than one pll or dcm
// tile per chip side right now.
ASSERT(top_pll_y != -1 && top_dcm_y != -1
&& bot_pll_y != -1 && bot_dcm_y != -1);
//
// 4 nets for each quarter of the chip
//
net.last_inc = 3;
net.num_pts = 0;
for (x = LEFT_IO_ROUTING; x < model->x_width - RIGHT_INNER_O; x++) {
if (is_atx(X_CENTER_ROUTING_COL, model, x)) {
// finish bottom net on left side
for (i = 0; i < net.num_pts; i++)
net.pt[i].start_count = 0;
regular_pts = net.num_pts;
// pll and dcm
net.pt[net.num_pts].name = pf("PLL_CLK_%s_TB%%i", wstr);
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = bot_pll_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
net.pt[net.num_pts].name = pf("DCM_CLK_%s_LR_TOP%%i", wstr);
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = bot_dcm_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
// left termination
net.pt[net.num_pts].name = model->tmp_str[LEFT_OUTER_COL];
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = LEFT_OUTER_COL;
net.num_pts++;
net.pt[net.num_pts].name = model->tmp_str[LEFT_INNER_COL];
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = LEFT_INNER_COL;
net.num_pts++;
// 3 columns from center major
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->center_x - CENTER_ROUTING_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
net.pt[net.num_pts].start_count = 8;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->center_x - CENTER_LOGIC_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
net.pt[net.num_pts].start_count = 8;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
// finish top net on left side
net.num_pts = regular_pts;
for (i = 0; i < net.num_pts; i++)
net.pt[i].start_count = 4;
// pll and dcm
net.pt[net.num_pts].name = pf("CMT_PLL_CLK_%s_LRBOT%%i", wstr);
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = top_pll_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
net.pt[net.num_pts].name = pf("DCM_CLK_%s_TB_BOT%%i", wstr);
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = top_dcm_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
// left termination
net.pt[net.num_pts].name = model->tmp_str[LEFT_OUTER_COL];
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = LEFT_OUTER_COL;
net.num_pts++;
net.pt[net.num_pts].name = model->tmp_str[LEFT_INNER_COL];
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = LEFT_INNER_COL;
net.num_pts++;
// 3 colums from center major
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->center_x - CENTER_ROUTING_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
net.pt[net.num_pts].start_count = 12;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->center_x - CENTER_LOGIC_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
net.pt[net.num_pts].start_count = 12;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
// continue on right side
net.num_pts = 0;
x = model->center_x;
continue;
if (!model->tmp_str[x])
continue;
if (is_atx(X_CENTER_LOGIC_COL, model, x)) {
start1 = 8;
last1 = 15;
start2 = 0;
} else if (is_atx(X_CENTER_CMTPLL_COL, model, x)) {
if (left_half) {
start1 = 8;
last1 = 15;
start2 = 0;
} else {
start1 = 0;
last1 = 3;
start2 = 4;
}
} else if (is_atx(X_CENTER_REGS_COL|X_INNER_RIGHT|X_OUTER_RIGHT, model, x)) {
start1 = 0;
last1 = 3;
start2 = 4;
} else {
start1 = 0;
last1 = 7;
start2 = 0;
net.pt[net.num_pts].name = model->tmp_str[x];
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = x;
net.num_pts++;
}
if ((rc = add_conn_range(model, NOPREF_BI_F,
model->center_y, x, model->tmp_str[x], start1, last1,
model->center_y, left_half ? model->left_gclk_sep_x : model->right_gclk_sep_x,
gclk_sep_str[i], start2))) FAIL(rc);
if (last1 == 3) {
if (start1 || start2 != 4) {
fprintf(stderr, "Internal error in line %i.\n", __LINE__);
FAIL(rc);
}
if ((rc = add_conn_range(model, NOPREF_BI_F,
model->center_y, x, model->tmp_str[x], 4, 7,
model->center_y, left_half ? model->left_gclk_sep_x : model->right_gclk_sep_x,
gclk_sep_str[i], 0))) FAIL(rc);
}
if (left_half && is_atx(X_CENTER_CMTPLL_COL, model, x)) {
left_half = 0;
x--; // wire up cmtpll col on right side as well
}
}
}
}
// finish bottom net on right side
for (i = 0; i < net.num_pts; i++)
net.pt[i].start_count = 0;
regular_pts = net.num_pts;
// pll and dcm
net.pt[net.num_pts].name = pf("PLL_CLK_%s_TB%%i", wstr);
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = bot_pll_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
net.pt[net.num_pts].name = pf("DCM_CLK_%s_LR_TOP%%i", wstr);
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = bot_dcm_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
// right termination
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->x_width - RIGHT_OUTER_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->x_width - RIGHT_INNER_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
// 2 columns from center major
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
net.pt[net.num_pts].start_count = 4;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->center_x;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
// finish top net on right side
net.num_pts = regular_pts;
for (i = 0; i < net.num_pts; i++)
net.pt[i].start_count = 4;
// pll and dcm
net.pt[net.num_pts].name = pf("CMT_PLL_CLK_%s_LRBOT%%i", wstr);
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = top_pll_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
net.pt[net.num_pts].name = pf("DCM_CLK_%s_TB_BOT%%i", wstr);
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = top_dcm_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.num_pts++;
// right termination
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->x_width - RIGHT_OUTER_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->x_width - RIGHT_INNER_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
// 2 columns from center major
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->center_x - CENTER_CMTPLL_O;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
net.pt[net.num_pts].start_count = 0;
net.pt[net.num_pts].y = model->center_y;
net.pt[net.num_pts].x = model->center_x;
net.pt[net.num_pts].name = model->tmp_str[net.pt[net.num_pts].x];
net.num_pts++;
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) FAIL(rc);
return 0;
fail:
return rc;

View File

@ -523,7 +523,7 @@ fail:
return rc;
}
void seed_strx(struct fpga_model *model, struct seed_data *data)
void seed_strx(struct fpga_model *model, const struct seed_data *data)
{
int x, i;
for (x = 0; x < model->x_width; x++) {
@ -535,7 +535,7 @@ void seed_strx(struct fpga_model *model, struct seed_data *data)
}
}
void seed_stry(struct fpga_model *model, struct seed_data *data)
void seed_stry(struct fpga_model *model, const struct seed_data *data)
{
int y, i;
for (y = 0; y < model->y_height; y++) {