cleanup, fixes, renames/reorg - messy but committed to set base for next steps...

This commit is contained in:
Wolfgang Spraul 2012-08-28 03:24:56 +02:00
parent 4d576e55fd
commit 9b059ec9b5
8 changed files with 473 additions and 211 deletions

View File

@ -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");

View File

@ -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;
}

178
control.c
View File

@ -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);
}

View File

@ -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);

View File

@ -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);

22
model.h
View File

@ -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

View File

@ -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);

View File

@ -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);