more clock routing
This commit is contained in:
parent
b7b2f594a3
commit
a3f42ee998
30
autotest.c
30
autotest.c
|
@ -22,6 +22,7 @@ time_t g_start_time;
|
||||||
struct test_state
|
struct test_state
|
||||||
{
|
{
|
||||||
int cmdline_skip;
|
int cmdline_skip;
|
||||||
|
int cmdline_count;
|
||||||
char cmdline_diff_exec[1024];
|
char cmdline_diff_exec[1024];
|
||||||
int dry_run;
|
int dry_run;
|
||||||
int diff_to_null;
|
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++);
|
printf("O Skipping diff %i.\n", tstate->next_diff_counter++);
|
||||||
return 0;
|
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,
|
snprintf(path, sizeof(path), "%s/autotest_%s_%06i", tstate->tmp_dir,
|
||||||
tstate->base_name, tstate->next_diff_counter);
|
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,
|
swto.start_switch = fdev_logic_pinstr_i(tstate->model,
|
||||||
dev->pinw_req_for_cfg[0]|LD1, LOGIC_M);
|
dev->pinw_req_for_cfg[0]|LD1, LOGIC_M);
|
||||||
swto.from_to = SW_TO;
|
swto.from_to = SW_TO;
|
||||||
|
swto.flags = SWTO_REL_DEFAULT;
|
||||||
swto.rel_y = 0;
|
swto.rel_y = 0;
|
||||||
swto.rel_x = -1;
|
swto.rel_x = -1;
|
||||||
swto.target_connpt = STRIDX_NO_ENTRY;
|
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
|
|| (latch_logic
|
||||||
&& (dev->pinw_req_for_cfg[i] == LI_CLK
|
&& (dev->pinw_req_for_cfg[i] == LI_CLK
|
||||||
|| dev->pinw_req_for_cfg[i] == LI_CE))) {
|
|| 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);
|
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],
|
rc = fpga_find_iob(tstate->model, tstate->model->pkg->gclk_pin[i],
|
||||||
&iob_clk_y, &iob_clk_x, &iob_clk_type_idx);
|
&iob_clk_y, &iob_clk_x, &iob_clk_type_idx);
|
||||||
if (rc) FAIL(rc);
|
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,
|
rc = fdev_iob_input(tstate->model, iob_clk_y, iob_clk_x,
|
||||||
iob_clk_type_idx, IO_LVCMOS33);
|
iob_clk_type_idx, IO_LVCMOS33);
|
||||||
if (rc) FAIL(rc);
|
if (rc) FAIL(rc);
|
||||||
|
@ -1782,7 +1793,6 @@ static int test_clock_routing(struct test_state* tstate)
|
||||||
logic_type_idx);
|
logic_type_idx);
|
||||||
fdev_delete(tstate->model, iob_clk_y, iob_clk_x, DEV_IOB,
|
fdev_delete(tstate->model, iob_clk_y, iob_clk_x, DEV_IOB,
|
||||||
iob_clk_type_idx);
|
iob_clk_type_idx);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
|
@ -1796,8 +1806,8 @@ static void printf_help(const char* argv_0, const char** available_tests)
|
||||||
printf( "\n"
|
printf( "\n"
|
||||||
"fpgatools automatic test suite\n"
|
"fpgatools automatic test suite\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Usage: %s [--test=<name>] [--skip=<num>] [--dry-run]\n"
|
"Usage: %s [--test=<name>] [--skip=<num>] [--count=<num>]\n"
|
||||||
" %*s [--diff=<diff executable>]\n"
|
" %*s [--dry-run] [--diff=<diff executable>]\n"
|
||||||
"Default diff executable: " DEFAULT_DIFF_EXEC "\n"
|
"Default diff executable: " DEFAULT_DIFF_EXEC "\n"
|
||||||
"Output dir: " AUTOTEST_TMP_DIR "\n", argv_0, (int) strlen(argv_0), "");
|
"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 fpga_model model;
|
||||||
struct test_state tstate;
|
struct test_state tstate;
|
||||||
char param[1024], cmdline_test[1024];
|
char param[1024], cmdline_test[1024];
|
||||||
int i, param_skip, rc;
|
int i, param_skip, param_count, rc;
|
||||||
const char* available_tests[] =
|
const char* available_tests[] =
|
||||||
{ "logic_cfg", "routing_sw", "io_sw", "iob_cfg",
|
{ "logic_cfg", "routing_sw", "io_sw", "iob_cfg",
|
||||||
"lut_encoding", "bufg_cfg", "bufio_cfg", "pll_cfg",
|
"lut_encoding", "bufg_cfg", "bufio_cfg", "pll_cfg",
|
||||||
|
@ -1840,6 +1850,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
memset(&tstate, 0, sizeof(tstate));
|
memset(&tstate, 0, sizeof(tstate));
|
||||||
tstate.cmdline_skip = -1;
|
tstate.cmdline_skip = -1;
|
||||||
|
tstate.cmdline_count = -1;
|
||||||
tstate.cmdline_diff_exec[0] = 0;
|
tstate.cmdline_diff_exec[0] = 0;
|
||||||
cmdline_test[0] = 0;
|
cmdline_test[0] = 0;
|
||||||
tstate.dry_run = -1;
|
tstate.dry_run = -1;
|
||||||
|
@ -1871,6 +1882,14 @@ int main(int argc, char** argv)
|
||||||
tstate.cmdline_skip = param_skip;
|
tstate.cmdline_skip = param_skip;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (sscanf(argv[i], "--count=%i", ¶m_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")) {
|
if (!strcmp(argv[i], "--dry-run")) {
|
||||||
tstate.dry_run = 1;
|
tstate.dry_run = 1;
|
||||||
continue;
|
continue;
|
||||||
|
@ -1910,6 +1929,7 @@ int main(int argc, char** argv)
|
||||||
printf("O Test: %s\n", cmdline_test);
|
printf("O Test: %s\n", cmdline_test);
|
||||||
printf("O Diff: %s\n", tstate.cmdline_diff_exec);
|
printf("O Diff: %s\n", tstate.cmdline_diff_exec);
|
||||||
printf("O Skip: %i\n", tstate.cmdline_skip);
|
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("O Dry run: %i\n", tstate.dry_run);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("O Time measured in seconds from 0.\n");
|
printf("O Time measured in seconds from 0.\n");
|
||||||
|
|
|
@ -106,7 +106,7 @@ static int find_es_switch(struct extract_state* es, int y, int x, swidx_t sw)
|
||||||
return 0;
|
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;
|
int i, y, x, type_idx, part_idx, dev_idx, first_iob, rc;
|
||||||
struct fpga_device* dev;
|
struct fpga_device* dev;
|
||||||
|
@ -571,6 +571,79 @@ fail:
|
||||||
return rc;
|
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,
|
static int lut2str(uint64_t lut, int lut_pos, int lut5_used,
|
||||||
char *lut6_buf, char** lut6_p, char *lut5_buf, char** lut5_p)
|
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);
|
rc = extract_switches(&es);
|
||||||
if (rc) RC_FAIL(model, rc);
|
if (rc) RC_FAIL(model, rc);
|
||||||
rc = extract_iobs(&es);
|
rc = extract_type2(&es);
|
||||||
if (rc) RC_FAIL(model, rc);
|
if (rc) RC_FAIL(model, rc);
|
||||||
rc = extract_logic(&es);
|
rc = extract_logic(&es);
|
||||||
if (rc) RC_FAIL(model, rc);
|
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++)
|
for (i = 0; i < sizeof(s_default_bits)/sizeof(s_default_bits[0]); i++)
|
||||||
set_bitp(bits, &s_default_bits[i]);
|
set_bitp(bits, &s_default_bits[i]);
|
||||||
write_switches(bits, model);
|
write_switches(bits, model);
|
||||||
write_iobs(bits, model);
|
write_type2(bits, model);
|
||||||
write_logic(bits, model);
|
write_logic(bits, model);
|
||||||
|
|
||||||
RC_RETURN(model);
|
RC_RETURN(model);
|
||||||
|
|
354
libs/control.c
354
libs/control.c
|
@ -8,6 +8,10 @@
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
|
|
||||||
|
#undef DBG_ENUM_SWITCH
|
||||||
|
#undef DBG_SWITCH_TO_YX
|
||||||
|
#undef DBG_SWITCH_TO_REL
|
||||||
|
|
||||||
struct iob_site
|
struct iob_site
|
||||||
{
|
{
|
||||||
int xy;
|
int xy;
|
||||||
|
@ -1574,14 +1578,11 @@ const char* fmt_swset(struct fpga_model* model, int y, int x,
|
||||||
return buf[last_buf];
|
return buf[last_buf];
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef DBG_ENUM_SWITCH
|
|
||||||
|
|
||||||
int construct_sw_chain(struct sw_chain* chain, struct fpga_model* model,
|
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,
|
int y, int x, str16_t start_switch, int from_to, int max_depth,
|
||||||
swidx_t* block_list, int block_list_len)
|
swidx_t* block_list, int block_list_len)
|
||||||
{
|
{
|
||||||
int rc;
|
RC_CHECK(model);
|
||||||
|
|
||||||
#ifdef DBG_ENUM_SWITCH
|
#ifdef DBG_ENUM_SWITCH
|
||||||
printf("construct_sw_chain() %s (%s)\n",
|
printf("construct_sw_chain() %s (%s)\n",
|
||||||
strarray_lookup(&model->str, start_switch),
|
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(
|
chain->internal_block_list = malloc(
|
||||||
MAX_SWITCHBOX_SIZE * sizeof(*chain->block_list));
|
MAX_SWITCHBOX_SIZE * sizeof(*chain->block_list));
|
||||||
if (!chain->internal_block_list)
|
if (!chain->internal_block_list)
|
||||||
FAIL(ENOMEM);
|
RC_FAIL(model, ENOMEM);
|
||||||
chain->block_list = chain->internal_block_list;
|
chain->block_list = chain->internal_block_list;
|
||||||
chain->block_list_len = 0;
|
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->first_round = 1;
|
||||||
chain->set.len = 1;
|
chain->set.len = 1;
|
||||||
chain->set.sw[0] = FIRST_SW | start_switch;
|
chain->set.sw[0] = FIRST_SW | start_switch;
|
||||||
return 0;
|
RC_RETURN(model);
|
||||||
fail:
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void destruct_sw_chain(struct sw_chain* chain)
|
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));
|
memset(conns, 0, sizeof(*conns));
|
||||||
construct_sw_chain(&conns->chain, model, y, x, start_switch,
|
construct_sw_chain(&conns->chain, model, y, x, start_switch,
|
||||||
from_to, max_depth, /*block_list*/ 0, /*block_list_len*/ 0);
|
from_to, max_depth, /*block_list*/ 0, /*block_list_len*/ 0);
|
||||||
return 0;
|
RC_RETURN(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destruct_sw_conns(struct sw_conns* conns)
|
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_conns conns;
|
||||||
struct sw_set best_set;
|
struct sw_set best_set;
|
||||||
int best_y, best_x, best_distance, distance;
|
int best_y, best_x, best_distance, distance;
|
||||||
int best_num_dests, rc;
|
int best_num_dests;
|
||||||
str16_t best_connpt;
|
str16_t best_connpt;
|
||||||
|
|
||||||
RC_CHECK(p->model);
|
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->from_to, (p->flags & SWTO_YX_MAX_SWITCH_DEPTH)
|
||||||
? p->max_switch_depth : SW_SET_SIZE);
|
? p->max_switch_depth : SW_SET_SIZE);
|
||||||
if (rc) FAIL(rc);
|
RC_CHECK(p->model);
|
||||||
|
|
||||||
best_y = -1;
|
best_y = -1;
|
||||||
while (fpga_switch_conns(&conns) != NO_CONN) {
|
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
|
if (p->flags & SWTO_YX_TARGET_CONNPT
|
||||||
&& conns.dest_str_i != p->target_connpt)
|
&& conns.dest_str_i != p->target_connpt)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1950,7 +1963,6 @@ int fpga_switch_to_yx(struct switch_to_yx* p)
|
||||||
if (!p->flags & SWTO_YX_CLOSEST)
|
if (!p->flags & SWTO_YX_CLOSEST)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (best_y == -1)
|
if (best_y == -1)
|
||||||
p->set.len = 0;
|
p->set.len = 0;
|
||||||
else {
|
else {
|
||||||
|
@ -1960,9 +1972,7 @@ int fpga_switch_to_yx(struct switch_to_yx* p)
|
||||||
p->dest_connpt = best_connpt;
|
p->dest_connpt = best_connpt;
|
||||||
}
|
}
|
||||||
destruct_sw_conns(&conns);
|
destruct_sw_conns(&conns);
|
||||||
return 0;
|
RC_RETURN(p->model);
|
||||||
fail:
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void printf_switch_to_yx_result(struct switch_to_yx* p)
|
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));
|
fmt_swset(p->model, p->y, p->x, &p->set, p->from_to));
|
||||||
}
|
}
|
||||||
|
|
||||||
int fpga_switch_to_rel(struct switch_to_rel* p)
|
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;
|
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_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);
|
p->start_switch, p->from_to, SW_SET_SIZE);
|
||||||
if (rc) FAIL(rc);
|
RC_CHECK(p->model);
|
||||||
p->set.len = 0;
|
|
||||||
|
best_y = -1;
|
||||||
while (fpga_switch_conns(&conns) != NO_CONN) {
|
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
|
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;
|
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
|
if (p->target_connpt != STRIDX_NO_ENTRY
|
||||||
&& conns.dest_str_i != p->target_connpt)
|
&& conns.dest_str_i != p->target_connpt)
|
||||||
continue;
|
continue;
|
||||||
p->set = conns.chain.set;
|
best_set = conns.chain.set;
|
||||||
p->dest_y = conns.dest_y;
|
best_y = conns.dest_y;
|
||||||
p->dest_x = conns.dest_x;
|
best_x = conns.dest_x;
|
||||||
p->dest_connpt = conns.dest_str_i;
|
best_connpt = conns.dest_str_i;
|
||||||
break;
|
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);
|
destruct_sw_conns(&conns);
|
||||||
return 0;
|
RC_RETURN(p->model);
|
||||||
fail:
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void printf_switch_to_rel_result(struct switch_to_rel* p)
|
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)
|
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)
|
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
|
// todo: gnd and vcc nets are special and have no outpin
|
||||||
// but lots of inpins
|
// but can have multiple inpins
|
||||||
out_i = -1;
|
out_i = fnet_pinw(model, net_i, /*out*/ 1, 0);
|
||||||
in_i = -1;
|
in_i = fnet_pinw(model, net_i, /*out*/ 0, 0);
|
||||||
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?
|
|
||||||
if (out_i == -1 || in_i == -1)
|
if (out_i == -1 || in_i == -1)
|
||||||
RC_FAIL(model, EINVAL);
|
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 =
|
switch_to_rel.start_switch =
|
||||||
in_dev->pinw[net_p->el[in_i].idx & NET_IDX_MASK];
|
in_dev->pinw[net_p->el[in_i].idx & NET_IDX_MASK];
|
||||||
switch_to_rel.from_to = SW_TO;
|
switch_to_rel.from_to = SW_TO;
|
||||||
|
switch_to_rel.flags = SWTO_REL_DEFAULT;
|
||||||
switch_to_rel.rel_y = 0;
|
switch_to_rel.rel_y = 0;
|
||||||
switch_to_rel.rel_x = -1;
|
switch_to_rel.rel_x = -1;
|
||||||
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
|
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 =
|
switch_to_rel.start_switch =
|
||||||
out_dev->pinw[net_p->el[out_i].idx & NET_IDX_MASK];
|
out_dev->pinw[net_p->el[out_i].idx & NET_IDX_MASK];
|
||||||
switch_to_rel.from_to = SW_FROM;
|
switch_to_rel.from_to = SW_FROM;
|
||||||
|
switch_to_rel.flags = SWTO_REL_DEFAULT;
|
||||||
switch_to_rel.rel_y = 0;
|
switch_to_rel.rel_y = 0;
|
||||||
switch_to_rel.rel_x = -1;
|
switch_to_rel.rel_x = -1;
|
||||||
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
|
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,
|
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_net* net_p;
|
||||||
struct fpga_device* dev_p;
|
struct fpga_device* dev_p;
|
||||||
str16_t from_i;
|
|
||||||
struct sw_set start_set, end_set;
|
struct sw_set start_set, end_set;
|
||||||
int i, rc;
|
int i;
|
||||||
|
|
||||||
RC_CHECK(model);
|
RC_CHECK(model);
|
||||||
net_p = fnet_get(model, net_i);
|
net_p = fnet_get(model, net_i);
|
||||||
if (!net_p) FAIL(EINVAL);
|
RC_ASSERT(model, net_p);
|
||||||
from_i = strarray_find(&model->str, from);
|
|
||||||
if (from_i == STRIDX_NO_ENTRY) FAIL(EINVAL);
|
|
||||||
|
|
||||||
for (i = 0; i < net_p->len; i++) {
|
for (i = 0; i < net_p->len; i++) {
|
||||||
if (!(net_p->el[i].idx & NET_IDX_IS_PINW))
|
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
|
// skip outpin
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rc = froute_direct(model, net_p->el[i].y, net_p->el[i].x-1,
|
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,
|
from, net_p->el[i].y, net_p->el[i].x,
|
||||||
dev_p->pinw[net_p->el[i].idx & NET_IDX_MASK],
|
dev_p->pinw[net_p->el[i].idx & NET_IDX_MASK],
|
||||||
&start_set, &end_set);
|
&start_set, &end_set);
|
||||||
if (rc) FAIL(rc);
|
RC_CHECK(model);
|
||||||
if (!start_set.len || !end_set.len)
|
if (!start_set.len || !end_set.len)
|
||||||
HERE();
|
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);
|
net_p->el[i].x-1, start_set.sw, start_set.len);
|
||||||
if (rc) FAIL(rc);
|
fnet_add_sw(model, net_i, net_p->el[i].y,
|
||||||
rc = fnet_add_sw(model, net_i, net_p->el[i].y,
|
|
||||||
net_p->el[i].x, end_set.sw, end_set.len);
|
net_p->el[i].x, end_set.sw, end_set.len);
|
||||||
if (rc) FAIL(rc);
|
|
||||||
}
|
}
|
||||||
return 0;
|
RC_RETURN(model);
|
||||||
fail:
|
}
|
||||||
return rc;
|
|
||||||
|
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,
|
int froute_direct(struct fpga_model* model, int start_y, int start_x,
|
||||||
|
|
|
@ -268,6 +268,8 @@ void printf_swconns(struct fpga_model* model, int y, int x,
|
||||||
str16_t sw, int from_to, int max_depth);
|
str16_t sw, int from_to, int max_depth);
|
||||||
|
|
||||||
#define SWTO_YX_DEF 0
|
#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_CLOSEST 0x0001
|
||||||
#define SWTO_YX_TARGET_CONNPT 0x0002
|
#define SWTO_YX_TARGET_CONNPT 0x0002
|
||||||
#define SWTO_YX_MAX_SWITCH_DEPTH 0x0004
|
#define SWTO_YX_MAX_SWITCH_DEPTH 0x0004
|
||||||
|
@ -292,8 +294,28 @@ struct switch_to_yx
|
||||||
str16_t dest_connpt;
|
str16_t dest_connpt;
|
||||||
};
|
};
|
||||||
|
|
||||||
int fpga_switch_to_yx(struct switch_to_yx* p);
|
int fpga_switch_to_yx(struct switch_to_yx *p);
|
||||||
void printf_switch_to_yx_result(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
|
struct switch_to_rel
|
||||||
{
|
{
|
||||||
|
@ -303,6 +325,7 @@ struct switch_to_rel
|
||||||
int start_x;
|
int start_x;
|
||||||
str16_t start_switch;
|
str16_t start_switch;
|
||||||
int from_to;
|
int from_to;
|
||||||
|
int flags; // SWTO_REL-value
|
||||||
int rel_y;
|
int rel_y;
|
||||||
int rel_x;
|
int rel_x;
|
||||||
str16_t target_connpt; // can be STRIDX_NO_ENTRY
|
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_autoroute(struct fpga_model* model, net_idx_t net_i);
|
||||||
|
|
||||||
int fnet_route_to_inpins(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);
|
const char* from);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -355,20 +355,22 @@ int parse_boolexpr(const char *expr, uint64_t *lut)
|
||||||
return 0;
|
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;
|
uint64_t u64;
|
||||||
|
uint16_t u16;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
num_printed = 0;
|
|
||||||
for (i = 0; i < num_entries; i++) {
|
for (i = 0; i < num_entries; i++) {
|
||||||
u64 = frame_get_u64(&d[inpos+i*8]);
|
u64 = frame_get_u64(&d[inpos+i*8]);
|
||||||
if (u64) {
|
if (!u64) continue;
|
||||||
printf("type2 i%i 0x%016lX\n", i, u64);
|
printf("type2 8*%i 0x%016lX\n", i, u64);
|
||||||
num_printed++;
|
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)
|
void printf_ramb16_data(uint8_t *bits, int inpos)
|
||||||
|
|
|
@ -69,7 +69,7 @@ const char* bool_bits2str(uint64_t u64, int num_bits);
|
||||||
|
|
||||||
int parse_boolexpr(const char* expr, uint64_t* lut);
|
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);
|
void printf_ramb16_data(uint8_t* bits, int inpos);
|
||||||
|
|
||||||
int is_empty(const uint8_t* d, int l);
|
int is_empty(const uint8_t* d, int l);
|
||||||
|
|
|
@ -293,6 +293,9 @@ int is_atx(int check, struct fpga_model* model, int x);
|
||||||
// boundary of the regular routing area.
|
// boundary of the regular routing area.
|
||||||
#define YX_OUTSIDE_OF_ROUTING 0x0400
|
#define YX_OUTSIDE_OF_ROUTING 0x0400
|
||||||
#define YX_ROUTING_BOUNDARY 0x0800
|
#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);
|
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);
|
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.
|
// 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 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);
|
const char* logicin_s(int wire, int routing_io);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
&& is_atyx(YX_ROUTING_TILE, model, y, x)
|
||||||
&& (x == LEFT_IO_ROUTING || x == model->x_width-RIGHT_IO_ROUTING_O
|
&& (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;
|
|| 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,6 +792,22 @@ int regular_row_pos(int y, struct fpga_model* model)
|
||||||
return row_pos;
|
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)
|
const char* logicin_s(int wire, int routing_io)
|
||||||
{
|
{
|
||||||
if (routing_io && ((wire & LWF_WIRE_MASK) == X_A5 || (wire & LWF_WIRE_MASK) == X_B4))
|
if (routing_io && ((wire & LWF_WIRE_MASK) == X_A5 || (wire & LWF_WIRE_MASK) == X_B4))
|
||||||
|
|
11
libs/parts.c
11
libs/parts.c
|
@ -389,7 +389,16 @@ const struct xc6_pkg_info *xc6_pkg_info(enum xc6_pkg pkg)
|
||||||
/* 16 */ "P131", "P132", "P133", "P134",
|
/* 16 */ "P131", "P132", "P133", "P134",
|
||||||
/* 20 */ "P14", "P15", "P16", "P17",
|
/* 20 */ "P14", "P15", "P16", "P17",
|
||||||
/* 24 */ "P21", "P22", "P23", "P24",
|
/* 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) {
|
switch (pkg) {
|
||||||
case TQG144: return &pkg_tqg144;
|
case TQG144: return &pkg_tqg144;
|
||||||
default: ;
|
default: ;
|
||||||
|
|
|
@ -105,6 +105,7 @@ struct xc6_pkg_info
|
||||||
// negative side of differential pairs: even numbers
|
// negative side of differential pairs: even numbers
|
||||||
// positive side of differential pairs: odd numbers
|
// positive side of differential pairs: odd numbers
|
||||||
const char* gclk_pin[XC6_NUM_GCLK_PINS];
|
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);
|
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 IOB_ENTRY_LEN 8
|
||||||
#define BITS_LEN (IOB_DATA_START+IOB_DATA_LEN)
|
#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_BYTES 2
|
||||||
#define XC6_HCLK_BITS (XC6_HCLK_BYTES*8)
|
#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_ML_A_CY0_O5 62 // implies lut5 on ML-A
|
||||||
|
|
||||||
#define XC6_L_A_FFSRINIT_1 63 // L-device only
|
#define XC6_L_A_FFSRINIT_1 63 // L-device only
|
||||||
|
|
||||||
|
#define XC6_TYPE2_GCLK_REG_SW 2 // bit 2 in 1st word
|
||||||
|
|
Loading…
Reference in New Issue
Block a user