don't stop me now

This commit is contained in:
Wolfgang Spraul 2012-08-15 06:00:53 +02:00
parent eef694d733
commit b1d665e84b
10 changed files with 523 additions and 256 deletions

View File

@ -77,7 +77,7 @@ xc6slx9_empty.fp: new_fp
xc6slx9.svg: draw_svg_tiles
./draw_svg_tiles | xmllint --pretty 1 - > $@
compare_all: compare.tiles compare.devices compare.conns compare.ports compare.sw
compare_all: compare.tiles compare.devs compare.conns compare.ports compare.sw
compare.%: xc6slx9_empty.%
@comm -1 -2 $< compare_other.$* > compare_$*_matching.txt
@ -92,11 +92,11 @@ compare.%: xc6slx9_empty.%
%.tiles: %.fp
@cat $<|awk '{if ($$1=="tile" && $$4=="name") printf "%s %s %s\n",$$2,$$3,$$5}'|sort >$@
%.devices: %.fp
@cat $<|awk '{if ($$1=="device") printf "%s %s %s\n",$$2,$$3,$$4}'|sort >$@
%.devs: %.fp
@cat $<|awk '{if ($$1=="dev") {if ($$6=="type") printf "%s %s %s %s\n",$$2,$$3,$$4,$$7; else printf "%s %s %s\n",$$2,$$3,$$4; }}'|sort >$@
%.nets: %.fp pair2net
cat $<|awk '{if ($$1=="static_conn") printf "%s-%s-%s %s-%s-%s\n",$$2,$$3,$$4,$$5,$$6,$$7}' |./pair2net -|sort >$@
cat $<|awk '{if ($$1=="conn") printf "%s-%s-%s %s-%s-%s\n",$$2,$$3,$$4,$$5,$$6,$$7}' |./pair2net -|sort >$@
@echo Number of nets:
@cat $@|wc -l
@echo Number of connection points:
@ -105,13 +105,13 @@ compare.%: xc6slx9_empty.%
@cat $@|awk '{if (NF>max) max=NF} END {print max}'
%.conns: %.fp sort_seq merge_seq
@cat $<|awk '{if ($$1=="static_conn") printf "%s %s %s %s %s %s\n",$$2,$$3,$$5,$$6,$$4,$$7}'|sort|./sort_seq -|./merge_seq -|awk '{printf "%s %s %s %s %s %s\n",$$1,$$2,$$5,$$3,$$4,$$6}'|sort >$@
@cat $<|awk '{if ($$1=="conn") printf "%s %s %s %s %s %s\n",$$2,$$3,$$5,$$6,$$4,$$7}'|sort|./sort_seq -|./merge_seq -|awk '{printf "%s %s %s %s %s %s\n",$$1,$$2,$$5,$$3,$$4,$$6}'|sort >$@
%.ports: %.fp
@cat $<|awk '{if ($$1=="port") printf "%s %s %s\n",$$2,$$3,$$4}'|sort >$@
%.sw: %.fp
@cat $<|awk '{if ($$1=="switch") printf "%s %s %s %s %s\n",$$2,$$3,$$4,$$5,$$6}'|sort >$@
@cat $<|awk '{if ($$1=="sw") printf "%s %s %s %s %s\n",$$2,$$3,$$4,$$5,$$6}'|sort >$@
clean:
rm -f bit2txt bit2txt.o \
@ -122,12 +122,12 @@ clean:
merge_seq merge_seq.o \
autotest.o control.o floorplan.o \
xc6slx9_empty.fp xc6slx9.svg \
xc6slx9_empty.tiles xc6slx9_empty.devices xc6slx9_empty.conns \
xc6slx9_empty.tiles xc6slx9_empty.devs xc6slx9_empty.conns \
xc6slx9_empty.ports xc6slx9_empty.sw xc6slx9_empty.nets \
compare_other.tiles compare_other.devices compare_other.conns compare_other.ports \
compare_other.tiles compare_other.devs compare_other.conns compare_other.ports \
compare_other.sw compare_other.nets \
compare_tiles_matching.txt compare_tiles_diff.txt compare_tiles_extra.txt \
compare_devices_matching.txt compare_devices_diff.txt compare_devices_extra.txt \
compare_devs_matching.txt compare_devs_diff.txt compare_devs_extra.txt \
compare_conns_matching.txt compare_conns_diff.txt compare_conns_extra.txt \
compare_ports_matching.txt compare_ports_diff.txt compare_ports_extra.txt \
compare_sw_matching.txt compare_sw_diff.txt compare_sw_extra.txt \

View File

@ -63,17 +63,29 @@ int main(int argc, char** argv)
printf("O Done\n");
TIME_AND_MEM();
// todo: pick 2 input IOBs, one output IOB and configure them
// todo: pick 1 logic block and configure
// configure P46
rc = fpga_find_iob(&model, "P46", &iob_y, &iob_x, &iob_idx);
EXIT(rc);
dev = fpga_dev(&model, iob_y, iob_x, DEV_IOB, iob_idx);
EXIT(!dev);
dev->instantiated = 1;
strcpy(dev->iob.istandard, IO_LVCMOS33);
dev->iob.bypass_mux = BYPASS_MUX_I;
dev->iob.imux = IMUX_I;
dev->iob.I_mux = IMUX_I;
// configure P48
rc = fpga_find_iob(&model, "P48", &iob_y, &iob_x, &iob_idx);
EXIT(rc);
dev = fpga_dev(&model, iob_y, iob_x, DEV_IOB, iob_idx);
EXIT(!dev);
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;
// todo: configure logic
mkdir(AUTOTEST_TMP_DIR, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH);
dest_f = fopen(AUTOTEST_TMP_DIR "/test_0001.fp", "w");

View File

