added lut_encoding tests
This commit is contained in:
parent
fd21f8ce9d
commit
3c04a14023
196
autotest.c
196
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<<j)))
|
||||
lut_str[lut_str_len++] = '~';
|
||||
lut_str[lut_str_len++] = 'A';
|
||||
lut_str[lut_str_len++] = '1' + j;
|
||||
}
|
||||
lut_str[lut_str_len] = 0;
|
||||
rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i],
|
||||
lut, lut_str, /*lut5*/ 0);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
// lut6 and lut5 pairs
|
||||
i = 0;
|
||||
while (lut5_parents[i]) {
|
||||
rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i],
|
||||
lut, /*lut6*/ lut5_parents[i], /*lut5*/ "0");
|
||||
if (rc) FAIL(rc);
|
||||
rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i],
|
||||
lut, /*lut6*/ lut5_parents[i], /*lut5*/ "1");
|
||||
if (rc) FAIL(rc);
|
||||
for (j = '1'; j <= '5'; j++) {
|
||||
snprintf(lut_str, sizeof(lut_str), "A%c", j);
|
||||
rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i],
|
||||
lut, /*lut6*/ lut5_parents[i], /*lut5*/ lut_str);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
for (j = 0; j < 32; j++) {
|
||||
lut_str_len = 0;
|
||||
for (k = 0; k < 5; k++) {
|
||||
if (lut_str_len)
|
||||
lut_str[lut_str_len++] = '*';
|
||||
if (!(j & (1<<k)))
|
||||
lut_str[lut_str_len++] = '~';
|
||||
lut_str[lut_str_len++] = 'A';
|
||||
lut_str[lut_str_len++] = '1' + k;
|
||||
}
|
||||
lut_str[lut_str_len] = 0;
|
||||
rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i],
|
||||
lut, /*lut6*/ lut5_parents[i], /*lut5*/ lut_str);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define DEFAULT_DIFF_EXEC "./autotest_diff.sh"
|
||||
|
||||
static void printf_help(const char* argv_0, const char** available_tests)
|
||||
|
@ -1016,7 +1162,7 @@ int main(int argc, char** argv)
|
|||
char param[1024], cmdline_test[1024];
|
||||
int i, param_skip, rc;
|
||||
const char* available_tests[] =
|
||||
{ "logic_cfg", "routing_sw", "io_sw", "iob_cfg", 0 };
|
||||
{ "logic_cfg", "routing_sw", "io_sw", "iob_cfg", "lut_encoding", 0 };
|
||||
|
||||
// flush after every line is better for the autotest
|
||||
// output, tee, etc.
|
||||
|
@ -1141,6 +1287,10 @@ int main(int argc, char** argv)
|
|||
rc = test_iob_config(&tstate);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
if (!strcmp(cmdline_test, "lut_encoding")) {
|
||||
rc = test_lut_encoding(&tstate);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("O Test completed.\n");
|
||||
|
|
|
@ -39,11 +39,9 @@ int main(int argc, char** argv)
|
|||
|
||||
logic_y = 68;
|
||||
logic_x = 13;
|
||||
logic_type_idx = DEV_LOGX;
|
||||
if ((rc = fdev_logic_set_lut(&model, logic_y, logic_x, logic_type_idx,
|
||||
logic_type_idx = DEV_LOG_X;
|
||||
if ((rc = fdev_logic_a2d_lut(&model, logic_y, logic_x, logic_type_idx,
|
||||
LUT_D, 6, "A3*A5", ZTERM))) FAIL(rc);
|
||||
if ((rc = fdev_logic_out_used(&model, logic_y, logic_x, logic_type_idx,
|
||||
LUT_D))) FAIL(rc);
|
||||
|
||||
if ((rc = fnet_new(&model, &inA_net))) FAIL(rc);
|
||||
if ((rc = fnet_add_port(&model, inA_net, iob_inA_y, iob_inA_x,
|
||||
|
|
|
@ -39,11 +39,9 @@ int main(int argc, char** argv)
|
|||
|
||||
logic_y = 68;
|
||||
logic_x = 13;
|
||||
logic_type_idx = DEV_LOGX;
|
||||
if ((rc = fdev_logic_set_lut(&model, logic_y, logic_x, logic_type_idx,
|
||||
logic_type_idx = DEV_LOG_X;
|
||||
if ((rc = fdev_logic_a2d_lut(&model, logic_y, logic_x, logic_type_idx,
|
||||
LUT_D, 6, "A3*A5", ZTERM))) FAIL(rc);
|
||||
if ((rc = fdev_logic_out_used(&model, logic_y, logic_x, logic_type_idx,
|
||||
LUT_D))) FAIL(rc);
|
||||
|
||||
if ((rc = fnet_new(&model, &inA_net))) FAIL(rc);
|
||||
if ((rc = fnet_add_port(&model, inA_net, iob_inA_y, iob_inA_x,
|
||||
|
|
|
@ -354,7 +354,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits)
|
|||
if (row_pos >= 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) {
|
||||
|
|
249
libs/control.c
249
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)
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
31
libs/model.h
31
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.
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user