more clock routing

This commit is contained in:
Wolfgang Spraul 2012-12-10 22:17:01 -05:00
parent b7b2f594a3
commit a3f42ee998
10 changed files with 492 additions and 102 deletions

View File

@ -22,6 +22,7 @@ time_t g_start_time;
struct test_state
{
int cmdline_skip;
int cmdline_count;
char cmdline_diff_exec[1024];
int dry_run;
int diff_to_null;
@ -78,6 +79,11 @@ static int diff_printf(struct test_state* tstate)
printf("O Skipping diff %i.\n", tstate->next_diff_counter++);
return 0;
}
if (tstate->cmdline_count != -1
&& tstate->next_diff_counter >= tstate->cmdline_skip + tstate->cmdline_count + 1) {
printf("\nO Finished %i tests.\n", tstate->cmdline_count);
exit(0);
}
snprintf(path, sizeof(path), "%s/autotest_%s_%06i", tstate->tmp_dir,
tstate->base_name, tstate->next_diff_counter);
@ -561,6 +567,7 @@ static int test_routing_sw_from_logic(struct test_state* tstate,
swto.start_switch = fdev_logic_pinstr_i(tstate->model,
dev->pinw_req_for_cfg[0]|LD1, LOGIC_M);
swto.from_to = SW_TO;
swto.flags = SWTO_REL_DEFAULT;
swto.rel_y = 0;
swto.rel_x = -1;
swto.target_connpt = STRIDX_NO_ENTRY;
@ -1061,7 +1068,8 @@ static int test_logic(struct test_state* tstate, int y, int x, int type_idx,
|| (latch_logic
&& (dev->pinw_req_for_cfg[i] == LI_CLK
|| dev->pinw_req_for_cfg[i] == LI_CE))) {
rc = fnet_route_to_inpins(tstate->model, pinw_nets[i], "VCC_WIRE");
rc = fnet_route_to_inpins_s(tstate->model,
pinw_nets[i], "VCC_WIRE");
if (rc) FAIL(rc);
}
}
@ -1745,6 +1753,9 @@ static int test_clock_routing(struct test_state* tstate)
rc = fpga_find_iob(tstate->model, tstate->model->pkg->gclk_pin[i],
&iob_clk_y, &iob_clk_x, &iob_clk_type_idx);
if (rc) FAIL(rc);
printf("\nO test %i: gclk pin %s (y%02i x%02i IOB %i)\n",
tstate->next_diff_counter, tstate->model->pkg->gclk_pin[i],
iob_clk_y, iob_clk_x, iob_clk_type_idx);
rc = fdev_iob_input(tstate->model, iob_clk_y, iob_clk_x,
iob_clk_type_idx, IO_LVCMOS33);
if (rc) FAIL(rc);
@ -1782,7 +1793,6 @@ static int test_clock_routing(struct test_state* tstate)
logic_type_idx);
fdev_delete(tstate->model, iob_clk_y, iob_clk_x, DEV_IOB,
iob_clk_type_idx);
break;
}
return 0;
fail:
@ -1796,8 +1806,8 @@ static void printf_help(const char* argv_0, const char** available_tests)
printf( "\n"
"fpgatools automatic test suite\n"
"\n"
"Usage: %s [--test=<name>] [--skip=<num>] [--dry-run]\n"
" %*s [--diff=<diff executable>]\n"
"Usage: %s [--test=<name>] [--skip=<num>] [--count=<num>]\n"
" %*s [--dry-run] [--diff=<diff executable>]\n"
"Default diff executable: " DEFAULT_DIFF_EXEC "\n"
"Output dir: " AUTOTEST_TMP_DIR "\n", argv_0, (int) strlen(argv_0), "");
@ -1818,7 +1828,7 @@ int main(int argc, char** argv)
struct fpga_model model;
struct test_state tstate;
char param[1024], cmdline_test[1024];
int i, param_skip, rc;
int i, param_skip, param_count, rc;
const char* available_tests[] =
{ "logic_cfg", "routing_sw", "io_sw", "iob_cfg",
"lut_encoding", "bufg_cfg", "bufio_cfg", "pll_cfg",
@ -1840,6 +1850,7 @@ int main(int argc, char** argv)
memset(&tstate, 0, sizeof(tstate));
tstate.cmdline_skip = -1;
tstate.cmdline_count = -1;
tstate.cmdline_diff_exec[0] = 0;
cmdline_test[0] = 0;
tstate.dry_run = -1;
@ -1871,6 +1882,14 @@ int main(int argc, char** argv)
tstate.cmdline_skip = param_skip;
continue;
}
if (sscanf(argv[i], "--count=%i", &param_count) == 1) {
if (tstate.cmdline_count != -1) {
printf_help(argv[0], available_tests);
return EINVAL;
}
tstate.cmdline_count = param_count;
continue;
}
if (!strcmp(argv[i], "--dry-run")) {
tstate.dry_run = 1;
continue;
@ -1910,6 +1929,7 @@ int main(int argc, char** argv)
printf("O Test: %s\n", cmdline_test);
printf("O Diff: %s\n", tstate.cmdline_diff_exec);
printf("O Skip: %i\n", tstate.cmdline_skip);
printf("O Count: %i\n", tstate.cmdline_count);
printf("O Dry run: %i\n", tstate.dry_run);
printf("\n");
printf("O Time measured in seconds from 0.\n");

View File

@ -106,7 +106,7 @@ static int find_es_switch(struct extract_state* es, int y, int x, swidx_t sw)
return 0;
}
static int write_iobs(struct fpga_bits* bits, struct fpga_model* model)
static int write_type2(struct fpga_bits* bits, struct fpga_model* model)
{
int i, y, x, type_idx, part_idx, dev_idx, first_iob, rc;
struct fpga_device* dev;
@ -571,6 +571,79 @@ fail:
return rc;
}
static int extract_type2(struct extract_state* es)
{
int i, bits_off;
uint16_t u16;
RC_CHECK(es->model);
extract_iobs(es);
for (i = 0; i < es->model->pkg->num_gclk_pins; i++) {
if (!es->model->pkg->gclk_pin[i])
continue;
bits_off = IOB_DATA_START
+ es->model->pkg->gclk_type2_o[i]*XC6_WORD_BYTES
+ XC6_TYPE2_GCLK_REG_SW/XC6_WORD_BITS;
u16 = frame_get_u16(&es->bits->d[bits_off]);
if (!u16)
continue;
if (u16 & (1<<(XC6_TYPE2_GCLK_REG_SW%XC6_WORD_BITS))) {
int iob_y, iob_x, iob_idx;
struct fpga_device *iob_dev;
struct switch_to_yx_l2 switch_to_yx_l2;
struct switch_to_rel switch_to_rel;
//
// find and enable reg-switch for gclk_pin[i]
//
fpga_find_iob(es->model, es->model->pkg->gclk_pin[i],
&iob_y, &iob_x, &iob_idx);
RC_CHECK(es->model);
iob_dev = fdev_p(es->model, iob_y, iob_x, DEV_IOB, iob_idx);
RC_ASSERT(es->model, iob_dev);
switch_to_yx_l2.l1.yx_req = YX_X_CENTER_CMTPLL | YX_Y_CENTER;
switch_to_yx_l2.l1.flags = SWTO_YX_CLOSEST;
switch_to_yx_l2.l1.model = es->model;
switch_to_yx_l2.l1.y = iob_y;
switch_to_yx_l2.l1.x = iob_x;
switch_to_yx_l2.l1.start_switch = iob_dev->pinw[IOB_OUT_I];
switch_to_yx_l2.l1.from_to = SW_FROM;
fpga_switch_to_yx_l2(&switch_to_yx_l2);
RC_CHECK(es->model);
if (!switch_to_yx_l2.l1.set.len)
{ HERE(); continue; }
switch_to_rel.model = es->model;
switch_to_rel.start_y = switch_to_yx_l2.l1.dest_y;
switch_to_rel.start_x = switch_to_yx_l2.l1.dest_x;
switch_to_rel.start_switch = switch_to_yx_l2.l1.dest_connpt;
switch_to_rel.from_to = SW_FROM;
switch_to_rel.flags = SWTO_REL_WEAK_TARGET;
switch_to_rel.rel_y = es->model->center_y - switch_to_rel.start_y;
switch_to_rel.rel_x = es->model->center_x - switch_to_rel.start_x;
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
fpga_switch_to_rel(&switch_to_rel);
RC_CHECK(es->model);
if (!switch_to_rel.set.len)
{ HERE(); continue; }
if (switch_to_rel.set.len != 1) HERE();
RC_ASSERT(es->model, es->num_yx_pos < MAX_YX_SWITCHES);
es->yx_pos[es->num_yx_pos].y = switch_to_rel.start_y;
es->yx_pos[es->num_yx_pos].x = switch_to_rel.start_x;
es->yx_pos[es->num_yx_pos].idx = switch_to_rel.set.sw[0];
es->num_yx_pos++;
u16 &= ~(1<<(XC6_TYPE2_GCLK_REG_SW%XC6_WORD_BITS));
}
if (u16) HERE();
frame_set_u16(&es->bits->d[bits_off], u16);
}
RC_RETURN(es->model);
}
static int lut2str(uint64_t lut, int lut_pos, int lut5_used,
char *lut6_buf, char** lut6_p, char *lut5_buf, char** lut5_p)
{
@ -1854,7 +1927,7 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits)
rc = extract_switches(&es);
if (rc) RC_FAIL(model, rc);
rc = extract_iobs(&es);
rc = extract_type2(&es);
if (rc) RC_FAIL(model, rc);
rc = extract_logic(&es);
if (rc) RC_FAIL(model, rc);
@ -2230,7 +2303,7 @@ int write_model(struct fpga_bits* bits, struct fpga_model* model)
for (i = 0; i < sizeof(s_default_bits)/sizeof(s_default_bits[0]); i++)
set_bitp(bits, &s_default_bits[i]);
write_switches(bits, model);
write_iobs(bits, model);
write_type2(bits, model);
write_logic(bits, model);
RC_RETURN(model);