@ -164,10 +164,10 @@ struct fpga_device* fpga_dev(struct fpga_model* model,
tile = YX_TILE(model, y, x);
type_count = 0;
for (i = 0; i < tile->num_devices; i++) {
if (tile->devices[i].type == type) {
for (i = 0; i < tile->num_devs; i++) {
if (tile->devs[i].type == type) {
if (type_count == idx)
return &tile->devices[i];
return &tile->devs[i];
type_count++;
}
}

View File

@ -5,6 +5,8 @@
// For details see the UNLICENSE file at the root of the source tree.
//
#include <stdarg.h>
#include "model.h"
#include "floorplan.h"
@ -57,105 +59,288 @@ int printf_tiles(FILE* f, struct fpga_model* model)
return 0;
}
static void printf_wrap(FILE* f, char* line, int prefix_len,
const char* fmt, ...)
{
va_list list;
int i;
va_start(list, fmt);
i = strlen(line);
if (i >= 80) {
line[i] = '\n';
line[i+1] = 0;
fprintf(f, line);
line[prefix_len] = 0;
i = prefix_len;
}
line[i] = ' ';
vsnprintf(&line[i+1], 256, fmt, list);
va_end(list);
}
static int printf_IOB(FILE* f, struct fpga_model* model,
int y, int x, int config_only)
{
struct fpga_tile* tile;
char line[1024];
int type_count, plen, i;
tile = YX_TILE(model, y, x);
type_count = 0;
for (i = 0; i < tile->num_devs; i++) {
if (tile->devs[i].type != DEV_IOB)
continue;
if (config_only && !(tile->devs[i].instantiated)) {
type_count++;
continue;
}
snprintf(line, sizeof(line), "dev y%02i x%02i IOB %i",
y, x, type_count);
type_count++;
plen = strlen(line);
printf_wrap(f, line, plen, "type %s",
tile->devs[i].iob.subtype == IOBM
? "M" : "S");
if (tile->devs[i].iob.istandard[0])
printf_wrap(f, line, plen, "istd %s",
tile->devs[i].iob.istandard);
if (tile->devs[i].iob.ostandard[0])
printf_wrap(f, line, plen, "ostd %s",
tile->devs[i].iob.ostandard);
switch (tile->devs[i].iob.bypass_mux) {
case BYPASS_MUX_I:
printf_wrap(f, line, plen, "bypass_mux I");
break;
case BYPASS_MUX_O:
printf_wrap(f, line, plen, "bypass_mux O");
break;
case BYPASS_MUX_T:
printf_wrap(f, line, plen, "bypass_mux T");
break;
case 0: break; default: EXIT(1);
}
switch (tile->devs[i].iob.I_mux) {
case IMUX_I_B:
printf_wrap(f, line, plen, "imux I_B");
break;
case IMUX_I:
printf_wrap(f, line, plen, "imux I");
break;
case 0: break; default: EXIT(1);
}
if (tile->devs[i].iob.drive_strength)
printf_wrap(f, line, plen, "strength %i",
tile->devs[i].iob.drive_strength);
switch (tile->devs[i].iob.slew) {
case SLEW_SLOW:
printf_wrap(f, line, plen, "slew SLOW");
break;
case SLEW_FAST:
printf_wrap(f, line, plen, "slew FAST");
break;
case SLEW_QUIETIO:
printf_wrap(f, line, plen, "slew QUIETIO");
break;
case 0: break; default: EXIT(1);
}
if (tile->devs[i].iob.O_used)
printf_wrap(f, line, plen, "o_used");
switch (tile->devs[i].iob.suspend) {
case SUSP_LAST_VAL:
printf_wrap(f, line, plen, "suspend DRIVE_LAST_VALUE");
break;
case SUSP_3STATE:
printf_wrap(f, line, plen, "suspend 3STATE");
break;
case SUSP_3STATE_PULLUP:
printf_wrap(f, line, plen, "suspend 3STATE_PULLUP");
break;
case SUSP_3STATE_PULLDOWN:
printf_wrap(f, line, plen, "suspend 3STATE_PULLDOWN");
break;
case SUSP_3STATE_KEEPER:
printf_wrap(f, line, plen, "suspend 3STATE_KEEPER");
break;
case SUSP_3STATE_OCT_ON:
printf_wrap(f, line, plen, "suspend 3STATE_OCT_ON");
break;
case 0: break; default: EXIT(1);
}
switch (tile->devs[i].iob.in_term) {
case ITERM_NONE:
printf_wrap(f, line, plen, "in_term NONE");
break;
case ITERM_UNTUNED_25:
printf_wrap(f, line, plen, "in_term UNTUNED_SPLIT_25");
break;
case ITERM_UNTUNED_50:
printf_wrap(f, line, plen, "in_term UNTUNED_SPLIT_50");
break;
case ITERM_UNTUNED_75:
printf_wrap(f, line, plen, "in_term UNTUNED_SPLIT_75");
break;
case 0: break; default: EXIT(1);
}
switch (tile->devs[i].iob.out_term) {
case OTERM_NONE:
printf_wrap(f, line, plen, "out_term NONE");
break;
case OTERM_UNTUNED_25:
printf_wrap(f, line, plen, "out_term UNTUNED_25");
break;
case OTERM_UNTUNED_50:
printf_wrap(f, line, plen, "out_term UNTUNED_50");
break;
case OTERM_UNTUNED_75:
printf_wrap(f, line, plen, "out_term UNTUNED_75");
break;
case 0: break; default: EXIT(1);
}
strcat(line, "\n");
fprintf(f, line);
}
return 0;
}
static int printf_LOGIC(FILE* f, struct fpga_model* model,
int y, int x, int config_only)
{
struct fpga_tile* tile;
char line[1024];
int type_count, plen, i;
tile = YX_TILE(model, y, x);
type_count = 0;
for (i = 0; i < tile->num_devs; i++) {
if (tile->devs[i].type != DEV_LOGIC)
continue;
if (config_only && !(tile->devs[i].instantiated)) {
type_count++;
continue;
}
snprintf(line, sizeof(line), "dev y%02i x%02i LOGIC %i",
y, x, type_count);
type_count++;
plen = strlen(line);
switch (tile->devs[i].logic.subtype) {
case LOGIC_X:
printf_wrap(f, line, plen, "type X");
break;
case LOGIC_L:
printf_wrap(f, line, plen, "type L");
break;
case LOGIC_M:
printf_wrap(f, line, plen, "type M");
break;
default: EXIT(1);
}
strcat(line, "\n");
fprintf(f, line);
}
return 0;
}
int printf_devices(FILE* f, struct fpga_model* model, int config_only)
{
int x, y, i;
int x, y, i, rc;
struct fpga_tile* tile;
for (x = 0; x < model->x_width; x++) {
for (y = 0; y < model->y_height; y++) {
rc = printf_IOB(f, model, y, x, config_only);
if (rc) goto fail;
rc = printf_LOGIC(f, model, y, x, config_only);
if (rc) goto fail;
tile = YX_TILE(model, y, x);
for (i = 0; i < tile->num_devices; i++) {
if (config_only && !(tile->devices[i].instantiated))
for (i = 0; i < tile->num_devs; i++) {
if (config_only && !(tile->devs[i].instantiated))
continue;
switch (tile->devices[i].type) {
case DEV_LOGIC_M:
fprintf(f, "device y%02i x%02i SLICEM\n", y, x);
break;
case DEV_LOGIC_L:
fprintf(f, "device y%02i x%02i SLICEL\n", y, x);
break;
case DEV_LOGIC_X:
fprintf(f, "device y%02i x%02i SLICEX\n", y, x);
break;
switch (tile->devs[i].type) {
case DEV_MACC:
fprintf(f, "device y%02i x%02i DSP48A1\n", y, x);
fprintf(f, "dev y%02i x%02i DSP48A1\n", y, x);
break;
case DEV_TIEOFF:
fprintf(f, "device y%02i x%02i TIEOFF\n", y, x);
break;
case DEV_IOB:
fprintf(f, "device y%02i x%02i %s\n", y, x,
tile->devices[i].iob.type == IOBM ? "IOBM" : "IOBS");
fprintf(f, "dev y%02i x%02i TIEOFF\n", y, x);
break;
case DEV_ILOGIC:
fprintf(f, "device y%02i x%02i ILOGIC2\n", y, x);
fprintf(f, "dev y%02i x%02i ILOGIC\n", y, x);
break;
case DEV_OLOGIC:
fprintf(f, "device y%02i x%02i OLOGIC2\n", y, x);
fprintf(f, "dev y%02i x%02i OLOGIC\n", y, x);
break;
case DEV_IODELAY:
fprintf(f, "device y%02i x%02i IODELAY2\n", y, x);
fprintf(f, "dev y%02i x%02i IODELAY\n", y, x);
break;
case DEV_BRAM16:
fprintf(f, "device y%02i x%02i RAMB16BWER\n", y, x);
fprintf(f, "dev y%02i x%02i RAMB16\n", y, x);
break;
case DEV_BRAM8:
fprintf(f, "device y%02i x%02i RAMB8BWER\n", y, x);
fprintf(f, "dev y%02i x%02i RAMB8\n", y, x);
break;
case DEV_BUFH:
fprintf(f, "device y%02i x%02i BUFH\n", y, x);
fprintf(f, "dev y%02i x%02i BUFH\n", y, x);
break;
case DEV_BUFIO:
fprintf(f, "device y%02i x%02i BUFIO2\n", y, x);
fprintf(f, "dev y%02i x%02i BUFIO2\n", y, x);
break;
case DEV_BUFIO_FB:
fprintf(f, "device y%02i x%02i BUFIO2FB\n", y, x);
fprintf(f, "dev y%02i x%02i BUFIO2FB\n", y, x);
break;
case DEV_BUFPLL:
fprintf(f, "device y%02i x%02i BUFPLL\n", y, x);
fprintf(f, "dev y%02i x%02i BUFPLL\n", y, x);
break;
case DEV_BUFPLL_MCB:
fprintf(f, "device y%02i x%02i BUFPLL_MCB\n", y, x);
fprintf(f, "dev y%02i x%02i BUFPLL_MCB\n", y, x);
break;
case DEV_BUFGMUX:
fprintf(f, "device y%02i x%02i BUFGMUX\n", y, x);
fprintf(f, "dev y%02i x%02i BUFGMUX\n", y, x);
break;
case DEV_BSCAN:
fprintf(f, "device y%02i x%02i BSCAN\n", y, x);
fprintf(f, "dev y%02i x%02i BSCAN\n", y, x);
break;
case DEV_DCM:
fprintf(f, "device y%02i x%02i DCM\n", y, x);
fprintf(f, "dev y%02i x%02i DCM\n", y, x);
break;
case DEV_PLL:
fprintf(f, "device y%02i x%02i PLL_ADV\n", y, x);
fprintf(f, "dev y%02i x%02i PLL\n", y, x);
break;
case DEV_ICAP:
fprintf(f, "device y%02i x%02i ICAP\n", y, x);
fprintf(f, "dev y%02i x%02i ICAP\n", y, x);
break;
case DEV_POST_CRC_INTERNAL:
fprintf(f, "device y%02i x%02i POST_CRC_INTERNAL\n", y, x);
fprintf(f, "dev y%02i x%02i POST_CRC_INTERNAL\n", y, x);
break;
case DEV_STARTUP:
fprintf(f, "device y%02i x%02i STARTUP\n", y, x);
fprintf(f, "dev y%02i x%02i STARTUP\n", y, x);
break;
case DEV_SLAVE_SPI:
fprintf(f, "device y%02i x%02i SLAVE_SPI\n", y, x);
fprintf(f, "dev y%02i x%02i SLAVE_SPI\n", y, x);
break;
case DEV_SUSPEND_SYNC:
fprintf(f, "device y%02i x%02i SUSPEND_SYNC\n", y, x);
fprintf(f, "dev y%02i x%02i SUSPEND_SYNC\n", y, x);
break;
case DEV_OCT_CALIBRATE:
fprintf(f, "device y%02i x%02i OCT_CALIBRATE\n", y, x);
fprintf(f, "dev y%02i x%02i OCT_CALIBRATE\n", y, x);
break;
case DEV_SPI_ACCESS:
fprintf(f, "device y%02i x%02i SPI_ACCESS\n", y, x);
fprintf(f, "dev y%02i x%02i SPI_ACCESS\n", y, x);
break;
case DEV_IOB:
case DEV_LOGIC:
// to suppress compiler warning
break;
}
}
}
}
return 0;
fail:
return rc;
}
int printf_ports(FILE* f, struct fpga_model* model)
@ -241,7 +426,7 @@ int printf_conns(FILE* f, struct fpga_model* model)
first_conn_printed = 1;
fprintf(f, "\n");
}
sprintf(tmp_line, "static_conn y%02i x%02i %s ",
sprintf(tmp_line, "conn y%02i x%02i %s ",
y, x, conn_point_name_src);
k = strlen(tmp_line);
while (k < 45)
@ -290,7 +475,7 @@ int printf_switches(FILE* f, struct fpga_model* model, int enabled_only)
first_switch_printed = 1;
fprintf(f, "\n");
}
fprintf(f, "switch y%02i x%02i %s %s %s\n",
fprintf(f, "sw y%02i x%02i %s %s %s\n",
y, x, from_str, is_bidirectional
? "<->" : "->", to_str);
}

38
model.h
View File

@ -271,9 +271,7 @@ const char* logicin_s(int wire, int routing_io);
enum fpgadev_type
{
DEV_LOGIC_M,
DEV_LOGIC_L,
DEV_LOGIC_X,
DEV_LOGIC,
DEV_TIEOFF,
DEV_MACC,
DEV_IOB,
@ -304,19 +302,13 @@ enum fpgadev_type
// 0 is never a valid configured setting. That way all config
// data can safely be initialized to 0 meaning unconfigured.
struct fpgadev_logic_x
{
int a;
};
enum { LOGIC_M = 1, LOGIC_L, LOGIC_X };
struct fpgadev_logic_l
struct fpgadev_logic
{
int b;
};
struct fpgadev_logic_m
{
int c;
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;
};
enum { IOBM = 1, IOBS };
@ -334,14 +326,14 @@ enum { OTERM_NONE = 1, OTERM_UNTUNED_25, OTERM_UNTUNED_50,
struct fpgadev_iob
{
int type;
int subtype; // IOBM or IOBS
IOSTANDARD istandard;
IOSTANDARD ostandard;
int bypass_mux;
int imux;
int I_mux;
int drive_strength; // supports 2,4,6,8,12,16 and 24
int slew;
int o_used;
int O_used;
int suspend;
int in_term;
int out_term;
@ -352,9 +344,7 @@ struct fpga_device
enum fpgadev_type type;
int instantiated;
union {
struct fpgadev_logic_m log_m;
struct fpgadev_logic_l log_l;
struct fpgadev_logic_x log_x;
struct fpgadev_logic logic;
struct fpgadev_iob iob;
};
};
@ -368,9 +358,9 @@ struct fpga_tile
enum fpga_tile_type type;
int flags;
// we currently support a maximum of 32 devices per tile
int num_devices;
struct fpga_device devices[32];
// expect up to 64 devices per tile
int num_devs;
struct fpga_device* devs;
// expect up to 5k connection point names per tile
// 2*16 bit per entry
@ -407,6 +397,7 @@ int init_tiles(struct fpga_model* model);
int init_conns(struct fpga_model* model);
int init_ports(struct fpga_model* model);
int init_devices(struct fpga_model* model);
void free_devices(struct fpga_model* model);
int init_switches(struct fpga_model* model);
const char* pf(const char* fmt, ...);
@ -417,6 +408,7 @@ int has_connpt(struct fpga_model* model, int y, int x, const char* name);
int add_connpt_name(struct fpga_model* model, int y, int x, const char* connpt_name);
int has_device(struct fpga_model* model, int y, int x, int dev);
int has_device_type(struct fpga_model* model, int y, int x, int dev, int subtype);
int add_connpt_2(struct fpga_model* model, int y, int x,
const char* connpt_name, const char* suffix1, const char* suffix2);

View File

@ -61,9 +61,9 @@ static int connect_logic_carry(struct fpga_model* model)
for (x = 0; x < model->x_width; x++) {
if (is_atx(X_LOGIC_COL, model, x)) {
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (has_device(model, y, x, DEV_LOGIC_M)) {
if (has_device_type(model, y, x, DEV_LOGIC, LOGIC_M)) {
if (is_aty(Y_CHIP_HORIZ_REGS, model, y-1)
&& has_device(model, y-2, x, DEV_LOGIC_M)) {
&& has_device_type(model, y-2, x, DEV_LOGIC, LOGIC_M)) {
struct w_net net = {
0,
{{ "M_CIN", 0, y-2, x },
@ -72,7 +72,7 @@ static int connect_logic_carry(struct fpga_model* model)
{ "" }}};
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) goto xout;
} else if (is_aty(Y_ROW_HORIZ_AXSYMM, model, y-1)
&& has_device(model, y-2, x, DEV_LOGIC_M)) {
&& has_device_type(model, y-2, x, DEV_LOGIC, LOGIC_M)) {
struct w_net net = {
0,
{{ "M_CIN", 0, y-2, x },
@ -80,7 +80,7 @@ static int connect_logic_carry(struct fpga_model* model)
{ "M_COUT_N", 0, y, x },
{ "" }}};
if ((rc = add_conn_net(model, NOPREF_BI_F, &net))) goto xout;
} else if (has_device(model, y-1, x, DEV_LOGIC_M)) {
} else if (has_device_type(model, y-1, x, DEV_LOGIC, LOGIC_M)) {
if ((rc = add_conn_bi(model, y, x, "M_COUT_N", y-1, x, "M_CIN"))) goto xout;
}
}
@ -120,13 +120,13 @@ static int connect_clk_sr(struct fpga_model* model, const char* clk_sr)
}
if (is_atx(X_FABRIC_LOGIC_ROUTING_COL|X_CENTER_ROUTING_COL, model, x)) {
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (has_device(model, y, x+1, DEV_LOGIC_M)) {
if (has_device_type(model, y, x+1, DEV_LOGIC, LOGIC_M)) {
if ((rc = add_conn_range(model,
NOPREF_BI_F,
y, x, pf("%s%%i", clk_sr), 0, 1,
y, x+1, pf("CLEXM_%s%%i", clk_sr), 0)))
goto xout;
} else if (has_device(model, y, x+1, DEV_LOGIC_L)) {
} else if (has_device_type(model, y, x+1, DEV_LOGIC, LOGIC_L)) {
if ((rc = add_conn_range(model,
NOPREF_BI_F,
y, x, pf("%s%%i", clk_sr), 0, 1,

View File

@ -8,241 +8,297 @@
#include <stdarg.h>
#include "model.h"
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++) {
if (model->tiles[i].devs[j].type != DEV_LOGIC)
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;
}
free(model->tiles[i].devs);
model->tiles[i].devs = 0;
model->tiles[i].num_devs = 0;
}
}
#define DEV_INCREMENT 8
static int add_dev(struct fpga_model* model,
int y, int x, int type, int subtype)
{
struct fpga_tile* tile = YX_TILE(model, y, x);
if (!(tile->num_devs % DEV_INCREMENT)) {
void* new_ptr = realloc(tile->devs,
(tile->num_devs+DEV_INCREMENT)*sizeof(*tile->devs));
EXIT(!new_ptr);
memset(new_ptr + tile->num_devs * sizeof(*tile->devs), 0, DEV_INCREMENT*sizeof(*tile->devs));
tile->devs = new_ptr;
}
tile->devs[tile->num_devs].type = type;
if (type == DEV_IOB)
tile->devs[tile->num_devs].iob.subtype = subtype;
else if (type == DEV_LOGIC)
tile->devs[tile->num_devs].logic.subtype = subtype;
tile->num_devs++;
return 0;
}
int init_devices(struct fpga_model* model)
{
int x, y, i, j;
struct fpga_tile* tile;
int x, y, i, j, rc;
// DCM, PLL_ADV
// DCM, PLL
for (i = 0; i < model->cfg_rows; i++) {
y = TOP_IO_TILES + HALF_ROW + i*ROW_SIZE;
y = TOP_IO_TILES + HALF_ROW-1 + i*ROW_SIZE;
if (y > model->center_y) y++; // central regs
tile = YX_TILE(model, y-1, model->center_x-CENTER_CMTPLL_O);
x = model->center_x-CENTER_CMTPLL_O;
if (i%2) {
tile->devices[tile->num_devices++].type = DEV_DCM;
tile->devices[tile->num_devices++].type = DEV_DCM;
if ((rc = add_dev(model, y, x, DEV_DCM, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_DCM, 0))) goto fail;
} else
tile->devices[tile->num_devices++].type = DEV_PLL;
if ((rc = add_dev(model, y, x, DEV_PLL, 0))) goto fail;
}
// BSCAN
tile = YX_TILE(model, TOP_IO_TILES, model->x_width-RIGHT_IO_DEVS_O);
tile->devices[tile->num_devices++].type = DEV_BSCAN;
tile->devices[tile->num_devices++].type = DEV_BSCAN;
y = TOP_IO_TILES;
x = model->x_width-RIGHT_IO_DEVS_O;
if ((rc = add_dev(model, y, x, DEV_BSCAN, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BSCAN, 0))) goto fail;
// BSCAN, OCT_CALIBRATE
tile = YX_TILE(model, TOP_IO_TILES+1, model->x_width-RIGHT_IO_DEVS_O);
tile->devices[tile->num_devices++].type = DEV_BSCAN;
tile->devices[tile->num_devices++].type = DEV_BSCAN;
tile->devices[tile->num_devices++].type = DEV_OCT_CALIBRATE;
y = TOP_IO_TILES+1;
x = model->x_width-RIGHT_IO_DEVS_O;
if ((rc = add_dev(model, y, x, DEV_BSCAN, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BSCAN, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_OCT_CALIBRATE, 0))) goto fail;
// ICAP, SPI_ACCESS, OCT_CALIBRATE
tile = YX_TILE(model, model->y_height-BOT_IO_TILES-1,
model->x_width-RIGHT_IO_DEVS_O);
tile->devices[tile->num_devices++].type = DEV_ICAP;
tile->devices[tile->num_devices++].type = DEV_SPI_ACCESS;
tile->devices[tile->num_devices++].type = DEV_OCT_CALIBRATE;
y = model->y_height-BOT_IO_TILES-1;
x = model->x_width-RIGHT_IO_DEVS_O;
if ((rc = add_dev(model, y, x, DEV_ICAP, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_SPI_ACCESS, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_OCT_CALIBRATE, 0))) goto fail;
// STARTUP, POST_CRC_INTERNAL, SLAVE_SPI, SUSPEND_SYNC
tile = YX_TILE(model, model->y_height-BOT_IO_TILES-2,
model->x_width-RIGHT_IO_DEVS_O);
tile->devices[tile->num_devices++].type = DEV_STARTUP;
tile->devices[tile->num_devices++].type = DEV_POST_CRC_INTERNAL;
tile->devices[tile->num_devices++].type = DEV_SLAVE_SPI;
tile->devices[tile->num_devices++].type = DEV_SUSPEND_SYNC;
y = model->y_height-BOT_IO_TILES-2;
x = model->x_width-RIGHT_IO_DEVS_O;
if ((rc = add_dev(model, y, x, DEV_STARTUP, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_POST_CRC_INTERNAL, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_SLAVE_SPI, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_SUSPEND_SYNC, 0))) goto fail;
// BUFGMUX
tile = YX_TILE(model, model->center_y, model->center_x);
y = model->center_y;
x = model->center_x;
for (i = 0; i < 16; i++)
tile->devices[tile->num_devices++].type = DEV_BUFGMUX;
if ((rc = add_dev(model, y, x, DEV_BUFGMUX, 0))) goto fail;
// BUFIO, BUFIO_FB, BUFPLL, BUFPLL_MCB
tile = YX_TILE(model, TOP_OUTER_ROW, model->center_x-CENTER_CMTPLL_O);
tile->devices[tile->num_devices++].type = DEV_BUFPLL;
tile->devices[tile->num_devices++].type = DEV_BUFPLL;
tile->devices[tile->num_devices++].type = DEV_BUFPLL_MCB;
y = TOP_OUTER_ROW;
x = model->center_x-CENTER_CMTPLL_O;
if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFPLL_MCB, 0))) goto fail;
for (j = 0; j < 8; j++) {
tile->devices[tile->num_devices++].type = DEV_BUFIO;
tile->devices[tile->num_devices++].type = DEV_BUFIO_FB;
if ((rc = add_dev(model, y, x, DEV_BUFIO, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFIO_FB, 0))) goto fail;
}
tile = YX_TILE(model, model->center_y, LEFT_OUTER_COL);
tile->devices[tile->num_devices++].type = DEV_BUFPLL;
tile->devices[tile->num_devices++].type = DEV_BUFPLL;
tile->devices[tile->num_devices++].type = DEV_BUFPLL_MCB;
y = model->center_y;
x = LEFT_OUTER_COL;
if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFPLL_MCB, 0))) goto fail;
for (j = 0; j < 8; j++) {
tile->devices[tile->num_devices++].type = DEV_BUFIO;
tile->devices[tile->num_devices++].type = DEV_BUFIO_FB;
if ((rc = add_dev(model, y, x, DEV_BUFIO, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFIO_FB, 0))) goto fail;
}
tile = YX_TILE(model, model->center_y, model->x_width - RIGHT_OUTER_O);
tile->devices[tile->num_devices++].type = DEV_BUFPLL;
tile->devices[tile->num_devices++].type = DEV_BUFPLL;
tile->devices[tile->num_devices++].type = DEV_BUFPLL_MCB;
y = model->center_y;
x = model->x_width - RIGHT_OUTER_O;
if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFPLL_MCB, 0))) goto fail;
for (j = 0; j < 8; j++) {
tile->devices[tile->num_devices++].type = DEV_BUFIO;
tile->devices[tile->num_devices++].type = DEV_BUFIO_FB;
if ((rc = add_dev(model, y, x, DEV_BUFIO, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFIO_FB, 0))) goto fail;
}
tile = YX_TILE(model, model->y_height - BOT_OUTER_ROW, model->center_x-CENTER_CMTPLL_O);
tile->devices[tile->num_devices++].type = DEV_BUFPLL;
tile->devices[tile->num_devices++].type = DEV_BUFPLL;
tile->devices[tile->num_devices++].type = DEV_BUFPLL_MCB;
y = model->y_height - BOT_OUTER_ROW;
x = model->center_x-CENTER_CMTPLL_O;
if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFPLL, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFPLL_MCB, 0))) goto fail;
for (j = 0; j < 8; j++) {
tile->devices[tile->num_devices++].type = DEV_BUFIO;
tile->devices[tile->num_devices++].type = DEV_BUFIO_FB;
if ((rc = add_dev(model, y, x, DEV_BUFIO, 0))) goto fail;
if ((rc = add_dev(model, y, x, DEV_BUFIO_FB, 0))) goto fail;
}
// BUFH
for (i = 0; i < model->cfg_rows; i++) {
y = TOP_IO_TILES + HALF_ROW + i*ROW_SIZE;
if (y > model->center_y) y++; // central regs
tile = YX_TILE(model, y, model->center_x);
x = model->center_x;
for (j = 0; j < 32; j++)
tile->devices[tile->num_devices++].type = DEV_BUFH;
if ((rc = add_dev(model, y, x, DEV_BUFH, 0))) goto fail;
}
// BRAM
for (x = 0; x < model->x_width; x++) {
if (is_atx(X_FABRIC_BRAM_COL, model, x)) {
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
tile = YX_TILE(model, y, x);
if (tile->flags & TF_BRAM_DEV) {
tile->devices[tile->num_devices++].type = DEV_BRAM16;
tile->devices[tile->num_devices++].type = DEV_BRAM8;
tile->devices[tile->num_devices++].type = DEV_BRAM8;
}
}
if (!is_atx(X_FABRIC_BRAM_COL, model, x))
continue;
for (y = TOP_IO_TILES; y < model->y_height-BOT_IO_TILES; y++) {
if (!(YX_TILE(model, y, x)->flags & TF_BRAM_DEV))
continue;
if ((rc = add_dev(model, y, x, DEV_BRAM16, 0)))
goto fail;
if ((rc = add_dev(model, y, x, DEV_BRAM8, 0)))
goto fail;
if ((rc = add_dev(model, y, x, DEV_BRAM8, 0)))
goto fail;
}
}
// MACC
for (x = 0; x < model->x_width; x++) {
if (is_atx(X_FABRIC_MACC_COL, model, x)) {
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
tile = YX_TILE(model, y, x);
if (tile->flags & TF_MACC_DEV)
tile->devices[tile->num_devices++].type = DEV_MACC;
}
if (!is_atx(X_FABRIC_MACC_COL, model, x))
continue;
for (y = TOP_IO_TILES; y < model->y_height-BOT_IO_TILES; y++) {
if (!(YX_TILE(model, y, x)->flags & TF_MACC_DEV))
continue;
if ((rc = add_dev(model, y, x, DEV_MACC, 0))) goto fail;
}
}
// ILOGIC/OLOGIC/IODELAY
for (x = LEFT_SIDE_WIDTH; x < model->x_width - RIGHT_SIDE_WIDTH; x++) {
if (is_atx(X_LOGIC_COL, model, x)
&& !is_atx(X_ROUTING_NO_IO, model, x-1)) {
for (i = 0; i <= 1; i++) {
tile = YX_TILE(model, TOP_IO_TILES+i, x);
for (j = 0; j <= 1; j++) {
tile->devices[tile->num_devices++].type = DEV_ILOGIC;
tile->devices[tile->num_devices++].type = DEV_OLOGIC;
tile->devices[tile->num_devices++].type = DEV_IODELAY;
}
tile = YX_TILE(model, model->y_height-BOT_IO_TILES-i-1, x);
for (j = 0; j <= 1; j++) {
tile->devices[tile->num_devices++].type = DEV_ILOGIC;
tile->devices[tile->num_devices++].type = DEV_OLOGIC;
tile->devices[tile->num_devices++].type = DEV_IODELAY;
}
if (!is_atx(X_LOGIC_COL, model, x)
|| is_atx(X_ROUTING_NO_IO, model, x-1))
continue;
for (i = 0; i <= 1; i++) {
y = TOP_IO_TILES+i;
for (j = 0; j <= 1; j++) {
if ((rc = add_dev(model, y, x, DEV_ILOGIC, 0)))
goto fail;
if ((rc = add_dev(model, y, x, DEV_OLOGIC, 0)))
goto fail;
if ((rc = add_dev(model, y, x, DEV_IODELAY, 0)))
goto fail;
}
y = model->y_height-BOT_IO_TILES-i-1;
for (j = 0; j <= 1; j++) {
if ((rc = add_dev(model, y, x, DEV_ILOGIC, 0)))
goto fail;
if ((rc = add_dev(model, y, x, DEV_OLOGIC, 0)))
goto fail;
if ((rc = add_dev(model, y, x, DEV_IODELAY, 0)))
goto fail;
}
}
}
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (is_aty(Y_LEFT_WIRED, model, y)) {
tile = YX_TILE(model, y, LEFT_IO_DEVS);
x = LEFT_IO_DEVS;
for (j = 0; j <= 1; j++) {
tile->devices[tile->num_devices++].type = DEV_ILOGIC;
tile->devices[tile->num_devices++].type = DEV_OLOGIC;
tile->devices[tile->num_devices++].type = DEV_IODELAY;
if ((rc = add_dev(model, y, x, DEV_ILOGIC, 0)))
goto fail;
if ((rc = add_dev(model, y, x, DEV_OLOGIC, 0)))
goto fail;
if ((rc = add_dev(model, y, x, DEV_IODELAY, 0)))
goto fail;
}
}
if (is_aty(Y_RIGHT_WIRED, model, y)) {
tile = YX_TILE(model, y, model->x_width-RIGHT_IO_DEVS_O);
x = model->x_width-RIGHT_IO_DEVS_O;
for (j = 0; j <= 1; j++) {
tile->devices[tile->num_devices++].type = DEV_ILOGIC;
tile->devices[tile->num_devices++].type = DEV_OLOGIC;
tile->devices[tile->num_devices++].type = DEV_IODELAY;
if ((rc = add_dev(model, y, x, DEV_ILOGIC, 0)))
goto fail;
if ((rc = add_dev(model, y, x, DEV_OLOGIC, 0)))
goto fail;
if ((rc = add_dev(model, y, x, DEV_IODELAY, 0)))
goto fail;
}
}
}
// IOB
for (x = 0; x < model->x_width; x++) {
// Note that the order of sub-types IOBM and IOBS must match
// the order in the control.c sitename arrays.
if (is_atx(X_OUTER_LEFT, model, x)) {
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (is_aty(Y_LEFT_WIRED, model, y)) {
tile = YX_TILE(model, y, x);
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBM;
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBS;
}
if (!is_aty(Y_LEFT_WIRED, model, y))
continue;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail;
}
}
if (is_atx(X_OUTER_RIGHT, model, x)) {
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (is_aty(Y_RIGHT_WIRED, model, y)) {
tile = YX_TILE(model, y, x);
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBM;
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBS;
}
if (!is_aty(Y_RIGHT_WIRED, model, y))
continue;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail;
}
}
if (is_atx(X_FABRIC_LOGIC_ROUTING_COL|X_CENTER_ROUTING_COL, model, x)
&& !is_atx(X_ROUTING_NO_IO, model, x)) {
tile = YX_TILE(model, TOP_OUTER_ROW, x);
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBM;
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBS;
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBM;
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBS;
y = TOP_OUTER_ROW;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail;
tile = YX_TILE(model, model->y_height-BOT_OUTER_ROW, x);
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBM;
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBS;
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBM;
tile->devices[tile->num_devices].type = DEV_IOB;
tile->devices[tile->num_devices++].iob.type = IOBS;
y = model->y_height-BOT_OUTER_ROW;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail;
if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail;
}
}
// TIEOFF
tile = YX_TILE(model, model->center_y, LEFT_OUTER_COL);
tile->devices[tile->num_devices++].type = DEV_TIEOFF;
tile = YX_TILE(model, model->center_y, model->x_width-RIGHT_OUTER_O);
tile->devices[tile->num_devices++].type = DEV_TIEOFF;
tile = YX_TILE(model, TOP_OUTER_ROW, model->center_x-1);
tile->devices[tile->num_devices++].type = DEV_TIEOFF;
tile = YX_TILE(model, model->y_height-BOT_OUTER_ROW, model->center_x-CENTER_CMTPLL_O);
tile->devices[tile->num_devices++].type = DEV_TIEOFF;
y = model->center_y;
x = LEFT_OUTER_COL;
if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail;
y = model->center_y;
x = model->x_width-RIGHT_OUTER_O;
if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail;
y = TOP_OUTER_ROW;
x = model->center_x-1;
if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail;
y = model->y_height-BOT_OUTER_ROW;
x = model->center_x-CENTER_CMTPLL_O;
if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail;
for (x = 0; x < model->x_width; x++) {
if (is_atx(X_LEFT_IO_DEVS_COL, model, x)) {
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (is_aty(Y_LEFT_WIRED, model, y)) {
tile = YX_TILE(model, y, x);
tile->devices[tile->num_devices++].type = DEV_TIEOFF;
}
if (!is_aty(Y_LEFT_WIRED, model, y))
continue;
if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail;
}
}
if (is_atx(X_RIGHT_IO_DEVS_COL, model, x)) {
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (is_aty(Y_RIGHT_WIRED, model, y)) {
tile = YX_TILE(model, y, x);
tile->devices[tile->num_devices++].type = DEV_TIEOFF;
}
if (!is_aty(Y_RIGHT_WIRED, model, y))
continue;
if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail;
}
}
if (is_atx(X_CENTER_CMTPLL_COL, model, x)) {
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
tile = YX_TILE(model, y, x);
if (tile->flags & TF_PLL_DEV)
tile->devices[tile->num_devices++].type = DEV_TIEOFF;
if (!(YX_TILE(model, y, x)->flags & TF_PLL_DEV))
continue;
if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail;
}
}
@ -251,35 +307,35 @@ int init_devices(struct fpga_model* model)
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS,
model, y))
continue;
tile = YX_TILE(model, y, x);
tile->devices[tile->num_devices++].type = DEV_TIEOFF;
if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail;
}
}
if (is_atx(X_LOGIC_COL, model, x)
&& !is_atx(X_ROUTING_NO_IO, model, x-1)) {
for (i = 0; i <= 1; i++) {
tile = YX_TILE(model, TOP_IO_TILES+i, x);
tile->devices[tile->num_devices++].type = DEV_TIEOFF;
tile = YX_TILE(model, model->y_height-BOT_IO_TILES-i-1, x);
tile->devices[tile->num_devices++].type = DEV_TIEOFF;
y = TOP_IO_TILES+i;
if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail;
y = model->y_height-BOT_IO_TILES-i-1;
if ((rc = add_dev(model, y, x, DEV_TIEOFF, 0))) goto fail;
}
}
}
// LOGIC
for (x = 0; x < model->x_width; x++) {
if (is_atx(X_LOGIC_COL, model, x)) {
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
tile = YX_TILE(model, y, x);
if (tile->flags & TF_LOGIC_XM_DEV) {
tile->devices[tile->num_devices++].type = DEV_LOGIC_X;
tile->devices[tile->num_devices++].type = DEV_LOGIC_M;
}
if (tile->flags & TF_LOGIC_XL_DEV) {
tile->devices[tile->num_devices++].type = DEV_LOGIC_X;
tile->devices[tile->num_devices++].type = DEV_LOGIC_L;
}
if (!is_atx(X_LOGIC_COL, model, x))
continue;
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (YX_TILE(model, y, x)->flags & TF_LOGIC_XM_DEV) {
if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_X))) goto fail;
if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_M))) goto fail;
}
if (YX_TILE(model, y, x)->flags & TF_LOGIC_XL_DEV) {
if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_X))) goto fail;
if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_L))) goto fail;
}
}
}
return 0;
fail:
return rc;
}

