more logic config

This commit is contained in:
Wolfgang Spraul 2012-09-09 03:20:19 +02:00
parent 1d21104b4b
commit 42cd049786
6 changed files with 578 additions and 162 deletions

View File

@ -23,6 +23,7 @@ struct test_state
{
int cmdline_skip;
char cmdline_diff_exec[1024];
int dry_run;
struct fpga_model* model;
// test filenames are: tmp_dir/autotest_<base_name>_<diff_counter>.???
@ -38,16 +39,18 @@ static int dump_file(const char* path)
printf("\n");
printf("O begin dump %s\n", path);
f = fopen(path, "r");
EXIT(!f);
while (fgets(line, sizeof(line), f)) {
if (!strncmp(line, "--- ", 4)
|| !strncmp(line, "+++ ", 4)
|| !strncmp(line, "@@ ", 3))
continue;
printf(line);
if (!(f = fopen(path, "r")))
printf("#E error opening %s\n", path);
else {
while (fgets(line, sizeof(line), f)) {
if (!strncmp(line, "--- ", 4)
|| !strncmp(line, "+++ ", 4)
|| !strncmp(line, "@@ ", 3))
continue;
printf(line);
}
fclose(f);
}
fclose(f);
printf("O end dump %s\n", path);
return 0;
}
@ -66,9 +69,12 @@ static int diff_printf(struct test_state* tstate)
FILE* dest_f = 0;
int rc;
if (tstate->dry_run) {
printf("O Dry run, skipping diff %i.\n", tstate->next_diff_counter++);
return 0;
}
if (tstate->cmdline_skip >= tstate->next_diff_counter) {
printf("O Skipping diff %i.\n", tstate->next_diff_counter);
tstate->next_diff_counter++;
printf("O Skipping diff %i.\n", tstate->next_diff_counter++);
return 0;
}
@ -101,6 +107,8 @@ static int diff_printf(struct test_state* tstate)
if (rc) {
printf("#E %s:%i system call '%s' failed with code %i, "
"check %s.log\n", __FILE__, __LINE__, tmp, rc, path);
// ENOENT comes back when pressing ctrl-c
if (rc == ENOENT) EXIT(rc);
// todo: report the error up so we can avoid adding a switch to the block list etc.
}
@ -118,7 +126,6 @@ fail:
// goal: configure logic devices in all supported variations
static 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;
@ -126,17 +133,53 @@ static int test_logic_config(struct test_state* tstate)
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 (j = LUT_A; j <= LUT_D; j++) {
// A1..A6 to A..D
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);
idx_enum[i], j, 6, pf("A%c", k), ZTERM);
if (rc) FAIL(rc);
rc = fdev_set_required_pins(tstate->model, y, x,
DEV_LOGIC, idx_enum[i]);
if (rc) FAIL(rc);
if (tstate->dry_run)
fdev_print_required_pins(tstate->model,
y, x, DEV_LOGIC, idx_enum[i]);
rc = diff_printf(tstate);
if (rc) FAIL(rc);
fdev_delete(tstate->model, y, x, DEV_LOGIC, idx_enum[i]);
}
// A1 to O6 to FF to AQ
rc = fdev_logic_set_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],
j, MUX_O6, FF_SRINIT0);
if (rc) FAIL(rc);
rc = fdev_logic_sync(tstate->model, y, x, idx_enum[i],
SYNCATTR_ASYNC);
if (rc) FAIL(rc);
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]);
if (rc) FAIL(rc);
rc = fdev_logic_srused(tstate->model, y, x, idx_enum[i]);
if (rc) FAIL(rc);
rc = fdev_set_required_pins(tstate->model, y, x,
DEV_LOGIC, idx_enum[i]);
if (rc) FAIL(rc);
if (tstate->dry_run)
fdev_print_required_pins(tstate->model,
y, x, DEV_LOGIC, idx_enum[i]);
rc = diff_printf(tstate);
if (rc) FAIL(rc);
fdev_delete(tstate->model, y, x, DEV_LOGIC, idx_enum[i]);
}
}
return 0;
@ -269,6 +312,10 @@ static int test_logic_net_l2(struct test_state* tstate, int y, int x,
if (m < *l2_done_len)
continue;
l2_done_list[(*l2_done_len)++] = set_l2.sw[l];
if (tstate->dry_run)
printf("l2_done_list %s at %i\n", fpga_switch_print(tstate->model,
switch_to.dest_y, switch_to.dest_x, l2_done_list[(*l2_done_len)-1]),
(*l2_done_len)-1);
// we did the l1 switches in an earlier round, but have to
// redo them before every l2 switch to make a clean diff
@ -305,7 +352,7 @@ static int test_logic_net_l1(struct test_state* tstate, int y, int x,
rc = fdev_set_required_pins(tstate->model, y, x, type, type_idx);
if (rc) FAIL(rc);
if (dbg)
if (tstate->dry_run)
fdev_print_required_pins(tstate->model, y, x, type, type_idx);
dev = fdev_p(tstate->model, y, x, type, type_idx);
@ -320,7 +367,7 @@ static int test_logic_net_l1(struct test_state* tstate, int y, int x,
if (j < *done_pinw_len)
continue;
done_pinw_list[(*done_pinw_len)++] = dev->pinw[dev->pinw_req_for_cfg[i]];
from_to = (i < dev->pinw_req_in) ? SW_TO : SW_FROM;
switch_to.yx_req = YX_ROUTING_TILE;
switch_to.flags = SWTO_YX_DEF;
@ -331,7 +378,7 @@ static int test_logic_net_l1(struct test_state* tstate, int y, int x,
switch_to.from_to = from_to;
rc = fpga_switch_to_yx(&switch_to);
if (rc) FAIL(rc);
if (dbg)
if (tstate->dry_run)
printf_switch_to_result(&switch_to);
rc = fpga_swset_fromto(tstate->model, switch_to.dest_y,
@ -356,7 +403,7 @@ static int test_logic_net_l1(struct test_state* tstate, int y, int x,
set_l1.sw[j], NO_SWITCH);
if (rc) FAIL(rc);
done_sw_list[(*done_sw_len)++] = set_l1.sw[j];
if (dbg)
if (tstate->dry_run)
printf("done_list %s at %i\n", fpga_switch_print(tstate->model,
switch_to.dest_y, switch_to.dest_x, set_l1.sw[j]),
(*done_sw_len)-1);
@ -368,11 +415,10 @@ fail:
}
// goal: use all switches in a routing switchbox
static int test_logic_routing_switches(struct test_state* tstate)
static int test_logic_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;
int y, x, i, j, k, r, rc;
swidx_t done_sw_list[MAX_SWITCHBOX_SIZE];
int done_sw_len;
str16_t done_pinw_list[2000];
@ -381,38 +427,68 @@ static int test_logic_routing_switches(struct test_state* tstate)
y = 68;
x = 13;
// first make one round over all configs with single-level nets only.
done_pinw_len = 0;
done_sw_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++) {
for (r = 0; r <= 1; r++) {
// two rounds:
// r == 0: round over all configs with single-level nets only
// r == 1: second round with two-level nets
done_pinw_len = 0; // reset done pinwires for each round
for (i = 0; i < sizeof(idx_enum)/sizeof(*idx_enum); i++) {
for (j = LUT_A; j <= LUT_D; j++) {
// A1-A6 to A (same for lut B-D)
for (k = '1'; k <= '6'; k++) {
rc = fdev_logic_set_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,
idx_enum[i], done_pinw_list, &done_pinw_len,
done_sw_list, &done_sw_len);
else
rc = test_logic_net_l2(tstate, y, x, DEV_LOGIC,
idx_enum[i], done_pinw_list, &done_pinw_len,
done_sw_list, &done_sw_len);
if (rc) FAIL(rc);
fdev_delete(tstate->model, y, x, DEV_LOGIC, idx_enum[i]);
}
// A1->O6->FF->AQ (same for lut B-D)
rc = fdev_logic_set_lut(tstate->model, y, x,
idx_enum[i], a_to_d[j], pf("A%c", k), ZTERM);
idx_enum[i], j, 6, "A1", ZTERM);
if (rc) FAIL(rc);
rc = test_logic_net_l1(tstate, y, x, DEV_LOGIC,
idx_enum[i], done_pinw_list, &done_pinw_len,
done_sw_list, &done_sw_len);
rc = fdev_logic_FF(tstate->model, y, x, idx_enum[i],
j, MUX_O6, FF_SRINIT0);
if (rc) FAIL(rc);
fdev_delete(tstate->model, y, x, DEV_LOGIC, idx_enum[i]);
}
}
}
// second round with two-level nets
done_pinw_len = 0; // reset done pinwires
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);
rc = fdev_logic_sync(tstate->model, y, x, idx_enum[i],
SYNCATTR_ASYNC);
if (rc) FAIL(rc);
rc = test_logic_net_l2(tstate, y, x, DEV_LOGIC,
idx_enum[i], done_pinw_list, &done_pinw_len,
done_sw_list, &done_sw_len);
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]);
if (rc) FAIL(rc);
rc = fdev_logic_srused(tstate->model, y, x, idx_enum[i]);
if (rc) FAIL(rc);
rc = fdev_set_required_pins(tstate->model, y, x,
DEV_LOGIC, idx_enum[i]);
if (rc) FAIL(rc);
if (!r)
rc = test_logic_net_l1(tstate, y, x, DEV_LOGIC,
idx_enum[i], done_pinw_list, &done_pinw_len,
done_sw_list, &done_sw_len);
else
rc = test_logic_net_l2(tstate, y, x, DEV_LOGIC,
idx_enum[i], done_pinw_list, &done_pinw_len,
done_sw_list, &done_sw_len);
if (rc) FAIL(rc);
fdev_delete(tstate->model, y, x, DEV_LOGIC, idx_enum[i]);
}
@ -431,7 +507,8 @@ static void printf_help(const char* argv_0, const char** available_tests)
"fpgatools automatic test suite\n"
"\n"
"Usage: %s [--test=<name>] [--diff=<diff executable>] [--skip=<num>]\n"
"Default diff executable: " DEFAULT_DIFF_EXEC "\n", argv_0);
" %*s [--dry-run]\n"
"Default diff executable: " DEFAULT_DIFF_EXEC "\n", argv_0, (int) strlen(argv_0), "");
if (available_tests) {
int i = 0;
@ -452,7 +529,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", 0 };
{ "logic_cfg", "logic_sw", 0 };
// flush after every line is better for the autotest
// output, tee, etc.
@ -472,6 +549,7 @@ int main(int argc, char** argv)
tstate.cmdline_skip = -1;
tstate.cmdline_diff_exec[0] = 0;
cmdline_test[0] = 0;
tstate.dry_run = -1;
for (i = 1; i < argc; i++) {
memset(param, 0, sizeof(param));
if (sscanf(argv[i], "--test=%1023c", param) == 1) {
@ -499,6 +577,10 @@ int main(int argc, char** argv)
tstate.cmdline_skip = param_skip;
continue;
}
if (!strcmp(argv[i], "--dry-run")) {
tstate.dry_run = 1;
continue;
}
printf_help(argv[0], available_tests);
return EINVAL;
}
@ -520,6 +602,8 @@ int main(int argc, char** argv)
strcpy(tstate.cmdline_diff_exec, DEFAULT_DIFF_EXEC);
if (tstate.cmdline_skip == -1)
tstate.cmdline_skip = 0;
if (tstate.dry_run == -1)
tstate.dry_run = 0;
//
// test
@ -532,6 +616,7 @@ int main(int argc, char** argv)
printf("O Test: %s\n", cmdline_test);
printf("O Diff: %s\n", tstate.cmdline_diff_exec);
printf("O Skip: %i\n", tstate.cmdline_skip);
printf("O Dry run: %i\n", tstate.dry_run);
printf("\n");
printf("O Time measured in seconds from 0.\n");
g_start_time = time(0);
@ -556,13 +641,13 @@ int main(int argc, char** argv)
rc = test_logic_config(&tstate);
if (rc) FAIL(rc);
}
if (!strcmp(cmdline_test, "routing_sw")) {
rc = test_logic_routing_switches(&tstate);
if (!strcmp(cmdline_test, "logic_sw")) {
rc = test_logic_switches(&tstate);
if (rc) FAIL(rc);
}
// test_iob_config
// test_iologic_routing_switches
// iob_sw: test_iob_switches
// test_iologic_switches
#if 0
// test_swchain:

View File

@ -193,7 +193,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits)
lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 1); }
if (*lut_str) {
rc = fdev_logic_set_lut(model, y, x, DEV_LOGM,
A6_LUT, lut_str, ZTERM);
LUT_A, 6, lut_str, ZTERM);
if (rc) FAIL(rc);
*(uint32_t*)(u8_p+24*FRAME_SIZE+byte_off+4) = 0;
*(uint32_t*)(u8_p+25*FRAME_SIZE+byte_off+4) = 0;
@ -207,7 +207,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits)
lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 1); }
if (*lut_str) {
rc = fdev_logic_set_lut(model, y, x, DEV_LOGM,
B6_LUT, lut_str, ZTERM);
LUT_B, 6, lut_str, ZTERM);
if (rc) FAIL(rc);
*(uint32_t*)(u8_p+21*FRAME_SIZE+byte_off+4) = 0;
*(uint32_t*)(u8_p+22*FRAME_SIZE+byte_off+4) = 0;
@ -221,7 +221,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits)
lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 1); }
if (*lut_str) {
rc = fdev_logic_set_lut(model, y, x, DEV_LOGM,
C6_LUT, lut_str, ZTERM);
LUT_C, 6, lut_str, ZTERM);
if (rc) FAIL(rc);
*(uint32_t*)(u8_p+24*FRAME_SIZE+byte_off) = 0;
*(uint32_t*)(u8_p+25*FRAME_SIZE+byte_off) = 0;
@ -235,7 +235,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits)
lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 1); }
if (*lut_str) {
rc = fdev_logic_set_lut(model, y, x, DEV_LOGM,
D6_LUT, lut_str, ZTERM);
LUT_D, 6, lut_str, ZTERM);
if (rc) FAIL(rc);
*(uint32_t*)(u8_p+21*FRAME_SIZE+byte_off) = 0;
*(uint32_t*)(u8_p+22*FRAME_SIZE+byte_off) = 0;
@ -271,7 +271,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits)
lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); }
if (*lut_str) {
rc = fdev_logic_set_lut(model, y, x, DEV_LOGX,
A6_LUT, lut_str, ZTERM);
LUT_A, 6, lut_str, ZTERM);
if (rc) FAIL(rc);
*(uint32_t*)(u8_p+27*FRAME_SIZE+byte_off+4) = 0;
*(uint32_t*)(u8_p+28*FRAME_SIZE+byte_off+4) = 0;
@ -282,7 +282,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits)
lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); }
if (*lut_str) {
rc = fdev_logic_set_lut(model, y, x, DEV_LOGX,
B6_LUT, lut_str, ZTERM);
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;
}
@ -292,7 +292,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits)
lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); }
if (*lut_str) {
rc = fdev_logic_set_lut(model, y, x, DEV_LOGX,
C6_LUT, lut_str, ZTERM);
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;
}
@ -302,7 +302,7 @@ static int extract_logic(struct fpga_model* model, struct fpga_bits* bits)
lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); }
if (*lut_str) {
rc = fdev_logic_set_lut(model, y, x, DEV_LOGX,
D6_LUT, lut_str, ZTERM);
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;
}

