diff --git a/autotest.c b/autotest.c index e28feb2..302ebbc 100644 --- a/autotest.c +++ b/autotest.c @@ -128,7 +128,7 @@ fail: // goal: configure logic devices in all supported variations static int test_logic_config(struct test_state* tstate) { - int idx_enum[] = { DEV_LOGM, DEV_LOGX }; + int idx_enum[] = { DEV_LOG_M_OR_L, DEV_LOG_X }; int y, x, i, j, k, rc; y = 68; @@ -139,7 +139,7 @@ static int test_logic_config(struct test_state* tstate) // A1..A6 to A..D for (k = '1'; k <= '6'; k++) { - rc = fdev_logic_set_lut(tstate->model, y, x, + rc = fdev_logic_a2d_lut(tstate->model, y, x, idx_enum[i], j, 6, pf("A%c", k), ZTERM); if (rc) FAIL(rc); rc = fdev_set_required_pins(tstate->model, y, x, @@ -155,10 +155,10 @@ static int test_logic_config(struct test_state* tstate) } // A1 to O6 to FF to AQ - rc = fdev_logic_set_lut(tstate->model, y, x, + rc = fdev_logic_a2d_lut(tstate->model, y, x, idx_enum[i], j, 6, "A1", ZTERM); if (rc) FAIL(rc); - rc = fdev_logic_FF(tstate->model, y, x, idx_enum[i], + rc = fdev_logic_a2d_ff(tstate->model, y, x, idx_enum[i], j, MUX_O6, FF_SRINIT0); if (rc) FAIL(rc); rc = fdev_logic_sync(tstate->model, y, x, idx_enum[i], @@ -167,9 +167,9 @@ static int test_logic_config(struct test_state* tstate) rc = fdev_logic_clk(tstate->model, y, x, idx_enum[i], CLKINV_B); if (rc) FAIL(rc); - rc = fdev_logic_ceused(tstate->model, y, x, idx_enum[i]); + rc = fdev_logic_ce_used(tstate->model, y, x, idx_enum[i]); if (rc) FAIL(rc); - rc = fdev_logic_srused(tstate->model, y, x, idx_enum[i]); + rc = fdev_logic_sr_used(tstate->model, y, x, idx_enum[i]); if (rc) FAIL(rc); rc = fdev_set_required_pins(tstate->model, y, x, @@ -599,24 +599,24 @@ static int test_routing_sw_from_logic(struct test_state* tstate, // from below, or sr1/sl1 wires from above. for (rel_y = -1; rel_y <= 1; rel_y += 2) { 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); + rc = fdev_logic_a2d_lut(tstate->model, y, x, + DEV_LOG_M_OR_L, 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); + DEV_LOGIC, DEV_LOG_M_OR_L); 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); + y, x, DEV_LOGIC, DEV_LOG_M_OR_L); + dev = fdev_p(tstate->model, y, x, DEV_LOGIC, DEV_LOG_M_OR_L); if (!dev) FAIL(EINVAL); if (!dev->pinw_req_in) FAIL(EINVAL); rc = fnet_new(tstate->model, &net); if (rc) FAIL(rc); rc = fnet_add_port(tstate->model, net, y, x, - DEV_LOGIC, DEV_LOGM, dev->pinw_req_for_cfg[0]); + DEV_LOGIC, DEV_LOG_M_OR_L, dev->pinw_req_for_cfg[0]); if (rc) FAIL(rc); swto.model = tstate->model; @@ -665,7 +665,7 @@ static int test_routing_sw_from_logic(struct test_state* tstate, if (rc) FAIL(rc); } destruct_sw_conns(&conns); - fdev_delete(tstate->model, y, x, DEV_LOGIC, DEV_LOGM); + fdev_delete(tstate->model, y, x, DEV_LOGIC, DEV_LOG_M_OR_L); fnet_delete(tstate->model, net); } } @@ -677,7 +677,7 @@ fail: // goal: use all switches in a routing switchbox static int test_routing_switches(struct test_state* tstate) { - int idx_enum[] = { DEV_LOGM, DEV_LOGX }; + int idx_enum[] = { DEV_LOG_M_OR_L, DEV_LOG_X }; int y, x, i, j, k, r, rc; swidx_t done_sw_list[MAX_SWITCHBOX_SIZE]; int done_sw_len; @@ -699,12 +699,9 @@ static int test_routing_switches(struct test_state* tstate) // A1-A6 to A (same for lut B-D) for (k = '1'; k <= '6'; k++) { - rc = fdev_logic_set_lut(tstate->model, y, x, + rc = fdev_logic_a2d_lut(tstate->model, y, x, idx_enum[i], j, 6, pf("A%c", k), ZTERM); if (rc) FAIL(rc); - rc = fdev_logic_out_used(tstate->model, y, x, - idx_enum[i], j); - if (rc) FAIL(rc); if (!r) rc = test_logic_net_l1(tstate, y, x, DEV_LOGIC, @@ -719,10 +716,10 @@ static int test_routing_switches(struct test_state* tstate) } // A1->O6->FF->AQ (same for lut B-D) - rc = fdev_logic_set_lut(tstate->model, y, x, + rc = fdev_logic_a2d_lut(tstate->model, y, x, idx_enum[i], j, 6, "A1", ZTERM); if (rc) FAIL(rc); - rc = fdev_logic_FF(tstate->model, y, x, idx_enum[i], + rc = fdev_logic_a2d_ff(tstate->model, y, x, idx_enum[i], j, MUX_O6, FF_SRINIT0); if (rc) FAIL(rc); rc = fdev_logic_sync(tstate->model, y, x, idx_enum[i], @@ -731,9 +728,9 @@ static int test_routing_switches(struct test_state* tstate) rc = fdev_logic_clk(tstate->model, y, x, idx_enum[i], CLKINV_B); if (rc) FAIL(rc); - rc = fdev_logic_ceused(tstate->model, y, x, idx_enum[i]); + rc = fdev_logic_ce_used(tstate->model, y, x, idx_enum[i]); if (rc) FAIL(rc); - rc = fdev_logic_srused(tstate->model, y, x, idx_enum[i]); + rc = fdev_logic_sr_used(tstate->model, y, x, idx_enum[i]); if (rc) FAIL(rc); rc = fdev_set_required_pins(tstate->model, y, x, @@ -986,6 +983,155 @@ fail: return rc; } +static int test_lut(struct test_state* tstate, int y, int x, int type_idx, + int lut, const char* lut6, const char* lut5) +{ + struct fpga_device* dev; + net_idx_t pinw_nets[MAX_NUM_PINW]; + int i, rc; + + if (tstate->dry_run) + printf("O lut6 '%s' lut5 '%s'\n", + lut6 ? lut6 : "-", lut5 ? lut5 : "-"); + if (lut6) { + rc = fdev_logic_a2d_lut(tstate->model, y, x, + type_idx, lut, 6, lut6, ZTERM); + if (rc) FAIL(rc); + } + if (lut5) { + rc = fdev_logic_a2d_lut(tstate->model, y, x, + type_idx, lut, 5, lut5, ZTERM); + if (rc) FAIL(rc); + } + rc = fdev_set_required_pins(tstate->model, y, x, DEV_LOGIC, type_idx); + if (rc) FAIL(rc); + if (tstate->dry_run) { + fdev_print_required_pins(tstate->model, y, x, + DEV_LOGIC, type_idx); + } + + // add stub nets for each required pin + dev = fdev_p(tstate->model, y, x, DEV_LOGIC, type_idx); + if (!dev) FAIL(EINVAL); + for (i = 0; i < dev->pinw_req_total; i++) { + // i < dev->pinw_req_in -> input + rc = fnet_new(tstate->model, &pinw_nets[i]); + if (rc) FAIL(rc); + rc = fnet_add_port(tstate->model, pinw_nets[i], y, x, + DEV_LOGIC, type_idx, dev->pinw_req_for_cfg[i]); + if (rc) FAIL(rc); + if ((dev->pinw_req_for_cfg[i] == LI_A6 + && dev->u.logic.a2d[LUT_A].lut5 + && *dev->u.logic.a2d[LUT_A].lut5) + || (dev->pinw_req_for_cfg[i] == LI_B6 + && dev->u.logic.a2d[LUT_B].lut5 + && *dev->u.logic.a2d[LUT_B].lut5) + || (dev->pinw_req_for_cfg[i] == LI_C6 + && dev->u.logic.a2d[LUT_C].lut5 + && *dev->u.logic.a2d[LUT_C].lut5) + || (dev->pinw_req_for_cfg[i] == LI_D6 + && dev->u.logic.a2d[LUT_D].lut5 + && *dev->u.logic.a2d[LUT_D].lut5)) { + rc = fnet_route_to_inpins(tstate->model, pinw_nets[i], "VCC_WIRE"); + if (rc) FAIL(rc); + } + } + + if ((rc = diff_printf(tstate))) FAIL(rc); + + for (i = 0; i < dev->pinw_req_total; i++) + fnet_delete(tstate->model, pinw_nets[i]); + fdev_delete(tstate->model, y, x, DEV_LOGIC, type_idx); + return 0; +fail: + return rc; +} + +static int test_lut_encoding(struct test_state* tstate) +{ + int idx_enum[] = { DEV_LOG_M_OR_L, DEV_LOG_X }; + int x_enum[] = { /*xm*/ 13, /* center-xl*/ 22, /*xl*/ 39 }; + int y, x_i, i, j, k, lut_str_len, rc; + int type_i, lut; + char lut_str[128]; + const char* lut5_parents[] = {"(A6+~A6)*1", "(A6+~A6)*0", + "(A6+~A6)*A1", "(A6+~A6)*A3", 0}; + + tstate->diff_to_null = 1; + + y = 68; + for (x_i = 0; x_i < sizeof(x_enum)/sizeof(*x_enum); x_i++) { + for (type_i = 0; type_i < sizeof(idx_enum)/sizeof(*idx_enum); type_i++) { + for (lut = LUT_A; lut <= LUT_D; lut++) { + // lut6 only + rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i], + lut, "0", /*lut5*/ 0); + if (rc) FAIL(rc); + rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i], + lut, "1", /*lut5*/ 0); + if (rc) FAIL(rc); + for (i = '1'; i <= '6'; i++) { + snprintf(lut_str, sizeof(lut_str), "A%c", i); + rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i], + lut, lut_str, /*lut5*/ 0); + if (rc) FAIL(rc); + } + for (i = 0; i < 64; i++) { + lut_str_len = 0; + for (j = 0; j < 6; j++) { + if (lut_str_len) + lut_str[lut_str_len++] = '*'; + if (!(i & (1<= 8) byte_off += HCLK_BYTES; // M device - dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGM); + dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOG_M_OR_L); if (dev_idx == NO_DEV) FAIL(EINVAL); // A6_LUT @@ -364,7 +364,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits) { int logic_base[6] = {0,1,0,0,1,0}; lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 1); } if (*lut_str) { - rc = fdev_logic_set_lut(model, y, x, DEV_LOGM, + rc = fdev_logic_a2d_lut(model, y, x, DEV_LOG_M_OR_L, LUT_A, 6, lut_str, ZTERM); if (rc) FAIL(rc); *(uint32_t*)(u8_p+24*FRAME_SIZE+byte_off+4) = 0; @@ -378,7 +378,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits) { int logic_base[6] = {1,1,0,1,0,1}; lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 1); } if (*lut_str) { - rc = fdev_logic_set_lut(model, y, x, DEV_LOGM, + rc = fdev_logic_a2d_lut(model, y, x, DEV_LOG_M_OR_L, LUT_B, 6, lut_str, ZTERM); if (rc) FAIL(rc); *(uint32_t*)(u8_p+21*FRAME_SIZE+byte_off+4) = 0; @@ -392,7 +392,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits) { int logic_base[6] = {0,1,0,0,1,0}; lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 1); } if (*lut_str) { - rc = fdev_logic_set_lut(model, y, x, DEV_LOGM, + rc = fdev_logic_a2d_lut(model, y, x, DEV_LOG_M_OR_L, LUT_C, 6, lut_str, ZTERM); if (rc) FAIL(rc); *(uint32_t*)(u8_p+24*FRAME_SIZE+byte_off) = 0; @@ -406,7 +406,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits) { int logic_base[6] = {1,1,0,1,0,1}; lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 1); } if (*lut_str) { - rc = fdev_logic_set_lut(model, y, x, DEV_LOGM, + rc = fdev_logic_a2d_lut(model, y, x, DEV_LOG_M_OR_L, LUT_D, 6, lut_str, ZTERM); if (rc) FAIL(rc); *(uint32_t*)(u8_p+21*FRAME_SIZE+byte_off) = 0; @@ -433,16 +433,19 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits) continue; } - dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGX); + dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOG_X); if (dev_idx == NO_DEV) FAIL(EINVAL); *(uint64_t*)(u8_p+26*FRAME_SIZE+byte_off) = 0; // A6_LUT u64 = read_lut64(u8_p + 27*FRAME_SIZE, (byte_off+4)*8); - { int logic_base[6] = {1,1,0,1,1,0}; - lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); } - if (*lut_str) { - rc = fdev_logic_set_lut(model, y, x, DEV_LOGX, + if (!u64) lut_str = 0; + else { + int logic_base[6] = {1,1,0,1,1,0}; + lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); + } + if (lut_str && *lut_str) { + rc = fdev_logic_a2d_lut(model, y, x, DEV_LOG_X, LUT_A, 6, lut_str, ZTERM); if (rc) FAIL(rc); *(uint32_t*)(u8_p+27*FRAME_SIZE+byte_off+4) = 0; @@ -450,30 +453,39 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits) } // B6_LUT u64 = read_lut64(u8_p + 29*FRAME_SIZE, (byte_off+4)*8); - { int logic_base[6] = {1,1,0,1,1,0}; - lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); } - if (*lut_str) { - rc = fdev_logic_set_lut(model, y, x, DEV_LOGX, + if (!u64) lut_str = 0; + else { + int logic_base[6] = {1,1,0,1,1,0}; + lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); + } + if (lut_str && *lut_str) { + rc = fdev_logic_a2d_lut(model, y, x, DEV_LOG_X, LUT_B, 6, lut_str, ZTERM); *(uint32_t*)(u8_p+29*FRAME_SIZE+byte_off+4) = 0; *(uint32_t*)(u8_p+30*FRAME_SIZE+byte_off+4) = 0; } // C6_LUT u64 = read_lut64(u8_p + 27*FRAME_SIZE, byte_off*8); - { int logic_base[6] = {0,1,0,0,0,1}; - lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); } - if (*lut_str) { - rc = fdev_logic_set_lut(model, y, x, DEV_LOGX, + if (!u64) lut_str = 0; + else { + int logic_base[6] = {0,1,0,0,0,1}; + lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); + } + if (lut_str && *lut_str) { + rc = fdev_logic_a2d_lut(model, y, x, DEV_LOG_X, LUT_C, 6, lut_str, ZTERM); *(uint32_t*)(u8_p+27*FRAME_SIZE+byte_off) = 0; *(uint32_t*)(u8_p+28*FRAME_SIZE+byte_off) = 0; } // D6_LUT u64 = read_lut64(u8_p + 29*FRAME_SIZE, byte_off*8); - { int logic_base[6] = {0,1,0,0,0,1}; - lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); } - if (*lut_str) { - rc = fdev_logic_set_lut(model, y, x, DEV_LOGX, + if (!u64) lut_str = 0; + else { + int logic_base[6] = {0,1,0,0,0,1}; + lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); + } + if (lut_str && *lut_str) { + rc = fdev_logic_a2d_lut(model, y, x, DEV_LOG_X, LUT_D, 6, lut_str, ZTERM); *(uint32_t*)(u8_p+29*FRAME_SIZE+byte_off) = 0; *(uint32_t*)(u8_p+30*FRAME_SIZE+byte_off) = 0; @@ -1074,7 +1086,7 @@ static int write_logic(struct fpga_bits* bits, struct fpga_model* model) if (xm_col) { // X device - dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGX); + dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOG_X); if (dev_idx == NO_DEV) FAIL(EINVAL); dev = FPGA_DEV(model, y, x, dev_idx); if (dev->instantiated) { @@ -1102,7 +1114,7 @@ static int write_logic(struct fpga_bits* bits, struct fpga_model* model) } // M device - dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGM); + dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOG_M_OR_L); if (dev_idx == NO_DEV) FAIL(EINVAL); dev = FPGA_DEV(model, y, x, dev_idx); if (dev->instantiated) { @@ -1110,7 +1122,7 @@ static int write_logic(struct fpga_bits* bits, struct fpga_model* model) } } else { // X device - dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGX); + dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOG_X); if (dev_idx == NO_DEV) FAIL(EINVAL); dev = FPGA_DEV(model, y, x, dev_idx); if (dev->instantiated) { @@ -1118,7 +1130,7 @@ static int write_logic(struct fpga_bits* bits, struct fpga_model* model) } // L device - dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGL); + dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOG_M_OR_L); if (dev_idx == NO_DEV) FAIL(EINVAL); dev = FPGA_DEV(model, y, x, dev_idx); if (dev->instantiated) { diff --git a/libs/control.c b/libs/control.c index 3a2ee1d..ee7182c 100644 --- a/libs/control.c +++ b/libs/control.c @@ -225,7 +225,11 @@ struct fpga_device* fdev_p(struct fpga_model* model, int y, int x, enum fpgadev_type type, dev_type_idx_t type_idx) { dev_idx_t dev_idx = fpga_dev_idx(model, y, x, type, type_idx); - if (dev_idx == NO_DEV) { HERE(); return 0; } + if (dev_idx == NO_DEV) { + fprintf(stderr, "#E %s:%i fdev_p() y%02i x%02i type %i/%i not" + " found\n", __FILE__, __LINE__, y, x, type, type_idx); + return 0; + } return FPGA_DEV(model, y, x, dev_idx); } @@ -395,6 +399,13 @@ void fdev_print_required_pins(struct fpga_model* model, int y, int x, static void add_req_inpin(struct fpga_device* dev, pinw_idx_t pinw_i) { + int i; + + // check for duplicate + for (i = 0; i < dev->pinw_req_in; i++) { + if (dev->pinw_req_for_cfg[i] == pinw_i) + return; + } if (dev->pinw_req_total > dev->pinw_req_in) { memmove(&dev->pinw_req_for_cfg[dev->pinw_req_in+1], &dev->pinw_req_for_cfg[dev->pinw_req_in], @@ -408,11 +419,40 @@ static void add_req_inpin(struct fpga_device* dev, pinw_idx_t pinw_i) static void add_req_outpin(struct fpga_device* dev, pinw_idx_t pinw_i) { + int i; + + // check for duplicate + for (i = dev->pinw_req_in; i < dev->pinw_req_total; i++) { + if (dev->pinw_req_for_cfg[i] == pinw_i) + return; + } dev->pinw_req_for_cfg[dev->pinw_req_total] = pinw_i; dev->pinw_req_total++; } -int fdev_logic_set_lut(struct fpga_model* model, int y, int x, int type_idx, +// +// logic device +// + +int fdev_logic_a2d_out_used(struct fpga_model* model, int y, int x, + int type_idx, int lut_a2d, int used) +{ + struct fpga_device* dev; + int rc; + + dev = fdev_p(model, y, x, DEV_LOGIC, type_idx); + if (!dev) FAIL(EINVAL); + rc = reset_required_pins(dev); + if (rc) FAIL(rc); + + dev->u.logic.a2d[lut_a2d].out_used = (used != 0); + dev->instantiated = 1; + return 0; +fail: + return rc; +} + +int fdev_logic_a2d_lut(struct fpga_model* model, int y, int x, int type_idx, int lut_a2d, int lut_5or6, const char* lut_str, int lut_len) { struct fpga_device* dev; @@ -435,31 +475,28 @@ int fdev_logic_set_lut(struct fpga_model* model, int y, int x, int type_idx, memcpy(*lut_ptr, lut_str, lut_len); (*lut_ptr)[lut_len] = 0; + // todo: the logic by which we auto-enable the direct + // output could have more cases, the O6 signal + // could go into the carry chain/XOR/CY, F7/F8, others? + // O5 could go into carry chain/XOR/CY, others? + // We need to find out over time what makes sense for + // the caller. + if (lut_5or6 == 6 + && dev->u.logic.a2d[lut_a2d].ff_mux != MUX_O6 + && dev->u.logic.a2d[lut_a2d].out_mux != MUX_O6) + dev->u.logic.a2d[lut_a2d].out_used = 1; + if (lut_5or6 == 5 + && dev->u.logic.a2d[lut_a2d].ff_mux != MUX_O5 + && !dev->u.logic.a2d[lut_a2d].out_mux) + dev->u.logic.a2d[lut_a2d].out_mux = MUX_O5; + dev->instantiated = 1; return 0; fail: return rc; } -int fdev_logic_out_used(struct fpga_model* model, int y, int x, int type_idx, - int lut_a2d) -{ - struct fpga_device* dev; - int rc; - - dev = fdev_p(model, y, x, DEV_LOGIC, type_idx); - if (!dev) FAIL(EINVAL); - rc = reset_required_pins(dev); - if (rc) FAIL(rc); - - dev->u.logic.a2d[lut_a2d].used = 1; - dev->instantiated = 1; - return 0; -fail: - return rc; -} - -int fdev_logic_FF(struct fpga_model* model, int y, int x, int type_idx, +int fdev_logic_a2d_ff(struct fpga_model* model, int y, int x, int type_idx, int lut_a2d, int ff_mux, int srinit) { struct fpga_device* dev; @@ -479,6 +516,44 @@ fail: return rc; } +int fdev_logic_a2d_out_mux(struct fpga_model* model, int y, int x, + int type_idx, int lut_a2d, int out_mux) +{ + struct fpga_device* dev; + int rc; + + dev = fdev_p(model, y, x, DEV_LOGIC, type_idx); + if (!dev) FAIL(EINVAL); + rc = reset_required_pins(dev); + if (rc) FAIL(rc); + + dev->u.logic.a2d[lut_a2d].out_mux = out_mux; + dev->instantiated = 1; + return 0; +fail: + return rc; +} + +int fdev_logic_a2d_cy0(struct fpga_model* model, int y, int x, + int type_idx, int lut_a2d, int cy0) +{ + struct fpga_device* dev; + int rc; + + dev = fdev_p(model, y, x, DEV_LOGIC, type_idx); + if (!dev) FAIL(EINVAL); + rc = reset_required_pins(dev); + if (rc) FAIL(rc); + + dev->u.logic.a2d[lut_a2d].cy0 = cy0; +// todo: when cy0 is CY0_O5 and lut5 is empty, set to "0" +// (same for setting ff_mux or out_mux to MUX_O5 + dev->instantiated = 1; + return 0; +fail: + return rc; +} + int fdev_logic_clk(struct fpga_model* model, int y, int x, int type_idx, int clk) { @@ -515,7 +590,7 @@ fail: return rc; } -int fdev_logic_ceused(struct fpga_model* model, int y, int x, int type_idx) +int fdev_logic_ce_used(struct fpga_model* model, int y, int x, int type_idx) { struct fpga_device* dev; int rc; @@ -532,7 +607,7 @@ fail: return rc; } -int fdev_logic_srused(struct fpga_model* model, int y, int x, int type_idx) +int fdev_logic_sr_used(struct fpga_model* model, int y, int x, int type_idx) { struct fpga_device* dev; int rc; @@ -549,6 +624,64 @@ fail: return rc; } +int fdev_logic_we_mux(struct fpga_model* model, int y, int x, + int type_idx, int we_mux) +{ + struct fpga_device* dev; + int rc; + + dev = fdev_p(model, y, x, DEV_LOGIC, type_idx); + if (!dev) FAIL(EINVAL); + rc = reset_required_pins(dev); + if (rc) FAIL(rc); + + dev->u.logic.we_mux = we_mux; + dev->instantiated = 1; + return 0; +fail: + return rc; +} + +int fdev_logic_cout_used(struct fpga_model* model, int y, int x, + int type_idx, int used) +{ + struct fpga_device* dev; + int rc; + + dev = fdev_p(model, y, x, DEV_LOGIC, type_idx); + if (!dev) FAIL(EINVAL); + rc = reset_required_pins(dev); + if (rc) FAIL(rc); + + dev->u.logic.cout_used = (used != 0); + dev->instantiated = 1; + return 0; +fail: + return rc; +} + +int fdev_logic_precyinit(struct fpga_model* model, int y, int x, + int type_idx, int precyinit) +{ + struct fpga_device* dev; + int rc; + + dev = fdev_p(model, y, x, DEV_LOGIC, type_idx); + if (!dev) FAIL(EINVAL); + rc = reset_required_pins(dev); + if (rc) FAIL(rc); + + dev->u.logic.precyinit = precyinit; + dev->instantiated = 1; + return 0; +fail: + return rc; +} + +// +// iob device +// + int fdev_iob_input(struct fpga_model* model, int y, int x, int type_idx) { struct fpga_device* dev; @@ -596,9 +729,13 @@ static void scan_lut_digits(const char* s, int* digits) for (i = 0; i < 6; i++) digits[i] = 0; if (!s) return; + // Note special cases "0" and "1" for a lut that + // always results in 0 or 1. for (i = 0; s[i]; i++) { - if (s[i] >= '1' && s[i] <= '6') - digits[s[i]-'1']++; + if (s[i] != 'A' && s[i] != 'a') + continue; + if (s[i+1] >= '1' && s[i+1] <= '6') + digits[s[++i]-'1']++; } } @@ -620,16 +757,28 @@ int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type, add_req_inpin(dev, LI_CE); if (dev->u.logic.sr_used) add_req_inpin(dev, LI_SR); + if (dev->u.logic.cout_used) { + add_req_outpin(dev, LO_COUT); + if (!dev->u.logic.precyinit) + add_req_inpin(dev, LI_CIN); + } + if (dev->u.logic.precyinit == PRECYINIT_AX) + add_req_inpin(dev, LI_AX); for (i = LUT_A; i <= LUT_D; i++) { - if (dev->u.logic.a2d[i].used) { + if (dev->u.logic.a2d[i].out_used) { // LO_A..LO_D are in sequence add_req_outpin(dev, LO_A+i); } + if (dev->u.logic.a2d[i].out_mux) { + // LO_AMUX..LO_DMUX are in sequence + add_req_outpin(dev, LO_AMUX+i); + } if (dev->u.logic.a2d[i].ff) { // LO_AQ..LO_DQ are in sequence add_req_outpin(dev, LO_AQ+i); } - if (dev->u.logic.a2d[i].ff_mux == MUX_X) { + if (dev->u.logic.a2d[i].ff_mux == MUX_X + || dev->u.logic.a2d[i].cy0 == CY0_X) { // LI_AX..LI_DX are in sequence add_req_inpin(dev, LI_AX+i); } @@ -641,12 +790,18 @@ int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type, } } if (dev->u.logic.a2d[i].lut5) { + // A6 must be high/vcc if lut5 is used + add_req_inpin(dev, LI_A6+i*6); scan_lut_digits(dev->u.logic.a2d[i].lut5, digits); for (j = 0; j < 6; j++) { if (!digits[j]) continue; add_req_inpin(dev, LI_A1+i*6+j); } } + if ((dev->u.logic.a2d[i].ff_mux == MUX_XOR + || dev->u.logic.a2d[i].out_mux == MUX_XOR) + && !dev->u.logic.precyinit) + add_req_inpin(dev, LI_CIN); } return 0; } @@ -1983,6 +2138,46 @@ fail: return rc; } +int fnet_route_to_inpins(struct fpga_model* model, net_idx_t net_i, + const char* from) +{ + struct fpga_net* net_p; + struct fpga_device* dev_p; + str16_t from_i; + struct sw_set start_set, end_set; + int i, rc; + + net_p = fnet_get(model, net_i); + if (!net_p) FAIL(EINVAL); + from_i = strarray_find(&model->str, from); + if (from_i == STRIDX_NO_ENTRY) FAIL(EINVAL); + + for (i = 0; i < net_p->len; i++) { + if (!(net_p->el[i].idx & NET_IDX_IS_PINW)) + // skip existing switch + continue; + 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) + // skip outpin + continue; + rc = froute_direct(model, net_p->el[i].y, net_p->el[i].x-1, + from_i, net_p->el[i].y, net_p->el[i].x, + dev_p->pinw[net_p->el[i].idx & NET_IDX_MASK], + &start_set, &end_set); + if (rc) FAIL(rc); + rc = fnet_add_sw(model, net_i, net_p->el[i].y, + net_p->el[i].x-1, start_set.sw, start_set.len); + if (rc) FAIL(rc); + rc = fnet_add_sw(model, net_i, net_p->el[i].y, + net_p->el[i].x, end_set.sw, end_set.len); + if (rc) FAIL(rc); + } + return 0; +fail: + return rc; +} + int froute_direct(struct fpga_model* model, int start_y, int start_x, str16_t start_pt, int end_y, int end_x, str16_t end_pt, struct sw_set* start_set, struct sw_set* end_set) diff --git a/libs/control.h b/libs/control.h index ec67fe9..220ce06 100644 --- a/libs/control.h +++ b/libs/control.h @@ -46,23 +46,37 @@ const char* fdev_pinw_idx2str(int devtype, pinw_idx_t idx); 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); -// 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, +// lut_a2d is LUT_A to LUT_D +int fdev_logic_a2d_out_used(struct fpga_model* model, int y, int x, + int type_idx, int lut_a2d, int used); +// lut_5or6 is int 5 or int 6 +int fdev_logic_a2d_lut(struct fpga_model* model, int y, int x, int type_idx, int lut_a2d, int lut_5or6, const char* lut_str, int lut_len); -int fdev_logic_out_used(struct fpga_model* model, int y, int x, int type_idx, - int lut_a2d); -// ff_mux is MUX_O6 or MUX_X // srinit is FF_SRINIT0 or FF_SRINIT1 -int fdev_logic_FF(struct fpga_model* model, int y, int x, int type_idx, +int fdev_logic_a2d_ff(struct fpga_model* model, int y, int x, int type_idx, int lut_a2d, int ff_mux, int srinit); +int fdev_logic_a2d_out_mux(struct fpga_model* model, int y, int x, + int type_idx, int lut_a2d, int out_mux); +// cy0 is CY0_X or CY0_O5 +int fdev_logic_a2d_cy0(struct fpga_model* model, int y, int x, + int type_idx, int lut_a2d, int cy0); + // clk is CLKINV_B or CLKINV_CLK int fdev_logic_clk(struct fpga_model* model, int y, int x, int type_idx, int clk); // sync is SYNCATTR_SYNC or SYNCATTR_ASYNC int fdev_logic_sync(struct fpga_model* model, int y, int x, int type_idx, int sync_attr); -int fdev_logic_ceused(struct fpga_model* model, int y, int x, int type_idx); -int fdev_logic_srused(struct fpga_model* model, int y, int x, int type_idx); +int fdev_logic_ce_used(struct fpga_model* model, int y, int x, int type_idx); +int fdev_logic_sr_used(struct fpga_model* model, int y, int x, int type_idx); +// we_mux can be WEMUX_WE or WEMUX_CE +int fdev_logic_we_mux(struct fpga_model* model, int y, int x, + int type_idx, int we_mux); +int fdev_logic_cout_used(struct fpga_model* model, int y, int x, + int type_idx, int used); +// precyinit can be PRECYINIT_O, PRECYINIT_1 or PRECYINIT_AX +int fdev_logic_precyinit(struct fpga_model* model, int y, int x, + int type_idx, int precyinit); int fdev_iob_input(struct fpga_model* model, int y, int x, int type_idx); int fdev_iob_output(struct fpga_model* model, int y, int x, int type_idx); @@ -335,6 +349,9 @@ void fnet_printf(FILE* f, struct fpga_model* model, net_idx_t net_i); int fnet_autoroute(struct fpga_model* model, net_idx_t net_i); +int fnet_route_to_inpins(struct fpga_model* model, net_idx_t net_i, + const char* from); + // // routing // diff --git a/libs/floorplan.c b/libs/floorplan.c index 7a62adc..9b33fd7 100644 --- a/libs/floorplan.c +++ b/libs/floorplan.c @@ -324,7 +324,7 @@ static int printf_LOGIC(FILE* f, struct fpga_model* model, } cfg = &tile->devs[i].u.logic; for (j = LUT_A; j <= LUT_D; j++) { - if (cfg->a2d[j].used) + if (cfg->a2d[j].out_used) fprintf(f, "%s %c_used\n", pref, 'A'+j); if (cfg->a2d[j].lut6 && cfg->a2d[j].lut6[0]) fprintf(f, "%s %c6_lut %s\n", pref, 'A'+j, @@ -343,15 +343,21 @@ static int printf_LOGIC(FILE* f, struct fpga_model* model, case MUX_X: fprintf(f, "%s %c_ffmux X\n", pref, 'A'+j); break; - case MUX_F7: - fprintf(f, "%s %c_ffmux F7\n", pref, 'A'+j); - break; case MUX_CY: fprintf(f, "%s %c_ffmux CY\n", pref, 'A'+j); break; case MUX_XOR: fprintf(f, "%s %c_ffmux XOR\n", pref, 'A'+j); break; + case MUX_F7: + fprintf(f, "%s %c_ffmux F7\n", pref, 'A'+j); + break; + case MUX_F8: + fprintf(f, "%s %c_ffmux F8\n", pref, 'A'+j); + break; + case MUX_MC31: + fprintf(f, "%s %c_ffmux MC31\n", pref, 'A'+j); + break; case 0: break; default: FAIL(EINVAL); } switch (cfg->a2d[j].ff_srinit) { @@ -373,15 +379,21 @@ static int printf_LOGIC(FILE* f, struct fpga_model* model, case MUX_5Q: fprintf(f, "%s %c_outmux 5Q\n", pref, 'A'+j); break; - case MUX_F7: - fprintf(f, "%s %c_outmux F7\n", pref, 'A'+j); - break; case MUX_CY: fprintf(f, "%s %c_outmux CY\n", pref, 'A'+j); break; case MUX_XOR: fprintf(f, "%s %c_outmux XOR\n", pref, 'A'+j); break; + case MUX_F7: + fprintf(f, "%s %c_outmux F7\n", pref, 'A'+j); + break; + case MUX_F8: + fprintf(f, "%s %c_outmux F8\n", pref, 'A'+j); + break; + case MUX_MC31: + fprintf(f, "%s %c_outmux MC31\n", pref, 'A'+j); + break; case 0: break; default: FAIL(EINVAL); } switch (cfg->a2d[j].ff) { @@ -474,7 +486,7 @@ static int read_LOGIC_attr(struct fpga_model* model, int y, int x, int type_idx, for (i = LUT_A; i <= LUT_D; i++) { snprintf(cmp_str, sizeof(cmp_str), "%c_used", 'A'+i); if (!str_cmp(w1, w1_len, cmp_str, ZTERM)) { - dev->u.logic.a2d[i].used = 1; + dev->u.logic.a2d[i].out_used = 1; goto inst_1; } } @@ -499,13 +511,13 @@ static int read_LOGIC_attr(struct fpga_model* model, int y, int x, int type_idx, for (i = LUT_A; i <= LUT_D; i++) { snprintf(cmp_str, sizeof(cmp_str), "%c6_lut", 'A'+i); if (!str_cmp(w1, w1_len, cmp_str, ZTERM)) { - rc = fdev_logic_set_lut(model, y, x, type_idx, i, 6, w2, w2_len); + rc = fdev_logic_a2d_lut(model, y, x, type_idx, i, 6, w2, w2_len); if (rc) return 0; goto inst_2; } snprintf(cmp_str, sizeof(cmp_str), "%c5_lut", 'A'+i); if (!str_cmp(w1, w1_len, cmp_str, ZTERM)) { - rc = fdev_logic_set_lut(model, y, x, type_idx, i, 5, w2, w2_len); + rc = fdev_logic_a2d_lut(model, y, x, type_idx, i, 5, w2, w2_len); if (rc) return 0; goto inst_2; } @@ -517,12 +529,16 @@ static int read_LOGIC_attr(struct fpga_model* model, int y, int x, int type_idx, dev->u.logic.a2d[i].ff_mux = MUX_O5; else if (!str_cmp(w2, w2_len, "X", ZTERM)) dev->u.logic.a2d[i].ff_mux = MUX_X; - else if (!str_cmp(w2, w2_len, "F7", ZTERM)) - dev->u.logic.a2d[i].ff_mux = MUX_F7; else if (!str_cmp(w2, w2_len, "CY", ZTERM)) dev->u.logic.a2d[i].ff_mux = MUX_CY; else if (!str_cmp(w2, w2_len, "XOR", ZTERM)) dev->u.logic.a2d[i].ff_mux = MUX_XOR; + else if (!str_cmp(w2, w2_len, "F7", ZTERM)) + dev->u.logic.a2d[i].ff_mux = MUX_F7; + else if (!str_cmp(w2, w2_len, "F8", ZTERM)) + dev->u.logic.a2d[i].ff_mux = MUX_F8; + else if (!str_cmp(w2, w2_len, "MC31", ZTERM)) + dev->u.logic.a2d[i].ff_mux = MUX_MC31; else return 0; goto inst_2; } @@ -543,12 +559,16 @@ static int read_LOGIC_attr(struct fpga_model* model, int y, int x, int type_idx, dev->u.logic.a2d[i].out_mux = MUX_O5; else if (!str_cmp(w2, w2_len, "5Q", ZTERM)) dev->u.logic.a2d[i].out_mux = MUX_5Q; - else if (!str_cmp(w2, w2_len, "F7", ZTERM)) - dev->u.logic.a2d[i].out_mux = MUX_F7; else if (!str_cmp(w2, w2_len, "CY", ZTERM)) dev->u.logic.a2d[i].out_mux = MUX_CY; else if (!str_cmp(w2, w2_len, "XOR", ZTERM)) dev->u.logic.a2d[i].out_mux = MUX_XOR; + else if (!str_cmp(w2, w2_len, "F7", ZTERM)) + dev->u.logic.a2d[i].out_mux = MUX_F7; + else if (!str_cmp(w2, w2_len, "F8", ZTERM)) + dev->u.logic.a2d[i].out_mux = MUX_F8; + else if (!str_cmp(w2, w2_len, "MC31", ZTERM)) + dev->u.logic.a2d[i].out_mux = MUX_MC31; else return 0; goto inst_2; } diff --git a/libs/helper.c b/libs/helper.c index ab2c6a0..5cf3ca3 100644 --- a/libs/helper.c +++ b/libs/helper.c @@ -245,6 +245,9 @@ const char* lut2bool(const uint64_t lut, int bits, int str_end, first_op; static char str[2048]; + if (!lut) return "0"; + if (lut == 0xFFFFFFFFFFFFFFFFULL) return "1"; + memset(mt, 0, sizeof(mt)); memset(mt_size, 0, sizeof(mt_size)); diff --git a/libs/model.h b/libs/model.h index 6b4c51e..96747a2 100644 --- a/libs/model.h +++ b/libs/model.h @@ -346,9 +346,8 @@ typedef int dev_type_idx_t; // M and L device is always at type index 0, X device // is always at type index 1. -#define DEV_LOGM 0 -#define DEV_LOGL 0 -#define DEV_LOGX 1 +#define DEV_LOG_M_OR_L 0 +#define DEV_LOG_X 1 // All device configuration is structured so that the value // 0 is never a valid configured setting. That way all config @@ -368,14 +367,10 @@ enum { // input: LI_FIRST = 0, - LI_A1 = LI_FIRST, - LI_A2, LI_A3, LI_A4, LI_A5, LI_A6, - LI_B1, LI_B2, LI_B3, LI_B4, LI_B5, - LI_B6, - LI_C1, LI_C2, LI_C3, LI_C4, LI_C5, - LI_C6, - LI_D1, LI_D2, LI_D3, LI_D4, LI_D5, - LI_D6, + LI_A1 = LI_FIRST, LI_A2, LI_A3, LI_A4, LI_A5, LI_A6, + LI_B1, LI_B2, LI_B3, LI_B4, LI_B5, LI_B6, + LI_C1, LI_C2, LI_C3, LI_C4, LI_C5, LI_C6, + LI_D1, LI_D2, LI_D3, LI_D4, LI_D5, LI_D6, LI_AX, LI_BX, LI_CX, LI_DX, LI_CLK, LI_CE, LI_SR, // only for L and M: @@ -410,7 +405,7 @@ enum { enum { LUT_A = 0, LUT_B, LUT_C, LUT_D }; // offset into a2d[] enum { FF_SRINIT0 = 1, FF_SRINIT1 }; -enum { MUX_O6 = 1, MUX_O5, MUX_5Q, MUX_X, MUX_F7, MUX_CY, MUX_XOR }; +enum { MUX_O6 = 1, MUX_O5, MUX_5Q, MUX_X, MUX_CY, MUX_XOR, MUX_F7, MUX_F8, MUX_MC31 }; enum { FF_OR2L = 1, FF_AND2L, FF_LATCH, FF_FF }; enum { CY0_X = 1, CY0_O5 }; enum { CLKINV_B = 1, CLKINV_CLK }; @@ -422,12 +417,12 @@ enum { PRECYINIT_0 = 1, PRECYINIT_1, PRECYINIT_AX }; struct fpgadev_logic_a2d { - int used; + int out_used; char* lut6; char* lut5; - int ff_mux; // O6, O5, X, F7, CY, XOR + int ff_mux; // O6, O5, X, F7(a/c), F8(b), MC31(d), CY, XOR int ff_srinit; // SRINIT0, SRINIT1 - int out_mux; // O6, O5, 5Q, F7, CY, XOR + int out_mux; // O6, O5, 5Q, F7(a/c), F8(b), MC31(d), CY, XOR int ff; // OR2L, AND2L, LATCH, FF int cy0; // X, O5 }; @@ -492,6 +487,10 @@ struct fpgadev_iob typedef int pinw_idx_t; // index into pinw array +// A bram dev has about 190 pinwires (input and output +// combined), macc about 350, mcb about 1200. +#define MAX_NUM_PINW 2048 + struct fpga_device { enum fpgadev_type type; @@ -501,8 +500,6 @@ struct fpga_device int subtype; int instantiated; - // A bram dev has about 190 pinwires (input and output - // combined), macc about 350, mcb about 1200. int num_pinw_total, num_pinw_in; // The array holds first the input wires, then the output wires. // Unused members are set to STRIDX_NO_ENTRY. diff --git a/libs/model_devices.c b/libs/model_devices.c index e43c864..029bb18 100644 --- a/libs/model_devices.c +++ b/libs/model_devices.c @@ -284,7 +284,8 @@ int init_devices(struct fpga_model* model) if (!is_atx(X_FABRIC_LOGIC_COL|X_CENTER_LOGIC_COL, model, x)) continue; for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { - // M and L are at index 0 (DEV_LOGM and DEV_LOGL), X is at index 1 (DEV_LOGX). + // M and L are at index 0 (DEV_LOG_M_OR_L), + // X is at index 1 (DEV_LOG_X). if (YX_TILE(model, y, x)->flags & TF_LOGIC_XM_DEV) { if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_M))) goto fail; if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_X))) goto fail;