a few more short north and south wires, autotester
This commit is contained in:
parent
988180051c
commit
0fa0e7f3c3
4
README
4
README
|
@ -19,7 +19,7 @@ Libraries
|
|||
|
||||
- libfpga-test autotest suite
|
||||
- libfpga-cores reusable cores
|
||||
- libfpga-design larger design elements on top of libfpga-control
|
||||
- libfpga-stdlib standard design elements on top of libfpga-control
|
||||
- libfpga-control programmatic access to libfpga-model
|
||||
- libfpga-model memory-only representation of an FPGA
|
||||
- libfpga-floorplan reads and writes .fp floorplan files
|
||||
|
@ -63,7 +63,7 @@ TODO (as of 2012-08, expected time to delivery: months to years
|
|||
* configuration of bram and macc blocks, bram initialization data
|
||||
* routing switches
|
||||
* many more cases in model of switches and inter-tile connections
|
||||
* write standard design elements for libfpga-design library
|
||||
* write standard design elements for libfpga-stdlib library
|
||||
* support lm32 or openrisc core, either via libfpga or iverilog backend
|
||||
* ipv6 or vnc in hardware?
|
||||
* iverilog fpga backend
|
||||
|
|
277
autotest.c
277
autotest.c
|
@ -201,8 +201,7 @@ static int test_logic_net(struct test_state* tstate, int logic_y, int logic_x,
|
|||
|
||||
// add port
|
||||
rc = fpga_net_add_port(tstate->model, net_idx, logic_y, logic_x,
|
||||
fpga_dev_idx(tstate->model, logic_y, logic_x, DEV_LOGIC,
|
||||
type_idx), port);
|
||||
DEV_LOGIC, type_idx, port);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// add (one) switch in logic tile
|
||||
|
@ -277,7 +276,7 @@ static int test_logic_net_l2(struct test_state* tstate, int y, int x,
|
|||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
if (dbg)
|
||||
printf_switch_to_result(&switch_to);
|
||||
printf_switch_to_yx_result(&switch_to);
|
||||
|
||||
switch_tile = YX_TILE(tstate->model, switch_to.dest_y, switch_to.dest_x);
|
||||
rc = fpga_swset_fromto(tstate->model, switch_to.dest_y,
|
||||
|
@ -379,7 +378,7 @@ static int test_logic_net_l1(struct test_state* tstate, int y, int x,
|
|||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
if (tstate->dry_run)
|
||||
printf_switch_to_result(&switch_to);
|
||||
printf_switch_to_yx_result(&switch_to);
|
||||
|
||||
rc = fpga_swset_fromto(tstate->model, switch_to.dest_y,
|
||||
switch_to.dest_x, switch_to.dest_connpt, from_to, &set_l1);
|
||||
|
@ -414,8 +413,259 @@ fail:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int test_switches(struct test_state* tstate, int y, int x,
|
||||
str16_t start_switch, net_idx_t net, swidx_t* done_list, int* done_list_len)
|
||||
{
|
||||
struct sw_set sw_set, w4_set;
|
||||
const char* switch_str;
|
||||
str16_t switch_str_i;
|
||||
int i, j, k, rc;
|
||||
|
||||
rc = fpga_swset_fromto(tstate->model, y, x, start_switch, SW_TO, &sw_set);
|
||||
if (rc) FAIL(rc);
|
||||
if (tstate->dry_run)
|
||||
fpga_swset_print(tstate->model, y, x, &sw_set, SW_TO);
|
||||
|
||||
for (i = 0; i < sw_set.len; i++) {
|
||||
switch_str_i = fpga_switch_str_i(tstate->model, y, x,
|
||||
sw_set.sw[i], SW_FROM);
|
||||
switch_str = strarray_lookup(&tstate->model->str, switch_str_i);
|
||||
if (!switch_str) FAIL(EINVAL);
|
||||
if (switch_str[2] == '4') {
|
||||
// base for len-4 wire
|
||||
if (tstate->dry_run)
|
||||
fprintf_net(stdout, tstate->model, net);
|
||||
rc = diff_printf(tstate);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// add len-4 wire
|
||||
rc = fpga_net_add_sw(tstate->model, net, y, x,
|
||||
&sw_set.sw[i], 1);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// enum dests of len-4 wire
|
||||
rc = fpga_swset_fromto(tstate->model, y, x,
|
||||
switch_str_i, SW_FROM, &w4_set);
|
||||
if (rc) FAIL(rc);
|
||||
if (tstate->dry_run)
|
||||
fpga_swset_print(tstate->model, y, x,
|
||||
&w4_set, SW_FROM);
|
||||
|
||||
for (j = 0; j < w4_set.len; j++) {
|
||||
// do not point to our base twice
|
||||
if (w4_set.sw[j] == sw_set.sw[i])
|
||||
continue;
|
||||
|
||||
// duplicate check and done_list
|
||||
for (k = 0; k < *done_list_len; k++) {
|
||||
if (done_list[k] == w4_set.sw[j])
|
||||
break;
|
||||
}
|
||||
if (k < *done_list_len)
|
||||
continue;
|
||||
done_list[(*done_list_len)++] = w4_set.sw[j];
|
||||
if (tstate->dry_run)
|
||||
printf("done_list %s at %i\n",
|
||||
fpga_switch_print(tstate->model,
|
||||
y, x, done_list[(*done_list_len)-1]),
|
||||
(*done_list_len)-1);
|
||||
|
||||
// base for len-4 target
|
||||
if (tstate->dry_run)
|
||||
fprintf_net(stdout, tstate->model, net);
|
||||
rc = diff_printf(tstate);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// add len-4 target
|
||||
rc = fpga_net_add_sw(tstate->model, net, y, x,
|
||||
&w4_set.sw[j], 1);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
if (tstate->dry_run)
|
||||
fprintf_net(stdout, tstate->model, net);
|
||||
rc = diff_printf(tstate);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
rc = fpga_net_remove_sw(tstate->model, net, y, x,
|
||||
&w4_set.sw[j], 1);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
rc = fpga_net_remove_sw(tstate->model, net, y, x,
|
||||
&sw_set.sw[i], 1);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int test_routing_sw_from_south(struct test_state* tstate,
|
||||
swidx_t* done_list, int* done_list_len)
|
||||
{
|
||||
struct switch_to_yx switch_to;
|
||||
int iob_y, iob_x, iob_type_idx, rc;
|
||||
struct fpga_device* iob_dev;
|
||||
net_idx_t net;
|
||||
|
||||
rc = fpga_find_iob(tstate->model, "P48", &iob_y, &iob_x, &iob_type_idx);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx);
|
||||
if (rc) FAIL(rc);
|
||||
iob_dev = fdev_p(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
|
||||
if (!iob_dev) FAIL(EINVAL);
|
||||
|
||||
rc = fpga_net_new(tstate->model, &net);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fpga_net_add_port(tstate->model, net, iob_y, iob_x,
|
||||
DEV_IOB, iob_type_idx, IOB_IN_O);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
switch_to.yx_req = YX_DEV_OLOGIC;
|
||||
switch_to.flags = SWTO_YX_DEF;
|
||||
switch_to.model = tstate->model;
|
||||
switch_to.y = iob_y;
|
||||
switch_to.x = iob_x;
|
||||
switch_to.start_switch = iob_dev->pinw[IOB_IN_O];
|
||||
switch_to.from_to = SW_TO;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
if (tstate->dry_run)
|
||||
printf_switch_to_yx_result(&switch_to);
|
||||
rc = fpga_net_add_sw(tstate->model, net, switch_to.y,
|
||||
switch_to.x, switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
switch_to.yx_req = YX_ROUTING_TILE;
|
||||
switch_to.flags = SWTO_YX_DEF;
|
||||
switch_to.model = tstate->model;
|
||||
switch_to.y = switch_to.dest_y;
|
||||
switch_to.x = switch_to.dest_x;
|
||||
switch_to.start_switch = switch_to.dest_connpt;
|
||||
switch_to.from_to = SW_TO;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fpga_net_add_sw(tstate->model, net, switch_to.y,
|
||||
switch_to.x, switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
if (tstate->dry_run)
|
||||
printf_switch_to_yx_result(&switch_to);
|
||||
|
||||
switch_to.yx_req = YX_ROUTING_TO_FABLOGIC;
|
||||
switch_to.flags = SWTO_YX_CLOSEST;
|
||||
switch_to.model = tstate->model;
|
||||
switch_to.y = switch_to.dest_y;
|
||||
switch_to.x = switch_to.dest_x;
|
||||
switch_to.start_switch = switch_to.dest_connpt;
|
||||
switch_to.from_to = SW_TO;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
if (tstate->dry_run)
|
||||
printf_switch_to_yx_result(&switch_to);
|
||||
rc = fpga_net_add_sw(tstate->model, net, switch_to.y,
|
||||
switch_to.x, switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
rc = test_switches(tstate, switch_to.dest_y, switch_to.dest_x,
|
||||
switch_to.dest_connpt, net, done_list, done_list_len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
fdev_delete(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
|
||||
fpga_net_delete(tstate->model, net);
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int test_routing_sw_from_north(struct test_state* tstate,
|
||||
swidx_t* done_list, int* done_list_len)
|
||||
{
|
||||
struct fpga_device* dev;
|
||||
struct switch_to_rel swto;
|
||||
struct sw_conns conns;
|
||||
const char* str;
|
||||
net_idx_t net;
|
||||
int y, x, i, rc;
|
||||
|
||||
y = 67;
|
||||
x = 13;
|
||||
for (i = '1'; i <= '6'; i++) {
|
||||
rc = fdev_logic_set_lut(tstate->model, y, x,
|
||||
DEV_LOGM, LUT_A, 6, pf("A%c", i), ZTERM);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fdev_set_required_pins(tstate->model, y, x,
|
||||
DEV_LOGIC, DEV_LOGM);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
if (tstate->dry_run)
|
||||
fdev_print_required_pins(tstate->model,
|
||||
y, x, DEV_LOGIC, DEV_LOGM);
|
||||
dev = fdev_p(tstate->model, y, x, DEV_LOGIC, DEV_LOGM);
|
||||
if (!dev) FAIL(EINVAL);
|
||||
if (!dev->pinw_req_in) FAIL(EINVAL);
|
||||
|
||||
rc = fpga_net_new(tstate->model, &net);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fpga_net_add_port(tstate->model, net, y, x,
|
||||
DEV_LOGIC, DEV_LOGM, dev->pinw_req_for_cfg[0]);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
swto.model = tstate->model;
|
||||
swto.start_y = y;
|
||||
swto.start_x = x;
|
||||
swto.start_switch = fdev_logic_pinstr_i(tstate->model,
|
||||
dev->pinw_req_for_cfg[0]|LD1, LOGIC_M);
|
||||
swto.from_to = SW_TO;
|
||||
swto.rel_y = 0;
|
||||
swto.rel_x = -1;
|
||||
swto.target_connpt = STRIDX_NO_ENTRY;
|
||||
rc = fpga_switch_to_rel(&swto);
|
||||
if (rc) FAIL(rc);
|
||||
if (!swto.set.len) FAIL(EINVAL);
|
||||
if (tstate->dry_run)
|
||||
printf_switch_to_rel_result(&swto);
|
||||
rc = fpga_net_add_sw(tstate->model, net, swto.start_y,
|
||||
swto.start_x, swto.set.sw, swto.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
rc = construct_sw_conns(&conns, tstate->model, swto.dest_y, swto.dest_x,
|
||||
swto.dest_connpt, SW_TO, /*max_depth*/ 1);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
while (fpga_switch_conns(&conns) != NO_CONN) {
|
||||
if (conns.dest_x != swto.dest_x
|
||||
|| conns.dest_y != swto.dest_y+1)
|
||||
continue;
|
||||
str = strarray_lookup(&tstate->model->str, conns.dest_str_i);
|
||||
if (!str) { HERE(); continue; }
|
||||
if (strlen(str) < 5
|
||||
|| str[2] != '1' || str[3] != 'B')
|
||||
continue;
|
||||
rc = fpga_net_add_sw(tstate->model, net, swto.dest_y,
|
||||
swto.dest_x, conns.chain.set.sw, conns.chain.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
if (tstate->dry_run)
|
||||
fprintf_net(stdout, tstate->model, net);
|
||||
|
||||
rc = test_switches(tstate, conns.dest_y, conns.dest_x,
|
||||
conns.dest_str_i, net, done_list, done_list_len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
rc = fpga_net_remove_sw(tstate->model, net, swto.dest_y,
|
||||
swto.dest_x, conns.chain.set.sw, conns.chain.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
destruct_sw_conns(&conns);
|
||||
fdev_delete(tstate->model, y, x, DEV_LOGIC, DEV_LOGM);
|
||||
fpga_net_delete(tstate->model, net);
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
// goal: use all switches in a routing switchbox
|
||||
static int test_logic_switches(struct test_state* tstate)
|
||||
static int test_routing_switches(struct test_state* tstate)
|
||||
{
|
||||
int idx_enum[] = { DEV_LOGM, DEV_LOGX };
|
||||
int y, x, i, j, k, r, rc;
|
||||
|
@ -426,7 +676,6 @@ static int test_logic_switches(struct test_state* tstate)
|
|||
|
||||
y = 68;
|
||||
x = 13;
|
||||
|
||||
done_sw_len = 0;
|
||||
for (r = 0; r <= 1; r++) {
|
||||
// two rounds:
|
||||
|
@ -494,6 +743,11 @@ static int test_logic_switches(struct test_state* tstate)
|
|||
}
|
||||
}
|
||||
}
|
||||
done_sw_len = 0;
|
||||
rc = test_routing_sw_from_south(tstate, done_sw_list, &done_sw_len);
|
||||
if (rc) FAIL(rc);
|
||||
rc = test_routing_sw_from_north(tstate, done_sw_list, &done_sw_len);
|
||||
if (rc) FAIL(rc);
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
|
@ -528,7 +782,7 @@ static int test_iologic_switches2(struct test_state* tstate, int iob_y, int iob_
|
|||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
if (tstate->dry_run)
|
||||
printf_switch_to_result(&switch_to);
|
||||
printf_switch_to_yx_result(&switch_to);
|
||||
|
||||
if (construct_sw_chain(&chain, tstate->model, switch_to.dest_y,
|
||||
switch_to.dest_x, switch_to.dest_connpt, from_to,
|
||||
|
@ -547,8 +801,7 @@ static int test_iologic_switches2(struct test_state* tstate, int iob_y, int iob_
|
|||
|
||||
// add iob port
|
||||
rc = fpga_net_add_port(tstate->model, net_idx, iob_y, iob_x,
|
||||
fpga_dev_idx(tstate->model, iob_y, iob_x, DEV_IOB,
|
||||
iob_type_idx), IOB_IN_O);
|
||||
DEV_IOB, iob_type_idx, IOB_IN_O);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// add switch in iob tile
|
||||
|
@ -643,7 +896,7 @@ int main(int argc, char** argv)
|
|||
char param[1024], cmdline_test[1024];
|
||||
int i, param_skip, rc;
|
||||
const char* available_tests[] =
|
||||
{ "logic_cfg", "logic_sw", "io_sw", 0 };
|
||||
{ "logic_cfg", "routing_sw", "io_sw", 0 };
|
||||
|
||||
// flush after every line is better for the autotest
|
||||
// output, tee, etc.
|
||||
|
@ -755,8 +1008,8 @@ int main(int argc, char** argv)
|
|||
rc = test_logic_config(&tstate);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
if (!strcmp(cmdline_test, "logic_sw")) {
|
||||
rc = test_logic_switches(&tstate);
|
||||
if (!strcmp(cmdline_test, "routing_sw")) {
|
||||
rc = test_routing_switches(&tstate);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
if (!strcmp(cmdline_test, "io_sw")) {
|
||||
|
|
135
control.c
135
control.c
|
@ -334,6 +334,54 @@ const char* fdev_logic_pinstr(pinw_idx_t idx, int ld1_type)
|
|||
return buf[last_buf];
|
||||
}
|
||||
|
||||
str16_t fdev_logic_pinstr_i(struct fpga_model* model, pinw_idx_t idx, int ld1_type)
|
||||
{
|
||||
int str_i;
|
||||
|
||||
str_i = strarray_find(&model->str, fdev_logic_pinstr(idx, ld1_type));
|
||||
if (OUT_OF_U16(str_i))
|
||||
{ HERE(); return STRIDX_NO_ENTRY; }
|
||||
return str_i;
|
||||
}
|
||||
|
||||
int fdev_logic_inbit(pinw_idx_t idx, int ld1_type)
|
||||
{
|
||||
if (idx & LD1) {
|
||||
idx &= ~LD1;
|
||||
if (idx >= LI_A1 && idx <= LI_C6)
|
||||
return M_A1 + (idx/6)*8+idx%6;
|
||||
if (idx >= LI_D1 && idx <= LI_D6)
|
||||
return M_D1 + (idx-LI_D1);
|
||||
switch (idx) {
|
||||
case LI_AX: return M_AX;
|
||||
case LI_BX: return M_BX;
|
||||
case LI_CE: return M_CE;
|
||||
case LI_CX: return M_CX;
|
||||
case LI_DX: return M_DX;
|
||||
case LI_AI: return M_AI;
|
||||
case LI_BI: return M_BI;
|
||||
case LI_CI: return M_CI;
|
||||
case LI_DI: return M_DI;
|
||||
case LI_WE: return M_WE;
|
||||
}
|
||||
HERE();
|
||||
return -1;
|
||||
}
|
||||
if (idx >= LI_A1 && idx <= LI_C6)
|
||||
return X_A1 + (idx/6)*7+idx%6;
|
||||
else if (idx >= LI_D1 && idx <= LI_D6)
|
||||
return X_D1 + (idx-LI_D1);
|
||||
else switch (idx) {
|
||||
case LI_AX: return X_AX;
|
||||
case LI_BX: return X_BX;
|
||||
case LI_CE: return X_CE;
|
||||
case LI_CX: return X_CX;
|
||||
case LI_DX: return X_DX;
|
||||
}
|
||||
HERE();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int reset_required_pins(struct fpga_device* dev)
|
||||
{
|
||||
int rc;
|
||||
|
@ -1453,7 +1501,7 @@ fail:
|
|||
return rc;
|
||||
}
|
||||
|
||||
void printf_switch_to_result(struct switch_to_yx* p)
|
||||
void printf_switch_to_yx_result(struct switch_to_yx* p)
|
||||
{
|
||||
printf("switch_to_yx() from y%02i x%02i connpt %s (%s)\n",
|
||||
p->y, p->x, strarray_lookup(&p->model->str, p->start_switch),
|
||||
|
@ -1465,6 +1513,46 @@ void printf_switch_to_result(struct switch_to_yx* p)
|
|||
fmt_swset(p->model, p->y, p->x, &p->set, p->from_to));
|
||||
}
|
||||
|
||||
int fpga_switch_to_rel(struct switch_to_rel* p)
|
||||
{
|
||||
struct sw_conns conns;
|
||||
int rc;
|
||||
|
||||
rc = 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;
|
||||
while (fpga_switch_conns(&conns) != NO_CONN) {
|
||||
if (conns.dest_y != p->start_y + p->rel_y
|
||||
|| 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;
|
||||
break;
|
||||
}
|
||||
destruct_sw_conns(&conns);
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
void printf_switch_to_rel_result(struct switch_to_rel* p)
|
||||
{
|
||||
printf("switch_to_rel() from y%02i x%02i connpt %s (%s)\n",
|
||||
p->start_y, p->start_x, strarray_lookup(&p->model->str, p->start_switch),
|
||||
p->from_to == SW_FROM ? "SW_FROM" : "SW_TO");
|
||||
printf(" %s y%02i x%02i %s via %s\n",
|
||||
p->from_to == SW_FROM ? "to" : "from",
|
||||
p->dest_y, p->dest_x,
|
||||
strarray_lookup(&p->model->str, p->dest_connpt),
|
||||
fmt_swset(p->model, p->start_y, p->start_x, &p->set, p->from_to));
|
||||
}
|
||||
|
||||
#define NET_ALLOC_INCREMENT 64
|
||||
|
||||
static int fpga_net_useidx(struct fpga_model* model, net_idx_t new_idx)
|
||||
|
@ -1551,7 +1639,8 @@ struct fpga_net* fpga_net_get(struct fpga_model* model, net_idx_t net_i)
|
|||
}
|
||||
|
||||
int fpga_net_add_port(struct fpga_model* model, net_idx_t net_i,
|
||||
int y, int x, dev_idx_t dev_idx, pinw_idx_t pinw_idx)
|
||||
int y, int x, enum fpgadev_type type, dev_type_idx_t type_idx,
|
||||
pinw_idx_t pinw_idx)
|
||||
{
|
||||
struct fpga_net* net;
|
||||
int rc;
|
||||
|
@ -1565,7 +1654,8 @@ int fpga_net_add_port(struct fpga_model* model, net_idx_t net_i,
|
|||
net->el[net->len].y = y;
|
||||
net->el[net->len].x = x;
|
||||
net->el[net->len].idx = pinw_idx | NET_IDX_IS_PINW;
|
||||
net->el[net->len].dev_idx = dev_idx;
|
||||
net->el[net->len].dev_idx = fpga_dev_idx(model, y, x, type, type_idx);
|
||||
if (net->el[net->len].dev_idx == NO_DEV) FAIL(EINVAL);
|
||||
net->len++;
|
||||
return 0;
|
||||
fail:
|
||||
|
@ -1599,6 +1689,45 @@ fail:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int fpga_net_remove_sw(struct fpga_model* model, net_idx_t net_i,
|
||||
int y, int x, const swidx_t* switches, int num_sw)
|
||||
{
|
||||
struct fpga_net* net;
|
||||
int i, j, rc;
|
||||
|
||||
if (net_i > model->highest_used_net)
|
||||
FAIL(EINVAL);
|
||||
net = &model->nets[net_i-1];
|
||||
if (!net->len) {
|
||||
HERE();
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < num_sw; i++) {
|
||||
for (j = 0; j < net->len; j++) {
|
||||
if (net->el[j].y == y
|
||||
&& net->el[j].x == x
|
||||
&& net->el[j].idx == switches[i])
|
||||
break;
|
||||
}
|
||||
if (j >= net->len) {
|
||||
// for now we expect the 'to-be-removed'
|
||||
// switches to be in the net
|
||||
HERE();
|
||||
continue;
|
||||
}
|
||||
if (!fpga_switch_is_used(model, y, x, switches[i]))
|
||||
HERE();
|
||||
fpga_switch_disable(model, y, x, switches[i]);
|
||||
if (net->len > j+1)
|
||||
memmove(&net->el[j], &net->el[j+1],
|
||||
(net->len-j-1)*sizeof(net->el[0]));
|
||||
net->len--;
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
void fpga_net_free_all(struct fpga_model* model)
|
||||
{
|
||||
free(model->nets);
|
||||
|
|
35
control.h
35
control.h
|
@ -38,9 +38,13 @@ dev_type_idx_t fdev_typeidx(struct fpga_model* model, int y, int x,
|
|||
pinw_idx_t fdev_pinw_str2idx(int devtype, const char* str, int len);
|
||||
// returns 0 when idx not found for the given devtype
|
||||
const char* fdev_pinw_idx2str(int devtype, pinw_idx_t idx);
|
||||
|
||||
// ld1_type can be LOGIC_M or LOGIC_L to specify whether
|
||||
// we are in a XM or XL column.
|
||||
// we are in a XM or XL column. You can |LD1 to idx for
|
||||
// the second logic device (L or M).
|
||||
const char* fdev_logic_pinstr(pinw_idx_t idx, int ld1_type);
|
||||
str16_t fdev_logic_pinstr_i(struct fpga_model* model, pinw_idx_t idx, int ld1_type);
|
||||
int fdev_logic_inbit(pinw_idx_t idx, int ld1_type);
|
||||
|
||||
// lut_a2d is LUT_A to LUT_D value, lut_5or6 is int 5 or int 6.
|
||||
int fdev_logic_set_lut(struct fpga_model* model, int y, int x, int type_idx,
|
||||
|
@ -247,7 +251,30 @@ struct switch_to_yx
|
|||
};
|
||||
|
||||
int fpga_switch_to_yx(struct switch_to_yx* p);
|
||||
void printf_switch_to_result(struct switch_to_yx* p);
|
||||
void printf_switch_to_yx_result(struct switch_to_yx* p);
|
||||
|
||||
struct switch_to_rel
|
||||
{
|
||||
// input:
|
||||
struct fpga_model* model;
|
||||
int start_y;
|
||||
int start_x;
|
||||
str16_t start_switch;
|
||||
int from_to;
|
||||
int rel_y;
|
||||
int rel_x;
|
||||
str16_t target_connpt; // can be STRIDX_NO_ENTRY
|
||||
|
||||
// output:
|
||||
struct sw_set set;
|
||||
int dest_y;
|
||||
int dest_x;
|
||||
str16_t dest_connpt;
|
||||
};
|
||||
|
||||
// if no switches are found, the returned set.len will be 0.
|
||||
int fpga_switch_to_rel(struct switch_to_rel* p);
|
||||
void printf_switch_to_rel_result(struct switch_to_rel* p);
|
||||
|
||||
//
|
||||
// nets
|
||||
|
@ -289,9 +316,11 @@ void fpga_net_delete(struct fpga_model* model, net_idx_t net_idx);
|
|||
int fpga_net_enum(struct fpga_model* model, net_idx_t last, net_idx_t* next);
|
||||
struct fpga_net* fpga_net_get(struct fpga_model* model, net_idx_t net_i);
|
||||
int fpga_net_add_port(struct fpga_model* model, net_idx_t net_i,
|
||||
int y, int x, dev_idx_t dev_idx, pinw_idx_t pinw_idx);
|
||||
int y, int x, enum fpgadev_type type, dev_type_idx_t type_idx, pinw_idx_t pinw_idx);
|
||||
int fpga_net_add_sw(struct fpga_model* model, net_idx_t net_i,
|
||||
int y, int x, const swidx_t* switches, int num_sw);
|
||||
int fpga_net_remove_sw(struct fpga_model* model, net_idx_t net_i,
|
||||
int y, int x, const swidx_t* switches, int num_sw);
|
||||
void fpga_net_free_all(struct fpga_model* model);
|
||||
|
||||
void fprintf_net(FILE* f, struct fpga_model* model, net_idx_t net_i);
|
||||
|
|
|
@ -775,7 +775,6 @@ static void read_net_line(struct fpga_model* model, const char* line, int start)
|
|||
enum fpgadev_type dev_type;
|
||||
char buf[1024];
|
||||
net_idx_t net_idx;
|
||||
dev_idx_t dev_idx;
|
||||
pinw_idx_t pinw_idx;
|
||||
int sw_is_bidir;
|
||||
|
||||
|
@ -872,14 +871,12 @@ static void read_net_line(struct fpga_model* model, const char* line, int start)
|
|||
{ HERE(); return; }
|
||||
dev_type = fdev_str2type(&line[dev_str_beg], dev_str_end-dev_str_beg);
|
||||
if (dev_type == DEV_NONE) { HERE(); return; }
|
||||
dev_idx = fpga_dev_idx(model, y_coord, x_coord, dev_type,
|
||||
to_i(&line[dev_type_idx_str_beg],
|
||||
dev_type_idx_str_end-dev_type_idx_str_beg));
|
||||
if (dev_idx == NO_DEV) { HERE(); return; }
|
||||
pinw_idx = fdev_pinw_str2idx(dev_type, &line[pin_name_beg],
|
||||
pin_name_end-pin_name_beg);
|
||||
if (pinw_idx == PINW_NO_IDX) { HERE(); return; }
|
||||
if (fpga_net_add_port(model, net_idx, y_coord, x_coord, dev_idx, pinw_idx))
|
||||
if (fpga_net_add_port(model, net_idx, y_coord, x_coord, dev_type,
|
||||
to_i(&line[dev_type_idx_str_beg], dev_type_idx_str_end
|
||||
-dev_type_idx_str_beg), pinw_idx))
|
||||
HERE();
|
||||
}
|
||||
|
||||
|
|
419
model_conns.c
419
model_conns.c
|
@ -1767,153 +1767,210 @@ static int run_direction_wires(struct fpga_model* model)
|
|||
int x, y, i, j, _row_num, _row_pos, rc;
|
||||
struct w_net net;
|
||||
|
||||
// SS4
|
||||
// todo: EL1, ER1, WR1, WL1
|
||||
|
||||
// SR1
|
||||
for (x = 0; x < model->x_width; x++) {
|
||||
if (!is_atx(X_ROUTING_COL, model, x))
|
||||
continue;
|
||||
// some wiring at the top
|
||||
net.last_inc = 3;
|
||||
for (i = 1; i < 5; i++) { // go through "BAMCE"
|
||||
net.pts[0].start_count = 0;
|
||||
net.pts[0].y = TOP_TERM(model);
|
||||
net.pts[0].x = x;
|
||||
net.pts[0].name = pf("SS4%c%%i", s_4wire[i]);
|
||||
for (j = i; j < 5; j++) {
|
||||
net.pts[j-i+1].start_count = 0;
|
||||
net.pts[j-i+1].y = TOP_TERM(model)+(j-i+1);
|
||||
net.pts[j-i+1].x = x;
|
||||
net.pts[j-i+1].name = pf("SS4%c%%i", s_4wire[j]);
|
||||
}
|
||||
net.pts[j-i+1].name = "";
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &net))) goto xout;
|
||||
if ((rc = wire_SS4E_N3(model, &net))) goto xout;
|
||||
}
|
||||
// rest going down to bottom termination
|
||||
for (y = 0; y < model->y_height; y++) {
|
||||
is_in_row(model, y, &_row_num, &_row_pos);
|
||||
if (is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)
|
||||
&& y > BOT_TERM(model)-5)
|
||||
break;
|
||||
if (_row_pos < 0 || _row_pos == 8)
|
||||
for (y = TOP_OUTER_IO; y <= model->y_height-BOT_OUTER_IO; y++) {
|
||||
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, model, y))
|
||||
continue;
|
||||
|
||||
net.last_inc = 3;
|
||||
j = 0;
|
||||
for (i = 0; i < 5; i++) { // go through "BAMCE"
|
||||
net.pts[j].start_count = 0;
|
||||
net.pts[j].y = y+j;
|
||||
net.pts[j].x = x;
|
||||
if (y+j == BOT_TERM(model)) {
|
||||
EXIT(!i);
|
||||
net.pts[j].name = pf("SS4%c%%i", s_4wire[i-1]);
|
||||
j++;
|
||||
break;
|
||||
if (is_aty(Y_INNER_BOTTOM, model, y+1)) {
|
||||
if (!is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "SR1B%i", 0, y, x },
|
||||
{ "SR1B%i", 0, y+1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if ((rc = add_conn_bi_pref(model, y, x, "SR1E_N3", y+1, x, "SR1E_N3"))) goto xout;
|
||||
}
|
||||
if (IS_CENTER_Y(y+j, model)
|
||||
|| pos_in_row(y+j, model) == HCLK_POS) {
|
||||
EXIT(!i);
|
||||
net.pts[j].name = pf("SS4%c%%i", s_4wire[i-1]);
|
||||
j++;
|
||||
net.pts[j].start_count = 0;
|
||||
net.pts[j].y = y+j;
|
||||
net.pts[j].x = x;
|
||||
}
|
||||
net.pts[j].name = pf("SS4%c%%i", s_4wire[i]);
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, model, y+1)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "SR1B%i", 0, y, x },
|
||||
{ "SR1B%i", 0, y+1, x },
|
||||
{ "SR1E%i", 0, y+2, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
{ struct w_net n = {
|
||||
0,
|
||||
{{ "SR1E_N3", 0, y, x },
|
||||
{ "SR1E_N3", 0, y+1, x },
|
||||
{ "SR1E3", 0, y+2, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if ((rc = add_conn_bi_pref(model, y+1, x, "SR1E_N3", y, x, "SR1B3"))) goto xout;
|
||||
if ((rc = add_conn_bi_pref(model, y+1, x, "SR1B3", y, x, "SR1E_N3"))) goto xout;
|
||||
continue;
|
||||
}
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "SR1B%i", 0, y, x },
|
||||
{ "SR1E%i", 0, y+1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if ((rc = add_conn_bi_pref(model, y+1, x, "SR1E3", y, x, "SR1E_N3"))) goto xout;
|
||||
if (is_aty(Y_INNER_TOP, model, y-1)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "SR1E%i", 0, y-1, x },
|
||||
{ "SR1E%i", 0, y, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if ((rc = add_conn_bi_pref(model, y, x, "SR1E3", y-1, x, "SR1E_N3"))) goto xout;
|
||||
}
|
||||
net.pts[j].name = "";
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &net))) goto xout;
|
||||
if ((rc = wire_SS4E_N3(model, &net))) goto xout;
|
||||
}
|
||||
}
|
||||
|
||||
// NN4
|
||||
// NL1
|
||||
for (x = 0; x < model->x_width; x++) {
|
||||
if (!is_atx(X_ROUTING_COL, model, x))
|
||||
continue;
|
||||
for (y = 0; y < model->y_height; y++) {
|
||||
is_in_row(model, y, &_row_num, &_row_pos);
|
||||
if (_row_pos >= 0 && _row_pos != 8) {
|
||||
net.last_inc = 3;
|
||||
j = 0;
|
||||
for (i = 0; i < 5; i++) { // go through "BAMCE"
|
||||
net.pts[j].start_count = 0;
|
||||
net.pts[j].y = y-j;
|
||||
net.pts[j].x = x;
|
||||
if (y-j == TOP_INNER_ROW) {
|
||||
EXIT(!i);
|
||||
net.pts[j].name = pf("NN4%c%%i", s_4wire[i-1]);
|
||||
j++;
|
||||
break;
|
||||
}
|
||||
net.pts[j].name = pf("NN4%c%%i", s_4wire[i]);
|
||||
if (IS_CENTER_Y(y-j, model)
|
||||
|| pos_in_row(y-j, model) == HCLK_POS) {
|
||||
EXIT(!i);
|
||||
i--;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
net.pts[j].name = "";
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &net))) goto xout;
|
||||
for (y = TOP_OUTER_IO; y <= model->y_height-BOT_OUTER_IO; y++) {
|
||||
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, model, y))
|
||||
continue;
|
||||
if (is_aty(Y_INNER_TOP, model, y-1)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NL1B%i", 0, y-1, x },
|
||||
{ "NL1B%i", 0, y, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if ((rc = add_conn_bi_pref(model, y, x, "NL1E_S0", y-1, x, "NL1E_S0"))) goto xout;
|
||||
continue;
|
||||
}
|
||||
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, model, y-1)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NL1E%i", 0, y-2, x },
|
||||
{ "NL1E%i", 0, y-1, x },
|
||||
{ "NL1B%i", 0, y, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
{ struct w_net n = {
|
||||
0,
|
||||
{{ "NL1E0", 0, y-2, x },
|
||||
{ "NL1E_S0", 0, y-1, x },
|
||||
{ "NL1E_S0", 0, y, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if ((rc = add_conn_bi_pref(model, y-1, x, "NL1E_S0", y, x, "NL1B0"))) goto xout;
|
||||
if ((rc = add_conn_bi_pref(model, y-1, x, "NL1E0", y, x, "NL1E_S0"))) goto xout;
|
||||
continue;
|
||||
}
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NL1E%i", 0, y-1, x },
|
||||
{ "NL1B%i", 0, y, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if ((rc = add_conn_bi_pref(model, y-1, x, "NL1E0", y, x, "NL1E_S0"))) goto xout;
|
||||
if (is_aty(Y_INNER_BOTTOM, model, y+1) && !is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NL1E%i", 0, y, x },
|
||||
{ "NL1E%i", 0, y+1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if ((rc = add_conn_bi_pref(model, y, x, "NL1E0", y+1, x, "NL1E_S0"))) goto xout;
|
||||
}
|
||||
}
|
||||
if (!is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)) {
|
||||
net.last_inc = 3;
|
||||
for (i = 1; i < 5; i++) { // go through "BAMCE"
|
||||
net.pts[0].start_count = 0;
|
||||
net.pts[0].y = BOT_TERM(model);
|
||||
net.pts[0].x = x;
|
||||
net.pts[0].name = pf("NN4%c%%i", s_4wire[i]);
|
||||
for (j = i; j < 5; j++) {
|
||||
net.pts[j-i+1].start_count = 0;
|
||||
net.pts[j-i+1].y = BOT_TERM(model)-(j-i+1);
|
||||
net.pts[j-i+1].x = x;
|
||||
net.pts[j-i+1].name = pf("NN4%c%%i", s_4wire[j]);
|
||||
}
|
||||
|
||||
// SL1
|
||||
for (x = 0; x < model->x_width; x++) {
|
||||
if (!is_atx(X_ROUTING_COL, model, x))
|
||||
continue;
|
||||
for (y = TOP_OUTER_IO; y <= model->y_height-BOT_OUTER_IO; y++) {
|
||||
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, model, y))
|
||||
continue;
|
||||
if (is_aty(Y_INNER_BOTTOM, model, y+1)) {
|
||||
if (!is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "SL1B%i", 0, y, x },
|
||||
{ "SL1B%i", 0, y+1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
}
|
||||
net.pts[j-i+1].name = "";
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &net))) goto xout;
|
||||
continue;
|
||||
}
|
||||
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, model, y+1)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "SL1B%i", 0, y, x },
|
||||
{ "SL1B%i", 0, y+1, x },
|
||||
{ "SL1E%i", 0, y+2, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
continue;
|
||||
}
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "SL1B%i", 0, y, x },
|
||||
{ "SL1E%i", 0, y+1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if (is_aty(Y_INNER_TOP, model, y-1)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "SL1E%i", 0, y-1, x },
|
||||
{ "SL1E%i", 0, y, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NR1
|
||||
for (x = 0; x < model->x_width; x++) {
|
||||
if (!is_atx(X_ROUTING_COL, model, x))
|
||||
continue;
|
||||
for (y = TOP_OUTER_IO; y <= model->y_height-BOT_OUTER_IO; y++) {
|
||||
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, model, y))
|
||||
continue;
|
||||
if (is_aty(Y_INNER_TOP, model, y-1)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NR1B%i", 0, y, x },
|
||||
{ "NR1B%i", 0, y-1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
continue;
|
||||
}
|
||||
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, model, y-1)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NR1B%i", 0, y, x },
|
||||
{ "NR1E%i", 0, y-1, x },
|
||||
{ "NR1E%i", 0, y-2, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
continue;
|
||||
}
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NR1B%i", 0, y, x },
|
||||
{ "NR1E%i", 0, y-1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if (is_aty(Y_INNER_BOTTOM, model, y+1) && !is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NR1E%i", 0, y, x },
|
||||
{ "NR1E%i", 0, y+1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < model->y_height; y++) {
|
||||
for (x = 0; x < model->x_width; x++) {
|
||||
// NR1
|
||||
if (is_atyx(YX_ROUTING_TILE, model, y, x)) {
|
||||
if (is_aty(Y_INNER_TOP, model, y-1)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NR1B%i", 0, y, x },
|
||||
{ "NR1B%i", 0, y-1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
} else if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS, model, y-1)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NR1B%i", 0, y, x },
|
||||
{ "NR1E%i", 0, y-1, x },
|
||||
{ "NR1E%i", 0, y-2, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
} else {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NR1B%i", 0, y, x },
|
||||
{ "NR1E%i", 0, y-1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
if (is_aty(Y_INNER_BOTTOM, model, y+1) && !is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)) {
|
||||
{ struct w_net n = {
|
||||
3,
|
||||
{{ "NR1E%i", 0, y, x },
|
||||
{ "NR1E%i", 0, y+1, x },
|
||||
{ "" }}};
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &n))) goto xout; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NN2
|
||||
if (is_atyx(YX_ROUTING_TILE, model, y, x)) {
|
||||
if (is_aty(Y_INNER_TOP, model, y-1)) {
|
||||
|
@ -2067,6 +2124,116 @@ static int run_direction_wires(struct fpga_model* model)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SS4
|
||||
for (x = 0; x < model->x_width; x++) {
|
||||
if (!is_atx(X_ROUTING_COL, model, x))
|
||||
continue;
|
||||
// some wiring at the top
|
||||
net.last_inc = 3;
|
||||
for (i = 1; i < 5; i++) { // go through "BAMCE"
|
||||
net.pts[0].start_count = 0;
|
||||
net.pts[0].y = TOP_TERM(model);
|
||||
net.pts[0].x = x;
|
||||
net.pts[0].name = pf("SS4%c%%i", s_4wire[i]);
|
||||
for (j = i; j < 5; j++) {
|
||||
net.pts[j-i+1].start_count = 0;
|
||||
net.pts[j-i+1].y = TOP_TERM(model)+(j-i+1);
|
||||
net.pts[j-i+1].x = x;
|
||||
net.pts[j-i+1].name = pf("SS4%c%%i", s_4wire[j]);
|
||||
}
|
||||
net.pts[j-i+1].name = "";
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &net))) goto xout;
|
||||
if ((rc = wire_SS4E_N3(model, &net))) goto xout;
|
||||
}
|
||||
// rest going down to bottom termination
|
||||
for (y = 0; y < model->y_height; y++) {
|
||||
is_in_row(model, y, &_row_num, &_row_pos);
|
||||
if (is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)
|
||||
&& y > BOT_TERM(model)-5)
|
||||
break;
|
||||
if (_row_pos < 0 || _row_pos == 8)
|
||||
continue;
|
||||
|
||||
net.last_inc = 3;
|
||||
j = 0;
|
||||
for (i = 0; i < 5; i++) { // go through "BAMCE"
|
||||
net.pts[j].start_count = 0;
|
||||
net.pts[j].y = y+j;
|
||||
net.pts[j].x = x;
|
||||
if (y+j == BOT_TERM(model)) {
|
||||
EXIT(!i);
|
||||
net.pts[j].name = pf("SS4%c%%i", s_4wire[i-1]);
|
||||
j++;
|
||||
break;
|
||||
}
|
||||
if (IS_CENTER_Y(y+j, model)
|
||||
|| pos_in_row(y+j, model) == HCLK_POS) {
|
||||
EXIT(!i);
|
||||
net.pts[j].name = pf("SS4%c%%i", s_4wire[i-1]);
|
||||
j++;
|
||||
net.pts[j].start_count = 0;
|
||||
net.pts[j].y = y+j;
|
||||
net.pts[j].x = x;
|
||||
}
|
||||
net.pts[j].name = pf("SS4%c%%i", s_4wire[i]);
|
||||
j++;
|
||||
}
|
||||
net.pts[j].name = "";
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &net))) goto xout;
|
||||
if ((rc = wire_SS4E_N3(model, &net))) goto xout;
|
||||
}
|
||||
}
|
||||
|
||||
// NN4
|
||||
for (x = 0; x < model->x_width; x++) {
|
||||
if (!is_atx(X_ROUTING_COL, model, x))
|
||||
continue;
|
||||
for (y = 0; y < model->y_height; y++) {
|
||||
is_in_row(model, y, &_row_num, &_row_pos);
|
||||
if (_row_pos >= 0 && _row_pos != 8) {
|
||||
net.last_inc = 3;
|
||||
j = 0;
|
||||
for (i = 0; i < 5; i++) { // go through "BAMCE"
|
||||
net.pts[j].start_count = 0;
|
||||
net.pts[j].y = y-j;
|
||||
net.pts[j].x = x;
|
||||
if (y-j == TOP_INNER_ROW) {
|
||||
EXIT(!i);
|
||||
net.pts[j].name = pf("NN4%c%%i", s_4wire[i-1]);
|
||||
j++;
|
||||
break;
|
||||
}
|
||||
net.pts[j].name = pf("NN4%c%%i", s_4wire[i]);
|
||||
if (IS_CENTER_Y(y-j, model)
|
||||
|| pos_in_row(y-j, model) == HCLK_POS) {
|
||||
EXIT(!i);
|
||||
i--;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
net.pts[j].name = "";
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &net))) goto xout;
|
||||
}
|
||||
}
|
||||
if (!is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)) {
|
||||
net.last_inc = 3;
|
||||
for (i = 1; i < 5; i++) { // go through "BAMCE"
|
||||
net.pts[0].start_count = 0;
|
||||
net.pts[0].y = BOT_TERM(model);
|
||||
net.pts[0].x = x;
|
||||
net.pts[0].name = pf("NN4%c%%i", s_4wire[i]);
|
||||
for (j = i; j < 5; j++) {
|
||||
net.pts[j-i+1].start_count = 0;
|
||||
net.pts[j-i+1].y = BOT_TERM(model)-(j-i+1);
|
||||
net.pts[j-i+1].x = x;
|
||||
net.pts[j-i+1].name = pf("NN4%c%%i", s_4wire[j]);
|
||||
}
|
||||
net.pts[j-i+1].name = "";
|
||||
if ((rc = add_conn_net(model, PREF_BI_F, &net))) goto xout;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
xout:
|
||||
return rc;
|
||||
|
|
Loading…
Reference in New Issue
Block a user