212
control.c
View File

@ -359,6 +359,11 @@ void fdev_print_required_pins(struct fpga_model* model, int y, int x,
dev = fdev_p(model, y, x, type, type_idx);
if (!dev) { HERE(); return; }
// We don't want to reset or write the required pins in this
// function because it is mainly used for debugging purposes
// and the caller should not suddenly be working with old
// required pins when the print() function is not called.
printf("y%02i x%02i %s %i inpin", y, x, fdev_type2str(type), type_idx);
if (!dev->pinw_req_in)
printf(" -\n");
@ -397,13 +402,11 @@ static void add_req_outpin(struct fpga_device* dev, pinw_idx_t pinw_i)
dev->pinw_req_total++;
}
#define MAX_LUT_LEN 512
int fdev_logic_set_lut(struct fpga_model* model, int y, int x, int type_idx,
int which_lut, const char* lut_str, int lut_len)
int lut_a2d, int lut_5or6, const char* lut_str, int lut_len)
{
struct fpga_device* dev;
char** luts;
char** lut_ptr;
int rc;
dev = fdev_p(model, y, x, DEV_LOGIC, type_idx);
@ -411,38 +414,125 @@ int fdev_logic_set_lut(struct fpga_model* model, int y, int x, int type_idx,
rc = reset_required_pins(dev);
if (rc) FAIL(rc);
luts = dev->u.logic.luts;
if (!luts[which_lut]) {
luts[which_lut] = malloc(MAX_LUT_LEN);
if (!luts[which_lut]) {
OUT_OF_MEM();
return -1;
}
lut_ptr = (lut_5or6 == 5)
? &dev->u.logic.a2d[lut_a2d].lut5
: &dev->u.logic.a2d[lut_a2d].lut6;
if (*lut_ptr == 0) {
*lut_ptr = malloc(MAX_LUT_LEN);
if (!(*lut_ptr)) FAIL(ENOMEM);
}
if (lut_len == ZTERM) lut_len = strlen(lut_str);
memcpy(luts[which_lut], lut_str, lut_len);
luts[which_lut][lut_len] = 0;
memcpy(*lut_ptr, lut_str, lut_len);
(*lut_ptr)[lut_len] = 0;
switch (which_lut) {
case A5_LUT:
case A6_LUT:
dev->u.logic.A_used = 1;
break;
case B5_LUT:
case B6_LUT:
dev->u.logic.B_used = 1;
break;
case C5_LUT:
case C6_LUT:
dev->u.logic.C_used = 1;
break;
case D5_LUT:
case D6_LUT:
dev->u.logic.D_used = 1;
break;
default: FAIL(EINVAL);
}
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 lut_a2d, int ff_mux, int srinit)
{
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].ff = FF_FF;
dev->u.logic.a2d[lut_a2d].ff_mux = ff_mux;
dev->u.logic.a2d[lut_a2d].ff_srinit = srinit;
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)
{
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.clk_inv = clk;
dev->instantiated = 1;
return 0;
fail:
return rc;
}
int fdev_logic_sync(struct fpga_model* model, int y, int x, int type_idx,
int sync_attr)
{
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.sync_attr = sync_attr;
dev->instantiated = 1;
return 0;
fail:
return rc;
}
int fdev_logic_ceused(struct fpga_model* model, int y, int x, int type_idx)
{
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.ce_used = 1;
dev->instantiated = 1;
return 0;
fail:
return rc;
}
int fdev_logic_srused(struct fpga_model* model, int y, int x, int type_idx)
{
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.sr_used = 1;
dev->instantiated = 1;
return 0;
fail:
@ -474,23 +564,38 @@ int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type,
rc = reset_required_pins(dev);
if (rc) FAIL(rc);
if (type == DEV_LOGIC) {
if (dev->u.logic.A_used)
add_req_outpin(dev, LO_A);
if (dev->u.logic.B_used)
add_req_outpin(dev, LO_B);
if (dev->u.logic.C_used)
add_req_outpin(dev, LO_C);
if (dev->u.logic.D_used)
add_req_outpin(dev, LO_D);
for (i = 0; i < sizeof(dev->u.logic.luts)
/sizeof(dev->u.logic.luts[0]); i++) {
if (!dev->u.logic.luts[i]) continue;
scan_lut_digits(dev->u.logic.luts[i], digits);
for (j = 0; j < 6; j++) {
// i/2 because luts order is A5-A6 B5-B6, etc.
if (digits[j])
add_req_inpin(dev,
LI_A1+(i/2)*6+j);
if (dev->u.logic.clk_inv)
add_req_inpin(dev, LI_CLK);
if (dev->u.logic.ce_used)
add_req_inpin(dev, LI_CE);
if (dev->u.logic.sr_used)
add_req_inpin(dev, LI_SR);
for (i = LUT_A; i <= LUT_D; i++) {
if (dev->u.logic.a2d[i].used) {
// LO_A..LO_D are in sequence
add_req_outpin(dev, LO_A+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) {
// LI_AX..LI_DX are in sequence
add_req_inpin(dev, LI_AX+i);
}
if (dev->u.logic.a2d[i].lut6) {
scan_lut_digits(dev->u.logic.a2d[i].lut6, 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].lut5) {
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);
}
}
}
}
@ -512,10 +617,11 @@ void fdev_delete(struct fpga_model* model, int y, int x, int type, int type_idx)
dev->pinw_req_total = 0;
dev->pinw_req_in = 0;
if (dev->type == DEV_LOGIC) {
for (i = 0; i < sizeof(dev->u.logic.luts)
/sizeof(dev->u.logic.luts[0]); i++) {
free(dev->u.logic.luts[i]);
dev->u.logic.luts[i] = 0;
for (i = LUT_A; i <= LUT_D; i++) {
free(dev->u.logic.a2d[i].lut6);
dev->u.logic.a2d[i].lut6 = 0;
free(dev->u.logic.a2d[i].lut5);
dev->u.logic.a2d[i].lut5 = 0;
}
}
dev->instantiated = 0;

View File

@ -42,8 +42,24 @@ const char* fdev_pinw_idx2str(int devtype, pinw_idx_t idx);
// we are in a XM or XL column.
const char* fdev_logic_pinstr(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,
int which_lut, const char* lut_str, int lut_len);
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 lut_a2d, int ff_mux, int srinit);
// 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_set_required_pins(struct fpga_model* model, int y, int x, int type,
int type_idx);
void fdev_print_required_pins(struct fpga_model* model, int y, int x,

View File

@ -287,14 +287,13 @@ inst_2:
return 2;
}
static const char* s_fplut_str[] = FP_LUT_STR;
static int printf_LOGIC(FILE* f, struct fpga_model* model,
int y, int x, int config_only)
{
struct fpga_tile* tile;
struct fpgadev_logic* cfg;
char pref[256];
int type_count, i, j;
int type_count, i, j, rc;
tile = YX_TILE(model, y, x);
type_count = 0;
@ -323,71 +322,253 @@ static int printf_LOGIC(FILE* f, struct fpga_model* model,
default: EXIT(1);
}
}
if (tile->devs[i].u.logic.A_used)
fprintf(f, "%s A_used\n", pref);
if (tile->devs[i].u.logic.B_used)
fprintf(f, "%s B_used\n", pref);
if (tile->devs[i].u.logic.C_used)
fprintf(f, "%s C_used\n", pref);
if (tile->devs[i].u.logic.D_used)
fprintf(f, "%s D_used\n", pref);
{
for (j = 0; j < sizeof(tile->devs[i].u.logic.luts)
/ sizeof(tile->devs[i].u.logic.luts[0]); j++) {
if (tile->devs[i].u.logic.luts[j]
&& tile->devs[i].u.logic.luts[j][0])
fprintf(f, "%s %s %s\n", pref,
s_fplut_str[j],
tile->devs[i].u.logic.luts[j]);
cfg = &tile->devs[i].u.logic;
for (j = LUT_A; j <= LUT_D; j++) {
if (cfg->a2d[j].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,
cfg->a2d[j].lut6);
if (cfg->a2d[j].lut5 && cfg->a2d[j].lut5[0])
fprintf(f, "%s %c5_lut %s\n", pref, 'A'+j,
cfg->a2d[j].lut5);
switch (cfg->a2d[j].ff_mux) {
case MUX_O6:
fprintf(f, "%s %c_ffmux O6\n", pref, 'A'+j);
break;
case MUX_O5:
fprintf(f, "%s %c_ffmux O5\n", pref, 'A'+j);
break;
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 0: break; default: FAIL(EINVAL);
}
switch (cfg->a2d[j].ff_srinit) {
case FF_SRINIT0:
fprintf(f, "%s %c_ffsrinit 0\n", pref, 'A'+j);
break;
case FF_SRINIT1:
fprintf(f, "%s %c_ffsrinit 1\n", pref, 'A'+j);
break;
case 0: break; default: FAIL(EINVAL);
}
switch (cfg->a2d[j].out_mux) {
case MUX_O6:
fprintf(f, "%s %c_outmux O6\n", pref, 'A'+j);
break;
case MUX_O5:
fprintf(f, "%s %c_outmux O5\n", pref, 'A'+j);
break;
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 0: break; default: FAIL(EINVAL);
}
switch (cfg->a2d[j].ff) {
case FF_OR2L:
fprintf(f, "%s %c_ff OR2L\n", pref, 'A'+j);
break;
case FF_AND2L:
fprintf(f, "%s %c_ff AND2L\n", pref, 'A'+j);
break;
case FF_LATCH:
fprintf(f, "%s %c_ff LATCH\n", pref, 'A'+j);
break;
case FF_FF:
fprintf(f, "%s %c_ff FF\n", pref, 'A'+j);
break;
case 0: break; default: FAIL(EINVAL);
}
}
switch (cfg->clk_inv) {
case CLKINV_B:
fprintf(f, "%s clk CLK_B\n", pref);
break;
case CLKINV_CLK:
fprintf(f, "%s clk CLK\n", pref);
break;
case 0: break; default: FAIL(EINVAL);
}
switch (cfg->sync_attr) {
case SYNCATTR_SYNC:
fprintf(f, "%s sync SYNC\n", pref);
break;
case SYNCATTR_ASYNC:
fprintf(f, "%s sync ASYNC\n", pref);
break;
case 0: break; default: FAIL(EINVAL);
}
if (cfg->ce_used)
fprintf(f, "%s ce_used\n", pref);
if (cfg->sr_used)
fprintf(f, "%s sr_used\n", pref);
switch (cfg->we_mux) {
case WEMUX_WE:
fprintf(f, "%s wemux WE\n", pref);
break;
case WEMUX_CE:
fprintf(f, "%s wemux CE\n", pref);
break;
case 0: break; default: FAIL(EINVAL);
}
}
return 0;
fail:
return rc;
}
static int read_LOGIC_attr(struct fpga_model* model, int y, int x, int type_idx,
const char* w1, int w1_len, const char* w2, int w2_len)
{
struct fpga_device* dev;
char cmp_str[128];
int i, rc;
dev = fdev_p(model, y, x, DEV_LOGIC, type_idx);
if (!dev) { HERE(); return 0; }
// First the one-word attributes.
if (!str_cmp(w1, w1_len, "A_used", ZTERM)) {
dev->u.logic.A_used = 1;
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;
goto inst_1;
}
}
if (!str_cmp(w1, w1_len, "ce_used", ZTERM)) {
dev->u.logic.ce_used = 1;
goto inst_1;
}
if (!str_cmp(w1, w1_len, "B_used", ZTERM)) {
dev->u.logic.B_used = 1;
goto inst_1;
}
if (!str_cmp(w1, w1_len, "C_used", ZTERM)) {
dev->u.logic.C_used = 1;
goto inst_1;
}
if (!str_cmp(w1, w1_len, "D_used", ZTERM)) {
dev->u.logic.D_used = 1;
if (!str_cmp(w1, w1_len, "sr_used", ZTERM)) {
dev->u.logic.sr_used = 1;
goto inst_1;
}
// The remaining attributes all require 2 words.
if (w2_len < 1) return 0;
if (!str_cmp(w1, w1_len, "type", ZTERM))
return 2; // no reason for instantiation
for (i = 0; i < sizeof(dev->u.logic.luts)/sizeof(dev->u.logic.luts[0]); i++) {
if (!str_cmp(w1, w1_len, s_fplut_str[i], ZTERM)) {
rc = fdev_logic_set_lut(model, y, x, type_idx, i, w2, w2_len);
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);
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);
if (rc) return 0;
goto inst_2;
}
snprintf(cmp_str, sizeof(cmp_str), "%c_ffmux", 'A'+i);
if (!str_cmp(w1, w1_len, cmp_str, ZTERM)) {
if (!str_cmp(w2, w2_len, "O6", ZTERM))
dev->u.logic.a2d[i].ff_mux = MUX_O6;
else if (!str_cmp(w2, w2_len, "O5", ZTERM))
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 return 0;
goto inst_2;
}
snprintf(cmp_str, sizeof(cmp_str), "%c_ffsrinit", 'A'+i);
if (!str_cmp(w1, w1_len, cmp_str, ZTERM)) {
if (!str_cmp(w2, w2_len, "0", ZTERM))
dev->u.logic.a2d[i].ff_srinit = FF_SRINIT0;
else if (!str_cmp(w2, w2_len, "1", ZTERM))
dev->u.logic.a2d[i].ff_srinit = FF_SRINIT1;
else return 0;
goto inst_2;
}
snprintf(cmp_str, sizeof(cmp_str), "%c_outmux", 'A'+i);
if (!str_cmp(w1, w1_len, cmp_str, ZTERM)) {
if (!str_cmp(w2, w2_len, "O6", ZTERM))
dev->u.logic.a2d[i].out_mux = MUX_O6;
if (!str_cmp(w2, w2_len, "O5", ZTERM))
dev->u.logic.a2d[i].out_mux = MUX_O5;
if (!str_cmp(w2, w2_len, "5Q", ZTERM))
dev->u.logic.a2d[i].out_mux = MUX_5Q;
if (!str_cmp(w2, w2_len, "F7", ZTERM))
dev->u.logic.a2d[i].out_mux = MUX_F7;
if (!str_cmp(w2, w2_len, "CY", ZTERM))
dev->u.logic.a2d[i].out_mux = MUX_CY;
if (!str_cmp(w2, w2_len, "XOR", ZTERM))
dev->u.logic.a2d[i].out_mux = MUX_XOR;
else return 0;
goto inst_2;
}
snprintf(cmp_str, sizeof(cmp_str), "%c_ff", 'A'+i);
if (!str_cmp(w1, w1_len, cmp_str, ZTERM)) {
if (!str_cmp(w2, w2_len, "OR2L", ZTERM))
dev->u.logic.a2d[i].ff = FF_OR2L;
if (!str_cmp(w2, w2_len, "AND2L", ZTERM))
dev->u.logic.a2d[i].ff = FF_AND2L;
if (!str_cmp(w2, w2_len, "LATCH", ZTERM))
dev->u.logic.a2d[i].ff = FF_LATCH;
if (!str_cmp(w2, w2_len, "FF", ZTERM))
dev->u.logic.a2d[i].ff = FF_FF;
else return 0;
goto inst_2;
}
}
if (!str_cmp(w1, w1_len, "clk", ZTERM)) {
if (!str_cmp(w2, w2_len, "CLK_B", ZTERM))
dev->u.logic.clk_inv = CLKINV_B;
else if (!str_cmp(w2, w2_len, "CLK", ZTERM))
dev->u.logic.clk_inv = CLKINV_CLK;
else return 0;
goto inst_2;
}
if (!str_cmp(w1, w1_len, "sync", ZTERM)) {
if (!str_cmp(w2, w2_len, "SYNC", ZTERM))
dev->u.logic.sync_attr = SYNCATTR_SYNC;
else if (!str_cmp(w2, w2_len, "ASYNC", ZTERM))
dev->u.logic.sync_attr = SYNCATTR_ASYNC;
else return 0;
goto inst_2;
}
if (!str_cmp(w1, w1_len, "wemux", ZTERM)) {
if (!str_cmp(w2, w2_len, "WE", ZTERM))
dev->u.logic.we_mux = WEMUX_WE;
else if (!str_cmp(w2, w2_len, "CE", ZTERM))
dev->u.logic.we_mux = WEMUX_CE;
else return 0;
goto inst_2;
}
return 0;
inst_1:
dev->instantiated = 1;
return 1;
inst_2:
dev->instantiated = 2;
dev->instantiated = 1;
return 2;
}

