From 05fe89cb9d7144be7b597df64855226d121025dc Mon Sep 17 00:00:00 2001 From: Wolfgang Spraul Date: Thu, 30 Aug 2012 05:37:42 +0200 Subject: [PATCH] what a mess, this can only be the first step... --- autotest.c | 124 ++++++++++---- bit_regs.c | 2 +- control.c | 474 ++++++++++++++++++++++++++++++++++++++++------------- control.h | 82 ++++++--- model.h | 6 + 5 files changed, 517 insertions(+), 171 deletions(-) diff --git a/autotest.c b/autotest.c index 290f119..f57afd8 100644 --- a/autotest.c +++ b/autotest.c @@ -110,7 +110,8 @@ static void cut_sw_from_end(struct fpga_net* net, int cut_o) net->len = 2 + net->len-cut_o; } -static int test_net(struct test_state* tstate, net_idx_t net_i) +int test_net(struct test_state* tstate, net_idx_t net_i); +int test_net(struct test_state* tstate, net_idx_t net_i) { struct fpga_net* net; struct fpga_net copy_net; @@ -136,7 +137,8 @@ static int test_net(struct test_state* tstate, net_idx_t net_i) net->el[2].y, net->el[2].x, fpga_switch_str_i(tstate->model, net->el[2].y, net->el[2].x, - net->el[2].idx, SW_TO), SW_TO, 1); + net->el[2].idx, SW_TO), + SW_TO, 1, 0, 0); same_len = sizeof(same_sw)/sizeof(*same_sw); rc = fpga_switch_same_fromto(tstate->model, net->el[2].y, net->el[2].x, @@ -154,7 +156,8 @@ fail: return rc; } -static int test_net2(struct test_state* tstate, net_idx_t net_i) +int test_net2(struct test_state* tstate, net_idx_t net_i); +int test_net2(struct test_state* tstate, net_idx_t net_i) { struct fpga_net* net; struct fpga_net copy_net; @@ -174,7 +177,8 @@ static int test_net2(struct test_state* tstate, net_idx_t net_i) net->el[i-1].y, net->el[i-1].x, fpga_switch_str_i(tstate->model, net->el[i-1].y, net->el[i-1].x, - net->el[i-1].idx, SW_FROM), SW_FROM, 1); + net->el[i-1].idx, SW_FROM), + SW_FROM, 1, 0, 0); same_len = sizeof(same_sw)/sizeof(*same_sw); rc = fpga_switch_same_fromto(tstate->model, net->el[i-1].y, net->el[i-1].x, @@ -193,8 +197,38 @@ fail: return rc; } +// goal: configure logic devices in all supported variations +int test_logic_config(struct test_state* tstate); +int test_logic_config(struct test_state* tstate) +{ + int a_to_d[] = { A6_LUT, B6_LUT, C6_LUT, D6_LUT }; + int idx_enum[] = { DEV_LOGM, DEV_LOGX }; + int y, x, i, j, k, rc; + + y = 68; + x = 13; + + for (i = 0; i < sizeof(idx_enum)/sizeof(*idx_enum); i++) { + for (j = 0; j < sizeof(a_to_d)/sizeof(*a_to_d); j++) { + for (k = '1'; k <= '6'; k++) { + rc = fdev_logic_set_lut(tstate->model, y, x, + idx_enum[i], a_to_d[j], pf("A%c", k), ZTERM); + if (rc) FAIL(rc); + + rc = diff_printf(tstate); + if (rc) FAIL(rc); + + fdev_delete(tstate->model, y, x, DEV_LOGIC, idx_enum[i]); + } + } + } + return 0; +fail: + return rc; +} + static int test_device_fingers(struct test_state* tstate, int y, int x, - int type, int type_idx, int test_inpins, int test_outpins) + int type, int type_idx, swidx_t* block_list, int* block_list_len) { struct fpga_device* dev; struct switch_to_yx switch_to; @@ -209,11 +243,6 @@ static int test_device_fingers(struct test_state* tstate, int y, int x, dev = fdev_p(tstate->model, y, x, type, type_idx); if (!dev) FAIL(EINVAL); for (i = 0; i < dev->pinw_req_total; i++) { - - if ((i < dev->pinw_req_in && !test_inpins) - || (i >= dev->pinw_req_in && !test_outpins)) - continue; - from_to = (i < dev->pinw_req_in) ? SW_TO : SW_FROM; switch_to.yx_req = YX_ROUTING_TILE; switch_to.flags = SWTO_YX_DEF; @@ -226,12 +255,10 @@ static int test_device_fingers(struct test_state* tstate, int y, int x, if (rc) FAIL(rc); // printf_switch_to_result(&switch_to); - chain.model = tstate->model; - chain.y = switch_to.dest_y; - chain.x = switch_to.dest_x; - chain.start_switch = switch_to.dest_connpt; - chain.from_to = from_to; - chain.max_chain_size = 1; + rc = construct_sw_chain(&chain, tstate->model, switch_to.dest_y, + switch_to.dest_x, switch_to.dest_connpt, from_to, + /*max_depth*/ 1, block_list, *block_list_len); + if (rc) FAIL(rc); while (fpga_switch_chain(&chain) != NO_SWITCH) { rc = fpga_net_new(tstate->model, &net_idx); if (rc) FAIL(rc); @@ -251,28 +278,37 @@ static int test_device_fingers(struct test_state* tstate, int y, int x, if (rc) FAIL(rc); // fprintf_net(stdout, tstate->model, net_idx); +// printf("set %s\n", fmt_swset(tstate->model, switch_to.dest_y, switch_to.dest_x, &chain.set, from_to)); +#if 0 rc = diff_printf(tstate); if (rc) FAIL(rc); +#endif fpga_net_delete(tstate->model, net_idx); } + *block_list_len = chain.block_list_len; +// printf("block_list_len now %i\n", *block_list_len); + destruct_sw_chain(&chain); } return 0; fail: return rc; } -static int test_all_logic_configs(struct test_state* tstate) +// goal: use all switches in a routing switchbox +int test_logic_routing_switches(struct test_state* tstate); +int test_logic_routing_switches(struct test_state* tstate) { int a_to_d[] = { A6_LUT, B6_LUT, C6_LUT, D6_LUT }; int idx_enum[] = { DEV_LOGM, DEV_LOGX }; int y, x, i, j, k, rc; + swidx_t done_list[MAX_SWITCHBOX_SIZE]; + int done_list_len; -// todo: goal: configure valid logic with as many possible in and out -// pins, for M and X device y = 68; x = 13; + done_list_len = 0; for (i = 0; i < sizeof(idx_enum)/sizeof(*idx_enum); i++) { for (j = 0; j < sizeof(a_to_d)/sizeof(*a_to_d); j++) { for (k = '1'; k <= '6'; k++) { @@ -281,12 +317,17 @@ static int test_all_logic_configs(struct test_state* tstate) if (rc) FAIL(rc); rc = test_device_fingers(tstate, y, x, DEV_LOGIC, - idx_enum[i], /*in*/ 1, /*out*/ k=='1'); + idx_enum[i], done_list, &done_list_len); if (rc) FAIL(rc); fdev_delete(tstate->model, y, x, DEV_LOGIC, idx_enum[i]); } } } +#if 0 +for (i = 0; i < done_list_len; i++) { + printf("done %i %s\n", i, fpga_switch_print(tstate->model, 68, 12, done_list[i])); +} +#endif return 0; fail: return rc; @@ -330,18 +371,37 @@ int main(int argc, char** argv) rc = diff_start(&tstate, "and"); if (rc) FAIL(rc); - // test_logic_config - // test_logic_routing_switches +#if 0 + rc = test_logic_config(&tstate); + if (rc) FAIL(rc); +#endif + +#if 1 + rc = test_logic_routing_switches(&tstate); + if (rc) FAIL(rc); +#endif + // test_iob_config // test_iologic_routing_switches #if 0 - rc = test_all_logic_configs(&tstate); - if (rc) FAIL(rc); +// test_swchain: +// printf_swchain(&model, 69, 13, strarray_find(&model.str, "BIOI_INNER_IBUF0"), SW_FROM, SW_SET_SIZE); + { + swidx_t done_list[MAX_SWITCHBOX_SIZE]; + int done_list_len = 0; + printf_swchain(&model, 68, 12, strarray_find(&model.str, "LOGICIN_B29"), + SW_TO, SW_SET_SIZE, done_list, &done_list_len); +#if 0 + printf_swchain(&model, 68, 12, strarray_find(&model.str, "NR1E0"), + SW_FROM, SW_SET_SIZE, done_list, &done_list_len); + printf_swchain(&model, 68, 12, strarray_find(&model.str, "NN2E0"), + SW_FROM, SW_SET_SIZE, done_list, &done_list_len); + printf_swchain(&model, 68, 12, strarray_find(&model.str, "SE2E2"), + SW_FROM, SW_SET_SIZE, done_list, &done_list_len); +#endif + } #endif - - printf_swchain(&model, 69, 13, strarray_find(&model.str, "BIOI_INNER_IBUF0"), SW_FROM, MAX_SW_DEPTH); -// printf_swchain(&model, 68, 12, strarray_find(&model.str, "NR1E0"), SW_FROM, MAX_SW_DEPTH); #if 0 // configure P46 @@ -439,11 +499,14 @@ int main(int argc, char** argv) switch_to.from_to = SW_FROM; switch_to.max_switch_depth = 1; { + note: update to constructor struct sw_chain c = { .model = &model, .y = switch_to.dest_y, .x = switch_to.dest_x+1, .start_switch = logic_dev->pinw[LOGIC_IN_D3], - .from_to = SW_TO, .max_chain_size = MAX_SW_DEPTH }; + .from_to = SW_TO, + .max_depth = SW_SET_SIZE, + .block_list = 0 }; if (fpga_switch_chain(&c) == NO_CONN) FAIL(EINVAL); if (c.set.len == 0) { HERE(); FAIL(EINVAL); } switch_to.target_connpt = fpga_switch_str_i(&model, @@ -457,11 +520,14 @@ int main(int argc, char** argv) if (rc) FAIL(rc); { + note: update to constructor struct sw_chain c = { .model = &model, .y = switch_to.dest_y, .x = switch_to.dest_x, .start_switch = switch_to.dest_connpt, - .from_to = SW_FROM, .max_chain_size = MAX_SW_DEPTH }; + .from_to = SW_FROM, + .max_depth = SW_SET_SIZE, + .block_list = 0 }; if (fpga_switch_chain(&c) == NO_CONN) FAIL(EINVAL); if (c.set.len == 0) { HERE(); FAIL(EINVAL); } rc = fpga_net_add_switches(&model, P46_net, c.y, c.x, &c.set); diff --git a/bit_regs.c b/bit_regs.c index 77b5180..2d47832 100644 --- a/bit_regs.c +++ b/bit_regs.c @@ -734,7 +734,7 @@ static void printf_routing_2minors(uint8_t* bits, int row, int major, if (u64_1 & (1ULL << i)) bit_str[i*2+1] = '1'; } - printf("r%i ma%i v64_%i mip%i %s\n", + printf("r%i ma%i v64_%02i mip%02i %s\n", row, major, y, even_minor, bit_str); } } diff --git a/control.c b/control.c index 806f3a8..ac42005 100644 --- a/control.c +++ b/control.c @@ -564,9 +564,14 @@ static swidx_t fpga_switch_search(struct fpga_model* model, int y, int x, { struct fpga_tile* tile; int connpt_o, name_i, i; - + tile = YX_TILE(model, y, x); - connpt_o = SW_I(tile->switches[last], from_to); + if (last & FIRST_SW) { + connpt_o = fpga_connpt_find(model, y, x, last & ~FIRST_SW, + /*dests_o*/ 0, /*num_dests*/ 0); + if (connpt_o == NO_CONN) { HERE(); return NO_SWITCH; } + } else + connpt_o = SW_I(tile->switches[last], from_to); name_i = tile->conn_point_names[connpt_o*2+1]; for (i = search_beg; i < tile->num_switches; i++) { @@ -580,7 +585,8 @@ static swidx_t fpga_switch_search(struct fpga_model* model, int y, int x, swidx_t fpga_switch_next(struct fpga_model* model, int y, int x, swidx_t last, int from_to) { - return fpga_switch_search(model, y, x, last, last+1, from_to); + return fpga_switch_search(model, y, x, last, + (last & FIRST_SW) ? 0 : last+1, from_to); } swidx_t fpga_switch_backtofirst(struct fpga_model* model, int y, int x, @@ -589,6 +595,118 @@ swidx_t fpga_switch_backtofirst(struct fpga_model* model, int y, int x, return fpga_switch_search(model, y, x, last, /*search_beg*/ 0, from_to); } +int fpga_swset_fromto(struct fpga_model* model, int y, int x, + str16_t start_switch, int from_to, struct sw_set* set) +{ + swidx_t idx; + + set->len = 0; + idx = fpga_switch_first(model, y, x, start_switch, from_to); + while (idx != NO_SWITCH) { + set->sw[set->len++] = idx; + idx = fpga_switch_next(model, y, x, idx, from_to); + } + return 0; +} + +int fpga_swset_contains(struct fpga_model* model, int y, int x, + const struct sw_set* set, int from_to, str16_t connpt) +{ + struct fpga_tile* tile; + int i; + + tile = YX_TILE(model, y, x); + for (i = 0; i < set->len; i++) { + if (CONNPT_STR16(tile, SW_I(set->sw[i], from_to)) == connpt) + return i; + } + return -1; +} + +void fpga_swset_remove_connpt(struct fpga_model* model, int y, int x, + struct sw_set* set, int from_to, str16_t connpt) +{ + int i; + while ((i = fpga_swset_contains(model, y, x, set, + from_to, connpt)) != -1) { + if (set->len > i+1) + memmove(&set->sw[i], &set->sw[i+1], + (set->len-i-1)*sizeof(set->sw[0])); + set->len--; + } +} + +void fpga_swset_remove_loop(struct fpga_model* model, int y, int x, + struct sw_set* set, const struct sw_set* parents, int from_to) +{ + int i; + struct fpga_tile* tile; + + tile = YX_TILE(model, y, x); + for (i = 0; i < parents->len; i++) { + fpga_swset_remove_connpt(model, y, x, set, !from_to, + CONNPT_STR16(tile, SW_I(parents->sw[i], from_to))); + } +} + +void fpga_swset_remove_sw(struct fpga_model* model, int y, int x, + struct sw_set* set, swidx_t sw) +{ + int sw_from_connpt, sw_to_connpt, cur_from_connpt, cur_to_connpt, i; + + sw_from_connpt = SW_I(sw, SW_FROM); + sw_to_connpt = SW_I(sw, SW_TO); + + for (i = 0; i < set->len; i++) { + cur_from_connpt = SW_I(set->sw[i], SW_FROM); + cur_to_connpt = SW_I(set->sw[i], SW_TO); + if (cur_from_connpt == sw_from_connpt + && cur_to_connpt == sw_to_connpt) { + if ((sw & SWITCH_BIDIRECTIONAL) + != (set->sw[i] & SWITCH_BIDIRECTIONAL)) + HERE(); + if (set->len > i+1) + memmove(&set->sw[i], &set->sw[i+1], + (set->len-i-1)*sizeof(set->sw[0])); + set->len--; + return; + } + if (cur_from_connpt == sw_to_connpt + && cur_to_connpt == sw_from_connpt) + HERE(); + } +} + +int fpga_swset_level_down(struct fpga_model* model, int y, int x, + struct sw_set* set, int from_to) +{ + int i; + + i = 0; + while (i < set->len) { + set->sw[i] = fpga_switch_first(model, y, x,fpga_switch_str_i( + model, y, x, set->sw[i], !from_to), from_to); + if (set->sw[i] == NO_SWITCH) { + if (set->len > i+1) + memmove(&set->sw[i], &set->sw[i+1], + (set->len-i-1)*sizeof(set->sw[0])); + set->len--; + } else + i++; + } + return 0; +} + +void fpga_swset_print(struct fpga_model* model, int y, int x, + struct sw_set* set, int from_to) +{ + int i; + for (i = 0; i < set->len; i++) { + printf("swset %i %s\n", i, fpga_switch_print(model, + y, x, set->sw[i])); + } +} + int fpga_switch_same_fromto(struct fpga_model* model, int y, int x, swidx_t sw, int from_to, swidx_t* same_sw, int *same_len) { @@ -599,7 +717,7 @@ int fpga_switch_same_fromto(struct fpga_model* model, int y, int x, *same_len = 0; if (max_len < 1) FAIL(EINVAL); cur_sw = fpga_switch_search(model, y, x, sw, /*search_beg*/ 0, from_to); - // We should at least fine sw itself, if not something is wrong... + // We should at least find sw itself, if not something is wrong... if (cur_sw == NO_SWITCH) FAIL(EINVAL); same_sw[(*same_len)++] = cur_sw; @@ -796,150 +914,262 @@ const char* fmt_swset(struct fpga_model* model, int y, int x, return buf[last_buf]; } -int fpga_switch_chain(struct sw_chain* chain) +#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; + +#ifdef DBG_ENUM_SWITCH + printf("construct_sw_chain() %s (%s)\n", + strarray_lookup(&model->str, start_switch), + (from_to == SW_FROM) ? "SW_FROM" : "SW_TO"); +#endif + memset(chain, 0, sizeof(*chain)); + chain->model = model; + chain->y = y; + chain->x = x; + chain->from_to = from_to; + chain->max_depth = max_depth; + if (block_list) { + chain->block_list = block_list; + chain->block_list_len = block_list_len; + // internal_block_list is 0 from memset() + } else { + chain->internal_block_list = malloc( + MAX_SWITCHBOX_SIZE * sizeof(*chain->block_list)); + if (!chain->internal_block_list) + FAIL(ENOMEM); + chain->block_list = chain->internal_block_list; + chain->block_list_len = 0; + } + // at every level, the first round returns all members + // at that level, then the second round tries to go + // one level down for each member. This sorts the + // returned switches in a nice way. + chain->first_round = 1; + chain->set.len = 1; + chain->set.sw[0] = FIRST_SW | start_switch; + return 0; +fail: + return rc; +} + +void destruct_sw_chain(struct sw_chain* chain) +{ + free(chain->internal_block_list); + memset(chain, 0, sizeof(*chain)); +} + +// returns NO_SWITCH if sw is not found in list, otherwise +// the offset in list where it is found. +static int switch_list_contains(struct fpga_model* model, int y, int x, + swidx_t* list, int list_len, swidx_t sw) +{ + int sw_from_connpt, sw_to_connpt, cur_from_connpt, cur_to_connpt, i; + + sw_from_connpt = SW_I(sw, SW_FROM); + sw_to_connpt = SW_I(sw, SW_TO); + + for (i = 0; i < list_len; i++) { + cur_from_connpt = SW_I(list[i], SW_FROM); + cur_to_connpt = SW_I(list[i], SW_TO); + if (cur_from_connpt == sw_from_connpt + && cur_to_connpt == sw_to_connpt) { + if ((sw & SWITCH_BIDIRECTIONAL) + != (list[i] & SWITCH_BIDIRECTIONAL)) + HERE(); + return i; + } + if (cur_from_connpt == sw_to_connpt + && cur_to_connpt == sw_from_connpt) + HERE(); + } + return NO_SWITCH; +} + +int fpga_switch_chain(struct sw_chain* ch) { swidx_t idx; struct fpga_tile* tile; - int child_from_to, i; + int child_from_to, loop_detect, block_detect, i; - if (chain->start_switch != STRIDX_NO_ENTRY) { - idx = fpga_switch_first(chain->model, chain->y, chain->x, - chain->start_switch, chain->from_to); - chain->start_switch = STRIDX_NO_ENTRY; - if (idx == NO_SWITCH) { - HERE(); // unusual and is probably some internal error - chain->set.len = 0; - return NO_SWITCH; - } - chain->set.sw[0] = idx; - chain->set.len = 1; - - // at every level, the first round returns all members - // at that level, then the second round tries to go - // one level down for each member. This sorts the - // returned switches in a nice way. - chain->first_round = 1; - chain->prior_parents = 0; - chain->num_prior_parents = 0; - return 0; - } - if (!chain->set.len) { - HERE(); goto internal_error; - } - if (chain->first_round) { + if (!ch->set.len) + { HERE(); goto internal_error; } + if (ch->first_round) { // first go through all members at present level - idx = fpga_switch_next(chain->model, chain->y, chain->x, - chain->set.sw[chain->set.len-1], chain->from_to); - if (idx != NO_SWITCH) { - chain->set.sw[chain->set.len-1] = idx; - return 0; + while (1) { + idx = fpga_switch_next(ch->model, ch->y, ch->x, + ch->set.sw[ch->set.len-1], ch->from_to); + if (idx == NO_SWITCH) + break; + ch->set.sw[ch->set.len-1] = idx; + if (switch_list_contains(ch->model, ch->y, ch->x, + ch->block_list, ch->block_list_len, idx) + == NO_SWITCH) + return 0; } - // if there are no more, initiate the second round - // looking for children - chain->first_round = 0; - idx = fpga_switch_backtofirst(chain->model, chain->y, chain->x, - chain->set.sw[chain->set.len-1], chain->from_to); + // if there are no more, start child round + ch->first_round = 0; + idx = fpga_switch_backtofirst(ch->model, ch->y, ch->x, + ch->set.sw[ch->set.len-1], ch->from_to); if (idx == NO_SWITCH) { HERE(); goto internal_error; } - chain->set.sw[chain->set.len-1] = idx; +#ifdef DBG_ENUM_SWITCH + printf("back_to_first from %s to %s\n", + fpga_switch_print(ch->model, ch->y, ch->x, + ch->set.sw[ch->set.len-1]), + fpga_switch_print(ch->model, ch->y, ch->x, + idx)); +#endif + ch->set.sw[ch->set.len-1] = idx; } // look for children - tile = YX_TILE(chain->model, chain->y, chain->x); + tile = YX_TILE(ch->model, ch->y, ch->x); while (1) { - idx = fpga_switch_first(chain->model, chain->y, chain->x, - fpga_switch_str_i(chain->model, chain->y, chain->x, - chain->set.sw[chain->set.len-1], !chain->from_to), - chain->from_to); - child_from_to = SW_I(tile->switches[chain->set.sw[chain->set.len-1]], - !chain->from_to); + idx = fpga_switch_first(ch->model, ch->y, ch->x, + fpga_switch_str_i(ch->model, ch->y, ch->x, + ch->set.sw[ch->set.len-1], !ch->from_to), + ch->from_to); +#ifdef DBG_ENUM_SWITCH + printf("child_check %s result %s\n", fpga_switch_str( + ch->model, ch->y, ch->x, + ch->set.sw[ch->set.len-1], !ch->from_to), + idx == NO_SWITCH ? "NO_SWITCH" : fpga_switch_print( + ch->model, ch->y, ch->x, idx)); +#endif if (idx != NO_SWITCH) { // If we have the same from-switch already among the - // parents, don't fall into endless recursion... - for (i = 0; i < chain->set.len; i++) { - if (SW_I(tile->switches[chain->set.sw[i]], chain->from_to) - == child_from_to) + // parents, don't enter into a loop. + child_from_to = SW_I(tile->switches[ch->set.sw[ + ch->set.len-1]], !ch->from_to); +#ifdef DBG_ENUM_SWITCH + printf(" child_from_to %s\n", connpt_str( + ch->model, ch->y, ch->x, + child_from_to)); +#endif + loop_detect = 0; + for (i = 0; i < ch->set.len; i++) { + int parent_connpt = SW_I(tile->switches[ + ch->set.sw[i]], ch->from_to); +#ifdef DBG_ENUM_SWITCH + printf(" parent connpt %s%s\n", connpt_str( + ch->model, ch->y, ch->x, + parent_connpt), parent_connpt + == child_from_to ? " (match)" : ""); +#endif + if (parent_connpt == child_from_to) { + loop_detect = 1; break; - } - if (i >= chain->set.len) { - if (chain->set.len >= MAX_SW_DEPTH) { - HERE(); goto internal_error; } - if (chain->max_chain_size < 1 - || chain->set.len < chain->max_chain_size) { - // back to first round at new level - chain->first_round = 1; - chain->set.sw[chain->set.len] = idx; - chain->set.len++; + } + block_detect = switch_list_contains(ch->model, + ch->y, ch->x, ch->block_list, + ch->block_list_len, idx) != NO_SWITCH; + if (!loop_detect && !block_detect) { + if (ch->set.len >= SW_SET_SIZE) + { HERE(); goto internal_error; } + if (ch->max_depth < 1 + || ch->set.len < ch->max_depth) { + // back to first round at next level +#ifdef DBG_ENUM_SWITCH + printf(" level_down %s\n", + fpga_switch_print(ch->model, + ch->y, ch->x, idx)); +#endif + ch->first_round = 1; + ch->set.sw[ch->set.len] = idx; + ch->set.len++; return 0; } } } while (1) { - chain->set.sw[chain->set.len-1] = fpga_switch_next( - chain->model, chain->y, chain->x, - chain->set.sw[chain->set.len-1], chain->from_to); - if (chain->set.sw[chain->set.len-1] != NO_SWITCH) + // todo: don't know why we catch blocklist duplicates + // if ch->set.len > 1 - needs more debugging + if (switch_list_contains(ch->model, ch->y, ch->x, + ch->block_list, ch->block_list_len, + ch->set.sw[ch->set.len-1]) == NO_SWITCH) { +#ifdef DBG_ENUM_SWITCH + printf(" block_list_add %s\n", fpga_switch_print( + ch->model, ch->y, ch->x, + ch->set.sw[ch->set.len-1])); +#endif + if (ch->block_list_len >= MAX_SWITCHBOX_SIZE) + { HERE(); goto internal_error; } + ch->block_list[ch->block_list_len++] + = ch->set.sw[ch->set.len-1]; + } + + idx = fpga_switch_next(ch->model, ch->y, ch->x, + ch->set.sw[ch->set.len-1], ch->from_to); + if (idx != NO_SWITCH) { +#ifdef DBG_ENUM_SWITCH + printf(" found %s\n", fpga_switch_print( + ch->model, ch->y, ch->x, idx)); +#endif + ch->set.sw[ch->set.len-1] = idx; break; - if (chain->set.len <= 1) { - chain->set.len = 0; + } + + if (ch->set.len <= 1) { + ch->set.len = 0; return NO_SWITCH; } - chain->set.len--; +#ifdef DBG_ENUM_SWITCH + printf(" level_up\n"); +#endif + ch->set.len--; } } internal_error: - chain->set.len = 0; + ch->set.len = 0; return NO_SWITCH; } -int fpga_switch_chains(struct sw_chain* chain, int max_sets, - struct sw_set* sets, int* num_sets) +int construct_sw_conns(struct sw_conns* conns, struct fpga_model* model, + int y, int x, str16_t start_switch, int from_to, int max_depth) { - *num_sets = 0; - while (*num_sets < max_sets - && fpga_switch_chain(chain) != NO_CONN) { - sets[*num_sets] = chain->set; - } + 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; } +void destruct_sw_conns(struct sw_conns* conns) +{ + destruct_sw_chain(&conns->chain); + memset(conns, 0, sizeof(*conns)); +} + int fpga_switch_conns(struct sw_conns* conns) { str16_t end_of_chain_str; - if (conns->start_switch != STRIDX_NO_ENTRY) { - conns->chain.model = conns->model; - conns->chain.y = conns->y; - conns->chain.x = conns->x; - conns->chain.start_switch = conns->start_switch; - conns->chain.from_to = conns->from_to; - conns->chain.max_chain_size = conns->max_switch_depth; - - conns->start_switch = STRIDX_NO_ENTRY; - conns->num_dests = 0; - conns->dest_i = 0; - } - else if (!conns->chain.set.len) { HERE(); goto internal_error; } + if (!conns->chain.set.len) { HERE(); goto internal_error; } + // on the first call, both dest_i and num_dests are 0 while (conns->dest_i >= conns->num_dests) { fpga_switch_chain(&conns->chain); if (conns->chain.set.len == 0) return NO_CONN; - end_of_chain_str = fpga_switch_str_i(conns->model, - conns->y, conns->x, + end_of_chain_str = fpga_switch_str_i(conns->chain.model, + conns->chain.y, conns->chain.x, conns->chain.set.sw[conns->chain.set.len-1], - !conns->from_to); + !conns->chain.from_to); if (end_of_chain_str == STRIDX_NO_ENTRY) { HERE(); goto internal_error; } conns->dest_i = 0; - fpga_connpt_find(conns->model, conns->y, conns->x, - end_of_chain_str, &conns->connpt_dest_start, - &conns->num_dests); + fpga_connpt_find(conns->chain.model, conns->chain.y, + conns->chain.x, end_of_chain_str, + &conns->connpt_dest_start, &conns->num_dests); if (conns->num_dests) break; } - fpga_conn_dest(conns->model, conns->y, conns->x, + fpga_conn_dest(conns->chain.model, conns->chain.y, conns->chain.x, conns->connpt_dest_start + conns->dest_i, &conns->dest_y, &conns->dest_x, &conns->dest_str_i); if (conns->dest_str_i == STRIDX_NO_ENTRY) @@ -953,45 +1183,58 @@ internal_error: } void printf_swchain(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, swidx_t* block_list, + int* block_list_len) { - struct sw_chain chain = - { .model = model, .y = y, .x = x, .start_switch = sw, - .from_to = from_to, .max_chain_size = max_depth}; + struct sw_chain chain; + int count = 0; + + printf("printf_swchain() y%02i x%02i %s blist_len %i\n", + y, x, strarray_lookup(&model->str, sw), + block_list_len ? *block_list_len : 0); + if (construct_sw_chain(&chain, model, y, x, sw, from_to, max_depth, + block_list, block_list_len ? *block_list_len : 0)) + { HERE(); return; } while (fpga_switch_chain(&chain) != NO_CONN) { - printf("sw %s\n", fmt_swset(model, y, x, + printf("sw %i %s\n", count++, fmt_swset(model, y, x, &chain.set, from_to)); } + printf("sw - block_list_len %i\n", chain.block_list_len); + if (block_list_len) + *block_list_len = chain.block_list_len; + destruct_sw_chain(&chain); } void printf_swconns(struct fpga_model* model, int y, int x, str16_t sw, int from_to, int max_depth) { - struct sw_conns conns = - { .model = model, .y = y, .x = x, .start_switch = sw, - .from_to = from_to, .max_switch_depth = max_depth }; + struct sw_conns conns; + + if (construct_sw_conns(&conns, model, y, x, sw, from_to, max_depth)) + { HERE(); return; } while (fpga_switch_conns(&conns) != NO_CONN) { printf("sw %s conn y%02i x%02i %s\n", fmt_swset(model, y, x, &conns.chain.set, from_to), conns.dest_y, conns.dest_x, strarray_lookup(&model->str, conns.dest_str_i)); } + printf("sw -\n"); + destruct_sw_conns(&conns); } int fpga_switch_to_yx(struct switch_to_yx* p) { - struct sw_conns conns = { - .model = p->model, .y = p->y, .x = p->x, - .start_switch = p->start_switch, .from_to = p->from_to, - .max_switch_depth = - (p->flags & SWTO_YX_MAX_SWITCH_DEPTH) - ? p->max_switch_depth : MAX_SW_DEPTH }; - + struct sw_conns conns; struct sw_set best_set; int best_y, best_x, best_distance, distance; - int best_num_dests; + int best_num_dests, rc; str16_t best_connpt; + rc = 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); + best_y = -1; while (fpga_switch_conns(&conns) != NO_CONN) { if (is_atyx(p->yx_req, p->model, conns.dest_y, conns.dest_x)) { @@ -1027,7 +1270,10 @@ int fpga_switch_to_yx(struct switch_to_yx* p) p->dest_x = best_x; p->dest_connpt = best_connpt; } + destruct_sw_conns(&conns); return 0; +fail: + return rc; } void printf_switch_to_result(struct switch_to_yx* p) diff --git a/control.h b/control.h index a784836..02c9958 100644 --- a/control.h +++ b/control.h @@ -63,11 +63,15 @@ void fpga_conn_dest(struct fpga_model* model, int y, int x, // typedef int swidx_t; // swidx_t is an index into the uint32_t switches array -#define MAX_SW_DEPTH 64 // largest seen so far was 20 +// SW_SET_SIZE should be enough for both the largest number +// of switches that can go from or to one specific connection +// point (32), as well as the largest depth of a path inside +// a switchbox (ca. 20). +#define SW_SET_SIZE 64 struct sw_set { - swidx_t sw[MAX_SW_DEPTH]; + swidx_t sw[SW_SET_SIZE]; int len; }; @@ -78,6 +82,25 @@ swidx_t fpga_switch_next(struct fpga_model* model, int y, int x, swidx_t last, int from_to); swidx_t fpga_switch_backtofirst(struct fpga_model* model, int y, int x, swidx_t last, int from_to); + +int fpga_swset_fromto(struct fpga_model* model, int y, int x, + str16_t start_switch, int from_to, struct sw_set* set); +// returns -1 if not found, otherwise index into the set +int fpga_swset_contains(struct fpga_model* model, int y, int x, + const struct sw_set* set, int from_to, str16_t connpt); +void fpga_swset_remove_connpt(struct fpga_model* model, int y, int x, + struct sw_set* set, int from_to, str16_t connpt); +// removes all switches from set whose !from_to is equal to the +// from_to in parents +void fpga_swset_remove_loop(struct fpga_model* model, int y, int x, + struct sw_set* set, const struct sw_set* parents, int from_to); +void fpga_swset_remove_sw(struct fpga_model* model, int y, int x, + struct sw_set* set, swidx_t sw); +int fpga_swset_level_down(struct fpga_model* model, int y, int x, + struct sw_set* set, int from_to); +void fpga_swset_print(struct fpga_model* model, int y, int x, + struct sw_set* set, int from_to); + // When calling, same_len must contain the size of the // same_sw array. Upon return same_len returns how many // switches were found and writen to same_sw. @@ -106,9 +129,10 @@ void fpga_switch_disable(struct fpga_model* model, int y, int x, const char* fmt_swset(struct fpga_model* model, int y, int x, struct sw_set* set, int from_to); -// MAX_PRIOR_PARENTS should be larger than the largest known -// numer of switches in a tile, currently 3459 in a slx9 routing tile. -#define MAX_PRIOR_PARENTS 4000 +// MAX_SWITCHBOX_SIZE can be used to allocate the block +// list and should be larger than the largest known number +// of switches in a tile, currently 3459 in a slx9 routing tile. +#define MAX_SWITCHBOX_SIZE 4000 struct sw_chain { @@ -116,41 +140,40 @@ struct sw_chain struct fpga_model* model; int y; int x; - // start_switch will be set to STRIDX_NO_ENTRY (0) after the first call - str16_t start_switch; int from_to; - int max_chain_size; + int max_depth; + // + // block_list works as if all switches from or to the ones + // on the block list are blocked, that is the recursion will + // never step into a part of the tree that goes through a + // blocked from or to point. + // Every call to fpga_switch_chain(), even the last one that + // returns NO_SWITCH, may add switches to the block list. + // + swidx_t* block_list; + int block_list_len; - // return values: + // return value: set is carried forward through the + // enumeration and must only be read from. struct sw_set set; // internal: int first_round; - swidx_t* prior_parents; - int num_prior_parents; + swidx_t* internal_block_list; }; +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); +void destruct_sw_chain(struct sw_chain* chain); + // Returns 0 if another switchset is returned in chain, or // NO_SWITCH (-1) if there is no other switchset. -// chain_size set to 0 when there are no more switches in the tree +// set.len is 0 when there are no more switches in the tree int fpga_switch_chain(struct sw_chain* chain); -// returns error code or 0 for no errors -int fpga_switch_chains(struct sw_chain* chain, int max_sets, - struct sw_set* sets, int* num_sets); - struct sw_conns { - // start and recurring values: - struct fpga_model* model; - int y; - int x; - // start_switch will be set to STRIDX_NO_ENTRY (0) after first call - str16_t start_switch; - int from_to; - int max_switch_depth; - - // return values: struct sw_chain chain; int connpt_dest_start; int num_dests; @@ -160,12 +183,17 @@ struct sw_conns str16_t dest_str_i; }; +int construct_sw_conns(struct sw_conns* conns, struct fpga_model* model, + int y, int x, str16_t start_switch, int from_to, int max_depth); +void destruct_sw_conns(struct sw_conns* conns); + // Returns 0 if another connection is returned in conns, or // NO_CONN (-1) if there is no other connection. int fpga_switch_conns(struct sw_conns* conns); void printf_swchain(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, swidx_t* block_list, + int* block_list_len); void printf_swconns(struct fpga_model* model, int y, int x, str16_t sw, int from_to, int max_depth); diff --git a/model.h b/model.h index 2e2a8bd..ea65419 100644 --- a/model.h +++ b/model.h @@ -481,8 +481,14 @@ struct fpga_device #define SW_TO 0 #define NO_SWITCH -1 +// FIRST_SW must be high enough to be above switch indices or +// connpt or str16. +#define FIRST_SW 0x80000 #define NO_CONN -1 +typedef int connpt_t; // index into conn_point_names (not yet *2) +#define CONNPT_STR16(tile, connpt) ((tile)->conn_point_names[(connpt)*2+1]) + struct fpga_tile { enum fpga_tile_type type;