diff --git a/autotest.c b/autotest.c index 0f9ca23..79025b9 100644 --- a/autotest.c +++ b/autotest.c @@ -46,7 +46,6 @@ static int dump_file(const char* path) } fclose(f); printf("O end dump %s\n", path); - printf("\n"); return 0; } @@ -103,6 +102,151 @@ fail: return rc; } +static void cut_sw_from_end(struct fpga_net* net, int cut_o) +{ + if (cut_o <= 2) return; + memmove(&net->el[2], &net->el[cut_o], + (net->len-cut_o)*sizeof(net->el[0])); + net->len = 2 + net->len-cut_o; +} + +static int test_net(struct test_state* tstate, net_idx_t net_i) +{ + struct fpga_net* net; + struct fpga_net copy_net; + swidx_t same_sw[64]; + int same_len; + int i, j, rc; + + net = fpga_net_get(tstate->model, net_i); + if (!net) FAIL(EINVAL); + copy_net = *net; + + for (i = net->len-1; i >= 2; i--) { + printf("round i %i\n", i); + *net = copy_net; + cut_sw_from_end(net, i); + if (net->len <= 2) { + rc = diff_printf(tstate); + if (rc) FAIL(rc); + continue; + } + // what other switches go to SW_TO(el[2])? + printf_swchain(tstate->model, + net->el[2].y, net->el[2].x, + fpga_switch_str_i(tstate->model, + net->el[2].y, net->el[2].x, + net->el[2].idx, SW_TO), 1, SW_TO); + same_len = sizeof(same_sw)/sizeof(*same_sw); + rc = fpga_switch_same_fromto(tstate->model, + net->el[2].y, net->el[2].x, + net->el[2].idx, SW_TO, same_sw, &same_len); + if (rc) FAIL(rc); + printf("same_len at this level %i\n", same_len); + for (j = 0; j < same_len; j++) { + net->el[2].idx = same_sw[j]; + rc = diff_printf(tstate); + if (rc) FAIL(rc); + } + } + return 0; +fail: + return rc; +} + +static int test_net2(struct test_state* tstate, net_idx_t net_i) +{ + struct fpga_net* net; + struct fpga_net copy_net; + swidx_t same_sw[64]; + int same_len; + int i, j, rc; + + net = fpga_net_get(tstate->model, net_i); + if (!net) FAIL(EINVAL); + copy_net = *net; + + for (i = 3; i <= net->len-1; i++) { + printf("round i %i\n", i); + net->len = i; + // what other switches go from SW_FROM(el[i-1])? + printf_swchain(tstate->model, + net->el[i-1].y, net->el[i-1].x, + fpga_switch_str_i(tstate->model, + net->el[i-1].y, net->el[i-1].x, + net->el[i-1].idx, SW_FROM), 1, SW_FROM); + same_len = sizeof(same_sw)/sizeof(*same_sw); + rc = fpga_switch_same_fromto(tstate->model, + net->el[i-1].y, net->el[i-1].x, + net->el[i-1].idx, SW_FROM, same_sw, &same_len); + if (rc) FAIL(rc); + printf("same_len at this level %i\n", same_len); +#if 1 + for (j = 0; j < same_len; j++) { + net->el[i-1].idx = same_sw[j]; + rc = diff_printf(tstate); + if (rc) FAIL(rc); + } +#endif + *net = copy_net; + } + return 0; +fail: + return rc; +} + +static void fdev_print_required_pins(struct fpga_model* model, int y, int x, + int type, int type_idx) +{ + struct fpga_device* dev; + int i; + + dev = fdev_p(model, y, x, type, type_idx); + if (!dev) { HERE(); return; } + + printf("y%02i x%02i %s %i inpin", y, x, fdev_type2str(type), type_idx); + if (!dev->pinw_req_in) + printf(" -\n"); + else { + for (i = 0; i < dev->pinw_req_in; i++) + printf(" %s", fdev_pinw_idx2str(type, dev->pinw_req_for_cfg[i])); + printf("\n"); + } + + printf("y%02i x%02i %s %i outpin", y, x, fdev_type2str(type), type_idx); + if (dev->pinw_req_total <= dev->pinw_req_in) + printf(" -\n"); + else { + for (i = dev->pinw_req_in; i < dev->pinw_req_total; i++) + printf(" %s", fdev_pinw_idx2str(type, dev->pinw_req_for_cfg[i])); + printf("\n"); + } +} + +static int test_all_logic_configs(struct test_state* tstate) +{ + int y, x, rc; + +// todo: goal: configure valid logic with as many possible in and out +// pins, for M and X device + y = 68; + x = 13; + + rc = fdev_logic_set_lut(tstate->model, y, x, + DEV_LOGX, D6_LUT, "A3", ZTERM); + if (rc) FAIL(rc); + + rc = fdev_set_required_pins(tstate->model, y, x, DEV_LOGIC, DEV_LOGX); + if (rc) FAIL(rc); + + fdev_print_required_pins(tstate->model, y, x, DEV_LOGIC, DEV_LOGX); + rc = diff_printf(tstate); + if (rc) FAIL(rc); + return 0; +fail: + return rc; +} + int main(int argc, char** argv) { struct fpga_model model; @@ -113,6 +257,11 @@ int main(int argc, char** argv) struct switch_to_yx switch_to; net_idx_t P46_net; + // flush after every line is better for the autotest + // output, tee, etc. + // for example: ./autotest 2>&1 | tee autotest.log + setvbuf(stdout, /*buf*/ 0, _IOLBF, /*size*/ 0); + printf("\n"); printf("O fpgatools automatic test suite. Be welcome and be " "our guest. namo namaha.\n"); @@ -136,6 +285,7 @@ int main(int argc, char** argv) rc = diff_start(&tstate, "and"); if (rc) FAIL(rc); +#if 0 // configure P46 rc = fpga_find_iob(&model, "P46", &P46_y, &P46_x, &P46_type_idx); if (rc) FAIL(rc); @@ -159,8 +309,12 @@ int main(int argc, char** argv) P48_dev->iob.O_used = 1; P48_dev->iob.slew = SLEW_SLOW; P48_dev->iob.suspend = SUSP_3STATE; +#endif // configure logic +// todo: goal: configure valid logic with as many possible in and out +// pins, for M and X device +#if 0 logic_dev_idx = fpga_dev_idx(&model, /*y*/ 68, /*x*/ 13, DEV_LOGIC, DEV_LOGX); if (logic_dev_idx == NO_DEV) FAIL(EINVAL); @@ -169,10 +323,16 @@ int main(int argc, char** argv) logic_dev->logic.D_used = 1; rc = fpga_set_lut(&model, logic_dev, D6_LUT, "A3", ZTERM); if (rc) FAIL(rc); - - rc = diff_printf(&tstate); +#endif + rc = test_all_logic_configs(&tstate); if (rc) FAIL(rc); +#if 0 + rc = diff_printf(&tstate); + if (rc) FAIL(rc); +#endif + +#if 0 // configure net from P46.I to logic.D3 rc = fpga_net_new(&model, &P46_net); if (rc) FAIL(rc); @@ -253,8 +413,9 @@ int main(int argc, char** argv) if (rc) FAIL(rc); } - rc = diff_printf(&tstate); + rc = test_net2(&tstate, P46_net); if (rc) FAIL(rc); +#endif printf("\n"); printf("O Test suite completed.\n"); diff --git a/bit_frames.c b/bit_frames.c index 706a0d5..347c15d 100644 --- a/bit_frames.c +++ b/bit_frames.c @@ -111,19 +111,19 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits) if ((u32_p[0] & 0xFFFFFF7F) == 0x00000100 && u32_p[1] == 0x06001100) { dev->instantiated = 1; - strcpy(dev->iob.ostandard, IO_LVCMOS33); - dev->iob.drive_strength = 12; - dev->iob.O_used = 1; - dev->iob.slew = SLEW_SLOW; - dev->iob.suspend = SUSP_3STATE; + strcpy(dev->u.iob.ostandard, IO_LVCMOS33); + dev->u.iob.drive_strength = 12; + dev->u.iob.O_used = 1; + dev->u.iob.slew = SLEW_SLOW; + dev->u.iob.suspend = SUSP_3STATE; u32_p[0] = 0; u32_p[1] = 0; } else if (u32_p[0] == 0x00000107 && u32_p[1] == 0x0B002400) { dev->instantiated = 1; - strcpy(dev->iob.istandard, IO_LVCMOS33); - dev->iob.bypass_mux = BYPASS_MUX_I; - dev->iob.I_mux = IMUX_I; + strcpy(dev->u.iob.istandard, IO_LVCMOS33); + dev->u.iob.bypass_mux = BYPASS_MUX_I; + dev->u.iob.I_mux = IMUX_I; u32_p[0] = 0; u32_p[1] = 0; } else HERE(); @@ -177,16 +177,15 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits) dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGX); if (dev_idx == NO_DEV) FAIL(EINVAL); dev = FPGA_DEV(model, y, x, dev_idx); - dev->instantiated = 1; *(uint64_t*)(u8_p+26*FRAME_SIZE+byte_off) = 0; 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 = fpga_set_lut(model, dev, A6_LUT, lut_str, ZTERM); + rc = fdev_logic_set_lut(model, y, x, DEV_LOGX, + A6_LUT, lut_str, ZTERM); if (rc) FAIL(rc); - dev->logic.A_used = 1; *(uint32_t*)(u8_p+27*FRAME_SIZE+byte_off+4) = 0; *(uint32_t*)(u8_p+28*FRAME_SIZE+byte_off+4) = 0; } @@ -194,9 +193,8 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits) { int logic_base[6] = {1,1,0,1,1,0}; lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); } if (*lut_str) { - rc = fpga_set_lut(model, dev, B6_LUT, lut_str, ZTERM); - if (rc) FAIL(rc); - dev->logic.B_used = 1; + rc = fdev_logic_set_lut(model, y, x, DEV_LOGX, + B6_LUT, 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; } @@ -204,9 +202,8 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits) { int logic_base[6] = {0,1,0,0,0,1}; lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); } if (*lut_str) { - rc = fpga_set_lut(model, dev, C6_LUT, lut_str, ZTERM); - if (rc) FAIL(rc); - dev->logic.C_used = 1; + rc = fdev_logic_set_lut(model, y, x, DEV_LOGX, + C6_LUT, lut_str, ZTERM); *(uint32_t*)(u8_p+27*FRAME_SIZE+byte_off) = 0; *(uint32_t*)(u8_p+28*FRAME_SIZE+byte_off) = 0; } @@ -214,9 +211,8 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits) { int logic_base[6] = {0,1,0,0,0,1}; lut_str = lut2bool(u64, 64, &logic_base, /*flip_b0*/ 0); } if (*lut_str) { - rc = fpga_set_lut(model, dev, D6_LUT, lut_str, ZTERM); - if (rc) FAIL(rc); - dev->logic.D_used = 1; + rc = fdev_logic_set_lut(model, y, x, DEV_LOGX, + D6_LUT, lut_str, ZTERM); *(uint32_t*)(u8_p+29*FRAME_SIZE+byte_off) = 0; *(uint32_t*)(u8_p+30*FRAME_SIZE+byte_off) = 0; } diff --git a/control.c b/control.c index 324699b..1363882 100644 --- a/control.c +++ b/control.c @@ -202,14 +202,14 @@ const char* fpga_iob_sitename(struct fpga_model* model, int y, int x, static const char* dev_str[] = FPGA_DEV_STR; -const char* fpgadev_str(enum fpgadev_type type) +const char* fdev_type2str(enum fpgadev_type type) { if (type < 0 || type >= sizeof(dev_str)/sizeof(*dev_str)) { HERE(); return 0; } return dev_str[type]; } -enum fpgadev_type fpgadev_str2type(const char* str, int len) +enum fpgadev_type fdev_str2type(const char* str, int len) { int i; for (i = 0; i < sizeof(dev_str)/sizeof(*dev_str); i++) { @@ -221,6 +221,14 @@ enum fpgadev_type fpgadev_str2type(const char* str, int len) return DEV_NONE; } +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; } + return FPGA_DEV(model, y, x, dev_idx); +} + dev_idx_t fpga_dev_idx(struct fpga_model* model, int y, int x, enum fpgadev_type type, dev_type_idx_t type_idx) { @@ -240,7 +248,7 @@ dev_idx_t fpga_dev_idx(struct fpga_model* model, return NO_DEV; } -dev_type_idx_t fpga_dev_typeidx(struct fpga_model* model, int y, int x, +dev_type_idx_t fdev_typeidx(struct fpga_model* model, int y, int x, dev_idx_t dev_idx) { struct fpga_tile* tile; @@ -258,7 +266,7 @@ dev_type_idx_t fpga_dev_typeidx(struct fpga_model* model, int y, int x, static const char* iob_pinw_str[] = IOB_PINW_STR; static const char* logic_pinw_str[] = LOGIC_PINW_STR; -pinw_idx_t fpgadev_pinw_str2idx(int devtype, const char* str, int len) +pinw_idx_t fdev_pinw_str2idx(int devtype, const char* str, int len) { int i; @@ -284,7 +292,7 @@ pinw_idx_t fpgadev_pinw_str2idx(int devtype, const char* str, int len) return PINW_NO_IDX; } -const char* fpgadev_pinw_idx2str(int devtype, pinw_idx_t idx) +const char* fdev_pinw_idx2str(int devtype, pinw_idx_t idx) { if (devtype == DEV_IOB) { if (idx < 0 || idx >= sizeof(iob_pinw_str)/sizeof(*iob_pinw_str)) { @@ -304,33 +312,106 @@ const char* fpgadev_pinw_idx2str(int devtype, pinw_idx_t idx) return 0; } +static void free_required_pins(struct fpga_device* dev) +{ + free(dev->pinw_req_for_cfg); + dev->pinw_req_for_cfg = 0; + dev->pinw_req_total = 0; + dev->pinw_req_in = 0; +} + #define MAX_LUT_LEN 512 -int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev, +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) { - char** ptr; + struct fpga_device* dev; + char** luts; + int rc; - if (dev->type != DEV_LOGIC) - return -1; - switch (which_lut) { - case A6_LUT: ptr = &dev->logic.A6_lut; break; - case B6_LUT: ptr = &dev->logic.B6_lut; break; - case C6_LUT: ptr = &dev->logic.C6_lut; break; - case D6_LUT: ptr = &dev->logic.D6_lut; break; - default: return -1; - } - if (!(*ptr)) { - *ptr = malloc(MAX_LUT_LEN); - if (!(*ptr)) { + dev = fdev_p(model, y, x, DEV_LOGIC, type_idx); + if (!dev) FAIL(EINVAL); + free_required_pins(dev); + + 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; } } if (lut_len == ZTERM) lut_len = strlen(lut_str); - memcpy(*ptr, lut_str, lut_len); - (*ptr)[lut_len] = 0; + memcpy(luts[which_lut], lut_str, lut_len); + luts[which_lut][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_set_required_pins(struct fpga_model* model, int y, int x, int type, + int type_idx) +{ + struct fpga_device* dev; + int rc; + + dev = fdev_p(model, y, x, type, type_idx); + if (!dev) FAIL(EINVAL); + free_required_pins(dev); + if (type == DEV_LOGIC) { +#if 0 +TODO: + // required pinwires depend on the given config and will + // be deleted/invalidated on any config change. + int pinw_req_total, pinw_req_in; + pinw_idx_t* pinw_req_for_cfg; +#endif + } + return 0; +fail: + return rc; +} + +void fdev_delete(struct fpga_model* model, int y, int x, int type, int type_idx) +{ + struct fpga_device* dev; + int i; + + dev = fdev_p(model, y, x, type, type_idx); + if (!dev) { HERE(); return; } + if (!dev->instantiated) return; + free_required_pins(dev); + 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; + } + } + dev->instantiated = 0; + memset(&dev->u, 0, sizeof(dev->u)); } int fpga_connpt_find(struct fpga_model* model, int y, int x, @@ -422,6 +503,29 @@ swidx_t fpga_switch_backtofirst(struct fpga_model* model, int y, int x, return fpga_switch_search(model, y, x, last, /*search_beg*/ 0, from_to); } +int fpga_switch_same_fromto(struct fpga_model* model, int y, int x, + swidx_t sw, int from_to, swidx_t* same_sw, int *same_len) +{ + swidx_t cur_sw; + int max_len, rc; + + max_len = *same_len; + *same_len = 0; + if (max_len < 1) FAIL(EINVAL); + cur_sw = fpga_switch_search(model, y, x, sw, /*search_beg*/ 0, from_to); + // We should at least fine sw itself, if not something is wrong... + if (cur_sw == NO_SWITCH) FAIL(EINVAL); + + same_sw[(*same_len)++] = cur_sw; + while ((cur_sw = fpga_switch_search(model, y, x, sw, cur_sw+1, from_to)) != NO_SWITCH) { + same_sw[(*same_len)++] = cur_sw; + if ((*same_len) >= max_len) FAIL(EINVAL); + } + return 0; +fail: + return rc; +} + swidx_t fpga_switch_lookup(struct fpga_model* model, int y, int x, str16_t from_str_i, str16_t to_str_i) { @@ -550,24 +654,20 @@ static const char* fmt_swset_el(struct fpga_model* model, int y, int x, char midstr[64]; last_buf = (last_buf+1)%NUM_SW_BUFS; - - strcpy(midstr, fpga_switch_is_used(model, y, x, sw) ? "on:" : ""); if (fpga_switch_is_bidir(model, y, x, sw)) - strcat(midstr, "<->"); - else { - // a 'to-switch' is actually still a switch that physically - // points in the other direction (unless it's a bidir switch), - // so when displaying the 'to-switch', we make the arrow point - // to the left side to match the physical direction. - strcat(midstr, (from_to == SW_TO) ? "<-" : "->"); - } - // fmt_swset_el() prints only the destination side of the switch (!from_to), - // because it is the significant one in a chain of switches, and if the - // caller wants the source side they can add it outside. + strcpy(midstr, "<->"); + else + strcpy(midstr, "->"); + // fmt_swset_el() prints only the destination side of the + // switch (!from_to), because it is the significant one in + // a chain of switches, and if the caller wants the source + // side they can add it outside. snprintf(sw_buf[last_buf], sizeof(sw_buf[0]), "%s%s%s", - (from_to == SW_FROM) ? "" : fpga_switch_str(model, y, x, sw, SW_FROM), + (from_to == SW_FROM) ? "" + : fpga_switch_str(model, y, x, sw, SW_FROM), midstr, - (from_to == SW_TO) ? "" : fpga_switch_str(model, y, x, sw, SW_TO)); + (from_to == SW_TO) ? "" + : fpga_switch_str(model, y, x, sw, SW_TO)); return sw_buf[last_buf]; } @@ -986,13 +1086,13 @@ static void fprintf_inout_pin(FILE* f, struct fpga_model* model, { HERE(); return; } in_pin = pinw_i < tile->devs[dev_idx].num_pinw_in; - pin_str = fpgadev_pinw_idx2str(tile->devs[dev_idx].type, pinw_i); + pin_str = fdev_pinw_idx2str(tile->devs[dev_idx].type, pinw_i); if (!pin_str) { HERE(); return; } snprintf(buf, sizeof(buf), "net %i %s y%02i x%02i %s %i pin %s\n", net_i, in_pin ? "in" : "out", el->y, el->x, - fpgadev_str(tile->devs[dev_idx].type), - fpga_dev_typeidx(model, el->y, el->x, dev_idx), + fdev_type2str(tile->devs[dev_idx].type), + fdev_typeidx(model, el->y, el->x, dev_idx), pin_str); fprintf(f, buf); } diff --git a/control.h b/control.h index e66dd76..54d8854 100644 --- a/control.h +++ b/control.h @@ -17,8 +17,12 @@ const char* fpga_iob_sitename(struct fpga_model* model, int y, int x, // 2. The index of the device within devices of the same type in the tile. // -const char* fpgadev_str(enum fpgadev_type type); -enum fpgadev_type fpgadev_str2type(const char* str, int len); +const char* fdev_type2str(enum fpgadev_type type); +enum fpgadev_type fdev_str2type(const char* str, int len); + +// returns 0 if device not found +struct fpga_device* fdev_p(struct fpga_model* model, + int y, int x, enum fpgadev_type type, dev_type_idx_t type_idx); // Looks up a device index based on the type index. // returns NO_DEV (-1) if not found @@ -27,18 +31,20 @@ dev_idx_t fpga_dev_idx(struct fpga_model* model, // Counts how many devices of the same type as dev_idx are in // the array up to dev_idx. -dev_type_idx_t fpga_dev_typeidx(struct fpga_model* model, int y, int x, +dev_type_idx_t fdev_typeidx(struct fpga_model* model, int y, int x, dev_idx_t dev_idx); #define PINW_NO_IDX -1 -pinw_idx_t fpgadev_pinw_str2idx(int devtype, const char* str, int len); +pinw_idx_t fdev_pinw_str2idx(int devtype, const char* str, int len); // returns 0 when idx not found for the given devtype -const char* fpgadev_pinw_idx2str(int devtype, pinw_idx_t idx); +const char* fdev_pinw_idx2str(int devtype, pinw_idx_t idx); -enum { A6_LUT, B6_LUT, C6_LUT, D6_LUT }; -// lut_len can be -1 (ZTERM) -int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev, +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 fdev_set_required_pins(struct fpga_model* model, int y, int x, int type, + int type_idx); +void fdev_delete(struct fpga_model* model, int y, int x, int type, + int type_idx); // Returns the connpt index or NO_CONN if the name was not // found. connpt_dests_o and num_dests are optional and may @@ -70,6 +76,11 @@ swidx_t fpga_switch_next(struct fpga_model* model, int y, int x, swidx_t last, int from_to); swidx_t fpga_switch_backtofirst(struct fpga_model* model, int y, int x, swidx_t last, int from_to); +// When calling, same_len must contain the size of the +// same_sw array. Upon return same_len returns how many +// switches were found and writen to same_sw. +int fpga_switch_same_fromto(struct fpga_model* model, int y, int x, + swidx_t sw, int from_to, swidx_t* same_sw, int *same_len); swidx_t fpga_switch_lookup(struct fpga_model* model, int y, int x, str16_t from_str_i, str16_t to_str_i); diff --git a/floorplan.c b/floorplan.c index 617b3f4..c6bfbd7 100644 --- a/floorplan.c +++ b/floorplan.c @@ -83,15 +83,15 @@ static int printf_IOB(FILE* f, struct fpga_model* model, if (!config_only) { fprintf(f, "%s type %s\n", pref, - tile->devs[i].iob.subtype == IOBM ? "M" : "S"); + tile->devs[i].subtype == IOBM ? "M" : "S"); } - if (tile->devs[i].iob.istandard[0]) + if (tile->devs[i].u.iob.istandard[0]) fprintf(f, "%s istd %s\n", pref, - tile->devs[i].iob.istandard); - if (tile->devs[i].iob.ostandard[0]) + tile->devs[i].u.iob.istandard); + if (tile->devs[i].u.iob.ostandard[0]) fprintf(f, "%s ostd %s\n", pref, - tile->devs[i].iob.ostandard); - switch (tile->devs[i].iob.bypass_mux) { + tile->devs[i].u.iob.ostandard); + switch (tile->devs[i].u.iob.bypass_mux) { case BYPASS_MUX_I: fprintf(f, "%s bypass_mux I\n", pref); break; @@ -103,7 +103,7 @@ static int printf_IOB(FILE* f, struct fpga_model* model, break; case 0: break; default: EXIT(1); } - switch (tile->devs[i].iob.I_mux) { + switch (tile->devs[i].u.iob.I_mux) { case IMUX_I_B: fprintf(f, "%s imux I_B\n", pref); break; @@ -112,10 +112,10 @@ static int printf_IOB(FILE* f, struct fpga_model* model, break; case 0: break; default: EXIT(1); } - if (tile->devs[i].iob.drive_strength) + if (tile->devs[i].u.iob.drive_strength) fprintf(f, "%s strength %i\n", pref, - tile->devs[i].iob.drive_strength); - switch (tile->devs[i].iob.slew) { + tile->devs[i].u.iob.drive_strength); + switch (tile->devs[i].u.iob.slew) { case SLEW_SLOW: fprintf(f, "%s slew SLOW\n", pref); break; @@ -127,9 +127,9 @@ static int printf_IOB(FILE* f, struct fpga_model* model, break; case 0: break; default: EXIT(1); } - if (tile->devs[i].iob.O_used) + if (tile->devs[i].u.iob.O_used) fprintf(f, "%s O_used\n", pref); - switch (tile->devs[i].iob.suspend) { + switch (tile->devs[i].u.iob.suspend) { case SUSP_LAST_VAL: fprintf(f, "%s suspend DRIVE_LAST_VALUE\n", pref); break; @@ -150,7 +150,7 @@ static int printf_IOB(FILE* f, struct fpga_model* model, break; case 0: break; default: EXIT(1); } - switch (tile->devs[i].iob.in_term) { + switch (tile->devs[i].u.iob.in_term) { case ITERM_NONE: fprintf(f, "%s in_term NONE\n", pref); break; @@ -165,7 +165,7 @@ static int printf_IOB(FILE* f, struct fpga_model* model, break; case 0: break; default: EXIT(1); } - switch (tile->devs[i].iob.out_term) { + switch (tile->devs[i].u.iob.out_term) { case OTERM_NONE: fprintf(f, "%s out_term NONE\n", pref); break; @@ -189,7 +189,7 @@ static int read_IOB_attr(struct fpga_model* model, struct fpga_device* dev, { // First the one-word attributes. if (!str_cmp(w1, w1_len, "O_used", ZTERM)) { - dev->iob.O_used = 1; + dev->u.iob.O_used = 1; goto inst_1; } // The remaining attributes all require 2 words. @@ -197,84 +197,84 @@ static int read_IOB_attr(struct fpga_model* model, struct fpga_device* dev, if (!str_cmp(w1, w1_len, "type", ZTERM)) return 2; // no reason for instantiation if (!str_cmp(w1, w1_len, "istd", ZTERM)) { - memcpy(dev->iob.istandard, w2, w2_len); - dev->iob.istandard[w2_len] = 0; + memcpy(dev->u.iob.istandard, w2, w2_len); + dev->u.iob.istandard[w2_len] = 0; goto inst_2; } if (!str_cmp(w1, w1_len, "ostd", ZTERM)) { - memcpy(dev->iob.ostandard, w2, w2_len); - dev->iob.ostandard[w2_len] = 0; + memcpy(dev->u.iob.ostandard, w2, w2_len); + dev->u.iob.ostandard[w2_len] = 0; goto inst_2; } if (!str_cmp(w1, w1_len, "bypass_mux", ZTERM)) { if (!str_cmp(w2, w2_len, "I", ZTERM)) - dev->iob.bypass_mux = BYPASS_MUX_I; + dev->u.iob.bypass_mux = BYPASS_MUX_I; else if (!str_cmp(w2, w2_len, "O", ZTERM)) - dev->iob.bypass_mux = BYPASS_MUX_O; + dev->u.iob.bypass_mux = BYPASS_MUX_O; else if (!str_cmp(w2, w2_len, "T", ZTERM)) - dev->iob.bypass_mux = BYPASS_MUX_T; + dev->u.iob.bypass_mux = BYPASS_MUX_T; else return 0; goto inst_2; } if (!str_cmp(w1, w1_len, "imux", ZTERM)) { if (!str_cmp(w2, w2_len, "I_B", ZTERM)) - dev->iob.I_mux = IMUX_I_B; + dev->u.iob.I_mux = IMUX_I_B; else if (!str_cmp(w2, w2_len, "I", ZTERM)) - dev->iob.I_mux = IMUX_I; + dev->u.iob.I_mux = IMUX_I; else return 0; goto inst_2; } if (!str_cmp(w1, w1_len, "strength", ZTERM)) { - dev->iob.drive_strength = to_i(w2, w2_len); + dev->u.iob.drive_strength = to_i(w2, w2_len); goto inst_2; } if (!str_cmp(w1, w1_len, "slew", ZTERM)) { if (!str_cmp(w2, w2_len, "SLOW", ZTERM)) - dev->iob.slew = SLEW_SLOW; + dev->u.iob.slew = SLEW_SLOW; else if (!str_cmp(w2, w2_len, "FAST", ZTERM)) - dev->iob.slew = SLEW_FAST; + dev->u.iob.slew = SLEW_FAST; else if (!str_cmp(w2, w2_len, "QUIETIO", ZTERM)) - dev->iob.slew = SLEW_QUIETIO; + dev->u.iob.slew = SLEW_QUIETIO; else return 0; goto inst_2; } if (!str_cmp(w1, w1_len, "suspend", 7)) { if (!str_cmp(w2, w2_len, "DRIVE_LAST_VALUE", ZTERM)) - dev->iob.suspend = SUSP_LAST_VAL; + dev->u.iob.suspend = SUSP_LAST_VAL; else if (!str_cmp(w2, w2_len, "3STATE", ZTERM)) - dev->iob.suspend = SUSP_3STATE; + dev->u.iob.suspend = SUSP_3STATE; else if (!str_cmp(w2, w2_len, "3STATE_PULLUP", ZTERM)) - dev->iob.suspend = SUSP_3STATE_PULLUP; + dev->u.iob.suspend = SUSP_3STATE_PULLUP; else if (!str_cmp(w2, w2_len, "3STATE_PULLDOWN", ZTERM)) - dev->iob.suspend = SUSP_3STATE_PULLDOWN; + dev->u.iob.suspend = SUSP_3STATE_PULLDOWN; else if (!str_cmp(w2, w2_len, "3STATE_KEEPER", ZTERM)) - dev->iob.suspend = SUSP_3STATE_KEEPER; + dev->u.iob.suspend = SUSP_3STATE_KEEPER; else if (!str_cmp(w2, w2_len, "3STATE_OCT_ON", ZTERM)) - dev->iob.suspend = SUSP_3STATE_OCT_ON; + dev->u.iob.suspend = SUSP_3STATE_OCT_ON; else return 0; goto inst_2; } if (!str_cmp(w1, w1_len, "in_term", ZTERM)) { if (!str_cmp(w2, w2_len, "NONE", ZTERM)) - dev->iob.in_term = ITERM_NONE; + dev->u.iob.in_term = ITERM_NONE; else if (!str_cmp(w2, w2_len, "UNTUNED_SPLIT_25", ZTERM)) - dev->iob.in_term = ITERM_UNTUNED_25; + dev->u.iob.in_term = ITERM_UNTUNED_25; else if (!str_cmp(w2, w2_len, "UNTUNED_SPLIT_50", ZTERM)) - dev->iob.in_term = ITERM_UNTUNED_50; + dev->u.iob.in_term = ITERM_UNTUNED_50; else if (!str_cmp(w2, w2_len, "UNTUNED_SPLIT_75", ZTERM)) - dev->iob.in_term = ITERM_UNTUNED_75; + dev->u.iob.in_term = ITERM_UNTUNED_75; else return 0; goto inst_2; } if (!str_cmp(w1, w1_len, "out_term", ZTERM)) { if (!str_cmp(w2, w2_len, "NONE", ZTERM)) - dev->iob.out_term = OTERM_NONE; + dev->u.iob.out_term = OTERM_NONE; else if (!str_cmp(w2, w2_len, "UNTUNED_25", ZTERM)) - dev->iob.out_term = OTERM_UNTUNED_25; + dev->u.iob.out_term = OTERM_UNTUNED_25; else if (!str_cmp(w2, w2_len, "UNTUNED_50", ZTERM)) - dev->iob.out_term = OTERM_UNTUNED_50; + dev->u.iob.out_term = OTERM_UNTUNED_50; else if (!str_cmp(w2, w2_len, "UNTUNED_75", ZTERM)) - dev->iob.out_term = OTERM_UNTUNED_75; + dev->u.iob.out_term = OTERM_UNTUNED_75; else return 0; goto inst_2; } @@ -287,12 +287,14 @@ 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; char pref[256]; - int type_count, i; + int type_count, i, j; tile = YX_TILE(model, y, x); type_count = 0; @@ -308,7 +310,7 @@ static int printf_LOGIC(FILE* f, struct fpga_model* model, type_count++; if (!config_only) { - switch (tile->devs[i].logic.subtype) { + switch (tile->devs[i].subtype) { case LOGIC_X: fprintf(f, "%s type X\n", pref); break; @@ -321,73 +323,64 @@ static int printf_LOGIC(FILE* f, struct fpga_model* model, default: EXIT(1); } } - if (tile->devs[i].logic.A_used) + if (tile->devs[i].u.logic.A_used) fprintf(f, "%s A_used\n", pref); - if (tile->devs[i].logic.B_used) + if (tile->devs[i].u.logic.B_used) fprintf(f, "%s B_used\n", pref); - if (tile->devs[i].logic.C_used) + if (tile->devs[i].u.logic.C_used) fprintf(f, "%s C_used\n", pref); - if (tile->devs[i].logic.D_used) + if (tile->devs[i].u.logic.D_used) fprintf(f, "%s D_used\n", pref); - if (tile->devs[i].logic.A6_lut && tile->devs[i].logic.A6_lut[0]) - fprintf(f, "%s A6_lut %s\n", pref, - tile->devs[i].logic.A6_lut); - if (tile->devs[i].logic.B6_lut && tile->devs[i].logic.B6_lut[0]) - fprintf(f, "%s B6_lut %s\n", pref, - tile->devs[i].logic.B6_lut); - if (tile->devs[i].logic.C6_lut && tile->devs[i].logic.C6_lut[0]) - fprintf(f, "%s C6_lut %s\n", pref, - tile->devs[i].logic.C6_lut); - if (tile->devs[i].logic.D6_lut && tile->devs[i].logic.D6_lut[0]) - fprintf(f, "%s D6_lut %s\n", pref, - tile->devs[i].logic.D6_lut); + { + 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]); + } + } } return 0; } -static int read_LOGIC_attr(struct fpga_model* model, struct fpga_device* dev, +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; + 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->logic.A_used = 1; + dev->u.logic.A_used = 1; goto inst_1; } if (!str_cmp(w1, w1_len, "B_used", ZTERM)) { - dev->logic.B_used = 1; + dev->u.logic.B_used = 1; goto inst_1; } if (!str_cmp(w1, w1_len, "C_used", ZTERM)) { - dev->logic.C_used = 1; + dev->u.logic.C_used = 1; goto inst_1; } if (!str_cmp(w1, w1_len, "D_used", ZTERM)) { - dev->logic.D_used = 1; + dev->u.logic.D_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 - if (!str_cmp(w1, w1_len, "A6_lut", ZTERM)) { - if (fpga_set_lut(model, dev, A6_LUT, w2, w2_len)) - return 0; - goto inst_2; - } - if (!str_cmp(w1, w1_len, "B6_lut", ZTERM)) { - if (fpga_set_lut(model, dev, B6_LUT, w2, w2_len)) - return 0; - goto inst_2; - } - if (!str_cmp(w1, w1_len, "C6_lut", ZTERM)) { - if (fpga_set_lut(model, dev, C6_LUT, w2, w2_len)) - return 0; - goto inst_2; - } - if (!str_cmp(w1, w1_len, "D6_lut", ZTERM)) { - if (fpga_set_lut(model, dev, D6_LUT, w2, w2_len)) - return 0; - goto inst_2; + 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); + if (rc) return 0; + goto inst_2; + } } return 0; inst_1: @@ -419,7 +412,7 @@ int printf_devices(FILE* f, struct fpga_model* model, int config_only) || tile->devs[i].type == DEV_IOB) continue; // handled above fprintf(f, "dev y%02i x%02i %s\n", y, x, - fpgadev_str(tile->devs[i].type)); + fdev_type2str(tile->devs[i].type)); } } } @@ -696,13 +689,13 @@ static void read_net_line(struct fpga_model* model, const char* line, int start) || !all_digits(&line[dev_type_idx_str_beg], dev_type_idx_str_end-dev_type_idx_str_beg) || str_cmp(&line[pin_str_beg], pin_str_end-pin_str_beg, "pin", 3)) { HERE(); return; } - dev_type = fpgadev_str2type(&line[dev_str_beg], dev_str_end-dev_str_beg); + dev_type = fdev_str2type(&line[dev_str_beg], dev_str_end-dev_str_beg); if (dev_type == DEV_NONE) { HERE(); return; } dev_idx = fpga_dev_idx(model, y_coord, x_coord, dev_type, to_i(&line[dev_type_idx_str_beg], dev_type_idx_str_end-dev_type_idx_str_beg)); if (dev_idx == NO_DEV) { HERE(); return; } - pinw_idx = fpgadev_pinw_str2idx(dev_type, &line[pin_name_beg], + pinw_idx = fdev_pinw_str2idx(dev_type, &line[pin_name_beg], pin_name_end-pin_name_beg); if (pinw_idx == PINW_NO_IDX) { HERE(); return; } if (fpga_net_add_port(model, net_idx, y_coord, x_coord, dev_idx, pinw_idx)) @@ -750,7 +743,8 @@ static void read_dev_line(struct fpga_model* model, const char* line, int start) second_end-second_beg); break; case DEV_LOGIC: - words_consumed = read_LOGIC_attr(model, dev_ptr, + words_consumed = read_LOGIC_attr(model, y_coord, + x_coord, dev_type_idx, &line[next_beg], next_end-next_beg, &line[second_beg], second_end-second_beg); diff --git a/model.h b/model.h index 81821b0..f1c5ac3 100644 --- a/model.h +++ b/model.h @@ -385,11 +385,16 @@ enum { // input: "AQ", "BQ", "CQ", "DQ", \ "COUT" } +// offsets into fpgadev_logic:luts[] +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" } + struct fpgadev_logic { - int subtype; // LOGIC_M, LOGIC_L or LOGIC_X int A_used, B_used, C_used, D_used; - char* A6_lut, *B6_lut, *C6_lut, *D6_lut; + char* luts[NUM_LUTS]; }; enum { IOBM = 1, IOBS }; @@ -417,7 +422,6 @@ enum { // input: struct fpgadev_iob { - int subtype; // IOBM or IOBS IOSTANDARD istandard; IOSTANDARD ostandard; int bypass_mux; @@ -435,6 +439,10 @@ typedef int pinw_idx_t; // index into pinw array struct fpga_device { enum fpgadev_type type; + // subtypes: + // IOB: IOBM, IOBS + // LOGIC: LOGIC_M, LOGIC_L, LOGIC_X + int subtype; int instantiated; // A bram dev has about 190 pinwires (input and output @@ -443,11 +451,17 @@ struct fpga_device // The array holds first the input wires, then the output wires. // Unused members are set to STRIDX_NO_ENTRY. str16_t* pinw; + + // required pinwires depend on the given config and will + // be deleted/invalidated on any config change. + int pinw_req_total, pinw_req_in; + pinw_idx_t* pinw_req_for_cfg; + // the rest will be memset to 0 on any device removal/uninstantiation union { struct fpgadev_logic logic; struct fpgadev_iob iob; - }; + } u; }; #define SWITCH_USED 0x80000000 diff --git a/model_devices.c b/model_devices.c index 67b1eae..a3a385f 100644 --- a/model_devices.c +++ b/model_devices.c @@ -11,10 +11,8 @@ static int add_dev(struct fpga_model* model, int y, int x, int type, int subtype); -static int init_iob(struct fpga_model* model, int y, int x, - int idx, int subtype); -static int init_logic(struct fpga_model* model, int y, int x, - int idx, int subtype); +static int init_iob(struct fpga_model* model, int y, int x, int idx); +static int init_logic(struct fpga_model* model, int y, int x, int idx); int init_devices(struct fpga_model* model) { @@ -304,32 +302,26 @@ fail: void free_devices(struct fpga_model* model) { - int i, j; - for (i = 0; i < model->x_width * model->y_height; i++) { - if (!model->tiles[i].num_devs) - continue; - EXIT(!model->tiles[i].devs); - for (j = 0; j < model->tiles[i].num_devs; j++) { - free(model->tiles[i].devs[j].pinw); - model->tiles[i].devs[j].pinw = 0; - model->tiles[i].devs[j].num_pinw_total = 0; - model->tiles[i].devs[j].num_pinw_in = 0; + struct fpga_tile* tile; + int x, y, i; - if (model->tiles[i].devs[j].type != DEV_LOGIC) + for (x = 0; x < model->x_width; x++) { + for (y = 0; y < model->y_height; y++) { + tile = YX_TILE(model, y, x); + if (!tile->num_devs) continue; - - free(model->tiles[i].devs[i].logic.A6_lut); - model->tiles[i].devs[i].logic.A6_lut = 0; - free(model->tiles[i].devs[i].logic.B6_lut); - model->tiles[i].devs[i].logic.B6_lut = 0; - free(model->tiles[i].devs[i].logic.C6_lut); - model->tiles[i].devs[i].logic.C6_lut = 0; - free(model->tiles[i].devs[i].logic.D6_lut); - model->tiles[i].devs[i].logic.D6_lut = 0; + if (!tile->devs) { + HERE(); + continue; + } + for (i = 0; i < tile->num_devs; i++) { + fdev_delete(model, y, x, tile->devs[i].type, + fdev_typeidx(model, y, x, i)); + } + free(tile->devs); + tile->devs = 0; + tile->num_devs = 0; } - free(model->tiles[i].devs); - model->tiles[i].devs = 0; - model->tiles[i].num_devs = 0; } } @@ -356,11 +348,12 @@ static int add_dev(struct fpga_model* model, // init new device tile->devs[new_dev_i].type = type; + tile->devs[new_dev_i].subtype = subtype; if (type == DEV_IOB) { - rc = init_iob(model, y, x, new_dev_i, subtype); + rc = init_iob(model, y, x, new_dev_i); if (rc) FAIL(rc); } else if (type == DEV_LOGIC) { - rc = init_logic(model, y, x, new_dev_i, subtype); + rc = init_logic(model, y, x, new_dev_i); if (rc) FAIL(rc); } return 0; @@ -368,8 +361,7 @@ fail: return rc; } -static int init_iob(struct fpga_model* model, int y, int x, - int idx, int subtype) +static int init_iob(struct fpga_model* model, int y, int x, int idx) { struct fpga_tile* tile; const char* prefix; @@ -377,8 +369,7 @@ static int init_iob(struct fpga_model* model, int y, int x, char tmp_str[128]; tile = YX_TILE(model, y, x); - tile->devs[idx].iob.subtype = subtype; - type_idx = fpga_dev_typeidx(model, y, x, idx); + type_idx = fdev_typeidx(model, y, x, idx); if (!y) prefix = "TIOB"; else if (y == model->y_height - BOT_OUTER_ROW) @@ -446,20 +437,18 @@ fail: return rc; } -static int init_logic(struct fpga_model* model, int y, int x, - int idx, int subtype) +static int init_logic(struct fpga_model* model, int y, int x, int idx) { struct fpga_tile* tile; const char* pre; int i, j, rc; tile = YX_TILE(model, y, x); - tile->devs[idx].logic.subtype = subtype; - if (subtype == LOGIC_M) + if (tile->devs[idx].subtype == LOGIC_M) pre = "M_"; - else if (subtype == LOGIC_L) + else if (tile->devs[idx].subtype == LOGIC_L) pre = "L_"; - else if (subtype == LOGIC_X) { + else if (tile->devs[idx].subtype == LOGIC_X) { pre = is_atx(X_FABRIC_LOGIC_XL_COL|X_CENTER_LOGIC_COL, model, x) ? "XX_" : "X_"; } else FAIL(EINVAL); @@ -481,7 +470,7 @@ static int init_logic(struct fpga_model* model, int y, int x, /*dup_warn*/ 1, &tile->devs[idx].pinw[LOGIC_IN_AX+i], 0); if (rc) FAIL(rc); - if (subtype == LOGIC_M) { + if (tile->devs[idx].subtype == LOGIC_M) { rc = add_connpt_name(model, y, x, pf("%s%cI", pre, 'A'+i), /*dup_warn*/ 1, &tile->devs[idx].pinw[LOGIC_IN_AI+i], 0); @@ -513,14 +502,14 @@ static int init_logic(struct fpga_model* model, int y, int x, /*dup_warn*/ 1, &tile->devs[idx].pinw[LOGIC_IN_SR], 0); if (rc) FAIL(rc); - if (subtype == LOGIC_M) { + if (tile->devs[idx].subtype == LOGIC_M) { rc = add_connpt_name(model, y, x, pf("%sWE", pre), /*dup_warn*/ 1, &tile->devs[idx].pinw[LOGIC_IN_WE], 0); if (rc) FAIL(rc); } else tile->devs[idx].pinw[LOGIC_IN_WE] = STRIDX_NO_ENTRY; - if (subtype != LOGIC_X + if (tile->devs[idx].subtype != LOGIC_X && ((is_atx(X_ROUTING_NO_IO, model, x-1) && is_aty(Y_INNER_BOTTOM, model, y+1)) || (!is_atx(X_ROUTING_NO_IO, model, x-1) @@ -531,12 +520,12 @@ static int init_logic(struct fpga_model* model, int y, int x, if (rc) FAIL(rc); } else tile->devs[idx].pinw[LOGIC_IN_CIN] = STRIDX_NO_ENTRY; - if (subtype == LOGIC_M) { + if (tile->devs[idx].subtype == LOGIC_M) { rc = add_connpt_name(model, y, x, "M_COUT", /*dup_warn*/ 1, &tile->devs[idx].pinw[LOGIC_OUT_COUT], 0); if (rc) FAIL(rc); - } else if (subtype == LOGIC_L) { + } else if (tile->devs[idx].subtype == LOGIC_L) { rc = add_connpt_name(model, y, x, "XL_COUT", /*dup_warn*/ 1, &tile->devs[idx].pinw[LOGIC_OUT_COUT], 0); diff --git a/model_helper.c b/model_helper.c index 526619e..725a76c 100644 --- a/model_helper.c +++ b/model_helper.c @@ -145,11 +145,8 @@ int has_device_type(struct fpga_model* model, int y, int x, int dev, int subtype if (tile->devs[i].type == dev) { switch (dev) { case DEV_LOGIC: - if (tile->devs[i].logic.subtype == subtype) - return 1; - break; case DEV_IOB: - if (tile->devs[i].iob.subtype == subtype) + if (tile->devs[i].subtype == subtype) return 1; break; default: EXIT(1);