48
model.h
View File

@ -338,6 +338,10 @@ typedef int dev_type_idx_t;
#define NO_DEV -1
#define FPGA_DEV(model, y, x, dev_idx) (&YX_TILE(model, y, x)->devs[dev_idx])
//
// logic device
//
// M and L device is always at type index 0, X device
// is always at type index 1.
#define DEV_LOGM 0
@ -394,21 +398,41 @@ enum { // input:
"AQ", "BQ", "CQ", "DQ", \
"COUT" }
// offsets into fpgadev_logic:luts[], also hardcoded in
// control.c:fdev_set_required_pins(), where we assume
// that div2 will lead to A-D
enum { A5_LUT = 0, A6_LUT, B5_LUT, B6_LUT,
C5_LUT, C6_LUT, D5_LUT, D6_LUT, NUM_LUTS };
#define FP_LUT_STR \
{ "A5_lut", "A6_lut", "B5_lut", "B6_lut", \
"C5_lut", "C6_lut", "D5_lut", "D6_lut" }
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 { FF_OR2L = 1, FF_AND2L, FF_LATCH, FF_FF };
enum { CLKINV_B = 1, CLKINV_CLK };
enum { SYNCATTR_SYNC = 1, SYNCATTR_ASYNC };
enum { WEMUX_WE = 1, WEMUX_CE };
#define MAX_LUT_LEN 2048
struct fpgadev_logic_a2d
{
int used;
char* lut6;
char* lut5;
int ff_mux; // O6, O5, X, F7, CY, XOR
int ff_srinit; // SRINIT0, SRINIT1
int out_mux; // O6, O5, 5Q, F7, CY, XOR
int ff; // OR2L, AND2L, LATCH, FF
};
struct fpgadev_logic
{
int A_used, B_used, C_used, D_used;
char* luts[NUM_LUTS];
struct fpgadev_logic_a2d a2d[4];
int clk_inv; // CLKINV_B, CLKINV_CLK
int sync_attr; // SYNCATTR_SYNC, SYNCATTR_ASYNC
int ce_used;
int sr_used;
int we_mux; // WEMUX_WE, WEMUX_CE
};
//
// iob device
//
enum { IOBM = 1, IOBS };
typedef char IOSTANDARD[32];
#define IO_LVCMOS33 "LVCMOS33"
@ -446,6 +470,10 @@ struct fpgadev_iob
int out_term;
};
//
// fpga_device
//
typedef int pinw_idx_t; // index into pinw array
struct fpga_device