View File

@ -137,13 +137,36 @@ int has_device(struct fpga_model* model, int y, int x, int dev)
struct fpga_tile* tile = YX_TILE(model, y, x);
int i;
for (i = 0; i < tile->num_devices; i++) {
if (tile->devices[i].type == dev)
for (i = 0; i < tile->num_devs; i++) {
if (tile->devs[i].type == dev)
return 1;
}
return 0;
}
int has_device_type(struct fpga_model* model, int y, int x, int dev, int subtype)
{
struct fpga_tile* tile = YX_TILE(model, y, x);
int i;
for (i = 0; i < tile->num_devs; i++) {
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)
return 1;
break;
default: EXIT(1);
}
}
}
return 0;
}
int add_connpt_2(struct fpga_model* model, int y, int x,
const char* connpt_name, const char* suffix1, const char* suffix2)
{

View File

@ -49,6 +49,7 @@ int fpga_build_model(struct fpga_model* model, int fpga_rows, const char* column
void fpga_free_model(struct fpga_model* model)
{
if (!model) return;
free_devices(model);
free(model->tmp_str);
strarray_free(&model->str);
free(model->tiles);

View File

@ -46,14 +46,13 @@ static int init_logic_tile(struct fpga_model* model, int y, int x)
int rc, i, j, ml;
const char* xp;
if (has_device(model, y, x, DEV_LOGIC_M)) {
if (has_device_type(model, y, x, DEV_LOGIC, LOGIC_M)) {
ml = 'M';
xp = "X";
} else if (has_device(model, y, x, DEV_LOGIC_L)) {
} else if (has_device_type(model, y, x, DEV_LOGIC, LOGIC_L)) {
ml = 'L';
xp = "XX";
} else
EXIT(1);
} else EXIT(1);
if ((rc = add_switch(model, y, x,
pf("CLEX%c_CLK0", ml), pf("%s_CLK", xp), 0 /* bidir */))) goto xout;
@ -137,8 +136,7 @@ static int init_logic_switches(struct fpga_model* model)
if (!is_atx(X_LOGIC_COL, model, x))
continue;
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (has_device(model, y, x, DEV_LOGIC_M)
|| has_device(model, y, x, DEV_LOGIC_L)) {
if (has_device(model, y, x, DEV_LOGIC)) {
rc = init_logic_tile(model, y, x);
if (rc) goto xout;
}