View File

@ -8,6 +8,10 @@
#include "model.h"
#include "control.h"
#undef DBG_ENUM_SWITCH
#undef DBG_SWITCH_TO_YX
#undef DBG_SWITCH_TO_REL
struct iob_site
{
int xy;
@ -1574,14 +1578,11 @@ const char* fmt_swset(struct fpga_model* model, int y, int x,
return buf[last_buf];
}
#undef DBG_ENUM_SWITCH
int construct_sw_chain(struct sw_chain* chain, struct fpga_model* model,
int y, int x, str16_t start_switch, int from_to, int max_depth,
swidx_t* block_list, int block_list_len)
{
int rc;
RC_CHECK(model);
#ifdef DBG_ENUM_SWITCH
printf("construct_sw_chain() %s (%s)\n",
strarray_lookup(&model->str, start_switch),
@ -1601,7 +1602,7 @@ int construct_sw_chain(struct sw_chain* chain, struct fpga_model* model,
chain->internal_block_list = malloc(
MAX_SWITCHBOX_SIZE * sizeof(*chain->block_list));
if (!chain->internal_block_list)
FAIL(ENOMEM);
RC_FAIL(model, ENOMEM);
chain->block_list = chain->internal_block_list;
chain->block_list_len = 0;
}
@ -1612,9 +1613,7 @@ int construct_sw_chain(struct sw_chain* chain, struct fpga_model* model,
chain->first_round = 1;
chain->set.len = 1;
chain->set.sw[0] = FIRST_SW | start_switch;
return 0;
fail:
return rc;
RC_RETURN(model);
}
void destruct_sw_chain(struct sw_chain* chain)
@ -1824,7 +1823,7 @@ int construct_sw_conns(struct sw_conns* conns, struct fpga_model* model,
memset(conns, 0, sizeof(*conns));
construct_sw_chain(&conns->chain, model, y, x, start_switch,
from_to, max_depth, /*block_list*/ 0, /*block_list_len*/ 0);
return 0;
RC_RETURN(model);
}
void destruct_sw_conns(struct sw_conns* conns)
@ -1915,18 +1914,32 @@ int fpga_switch_to_yx(struct switch_to_yx* p)
struct sw_conns conns;
struct sw_set best_set;
int best_y, best_x, best_distance, distance;
int best_num_dests, rc;
int best_num_dests;
str16_t best_connpt;
RC_CHECK(p->model);
rc = construct_sw_conns(&conns, p->model, p->y, p->x, p->start_switch,
#ifdef DBG_SWITCH_TO_YX
printf("fpga_switch_to_yx() %s y%02i-x%02i-%s yx_req %Xh flags %Xh\n",
p->from_to == SW_FROM ? "SW_FROM" : "SW_TO",
p->y, p->x, strarray_lookup(&p->model->str, p->start_switch),
p->yx_req, p->flags);
#endif
construct_sw_conns(&conns, p->model, p->y, p->x, p->start_switch,
p->from_to, (p->flags & SWTO_YX_MAX_SWITCH_DEPTH)
? p->max_switch_depth : SW_SET_SIZE);
if (rc) FAIL(rc);
RC_CHECK(p->model);
best_y = -1;
while (fpga_switch_conns(&conns) != NO_CONN) {
if (is_atyx(p->yx_req, p->model, conns.dest_y, conns.dest_x)) {
if (!is_atyx(p->yx_req, p->model, conns.dest_y, conns.dest_x))
continue;
#ifdef DBG_SWITCH_TO_YX
printf(" sw %s conn y%02i x%02i %s\n",
fmt_swset(p->model, p->y, p->x,
&conns.chain.set, p->from_to),
conns.dest_y, conns.dest_x,
strarray_lookup(&p->model->str, conns.dest_str_i));
#endif
if (p->flags & SWTO_YX_TARGET_CONNPT
&& conns.dest_str_i != p->target_connpt)
continue;
@ -1950,7 +1963,6 @@ int fpga_switch_to_yx(struct switch_to_yx* p)
if (!p->flags & SWTO_YX_CLOSEST)
break;
}
}
if (best_y == -1)
p->set.len = 0;
else {
@ -1960,9 +1972,7 @@ int fpga_switch_to_yx(struct switch_to_yx* p)
p->dest_connpt = best_connpt;
}
destruct_sw_conns(&conns);
return 0;
fail:
return rc;
RC_RETURN(p->model);
}
void printf_switch_to_yx_result(struct switch_to_yx* p)
@ -1977,33 +1987,114 @@ void printf_switch_to_yx_result(struct switch_to_yx* p)
fmt_swset(p->model, p->y, p->x, &p->set, p->from_to));
}
int fpga_switch_to_yx_l2(struct switch_to_yx_l2 *p)
{
RC_CHECK(p->l1.model);
fpga_switch_to_yx(&p->l1);
RC_CHECK(p->l1.model);
p->l2_set.len = 0;
if (!p->l1.set.len) {
struct sw_conns conns;
struct switch_to_yx l2 = p->l1;
construct_sw_conns(&conns, p->l1.model, p->l1.y, p->l1.x, p->l1.start_switch,
p->l1.from_to, (p->l1.flags & SWTO_YX_MAX_SWITCH_DEPTH)
? p->l1.max_switch_depth : SW_SET_SIZE);
RC_CHECK(p->l1.model);
while (fpga_switch_conns(&conns) != NO_CONN) {
l2.y = conns.dest_y;
l2.x = conns.dest_x;
l2.start_switch = conns.dest_str_i;
fpga_switch_to_yx(&l2);
RC_CHECK(l2.model);
if (l2.set.len) {
p->l1.set = conns.chain.set;
p->l1.dest_y = l2.dest_y;
p->l1.dest_x = l2.dest_x;
p->l1.dest_connpt = l2.dest_connpt;
p->l2_set = l2.set;
p->l2_y = l2.y;
p->l2_x = l2.x;
break;
}
}
destruct_sw_conns(&conns);
}
RC_RETURN(p->l1.model);
}
int fpga_switch_to_rel(struct switch_to_rel *p)
{
struct sw_conns conns;
int rc;
struct sw_set best_set;
int best_y, best_x, best_distance;
str16_t best_connpt;
RC_CHECK(p->model);
rc = construct_sw_conns(&conns, p->model, p->start_y, p->start_x,
#ifdef DBG_SWITCH_TO_REL
printf("fpga_switch_to_rel() %s y%02i-x%02i-%s flags %Xh rel_y %i rel_x %i target_connpt %s\n",
p->from_to == SW_FROM ? "SW_FROM" : "SW_TO",
p->start_y, p->start_x, strarray_lookup(&p->model->str, p->start_switch),
p->flags, p->rel_y, p->rel_x,
p->target_connpt == STRIDX_NO_ENTRY ? "-" :
strarray_lookup(&p->model->str, p->target_connpt));
#endif
construct_sw_conns(&conns, p->model, p->start_y, p->start_x,
p->start_switch, p->from_to, SW_SET_SIZE);
if (rc) FAIL(rc);
p->set.len = 0;
RC_CHECK(p->model);
best_y = -1;
while (fpga_switch_conns(&conns) != NO_CONN) {
#ifdef DBG_SWITCH_TO_REL
printf(" sw %s conn y%02i x%02i %s\n",
fmt_swset(p->model, p->start_y, p->start_x,
&conns.chain.set, p->from_to),
conns.dest_y, conns.dest_x,
strarray_lookup(&p->model->str, conns.dest_str_i));
#endif
if (conns.dest_y != p->start_y + p->rel_y
|| conns.dest_x != p->start_x + p->rel_x)
|| conns.dest_x != p->start_x + p->rel_x) {
if (!(p->flags & SWTO_REL_WEAK_TARGET))
continue;
if (best_y != -1) {
int distance = abs(conns.dest_y - (p->start_y+p->rel_y))
+ abs(conns.dest_x - (p->start_x+p->rel_x));
if (distance > best_distance)
continue;
}
best_set = conns.chain.set;
best_y = conns.dest_y;
best_x = conns.dest_x;
best_connpt = conns.dest_str_i;
best_distance = abs(conns.dest_y - (p->start_y+p->rel_y))
+ abs(conns.dest_x - (p->start_x+p->rel_x));
continue;
}
if (p->target_connpt != STRIDX_NO_ENTRY
&& conns.dest_str_i != p->target_connpt)
continue;
p->set = conns.chain.set;
p->dest_y = conns.dest_y;
p->dest_x = conns.dest_x;
p->dest_connpt = conns.dest_str_i;
best_set = conns.chain.set;
best_y = conns.dest_y;
best_x = conns.dest_x;
best_connpt = conns.dest_str_i;
break;
}
if (best_y == -1)
p->set.len = 0;
else {
#ifdef DBG_SWITCH_TO_REL
printf(" sw %s\n", fmt_swset(p->model, p->start_y, p->start_x,
&best_set, p->from_to));
printf(" dest y%02i-x%02i-%s\n", best_y, best_x,
strarray_lookup(&p->model->str, best_connpt));
#endif
p->set = best_set;
p->dest_y = best_y;
p->dest_x = best_x;
p->dest_connpt = best_connpt;
}
destruct_sw_conns(&conns);
return 0;
fail:
return rc;
RC_RETURN(p->model);
}
void printf_switch_to_rel_result(struct switch_to_rel* p)
@ -2260,9 +2351,153 @@ void fnet_printf(FILE* f, struct fpga_model* model, net_idx_t net_i)
}
}
static int fnet_pinw(struct fpga_model *model, net_idx_t net_i,
int out_pinw, int idx)
{
struct fpga_net *net_p;
struct fpga_device *dev_p;
int i, next_idx;
if (model->rc) { HERE(); return -1; };
net_p = fnet_get(model, net_i);
if (!net_p) { HERE(); return -1; };
next_idx = 0;
for (i = 0; i < net_p->len; i++) {
if (!(net_p->el[i].idx & NET_IDX_IS_PINW))
continue;
dev_p = FPGA_DEV(model, net_p->el[i].y,
net_p->el[i].x, net_p->el[i].dev_idx);
if ((out_pinw && (net_p->el[i].idx & NET_IDX_MASK) < dev_p->num_pinw_in)
|| (!out_pinw && (net_p->el[i].idx & NET_IDX_MASK) >= dev_p->num_pinw_in))
continue;
if (next_idx == idx)
return i;
next_idx++;
}
return -1;
}
static int fnet_autoroute_clock(struct fpga_model* model, net_idx_t net_i)
{
return 0;
struct fpga_net *net_p;
int out_i, in_i, hclk_y;
struct fpga_device *out_dev, *in_dev;
struct switch_to_yx_l2 switch_to_yx_l2;
struct switch_to_rel switch_to_rel;
RC_CHECK(model);
net_p = fnet_get(model, net_i);
if (!net_p) RC_FAIL(model, EINVAL);
out_i = fnet_pinw(model, net_i, /*out*/ 1, 0);
in_i = fnet_pinw(model, net_i, /*out*/ 0, 0);
if (out_i == -1 || in_i == -1)
RC_FAIL(model, EINVAL);
out_dev = FPGA_DEV(model, net_p->el[out_i].y,
net_p->el[out_i].x, net_p->el[out_i].dev_idx);
in_dev = FPGA_DEV(model, net_p->el[in_i].y,
net_p->el[in_i].x, net_p->el[in_i].dev_idx);
if (out_dev->type != DEV_IOB || in_dev->type != DEV_LOGIC)
RC_FAIL(model, ENOTSUP);
// to regs (l2 allows one intermediate hop)
switch_to_yx_l2.l1.yx_req = YX_X_CENTER_CMTPLL | YX_Y_CENTER;
switch_to_yx_l2.l1.flags = SWTO_YX_CLOSEST;
switch_to_yx_l2.l1.model = model;
switch_to_yx_l2.l1.y = net_p->el[out_i].y;
switch_to_yx_l2.l1.x = net_p->el[out_i].x;
switch_to_yx_l2.l1.start_switch = out_dev->pinw[net_p->el[out_i].idx
& NET_IDX_MASK];
switch_to_yx_l2.l1.from_to = SW_FROM;
fpga_switch_to_yx_l2(&switch_to_yx_l2);
RC_ASSERT(model, switch_to_yx_l2.l1.set.len);
fnet_add_sw(model, net_i, switch_to_yx_l2.l1.y, switch_to_yx_l2.l1.x,
switch_to_yx_l2.l1.set.sw, switch_to_yx_l2.l1.set.len);
if (switch_to_yx_l2.l2_set.len)
fnet_add_sw(model, net_i, switch_to_yx_l2.l2_y, switch_to_yx_l2.l2_x,
switch_to_yx_l2.l2_set.sw, switch_to_yx_l2.l2_set.len);
// to center (possibly over intermediate)
switch_to_rel.dest_y = switch_to_yx_l2.l1.dest_y;
switch_to_rel.dest_x = switch_to_yx_l2.l1.dest_x;
switch_to_rel.dest_connpt = switch_to_yx_l2.l1.dest_connpt;
do {
switch_to_rel.model = model;
switch_to_rel.start_y = switch_to_rel.dest_y;
switch_to_rel.start_x = switch_to_rel.dest_x;
switch_to_rel.start_switch = switch_to_rel.dest_connpt;
switch_to_rel.from_to = SW_FROM;
switch_to_rel.flags = SWTO_REL_WEAK_TARGET;
switch_to_rel.rel_y = model->center_y - switch_to_rel.start_y;
switch_to_rel.rel_x = model->center_x - switch_to_rel.start_x;
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
fpga_switch_to_rel(&switch_to_rel);
RC_ASSERT(model, switch_to_rel.set.len);
fnet_add_sw(model, net_i, switch_to_rel.start_y, switch_to_rel.start_x,
switch_to_rel.set.sw, switch_to_rel.set.len);
} while (switch_to_rel.dest_y != model->center_y
|| switch_to_rel.dest_x != model->center_x);
// to hclk
RC_ASSERT(model, switch_to_rel.dest_y == model->center_y
&& switch_to_rel.dest_x == model->center_x);
hclk_y = y_to_hclk(net_p->el[in_i].y, model);
RC_ASSERT(model, hclk_y != -1);
do {
switch_to_rel.model = model;
switch_to_rel.start_y = switch_to_rel.dest_y;
switch_to_rel.start_x = switch_to_rel.dest_x;
switch_to_rel.start_switch = switch_to_rel.dest_connpt;
switch_to_rel.from_to = SW_FROM;
switch_to_rel.flags = SWTO_REL_WEAK_TARGET;
switch_to_rel.rel_y = hclk_y - switch_to_rel.start_y;
switch_to_rel.rel_x = 0;
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
fpga_switch_to_rel(&switch_to_rel);
RC_ASSERT(model, switch_to_rel.set.len);
fnet_add_sw(model, net_i, switch_to_rel.start_y, switch_to_rel.start_x,
switch_to_rel.set.sw, switch_to_rel.set.len);
} while (switch_to_rel.dest_y != hclk_y);
// to routing col
do {
switch_to_rel.model = model;
switch_to_rel.start_y = switch_to_rel.dest_y;
switch_to_rel.start_x = switch_to_rel.dest_x;
switch_to_rel.start_switch = switch_to_rel.dest_connpt;
switch_to_rel.from_to = SW_FROM;
switch_to_rel.flags = SWTO_REL_WEAK_TARGET;
switch_to_rel.rel_y = 0;
switch_to_rel.rel_x = net_p->el[in_i].x-1 - switch_to_rel.start_x;
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
fpga_switch_to_rel(&switch_to_rel);
RC_ASSERT(model, switch_to_rel.set.len);
fnet_add_sw(model, net_i, switch_to_rel.start_y, switch_to_rel.start_x,
switch_to_rel.set.sw, switch_to_rel.set.len);
} while (switch_to_rel.dest_x != net_p->el[in_i].x-1);
// to logic device routing
switch_to_rel.model = model;
switch_to_rel.start_y = switch_to_rel.dest_y;
switch_to_rel.start_x = switch_to_rel.dest_x;
switch_to_rel.start_switch = switch_to_rel.dest_connpt;
switch_to_rel.from_to = SW_FROM;
switch_to_rel.flags = SWTO_REL_DEFAULT;
switch_to_rel.rel_y = net_p->el[in_i].y - switch_to_rel.start_y;
switch_to_rel.rel_x = net_p->el[in_i].x-1 - switch_to_rel.start_x;
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
fpga_switch_to_rel(&switch_to_rel);
RC_ASSERT(model, switch_to_rel.set.len);
fnet_add_sw(model, net_i, switch_to_rel.start_y, switch_to_rel.start_x,
switch_to_rel.set.sw, switch_to_rel.set.len);
// connect with pinw
fnet_route_to_inpins(model, net_i, switch_to_rel.dest_connpt);
RC_RETURN(model);
}
int fnet_autoroute(struct fpga_model* model, net_idx_t net_i)
@ -2294,22 +2529,9 @@ int fnet_autoroute(struct fpga_model* model, net_idx_t net_i)
}
// todo: gnd and vcc nets are special and have no outpin
// but lots of inpins
out_i = -1;
in_i = -1;
for (i = 0; i < net_p->len; i++) {
dev_p = FPGA_DEV(model, net_p->el[i].y,
net_p->el[i].x, net_p->el[i].dev_idx);
if ((net_p->el[i].idx & NET_IDX_MASK) < dev_p->num_pinw_in) {
// todo: right now we only support 1 inpin
if (in_i != -1) RC_FAIL(model, ENOTSUP);
in_i = i;
continue;
}
if (out_i != -1) RC_FAIL(model, EINVAL); // at most 1 outpin
out_i = i;
}
// todo: vcc and gnd have no outpin?
// but can have multiple inpins
out_i = fnet_pinw(model, net_i, /*out*/ 1, 0);
in_i = fnet_pinw(model, net_i, /*out*/ 0, 0);
if (out_i == -1 || in_i == -1)
RC_FAIL(model, EINVAL);
@ -2353,6 +2575,7 @@ int fnet_autoroute(struct fpga_model* model, net_idx_t net_i)
switch_to_rel.start_switch =
in_dev->pinw[net_p->el[in_i].idx & NET_IDX_MASK];
switch_to_rel.from_to = SW_TO;
switch_to_rel.flags = SWTO_REL_DEFAULT;
switch_to_rel.rel_y = 0;
switch_to_rel.rel_x = -1;
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
@ -2410,6 +2633,7 @@ int fnet_autoroute(struct fpga_model* model, net_idx_t net_i)
switch_to_rel.start_switch =
out_dev->pinw[net_p->el[out_i].idx & NET_IDX_MASK];
switch_to_rel.from_to = SW_FROM;
switch_to_rel.flags = SWTO_REL_DEFAULT;
switch_to_rel.rel_y = 0;
switch_to_rel.rel_x = -1;
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
@ -2435,19 +2659,16 @@ int fnet_autoroute(struct fpga_model* model, net_idx_t net_i)
}
int fnet_route_to_inpins(struct fpga_model* model, net_idx_t net_i,
const char* from)
str16_t from)
{
struct fpga_net* net_p;
struct fpga_device* dev_p;
str16_t from_i;
struct sw_set start_set, end_set;
int i, rc;
int i;
RC_CHECK(model);
net_p = fnet_get(model, net_i);
if (!net_p) FAIL(EINVAL);
from_i = strarray_find(&model->str, from);
if (from_i == STRIDX_NO_ENTRY) FAIL(EINVAL);
RC_ASSERT(model, net_p);
for (i = 0; i < net_p->len; i++) {
if (!(net_p->el[i].idx & NET_IDX_IS_PINW))
@ -2459,23 +2680,30 @@ int fnet_route_to_inpins(struct fpga_model* model, net_idx_t net_i,
// skip outpin
continue;
rc = froute_direct(model, net_p->el[i].y, net_p->el[i].x-1,
from_i, net_p->el[i].y, net_p->el[i].x,
froute_direct(model, net_p->el[i].y, net_p->el[i].x-1,
from, net_p->el[i].y, net_p->el[i].x,
dev_p->pinw[net_p->el[i].idx & NET_IDX_MASK],
&start_set, &end_set);
if (rc) FAIL(rc);
RC_CHECK(model);
if (!start_set.len || !end_set.len)
HERE();
rc = fnet_add_sw(model, net_i, net_p->el[i].y,
fnet_add_sw(model, net_i, net_p->el[i].y,
net_p->el[i].x-1, start_set.sw, start_set.len);
if (rc) FAIL(rc);
rc = fnet_add_sw(model, net_i, net_p->el[i].y,
fnet_add_sw(model, net_i, net_p->el[i].y,
net_p->el[i].x, end_set.sw, end_set.len);
if (rc) FAIL(rc);
}
return 0;
fail:
return rc;
RC_RETURN(model);
}
int fnet_route_to_inpins_s(struct fpga_model *model, net_idx_t net_i,
const char *from)
{
str16_t from_i;
RC_CHECK(model);
from_i = strarray_find(&model->str, from);
RC_ASSERT(model, from_i != STRIDX_NO_ENTRY);
return fnet_route_to_inpins(model, net_i, from_i);
}
int froute_direct(struct fpga_model* model, int start_y, int start_x,

View File

@ -268,6 +268,8 @@ void printf_swconns(struct fpga_model* model, int y, int x,
str16_t sw, int from_to, int max_depth);
#define SWTO_YX_DEF 0
// SWTO_YX_CLOSEST finds the closest tile that satisfies
// the YX requirement.
#define SWTO_YX_CLOSEST 0x0001
#define SWTO_YX_TARGET_CONNPT 0x0002
#define SWTO_YX_MAX_SWITCH_DEPTH 0x0004
@ -295,6 +297,26 @@ struct switch_to_yx
int fpga_switch_to_yx(struct switch_to_yx *p);
void printf_switch_to_yx_result(struct switch_to_yx *p);
struct switch_to_yx_l2
{
struct switch_to_yx l1;
// l2 y/x/set is inserted between l1.y/x/start_switch
// and l1.dest_y/dest_x/dest_connpt
struct sw_set l2_set;
int l2_y, l2_x;
};
// fpga_switch_to_yx_l2() allows for an optional intermediate tile
// to come before the yx_req. If a direct link was found, l2_set.len
// will be 0 and l2_y and l2_x are undefined.
int fpga_switch_to_yx_l2(struct switch_to_yx_l2 *p);
#define SWTO_REL_DEFAULT 0
// If a connection to the actal target is not found,
// WEAK_TARGET will allow to return the connection that
// reaches as close as possible to the x/y target.
#define SWTO_REL_WEAK_TARGET 0x0001
struct switch_to_rel
{
// input:
@ -303,6 +325,7 @@ struct switch_to_rel
int start_x;
str16_t start_switch;
int from_to;
int flags; // SWTO_REL-value
int rel_y;
int rel_x;
str16_t target_connpt; // can be STRIDX_NO_ENTRY
@ -370,6 +393,8 @@ void fnet_printf(FILE* f, struct fpga_model* model, net_idx_t net_i);
int fnet_autoroute(struct fpga_model* model, net_idx_t net_i);
int fnet_route_to_inpins(struct fpga_model* model, net_idx_t net_i,
str16_t from);
int fnet_route_to_inpins_s(struct fpga_model* model, net_idx_t net_i,
const char* from);
//

View File

@ -355,20 +355,22 @@ int parse_boolexpr(const char *expr, uint64_t *lut)
return 0;
}
int printf_type2(uint8_t *d, int len, int inpos, int num_entries)
void printf_type2(uint8_t *d, int len, int inpos, int num_entries)
{
int i, num_printed;
uint64_t u64;
uint16_t u16;
int i, j;
num_printed = 0;
for (i = 0; i < num_entries; i++) {
u64 = frame_get_u64(&d[inpos+i*8]);
if (u64) {
printf("type2 i%i 0x%016lX\n", i, u64);
num_printed++;
if (!u64) continue;
printf("type2 8*%i 0x%016lX\n", i, u64);
for (j = 0; j < 4; j++) {
u16 = frame_get_u16(&d[inpos+i*8+j*2]);
if (u16)
printf("type2 2*%i 8*%i+%i 0x%04X\n", i*4+j, i, j, u16);
}
}
return num_printed;
}
void printf_ramb16_data(uint8_t *bits, int inpos)

View File

@ -69,7 +69,7 @@ const char* bool_bits2str(uint64_t u64, int num_bits);
int parse_boolexpr(const char* expr, uint64_t* lut);
int printf_type2(uint8_t* d, int len, int inpos, int num_entries);
void printf_type2(uint8_t* d, int len, int inpos, int num_entries);
void printf_ramb16_data(uint8_t* bits, int inpos);
int is_empty(const uint8_t* d, int l);

View File

@ -293,6 +293,9 @@ int is_atx(int check, struct fpga_model* model, int x);
// boundary of the regular routing area.
#define YX_OUTSIDE_OF_ROUTING 0x0400
#define YX_ROUTING_BOUNDARY 0x0800
#define YX_X_CENTER_CMTPLL 0x1000
#define YX_Y_CENTER 0x2000
#define YX_CENTER 0x4000
int is_atyx(int check, struct fpga_model* model, int y, int x);
@ -307,6 +310,7 @@ int which_row(int y, struct fpga_model* model);
int pos_in_row(int y, struct fpga_model* model);
// regular_row_pos() returns the index (0..15) without hclk, or -1 if y is a hclk.
int regular_row_pos(int y, struct fpga_model* model);
int y_to_hclk(int y, struct fpga_model *model);
const char* logicin_s(int wire, int routing_io);

View File

@ -736,6 +736,13 @@ int is_atyx(int check, struct fpga_model* model, int y, int x)
&& is_atyx(YX_ROUTING_TILE, model, y, x)
&& (x == LEFT_IO_ROUTING || x == model->x_width-RIGHT_IO_ROUTING_O
|| y == TOP_FIRST_REGULAR || y == model->y_height-BOT_LAST_REGULAR_O)) return 1;
if (check & YX_X_CENTER_CMTPLL
&& is_atx(X_CENTER_CMTPLL_COL, model, x)) return 1;
if (check & YX_Y_CENTER
&& is_aty(Y_CHIP_HORIZ_REGS, model, y)) return 1;
if (check & YX_CENTER
&& is_atx(X_CENTER_REGS_COL, model, x)
&& is_aty(Y_CHIP_HORIZ_REGS, model, y)) return 1;
return 0;
}
@ -785,6 +792,22 @@ int regular_row_pos(int y, struct fpga_model* model)
return row_pos;
}
int y_to_hclk(int y, struct fpga_model *model)
{
int row_num, row_pos, hclk_pos;
is_in_row(model, y, &row_num, &row_pos);
if (row_num == -1
|| row_pos == -1 || row_pos == HCLK_POS)
{ HERE(); return -1; }
hclk_pos = model->y_height - BOT_LAST_REGULAR_O - row_num*ROW_SIZE - HCLK_POS;
if (hclk_pos < model->center_y)
hclk_pos--; // center regs
if (hclk_pos < TOP_FIRST_REGULAR)
{ HERE(); return -1; }
return hclk_pos;
}
const char* logicin_s(int wire, int routing_io)
{
if (routing_io && ((wire & LWF_WIRE_MASK) == X_A5 || (wire & LWF_WIRE_MASK) == X_B4))

View File

@ -389,7 +389,16 @@ const struct xc6_pkg_info *xc6_pkg_info(enum xc6_pkg pkg)
/* 16 */ "P131", "P132", "P133", "P134",
/* 20 */ "P14", "P15", "P16", "P17",
/* 24 */ "P21", "P22", "P23", "P24",
/* 28 */ 0, 0, "P50", "P51" }};
/* 28 */ 0, 0, "P50", "P51" },
.gclk_type2_o = {
/* 0 */ 20*4+ 6, 20*4+ 9, -1, -1,
/* 4 */ 190*4+18, 190*4+21, 190*4+12, 190*4+15,
/* 8 */ 190*4+ 6, 190*4+ 9, 190*4+ 0, 190*4+ 3,
/* 12 */ 136*4+18, 136*4+21, 136*4+12, 136*4+15,
/* 16 */ 136*4+ 6, 136*4+ 9, 136*4+ 0, 136*4+ 3,
/* 20 */ 78*4+21, 78*4+18, 78*4+15, 78*4+12,
/* 24 */ 78*4+ 9, 78*4+ 6, 78*4+ 3, 78*4+ 0,
/* 28 */ -1, -1, 20*4+12, 20*4+15 }};
switch (pkg) {
case TQG144: return &pkg_tqg144;
default: ;

View File

@ -105,6 +105,7 @@ struct xc6_pkg_info
// negative side of differential pairs: even numbers
// positive side of differential pairs: odd numbers
const char* gclk_pin[XC6_NUM_GCLK_PINS];
int gclk_type2_o[XC6_NUM_GCLK_PINS]; // in words
};
const struct xc6_pkg_info *xc6_pkg_info(enum xc6_pkg pkg);
@ -124,6 +125,9 @@ const struct xc6_pkg_info *xc6_pkg_info(enum xc6_pkg pkg);
#define IOB_ENTRY_LEN 8
#define BITS_LEN (IOB_DATA_START+IOB_DATA_LEN)
#define XC6_WORD_BYTES 2
#define XC6_WORD_BITS (XC6_WORD_BYTES*8)
#define XC6_HCLK_BYTES 2
#define XC6_HCLK_BITS (XC6_HCLK_BYTES*8)
@ -421,3 +425,5 @@ void xc6_lut_bitmap(int lut_pos, int (*map)[64], int num_bits);
#define XC6_ML_A_CY0_O5 62 // implies lut5 on ML-A
#define XC6_L_A_FFSRINIT_1 63 // L-device only
#define XC6_TYPE2_GCLK_REG_SW 2 // bit 2 in 1st word