diff --git a/blinking_led.c b/blinking_led.c index 8ce28d8..3890949 100644 --- a/blinking_led.c +++ b/blinking_led.c @@ -117,43 +117,68 @@ int main(int argc, char** argv) fnet_new(&model, &net); fnet_add_port(&model, net, 55, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_A6); fnet_add_port(&model, net, 55, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_B6); - fnet_add_port(&model, net, 55, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_C6); - fnet_add_port(&model, net, 55, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_D6); fnet_vcc_gnd(&model, net, /*is_vcc*/ 1); + fnet_new(&model, &net); fnet_add_port(&model, net, 56, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_A6); fnet_add_port(&model, net, 56, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_B6); fnet_add_port(&model, net, 56, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_C6); fnet_add_port(&model, net, 56, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_D6); fnet_vcc_gnd(&model, net, /*is_vcc*/ 1); + fnet_new(&model, &net); fnet_add_port(&model, net, 57, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_A6); fnet_add_port(&model, net, 57, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_B6); fnet_add_port(&model, net, 57, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_C6); fnet_add_port(&model, net, 57, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_D6); fnet_vcc_gnd(&model, net, /*is_vcc*/ 1); + fnet_new(&model, &net); fnet_add_port(&model, net, 58, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_A6); fnet_add_port(&model, net, 58, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_B6); + fnet_add_port(&model, net, 58, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_C6); + fnet_add_port(&model, net, 58, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_D6); fnet_vcc_gnd(&model, net, /*is_vcc*/ 1); // carry chain -#if 0 - fnet_new(&model, &net); - fnet_add_port(&model, net, 55, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LO_COUT); - fnet_add_port(&model, net, 56, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_CIN); - fnet_route(&model, net); - fnet_new(&model, &net); + fnet_add_port(&model, net, 55, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_CIN); fnet_add_port(&model, net, 56, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LO_COUT); - fnet_add_port(&model, net, 57, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_CIN); fnet_route(&model, net); fnet_new(&model, &net); + fnet_add_port(&model, net, 56, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_CIN); fnet_add_port(&model, net, 57, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LO_COUT); - fnet_add_port(&model, net, 58, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_CIN); fnet_route(&model, net); -#endif + + fnet_new(&model, &net); + fnet_add_port(&model, net, 57, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_CIN); + fnet_add_port(&model, net, 58, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LO_COUT); + fnet_route(&model, net); + + // bit chain + { + int out_pin[] = {LO_AQ, LO_BQ, LO_CQ, LO_DQ}; + int in_pin[] = {LI_A5, LI_B5, LI_C5, LI_D5}; + int cur_y, i; + + for (cur_y = 58; cur_y >= 55; cur_y--) { + for (i = 0; i < 4; i++) { + if (cur_y == 55 && i >= 2) + break; + fnet_new(&model, &net); + fnet_add_port(&model, net, cur_y, 13, DEV_LOGIC, DEV_LOG_M_OR_L, out_pin[i]); + fnet_add_port(&model, net, cur_y, 13, DEV_LOGIC, DEV_LOG_M_OR_L, in_pin[i]); + fnet_route(&model, net); + } + } + } + fnet_new(&model, &net); + fnet_add_port(&model, net, 55, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LO_CQ); + fnet_add_port(&model, net, 55, 13, DEV_LOGIC, DEV_LOG_M_OR_L, LI_C5); +// fnet_add_port(&model, net, iob_led_y, iob_led_x, DEV_IOB, +// iob_led_type_idx, IOB_IN_O); + fnet_route(&model, net); write_floorplan(stdout, &model, FP_DEFAULT); return fpga_free_model(&model); diff --git a/libs/bit_frames.c b/libs/bit_frames.c index 437af73..b00ae05 100644 --- a/libs/bit_frames.c +++ b/libs/bit_frames.c @@ -2765,7 +2765,7 @@ static int write_logic(struct fpga_bits* bits, struct fpga_model* model) } // Except for XC6_ML_CIN_USED (which is set by a switch elsewhere), // everything else should be 0. - if (mi20 || mi23_M || (mi2526 & ~XC6_ML_CIN_USED) + if (mi20 || mi23_M || (mi2526 & ~(1ULL<len = 0; + construct_sw_chain(&sw_chain, model, y, x, from_sw, SW_FROM, max_depth, + exclusive_net, /*block_list*/ 0, /*block_list_len*/ 0); + RC_CHECK(model); + + while (fpga_switch_chain(&sw_chain) != NO_CONN) { + RC_ASSERT(model, sw_chain.set.len); + if (fpga_switch_str_i(model, y, x, sw_chain.set.sw[sw_chain.set.len-1], + SW_TO) == to_sw) { + *sw_set = sw_chain.set; + break; + } + } + destruct_sw_chain(&sw_chain); + RC_RETURN(model); +} + int fpga_switch_conns(struct sw_conns* conns) { str16_t end_of_chain_str; @@ -1898,6 +1922,26 @@ internal_error: return NO_CONN; } +int fpga_first_conn(struct fpga_model *model, int sw_y, int sw_x, str16_t sw_str, + int from_to, int max_depth, net_idx_t exclusive_net, + struct sw_set *sw_set, int *dest_y, int *dest_x, str16_t *dest_connpt) +{ + struct sw_conns sw_conns; + + construct_sw_conns(&sw_conns, model, sw_y, sw_x, sw_str, from_to, + max_depth, exclusive_net); + RC_CHECK(model); + if (fpga_switch_conns(&sw_conns) == NO_CONN) + RC_FAIL(model, EINVAL); + + *sw_set = sw_conns.chain.set; + *dest_y = sw_conns.dest_y; + *dest_x = sw_conns.dest_x; + *dest_connpt = sw_conns.dest_str_i; + destruct_sw_conns(&sw_conns); + RC_RETURN(model); +} + void printf_swchain(struct fpga_model* model, int y, int x, str16_t sw, int from_to, int max_depth, swidx_t* block_list, int* block_list_len) @@ -2303,6 +2347,9 @@ int fnet_add_sw(struct fpga_model* model, net_idx_t net_i, net = &model->nets[net_i-1]; for (i = 0; i < num_sw; i++) { + if (switches[i] == NO_SWITCH) + { HERE(); continue; } + // check whether the switch is already in the net for (j = 0; j < net->len; j++) { if (net->el[j].y == y @@ -2477,6 +2524,11 @@ static int fpga_switch_2sets(struct fpga_model* model, int from_y, int from_x, struct sw_set to_switches; int i; +#ifdef DBG_SWITCH_2SETS + printf("fpga_switch_2sets() from y%i-x%i-%s to y%i-x%i-%s\n", + from_y, from_x, strarray_lookup(&model->str, from_pt), + to_y, to_x, strarray_lookup(&model->str, to_pt)); +#endif // only supports 1 switch on the end side right now fpga_swset_fromto(model, to_y, to_x, to_pt, SW_TO, &to_switches); RC_ASSERT(model, to_switches.len); @@ -2759,6 +2811,86 @@ static int fnet_route_logic_to_iob(struct fpga_model *model, net_idx_t net_i, in RC_RETURN(model); } +static int fnet_route_logic_carry(struct fpga_model *model, net_idx_t net_i, int out_i, int in_i) +{ + struct fpga_net *net_p; + struct fpga_device *out_dev, *in_dev; + int xm_col, from_str_i, to_str_i; + swidx_t sw; + + net_p = fnet_get(model, net_i); + RC_ASSERT(model, net_p); + 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); + RC_ASSERT(model, out_dev && in_dev); + + RC_ASSERT(model, (net_p->el[in_i].x == net_p->el[out_i].x) + && (net_p->el[in_i].y == regular_row_up(net_p->el[out_i].y, model))); + + xm_col = has_device_type(model, net_p->el[out_i].y, net_p->el[out_i].x, DEV_LOGIC, LOGIC_M); + if (xm_col) { + from_str_i = strarray_find(&model->str, "M_COUT"); + to_str_i = strarray_find(&model->str, "M_COUT_N"); + } else { // xl + from_str_i = strarray_find(&model->str, "XL_COUT"); + to_str_i = strarray_find(&model->str, "XL_COUT_N"); + } + RC_ASSERT(model, from_str_i != STRIDX_NO_ENTRY && !OUT_OF_U16(from_str_i)); + RC_ASSERT(model, to_str_i != STRIDX_NO_ENTRY && !OUT_OF_U16(to_str_i)); + + sw = fpga_switch_lookup(model, net_p->el[out_i].y, net_p->el[out_i].x, + from_str_i, to_str_i); + fnet_add_sw(model, net_i, net_p->el[out_i].y, net_p->el[out_i].x, + &sw, /*len*/ 1); + RC_RETURN(model); +} + +static int fnet_route_logic_to_self(struct fpga_model *model, + net_idx_t net_i, int out_i, int in_i) +{ + struct fpga_net *net_p; + int logic_y, logic_x, logic_dev_idx; + struct fpga_device *logic_dev; + struct sw_set sw_set; + int out_dest_y, out_dest_x, in_dest_y, in_dest_x; + str16_t out_dest_connpt, in_dest_connpt; + + net_p = fnet_get(model, net_i); + RC_ASSERT(model, net_p); + + logic_y = net_p->el[out_i].y; + logic_x = net_p->el[out_i].x; + logic_dev_idx = net_p->el[out_i].dev_idx; + RC_ASSERT(model, net_p->el[in_i].y == logic_y + && net_p->el[in_i].x == logic_x + && net_p->el[in_i].dev_idx == logic_dev_idx); + logic_dev = FPGA_DEV(model, logic_y, logic_x, logic_dev_idx); + RC_ASSERT(model, logic_dev); + + fpga_first_conn(model, logic_y, logic_x, + logic_dev->pinw[net_p->el[out_i].idx & NET_IDX_MASK], SW_FROM, + /*max_depth*/ 2, net_i, + &sw_set, &out_dest_y, &out_dest_x, &out_dest_connpt); + RC_CHECK(model); + fnet_add_sw(model, net_i, logic_y, logic_x, sw_set.sw, sw_set.len); + + fpga_first_conn(model, logic_y, logic_x, + logic_dev->pinw[net_p->el[in_i].idx & NET_IDX_MASK], SW_TO, + /*max_depth*/ 2, net_i, + &sw_set, &in_dest_y, &in_dest_x, &in_dest_connpt); + RC_ASSERT(model, out_dest_y == in_dest_y + && out_dest_x == in_dest_x); + fnet_add_sw(model, net_i, logic_y, logic_x, sw_set.sw, sw_set.len); + + fpga_multi_switch_lookup(model, out_dest_y, out_dest_x, + out_dest_connpt, in_dest_connpt, /*max_depth*/ 2, net_i, + &sw_set); + RC_ASSERT(model, sw_set.len); + fnet_add_sw(model, net_i, out_dest_y, out_dest_x, sw_set.sw, sw_set.len); + + RC_RETURN(model); +} + static int fnet_route_to_inpin(struct fpga_model *model, net_idx_t net_i, int out_i, int in_i) { struct fpga_net *net_p; @@ -2784,9 +2916,11 @@ static int fnet_route_to_inpin(struct fpga_model *model, net_idx_t net_i, int ou else if (in_dev->type == DEV_LOGIC) { if (net_p->el[in_i].y == net_p->el[out_i].y && net_p->el[in_i].x == net_p->el[out_i].x) { -// fnet_route_logic_to_logic + fnet_route_logic_to_self(model, net_i, out_i, in_i); } else { -// fnet_route_logic_carry + RC_ASSERT(model, (net_p->el[out_i].idx & NET_IDX_MASK) == LO_COUT + && (net_p->el[in_i].idx & NET_IDX_MASK) == LI_CIN); + fnet_route_logic_carry(model, net_i, out_i, in_i); } } else RC_FAIL(model, ENOTSUP); } else diff --git a/libs/control.h b/libs/control.h index dcad6d1..f541265 100644 --- a/libs/control.h +++ b/libs/control.h @@ -138,8 +138,6 @@ typedef int swidx_t; // swidx_t is an index into the uint32_t switches array // *) some wires that go 'everywhere' like GFAN (70) #define SW_SET_SIZE 128 -// todo: maybe it's better to stop using this structure and use two -// separate parameters instead (swidx_t* and len). struct sw_set { swidx_t sw[SW_SET_SIZE]; @@ -250,6 +248,10 @@ void destruct_sw_chain(struct sw_chain* chain); // set.len is 0 when there are no more switches in the tree int fpga_switch_chain(struct sw_chain* chain); +int fpga_multi_switch_lookup(struct fpga_model *model, int y, int x, + str16_t from_sw, str16_t to_sw, int max_depth, net_idx_t exclusive_net, + struct sw_set *sw_set); + struct sw_conns { struct sw_chain chain; @@ -270,6 +272,10 @@ void destruct_sw_conns(struct sw_conns* conns); // NO_CONN (-1) if there is no other connection. int fpga_switch_conns(struct sw_conns* conns); +int fpga_first_conn(struct fpga_model *model, int sw_y, int sw_x, str16_t sw_str, + int from_to, int max_depth, net_idx_t exclusive_net, + struct sw_set *sw_set, int *dest_y, int *dest_x, str16_t *dest_connpt); + // max_depth can be -1 for internal maximum (SW_SET_SIZE) void printf_swchain(struct fpga_model* model, int y, int x, str16_t sw, int from_to, int max_depth, swidx_t* block_list,