autotest, minor fixes all over

This commit is contained in:
Wolfgang Spraul 2012-08-23 07:27:23 +02:00
parent 63f16c95d0
commit a88c4f1835
12 changed files with 651 additions and 436 deletions

View File

@ -10,6 +10,12 @@ PREFIX ?= /usr/local
.PHONY: all clean install uninstall
.SECONDARY:
# -fno-omit-frame-pointer and -ggdb add almost nothing to execution
# time right now, so we can leave them in all the time.
CFLAGS_DBG = -fno-omit-frame-pointer -ggdb
CFLAGS += $(CFLAGS_DBG)
CFLAGS += -Wall -Wshadow -Wmissing-prototypes -Wmissing-declarations \
-Wno-format-zero-length -Ofast
CFLAGS += `pkg-config libxml-2.0 --cflags`

View File

@ -110,8 +110,10 @@ static int printf_switchtree(struct fpga_model* model, int y, int x,
{
int i, idx, conn_to_y, conn_to_x, num_dests, connpt_dests_o, rc;
const char* to_str;
char tmp_str[128];
printf("%.*sy%02i x%02i %s\n", indent, s_spaces, y, x, start);
// printf("%.*sy%02i x%02i %s\n", indent, s_spaces, y, x, start);
#if 0
num_dests = fpga_connpt_lookup(model, y, x, start, &connpt_dests_o);
for (i = 0; i < num_dests; i++) {
if (!i)
@ -132,16 +134,22 @@ static int printf_switchtree(struct fpga_model* model, int y, int x,
to_str);
idx = fpga_switch_next(model, y, x, idx, SW_TO);
}
#endif
idx = fpga_switch_first(model, y, x, start, SW_FROM);
if (idx != NO_SWITCH)
printf("%.*s| switches to:\n", indent, s_spaces);
while (idx != NO_SWITCH) {
printf("%.*s %s\n", indent, s_spaces,
fmt_sw(model, y, x, idx, SW_FROM));
to_str = fpga_switch_str(model, y, x, idx, SW_TO);
#if 0
printf("%.*s %s %s\n", indent, s_spaces,
fpga_switch_is_bidir(model, y, x, idx) ? "<->" : "->",
to_str);
rc = printf_switchtree(model, y, x, to_str, indent+2);
#endif
strcpy(tmp_str, to_str);
rc = printf_switchtree(model, y, x, tmp_str, indent+2);
if (rc) FAIL(rc);
idx = fpga_switch_next(model, y, x, idx, SW_FROM);
}
@ -150,15 +158,46 @@ fail:
return rc;
}
void printf_swconns(struct fpga_model* model, int y, int x, const char* sw)
{
struct swchain_conns conns =
{ .model = model, .y = y, .x = x, .start_switch = sw };
while (fpga_switch_conns_enum(&conns) != NO_CONN) {
printf("sw %s conn y%02i x%02i %s\n", fmt_swchain(model, y, x,
conns.chain.chain, conns.chain.chain_size),
conns.dest_y, conns.dest_x, conns.dest_str);
}
}
// return dest_y, dest_x, dest_str
int fpga_switch_to_yx(int yx_req, struct fpga_model* model, int y, int x,
const char* start_switch, swidx_t* sw_chain, int* sw_chain_size)
{
struct swchain_conns conns = { .model = model, .y = y, .x = x,
.start_switch = start_switch };
while (fpga_switch_conns_enum(&conns) != NO_CONN) {
if (is_atyx(yx_req, model, conns.dest_y, conns.dest_x)) {
memcpy(sw_chain, conns.chain.chain,
conns.chain.chain_size*sizeof(*sw_chain));
*sw_chain_size = conns.chain.chain_size;
return 0;
}
}
*sw_chain_size = 0;
return 0;
}
int main(int argc, char** argv)
{
struct fpga_model model;
struct fpga_device* P46_dev, *P48_dev, *logic_dev;
int P46_y, P46_x, P46_idx, P48_y, P48_x, P48_idx, rc;
struct test_state tstate;
struct sw_chain chain;
struct swchain_conns conns;
// struct sw_chain chain;
// struct swchain_conns conns;
char tmp_str[128];
swidx_t switch_chain[MAX_SW_CHAIN_SIZE];
int switch_chain_size;
printf("\n");
printf("O fpgatools automatic test suite. Be welcome and be "
@ -214,16 +253,28 @@ int main(int argc, char** argv)
if (rc) FAIL(rc);
rc = diff_printf(&tstate);
if (rc) goto fail;
if (rc) FAIL(rc);
rc = fpga_switch_to_yx(YX_DEV_ILOGIC, &model, P46_y, P46_x,
P46_dev->iob.pinw_out_I, switch_chain, &switch_chain_size);
if (rc) FAIL(rc);
// todo: needs to return dest_y, dest_x, dest_connpt
printf("%s\n", fmt_swchain(&model, P46_y, P46_x, switch_chain, switch_chain_size));
#if 0
printf("P46 I pinw %s\n", P46_dev->iob.pinw_out_I);
printf_swconns(&model, P46_y, P46_x, P46_dev->iob.pinw_out_I);
conns.model = &model;
conns.y = P46_y;
conns.x = P46_x;
conns.start_switch = P46_dev->iob.pinw_out_I;
while (fpga_switch_conns_enum(&conns) != NO_CONN) {
if (is_aty(Y_TOP_INNER_IO|Y_BOT_INNER_IO, &model, conns.dest_y)) {
if (is_atyx(YX_DEV_ILOGIC, &model, conns.dest_y, conns.dest_x)) {
struct swchain_conns conns2;
printf("conn chain_size %i connpt_o %i num_dests %i i %i y %i x %i str %s\n",
@ -235,55 +286,36 @@ int main(int argc, char** argv)
conns2.y = conns.dest_y;
conns2.x = conns.dest_x;
conns2.start_switch = tmp_str;
while (fpga_switch_conns_enum(&conns2) != NO_CONN) {
if (is_atyx(YX_ROUTING_TILE, &model, conns2.dest_y, conns2.dest_x)) {
struct swchain_conns conns3;
struct sw_chain chain3;
printf("conn2 chain_size %i connpt_o %i num_dests %i i %i y %i x %i str %s\n",
conns2.chain.chain_size, conns2.connpt_dest_start,
conns2.num_dests, conns2.dest_i, conns2.dest_y, conns2.dest_x, conns2.dest_str);
#if 0
rc = printf_switchtree(&model, conns2.dest_y,
conns2.dest_x, conns2.dest_str, /*indent*/ 3);
if (rc) FAIL(rc);
#endif
strcpy(tmp_str, conns2.dest_str);
printf_swconns(&model, conns2.dest_y, conns2.dest_x, tmp_str);
conns3.model = &model;
conns3.y = conns2.dest_y;
conns3.x = conns2.dest_x;
conns3.start_switch = tmp_str;
while (fpga_switch_conns_enum(&conns3) != NO_CONN) {
printf("conn3 chain_size %i connpt_o %i num_dests %i i %i y %i x %i str %s\n",
conns3.chain.chain_size, conns3.connpt_dest_start,
conns3.num_dests, conns3.dest_i, conns3.dest_y, conns3.dest_x, conns3.dest_str);
if (is_atyx(YX_ROUTING_TO_FABLOGIC, &model, conns3.dest_y, conns3.dest_x)) {
printf("route to y%02i x%02i\n", conns3.dest_y, conns3.dest_x);
break;
}
}
break;
}
}
break;
#if 0
rc = printf_switchtree(&model, conns.dest_y,
conns.dest_x, conns.dest_str, /*indent*/ 3);
if (rc) FAIL(rc);
// go through whole tree of what is reachable from that
// switch, look for outside connections that reach to a routing tile
chain.model = &model;
chain.y = conns.dest_y;
chain.x = conns.dest_x;
chain.start_switch = conns.dest_str;
chain.from_to = SW_FROM;
while (fpga_switch_chain_enum(&chain) != NO_SWITCH) {
printf("idx %i chain_size %i from %s to %s\n",
chain.chain[chain.chain_size-1], chain.chain_size-1,
fpga_switch_str(&model, chain.y, chain.x, chain.chain[chain.chain_size-1], SW_FROM),
fpga_switch_str(&model, chain.y, chain.x, chain.chain[chain.chain_size-1], SW_TO));
}
}
#endif
}
}
printf("P48 O pinw %s\n", P48_dev->iob.pinw_in_O);

View File

@ -333,9 +333,7 @@ swidx_t fpga_switch_first(struct fpga_model* model, int y, int x,
// Finds the first switch either from or to the name given.
tile = YX_TILE(model, y, x);
for (i = 0; i < tile->num_switches; i++) {
connpt_o = (from_to == SW_FROM)
? SWITCH_FROM(tile->switches[i])
: SWITCH_TO(tile->switches[i]);
connpt_o = SW_I(tile->switches[i], from_to);
if (tile->conn_point_names[connpt_o*2+1] == name_i)
break;
}
@ -351,15 +349,11 @@ static swidx_t fpga_switch_search(struct fpga_model* model, int y, int x,
int connpt_o, name_i, i;
tile = YX_TILE(model, y, x);
connpt_o = (from_to == SW_FROM)
? SWITCH_FROM(tile->switches[last])
: SWITCH_TO(tile->switches[last]);
connpt_o = SW_I(tile->switches[last], from_to);
name_i = tile->conn_point_names[connpt_o*2+1];
for (i = search_beg; i < tile->num_switches; i++) {
connpt_o = (from_to == SW_FROM)
? SWITCH_FROM(tile->switches[i])
: SWITCH_TO(tile->switches[i]);
connpt_o = SW_I(tile->switches[i], from_to);
if (tile->conn_point_names[connpt_o*2+1] == name_i)
break;
}
@ -378,7 +372,7 @@ 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);
}
#define NUM_CONNPT_BUFS 16
#define NUM_CONNPT_BUFS 64
#define CONNPT_BUF_SIZE 128
static const char* connpt_str(struct fpga_model* model, int y, int x, int connpt_o)
@ -406,8 +400,7 @@ const char* fpga_switch_str(struct fpga_model* model, int y, int x,
swidx_t swidx, int from_to)
{
uint32_t sw = YX_TILE(model, y, x)->switches[swidx];
return connpt_str(model, y, x,
(from_to == SW_FROM) ? SWITCH_FROM(sw) : SWITCH_TO(sw));
return connpt_str(model, y, x, SW_I(sw, from_to));
}
int fpga_switch_is_bidir(struct fpga_model* model, int y, int x,
@ -434,9 +427,64 @@ void fpga_switch_disable(struct fpga_model* model, int y, int x,
YX_TILE(model, y, x)->switches[swidx] &= ~SWITCH_ON;
}
#define SW_BUF_SIZE 256
#define NUM_SW_BUFS 64
const char* fmt_sw(struct fpga_model* model, int y, int x, swidx_t sw, int from_to)
{
static char sw_buf[NUM_SW_BUFS][SW_BUF_SIZE];
static int last_buf = 0;
char midstr[64];
last_buf = (last_buf+1)%NUM_SW_BUFS;
strcpy(midstr, fpga_switch_is_enabled(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_sw() 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),
midstr,
(from_to == SW_TO) ? "" : fpga_switch_str(model, y, x, sw, SW_TO));
return sw_buf[last_buf];
}
#define FMT_SWCHAIN_BUF_SIZE 2048
#define FMT_SWCHAIN_NUM_BUFS 8
const char* fmt_swchain(struct fpga_model* model, int y, int x,
swidx_t* sw, int sw_size)
{
static char buf[FMT_SWCHAIN_NUM_BUFS][FMT_SWCHAIN_BUF_SIZE];
static int last_buf = 0;
int i, o;
last_buf = (last_buf+1)%FMT_SWCHAIN_NUM_BUFS;
o = 0;
for (i = 0; i < sw_size; i++) {
if (i) buf[last_buf][o++] = ' ';
strcpy(&buf[last_buf][o], fmt_sw(model, y, x, sw[i], SW_FROM));
o += strlen(&buf[last_buf][o]);
}
buf[last_buf][o] = 0;
return buf[last_buf];
}
int fpga_switch_chain_enum(struct sw_chain* chain)
{
swidx_t idx;
struct fpga_tile* tile;
int child_from_to, i;
if (chain->start_switch != SW_CHAIN_NEXT) {
idx = fpga_switch_first(chain->model, chain->y, chain->x,
@ -478,24 +526,39 @@ int fpga_switch_chain_enum(struct sw_chain* chain)
chain->chain[chain->chain_size-1] = idx;
}
// look for children
tile = YX_TILE(chain->model, chain->y, chain->x);
while (1) {
idx = fpga_switch_first(chain->model, chain->y, chain->x,
fpga_switch_str(chain->model, chain->y, chain->x,
chain->chain[chain->chain_size-1], !chain->from_to),
chain->from_to);
chain->chain[chain->chain_size-1] = fpga_switch_next(
chain->model, chain->y, chain->x,
chain->chain[chain->chain_size-1], chain->from_to);
child_from_to = SW_I(tile->switches[chain->chain[chain->chain_size-1]],
!chain->from_to);
if (idx != NO_SWITCH) {
// If we have the same from-switch already among the
// parents, don't fall into endless recursion...
for (i = 0; i < chain->chain_size; i++) {
if (SW_I(tile->switches[chain->chain[i]], chain->from_to)
== child_from_to)
break;
}
if (i >= chain->chain_size) {
if (chain->chain_size >= MAX_SW_CHAIN_SIZE) {
HERE(); goto internal_error;
}
chain->first_round = 1; // back to first round at new level
// back to first round at new level
chain->first_round = 1;
chain->chain[chain->chain_size] = idx;
chain->chain_size++;
return 0;
}
while (chain->chain[chain->chain_size-1] == NO_SWITCH) {
}
while (1) {
chain->chain[chain->chain_size-1] = fpga_switch_next(
chain->model, chain->y, chain->x,
chain->chain[chain->chain_size-1], chain->from_to);
if (chain->chain[chain->chain_size-1] != NO_SWITCH)
break;
if (chain->chain_size <= 1) {
chain->chain_size = 0;
return NO_SWITCH;

View File

@ -40,11 +40,7 @@ int fpga_connpt_lookup(struct fpga_model* model, int y, int x,
const char* fpga_conn_dest(struct fpga_model* model, int y, int x,
int connpt_dest_idx, int* dest_y, int* dest_x);
typedef int swidx_t;
// SW_FROM and SW_TO values are chosen such that ! inverts them.
#define SW_FROM 0
#define SW_TO 1
typedef int swidx_t; // swidx_t is an index into the uint32_t switches array
// returns a switch index, or -1 (NO_SWITCH) if no switch was found
swidx_t fpga_switch_first(struct fpga_model* model, int y, int x,
@ -65,8 +61,13 @@ void fpga_switch_enable(struct fpga_model* model, int y, int x,
void fpga_switch_disable(struct fpga_model* model, int y, int x,
swidx_t swidx);
const char* fmt_sw(struct fpga_model* model, int y, int x,
swidx_t sw, int from_to);
const char* fmt_swchain(struct fpga_model* model, int y, int x,
swidx_t* sw, int sw_size);
#define SW_CHAIN_NEXT 0 // use for name
#define MAX_SW_CHAIN_SIZE 32
#define MAX_SW_CHAIN_SIZE 32 // largest seen so far was 10
struct sw_chain
{

View File

@ -115,6 +115,8 @@ struct hashed_strarray
#define STRIDX_64K 0xFFFF
#define STRIDX_1M 1000000
typedef uint16_t str16_t;
int strarray_init(struct hashed_strarray* array, int highest_index);
void strarray_free(struct hashed_strarray* array);

37
model.h
View File

@ -270,6 +270,10 @@ int is_atx(int check, struct fpga_model* model, int x);
// True for all tiles that are in the regular 0..15 row tiles of a routing col
#define YX_ROUTING_TILE 0x0001
#define YX_IO_ROUTING 0x0002
#define YX_ROUTING_TO_FABLOGIC 0x0004 // left of a regular fabric logic device
#define YX_DEV_ILOGIC 0x0008
#define YX_DEV_OLOGIC 0x0010
#define YX_DEV_LOGIC 0x0020
int is_atyx(int check, struct fpga_model* model, int y, int x);
@ -387,8 +391,14 @@ struct fpga_device
#define SWITCH_ON 0x80000000
#define SWITCH_BIDIRECTIONAL 0x40000000
#define SWITCH_MAX_CONNPT_O 0x7FFF // 15 bits
#define SWITCH_FROM(u32) (((u32) >> 15) & SWITCH_MAX_CONNPT_O)
#define SWITCH_TO(u32) ((u32) & SWITCH_MAX_CONNPT_O)
#define SW_FROM_I(u32) (((u32) >> 15) & SWITCH_MAX_CONNPT_O)
#define SW_TO_I(u32) ((u32) & SWITCH_MAX_CONNPT_O)
#define SW_I(u32, from_to) ((from_to) ? SW_FROM_I(u32) : SW_TO_I(u32))
// SW_FROM and SW_TO values are chosen such that ! inverts them,
// and swf() assumes that SW_FROM is positive.
#define SW_FROM 1
#define SW_TO 0
#define NO_SWITCH -1
#define NO_CONN -1
@ -435,23 +445,30 @@ void fpga_free_model(struct fpga_model* model);
const char* fpga_tiletype_str(enum fpga_tile_type type);
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);
int init_ports(struct fpga_model* model, int dup_warn);
int init_conns(struct fpga_model* model);
int init_switches(struct fpga_model* model, int routing_sw);
// replicate_routing_switches() is a high-speed optimized way to
// initialize the routing switches, will only work before ports,
// connections or other switches.
int replicate_routing_switches(struct fpga_model* model);
const char* pf(const char* fmt, ...);
const char* wpref(struct fpga_model* model, int y, int x, const char* wire_name);
char next_non_whitespace(const char* s);
char last_major(const char* str, int cur_o);
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 add_connpt_name(struct fpga_model* model, int y, int x,
const char* connpt_name, int dup_warn);
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);
const char* connpt_name, const char* suffix1, const char* suffix2,
int dup_warn);
typedef int (*add_conn_f)(struct fpga_model* model,
int y1, int x1, const char* name1,
@ -508,6 +525,12 @@ int add_switch(struct fpga_model* model, int y, int x, const char* from,
int add_switch_set(struct fpga_model* model, int y, int x, const char* prefix,
const char** pairs, int suffix_inc);
// This will replicate the entire conn_point_names and switches arrays
// from one tile to another, assuming that all of conn_point_names,
// switches and conn_point_dests in the destination tile are empty.
int replicate_switches_and_names(struct fpga_model* model,
int y_from, int x_from, int y_to, int x_to);
struct seed_data
{
int x_flags;

View File

@ -788,11 +788,11 @@ static int run_io_wires(struct fpga_model* model)
for (i = 0; s[i][0]; i++) {
struct w_net net1 = {
1,
{{ pf("BIOB_%s%%i", s[i]), 0, y, x },
{ pf("IOI_BTERM_IOIUP_%s%%i", s[i]), 0, y-1, x },
{ pf("BTERM_IOIUP_%s%%i", s[i]), 0, y-1, x+1 },
{{ pf("BIOI_INNER_%s%%i", s[i]), 0, y-3, x+1 },
{ pf("BIOI_OUTER_%s%%i_EXT", s[i]), 0, y-2, x+1 },
{ pf("BIOI_INNER_%s%%i", s[i]), 0, y-3, x+1 },
{ pf("BTERM_IOIUP_%s%%i", s[i]), 0, y-1, x+1 },
{ pf("IOI_BTERM_IOIUP_%s%%i", s[i]), 0, y-1, x },
{ pf("BIOB_%s%%i", s[i]), 0, y, x },
{ "" }}};
if ((rc = add_conn_net(model, NOPREF_BI_F, &net1))) goto xout;

View File

@ -57,37 +57,37 @@ static int init_iob(struct fpga_model* model, int y, int x,
snprintf(tile->devs[idx].iob.pinw_in_O,
sizeof(tile->devs[idx].iob.pinw_in_O),
"%s_O%i_PINW", prefix, type_idx);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_O);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_O, /*dup_warn*/ 1);
if (rc) FAIL(rc);
snprintf(tile->devs[idx].iob.pinw_in_T,
sizeof(tile->devs[idx].iob.pinw_in_T),
"%s_T%i_PINW", prefix, type_idx);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_T);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_T, /*dup_warn*/ 1);
if (rc) FAIL(rc);
snprintf(tile->devs[idx].iob.pinw_out_I,
sizeof(tile->devs[idx].iob.pinw_out_I),
"%s_IBUF%i_PINW", prefix, type_idx);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_I);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_I, /*dup_warn*/ 1);
if (rc) FAIL(rc);
snprintf(tile->devs[idx].iob.pinw_out_PADOUT,
sizeof(tile->devs[idx].iob.pinw_out_PADOUT),
"%s_PADOUT%i", prefix, type_idx);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_PADOUT);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_PADOUT, /*dup_warn*/ 1);
if (rc) FAIL(rc);
snprintf(tile->devs[idx].iob.pinw_in_DIFFI_IN,
sizeof(tile->devs[idx].iob.pinw_in_DIFFI_IN),
"%s_DIFFI_IN%i", prefix, type_idx);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_DIFFI_IN);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_DIFFI_IN, /*dup_warn*/ 1);
if (rc) FAIL(rc);
snprintf(tile->devs[idx].iob.pinw_in_DIFFO_IN,
sizeof(tile->devs[idx].iob.pinw_in_DIFFO_IN),
"%s_DIFFO_IN%i", prefix, type_idx);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_DIFFO_IN);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_DIFFO_IN, /*dup_warn*/ 1);
if (rc) FAIL(rc);
snprintf(tile->devs[idx].iob.pinw_out_DIFFO_OUT,
sizeof(tile->devs[idx].iob.pinw_out_DIFFO_OUT),
"%s_DIFFO_OUT%i", prefix, type_idx);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_DIFFO_OUT);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_DIFFO_OUT, /*dup_warn*/ 1);
if (rc) FAIL(rc);
if (!x && y == model->center_y - CENTER_TOP_IOB_O && type_idx == 1)
@ -103,7 +103,7 @@ static int init_iob(struct fpga_model* model, int y, int x,
sizeof(tile->devs[idx].iob.pinw_out_PCI_RDY),
"%s_PCI_RDY%i", prefix, type_idx);
}
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_PCI_RDY);
rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_PCI_RDY, /*dup_warn*/ 1);
if (rc) FAIL(rc);
return 0;
fail:

View File

@ -76,15 +76,29 @@ static int _add_connpt_name(struct fpga_model* model, int y, int x,
int* conn_point_o);
int add_connpt_name(struct fpga_model* model, int y, int x,
const char* connpt_name)
const char* connpt_name, int dup_warn)
{
return _add_connpt_name(model, y, x, connpt_name,
1 /* warn_if_duplicate */,
return _add_connpt_name(model, y, x, connpt_name, dup_warn,
0 /* name_i */, 0 /* conn_point_o */);
}
#define CONN_NAMES_INCREMENT 128
// add_switch() assumes that the new element is appended
// at the end of the array.
static void connpt_names_array_append(struct fpga_tile* tile, int name_i)
{
if (!(tile->num_conn_point_names % CONN_NAMES_INCREMENT)) {
uint16_t* new_ptr = realloc(tile->conn_point_names,
(tile->num_conn_point_names+CONN_NAMES_INCREMENT)*2*sizeof(uint16_t));
if (!new_ptr) EXIT(ENOMEM);
tile->conn_point_names = new_ptr;
}
tile->conn_point_names[tile->num_conn_point_names*2] = tile->num_conn_point_dests;
tile->conn_point_names[tile->num_conn_point_names*2+1] = name_i;
tile->num_conn_point_names++;
}
static int _add_connpt_name(struct fpga_model* model, int y, int x,
const char* connpt_name, int warn_if_duplicate, uint16_t* name_i,
int* conn_point_o)
@ -117,18 +131,7 @@ static int _add_connpt_name(struct fpga_model* model, int y, int x,
return 0;
}
// This is the first connection under name, add name.
if (!(tile->num_conn_point_names % CONN_NAMES_INCREMENT)) {
uint16_t* new_ptr = realloc(tile->conn_point_names,
(tile->num_conn_point_names+CONN_NAMES_INCREMENT)*2*sizeof(uint16_t));
if (!new_ptr) {
fprintf(stderr, "Out of memory %s:%i\n", __FILE__, __LINE__);
return 0;
}
tile->conn_point_names = new_ptr;
}
tile->conn_point_names[tile->num_conn_point_names*2] = tile->num_conn_point_dests;
tile->conn_point_names[tile->num_conn_point_names*2+1] = _name_i;
tile->num_conn_point_names++;
connpt_names_array_append(tile, _name_i);
return 0;
}
@ -168,16 +171,17 @@ 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)
const char* connpt_name, const char* suffix1, const char* suffix2,
int dup_warn)
{
char name_buf[64];
int rc;
snprintf(name_buf, sizeof(name_buf), "%s%s", connpt_name, suffix1);
rc = add_connpt_name(model, y, x, name_buf);
rc = add_connpt_name(model, y, x, name_buf, dup_warn);
if (rc) goto xout;
snprintf(name_buf, sizeof(name_buf), "%s%s", connpt_name, suffix2);
rc = add_connpt_name(model, y, x, name_buf);
rc = add_connpt_name(model, y, x, name_buf, dup_warn);
if (rc) goto xout;
return 0;
xout:
@ -322,9 +326,13 @@ xout:
return rc;
}
#define SWITCH_ALLOC_INCREMENT 64
#define SWITCH_ALLOC_INCREMENT 256
#define DBG_ALLOW_ADDPOINTS
// Enable CHECK_DUPLICATES when working on the switch architecture,
// but otherwise keep it disabled since it slows down building the
// model a lot.
#undef CHECK_DUPLICATES
int add_switch(struct fpga_model* model, int y, int x, const char* from,
const char* to, int is_bidirectional)
@ -352,42 +360,31 @@ int add_switch(struct fpga_model* model, int y, int x, const char* from,
return -1;
}
// It seems searching backwards is a little faster than
// searching forwards. Merging the two loops into one
// made the total slower, presumably due to cache issues.
from_connpt_o = -1;
for (i = 0; i < tile->num_conn_point_names; i++) {
for (i = tile->num_conn_point_names-1; i >= 0; i--) {
if (tile->conn_point_names[i*2+1] == from_idx) {
from_connpt_o = i;
break;
}
}
to_connpt_o = -1;
for (i = tile->num_conn_point_names-1; i >= 0; i--) {
if (tile->conn_point_names[i*2+1] == to_idx) {
to_connpt_o = i;
break;
}
}
#ifdef DBG_ALLOW_ADDPOINTS
if (from_connpt_o == -1) {
rc = add_connpt_name(model, y, x, from);
if (rc) goto xout;
for (i = 0; i < tile->num_conn_point_names; i++) {
if (tile->conn_point_names[i*2+1] == from_idx) {
from_connpt_o = i;
break;
from_connpt_o = tile->num_conn_point_names;
connpt_names_array_append(tile, from_idx);
}
}
}
#endif
to_connpt_o = -1;
for (i = 0; i < tile->num_conn_point_names; i++) {
if (tile->conn_point_names[i*2+1] == to_idx) {
to_connpt_o = i;
break;
}
}
#ifdef DBG_ALLOW_ADDPOINTS
if (to_connpt_o == -1) {
rc = add_connpt_name(model, y, x, to);
if (rc) goto xout;
for (i = 0; i < tile->num_conn_point_names; i++) {
if (tile->conn_point_names[i*2+1] == to_idx) {
to_connpt_o = i;
break;
}
}
to_connpt_o = tile->num_conn_point_names;
connpt_names_array_append(tile, to_idx);
}
#endif
if (from_connpt_o == -1 || to_connpt_o == -1) {
@ -405,6 +402,7 @@ int add_switch(struct fpga_model* model, int y, int x, const char* from,
if (is_bidirectional)
new_switch |= SWITCH_BIDIRECTIONAL;
#ifdef CHECK_DUPLICATES
for (i = 0; i < tile->num_switches; i++) {
if ((tile->switches[i] & 0x3FFFFFFF) == (new_switch & 0x3FFFFFFF)) {
fprintf(stderr, "Internal error in %s:%i duplicate switch from %s to %s\n",
@ -412,6 +410,7 @@ int add_switch(struct fpga_model* model, int y, int x, const char* from,
return -1;
}
}
#endif
if (!(tile->num_switches % SWITCH_ALLOC_INCREMENT)) {
uint32_t* new_ptr = realloc(tile->switches,
(tile->num_switches+SWITCH_ALLOC_INCREMENT)*sizeof(*tile->switches));
@ -457,6 +456,35 @@ xout:
return rc;
}
int replicate_switches_and_names(struct fpga_model* model,
int y_from, int x_from, int y_to, int x_to)
{
struct fpga_tile* from_tile, *to_tile;
int rc;
from_tile = YX_TILE(model, y_from, x_from);
to_tile = YX_TILE(model, y_to, x_to);
if (to_tile->num_conn_point_names
|| to_tile->num_conn_point_dests
|| to_tile->num_switches
|| from_tile->num_conn_point_dests
|| !from_tile->num_conn_point_names
|| !from_tile->num_switches) FAIL(EINVAL);
to_tile->conn_point_names = malloc(((from_tile->num_conn_point_names/CONN_NAMES_INCREMENT)+1)*CONN_NAMES_INCREMENT*2*sizeof(uint16_t));
if (!to_tile->conn_point_names) EXIT(ENOMEM);
memcpy(to_tile->conn_point_names, from_tile->conn_point_names, from_tile->num_conn_point_names*2*sizeof(uint16_t));
to_tile->num_conn_point_names = from_tile->num_conn_point_names;
to_tile->switches = malloc(((from_tile->num_switches/SWITCH_ALLOC_INCREMENT)+1)*SWITCH_ALLOC_INCREMENT*sizeof(*from_tile->switches));
if (!to_tile->switches) EXIT(ENOMEM);
memcpy(to_tile->switches, from_tile->switches, from_tile->num_switches*sizeof(*from_tile->switches));
to_tile->num_switches = from_tile->num_switches;
return 0;
fail:
return rc;
}
void seed_strx(struct fpga_model* model, struct seed_data* data)
{
int x, i;
@ -584,6 +612,12 @@ int is_atyx(int check, struct fpga_model* model, int y, int x)
tile = YX_TILE(model, y, x);
if (check & YX_IO_ROUTING
&& (tile->type == IO_ROUTING || tile->type == ROUTING_IO_L)) return 1;
if (check & YX_ROUTING_TO_FABLOGIC
&& model->tiles[x].flags & TF_FABRIC_ROUTING_COL
&& has_device(model, y, x+1, DEV_LOGIC)) return 1;
if (check & YX_DEV_ILOGIC && has_device(model, y, x, DEV_ILOGIC)) return 1;
if (check & YX_DEV_OLOGIC && has_device(model, y, x, DEV_OLOGIC)) return 1;
if (check & YX_DEV_LOGIC && has_device(model, y, x, DEV_LOGIC)) return 1;
return 0;
}

View File

@ -8,8 +8,10 @@
#include <stdarg.h>
#include "model.h"
int fpga_build_model(struct fpga_model* model, int fpga_rows, const char* columns,
const char* left_wiring, const char* right_wiring)
static int s_high_speed_replicate = 1;
int fpga_build_model(struct fpga_model* model, int fpga_rows,
const char* columns, const char* left_wiring, const char* right_wiring)
{
int rc;
@ -27,21 +29,30 @@ int fpga_build_model(struct fpga_model* model, int fpga_rows, const char* column
// that the codes can build upon each other.
rc = init_tiles(model);
if (rc) return rc;
if (rc) FAIL(rc);
rc = init_devices(model);
if (rc) return rc;
if (rc) FAIL(rc);
rc = init_ports(model);
if (rc) return rc;
if (s_high_speed_replicate) {
rc = replicate_routing_switches(model);
if (rc) FAIL(rc);
}
// todo: compare.ports only works if other switches and conns
// are disabled, as long as not all connections are supported
rc = init_ports(model, /*dup_warn*/ !s_high_speed_replicate);
if (rc) FAIL(rc);
rc = init_conns(model);
if (rc) return rc;
if (rc) FAIL(rc);
rc = init_switches(model);
if (rc) return rc;
rc = init_switches(model, /*routing_sw*/ !s_high_speed_replicate);
if (rc) FAIL(rc);
return 0;
fail:
return rc;
}
void fpga_free_model(struct fpga_model* model)

View File

@ -13,7 +13,8 @@ enum which_side
TOP_S, BOTTOM_S, RIGHT_S, LEFT_S
};
static int init_iologic_ports(struct fpga_model* model, int y, int x, enum which_side side)
static int init_iologic_ports(struct fpga_model* model, int y, int x,
enum which_side side, int dup_warn)
{
static const char* prefix, *suffix1, *suffix2;
int rc, i;
@ -34,53 +35,53 @@ static int init_iologic_ports(struct fpga_model* model, int y, int x, enum which
}
for (i = X_A /* 0 */; i <= M_DQ /* 23 */; i++) {
rc = add_connpt_name(model, y, x, pf("IOI_INTER_LOGICOUT%i", i));
rc = add_connpt_name(model, y, x, pf("IOI_INTER_LOGICOUT%i", i), dup_warn);
if (rc) goto xout;
}
rc = add_connpt_name(model, y, x, pf("%s_GND_TIEOFF", prefix));
rc = add_connpt_name(model, y, x, pf("%s_GND_TIEOFF", prefix), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_VCC_TIEOFF", prefix));
rc = add_connpt_name(model, y, x, pf("%s_VCC_TIEOFF", prefix), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_KEEP1_STUB", prefix));
rc = add_connpt_name(model, y, x, pf("%s_KEEP1_STUB", prefix), dup_warn);
if (rc) goto xout;
for (i = 0; i <= 4; i++) {
rc = add_connpt_2(model, y, x, pf("AUXADDR%i_IODELAY", i), suffix1, suffix2);
rc = add_connpt_2(model, y, x, pf("AUXADDR%i_IODELAY", i), suffix1, suffix2, dup_warn);
if (rc) goto xout;
}
rc = add_connpt_2(model, y, x, "AUXSDOIN_IODELAY", suffix1, suffix2);
rc = add_connpt_2(model, y, x, "AUXSDOIN_IODELAY", suffix1, suffix2, dup_warn);
if (rc) goto xout;
rc = add_connpt_2(model, y, x, "AUXSDO_IODELAY", suffix1, suffix2);
rc = add_connpt_2(model, y, x, "AUXSDO_IODELAY", suffix1, suffix2, dup_warn);
if (rc) goto xout;
rc = add_connpt_2(model, y, x, "MEMUPDATE_IODELAY", suffix1, suffix2);
rc = add_connpt_2(model, y, x, "MEMUPDATE_IODELAY", suffix1, suffix2, dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "OUTN_IODELAY_SITE");
rc = add_connpt_name(model, y, x, "OUTN_IODELAY_SITE", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "STUB_OUTN_IODELAY_S");
rc = add_connpt_name(model, y, x, "STUB_OUTN_IODELAY_S", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "OUTP_IODELAY_SITE");
rc = add_connpt_name(model, y, x, "OUTP_IODELAY_SITE", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "STUB_OUTP_IODELAY_S");
rc = add_connpt_name(model, y, x, "STUB_OUTP_IODELAY_S", dup_warn);
if (rc) goto xout;
for (i = 1; i <= 4; i++) {
rc = add_connpt_2(model, y, x, pf("Q%i_ILOGIC_SITE", i), "", "_S");
rc = add_connpt_2(model, y, x, pf("Q%i_ILOGIC_SITE", i), "", "_S", dup_warn);
if (rc) goto xout;
rc = add_connpt_2(model, y, x, pf("D%i_OLOGIC_SITE", i), "", "_S");
rc = add_connpt_2(model, y, x, pf("D%i_OLOGIC_SITE", i), "", "_S", dup_warn);
if (rc) goto xout;
rc = add_connpt_2(model, y, x, pf("T%i_OLOGIC_SITE", i), "", "_S");
rc = add_connpt_2(model, y, x, pf("T%i_OLOGIC_SITE", i), "", "_S", dup_warn);
if (rc) goto xout;
rc = add_connpt_2(model, y, x, pf("SHIFTIN%i_OLOGIC_SITE", i), "", "_S");
rc = add_connpt_2(model, y, x, pf("SHIFTIN%i_OLOGIC_SITE", i), "", "_S", dup_warn);
if (rc) goto xout;
rc = add_connpt_2(model, y, x, pf("SHIFTOUT%i_OLOGIC_SITE", i), "", "_S");
rc = add_connpt_2(model, y, x, pf("SHIFTOUT%i_OLOGIC_SITE", i), "", "_S", dup_warn);
if (rc) goto xout;
}
for (i = 0; i <= 1; i++) {
rc = add_connpt_2(model, y, x, pf("CFB%i_ILOGIC_SITE", i), "", "_S");
rc = add_connpt_2(model, y, x, pf("CFB%i_ILOGIC_SITE", i), "", "_S", dup_warn);
if (rc) goto xout;
rc = add_connpt_2(model, y, x, pf("CLK%i_ILOGIC_SITE", i), "", "_S");
rc = add_connpt_2(model, y, x, pf("CLK%i_ILOGIC_SITE", i), "", "_S", dup_warn);
if (rc) goto xout;
rc = add_connpt_2(model, y, x, pf("CLK%i_OLOGIC_SITE", i), "", "_S");
rc = add_connpt_2(model, y, x, pf("CLK%i_OLOGIC_SITE", i), "", "_S", dup_warn);
if (rc) goto xout;
}
{
@ -110,29 +111,29 @@ static int init_iologic_ports(struct fpga_model* model, int y, int x, enum which
"VALID_ILOGIC_SITE", "" };
for (i = 0; mcb_2[i][0]; i++) {
rc = add_connpt_2(model, y, x, mcb_2[i], "", "_S");
rc = add_connpt_2(model, y, x, mcb_2[i], "", "_S", dup_warn);
}
}
rc = add_connpt_name(model, y, x, "DATAOUT2_IODELAY_SITE");
rc = add_connpt_name(model, y, x, "DATAOUT2_IODELAY_SITE", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "DATAOUT2_IODELAY2_SITE_S");
rc = add_connpt_name(model, y, x, "DATAOUT2_IODELAY2_SITE_S", dup_warn);
if (rc) goto xout;
for (i = 0; i <= 2; i++) {
rc = add_connpt_2(model, y, x, pf("IOI_CLK%iINTER", i),
"_M", "_S");
"_M", "_S", dup_warn);
if (rc) goto xout;
}
for (i = 0; i <= 1; i++) {
rc = add_connpt_2(model, y, x, pf("IOI_CLKDIST_IOCE%i", i),
"_M", "_S");
"_M", "_S", dup_warn);
if (rc) goto xout;
}
rc = add_connpt_2(model, y, x, "IOI_CLKDIST_CLK0_ILOGIC", "_M", "_S");
rc = add_connpt_2(model, y, x, "IOI_CLKDIST_CLK0_ILOGIC", "_M", "_S", dup_warn);
if (rc) goto xout;
rc = add_connpt_2(model, y, x, "IOI_CLKDIST_CLK0_OLOGIC", "_M", "_S");
rc = add_connpt_2(model, y, x, "IOI_CLKDIST_CLK0_OLOGIC", "_M", "_S", dup_warn);
if (rc) goto xout;
rc = add_connpt_2(model, y, x, "IOI_CLKDIST_CLK1", "_M", "_S");
rc = add_connpt_2(model, y, x, "IOI_CLKDIST_CLK1", "_M", "_S", dup_warn);
if (rc) goto xout;
if (side == TOP_S || side == BOTTOM_S) {
@ -147,11 +148,11 @@ static int init_iologic_ports(struct fpga_model* model, int y, int x, enum which
"IOI_MCB_DRPTRAIN", "" };
for (i = 0; mcb_2[i][0]; i++) {
rc = add_connpt_2(model, y, x, mcb_2[i], "_M", "_S");
rc = add_connpt_2(model, y, x, mcb_2[i], "_M", "_S", dup_warn);
if (rc) goto xout;
}
for (i = 0; mcb_1[i][0]; i++) {
rc = add_connpt_name(model, y, x, mcb_1[i]);
rc = add_connpt_name(model, y, x, mcb_1[i], dup_warn);
if (rc) goto xout;
}
}
@ -160,36 +161,36 @@ xout:
return rc;
}
int init_ports(struct fpga_model* model)
int init_ports(struct fpga_model* model, int dup_warn)
{
int x, y, i, j, k, row_num, row_pos, rc;
// inner and outer IO tiles (ILOGIC/ILOGIC/IODELAY)
for (x = LEFT_SIDE_WIDTH; x < model->x_width - RIGHT_SIDE_WIDTH; x++) {
if (has_device(model, TOP_OUTER_IO, x, DEV_ILOGIC)) {
rc = init_iologic_ports(model, TOP_OUTER_IO, x, TOP_S);
rc = init_iologic_ports(model, TOP_OUTER_IO, x, TOP_S, dup_warn);
if (rc) goto xout;
}
if (has_device(model, TOP_INNER_IO, x, DEV_ILOGIC)) {
rc = init_iologic_ports(model, TOP_INNER_IO, x, TOP_S);
rc = init_iologic_ports(model, TOP_INNER_IO, x, TOP_S, dup_warn);
if (rc) goto xout;
}
if (has_device(model, model->y_height - BOT_INNER_IO, x, DEV_ILOGIC)) {
rc = init_iologic_ports(model, model->y_height - BOT_INNER_IO, x, BOTTOM_S);
rc = init_iologic_ports(model, model->y_height - BOT_INNER_IO, x, BOTTOM_S, dup_warn);
if (rc) goto xout;
}
if (has_device(model, model->y_height - BOT_OUTER_IO, x, DEV_ILOGIC)) {
rc = init_iologic_ports(model, model->y_height - BOT_OUTER_IO, x, BOTTOM_S);
rc = init_iologic_ports(model, model->y_height - BOT_OUTER_IO, x, BOTTOM_S, dup_warn);
if (rc) goto xout;
}
}
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (has_device(model, y, LEFT_IO_DEVS, DEV_ILOGIC)) {
rc = init_iologic_ports(model, y, LEFT_IO_DEVS, LEFT_S);
rc = init_iologic_ports(model, y, LEFT_IO_DEVS, LEFT_S, dup_warn);
if (rc) goto xout;
}
if (has_device(model, y, model->x_width - RIGHT_IO_DEVS_O, DEV_ILOGIC)) {
rc = init_iologic_ports(model, y, model->x_width - RIGHT_IO_DEVS_O, RIGHT_S);
rc = init_iologic_ports(model, y, model->x_width - RIGHT_IO_DEVS_O, RIGHT_S, dup_warn);
if (rc) goto xout;
}
}
@ -200,20 +201,20 @@ int init_ports(struct fpga_model* model)
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS,
model, y))
continue;
rc = add_connpt_name(model, y, x, "VCC_WIRE");
rc = add_connpt_name(model, y, x, "VCC_WIRE", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "GND_WIRE");
rc = add_connpt_name(model, y, x, "GND_WIRE", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "KEEP1_WIRE");
rc = add_connpt_name(model, y, x, "KEEP1_WIRE", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "FAN");
rc = add_connpt_name(model, y, x, "FAN", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "FAN_B");
rc = add_connpt_name(model, y, x, "FAN_B", dup_warn);
if (rc) goto xout;
if (!is_atyx(YX_IO_ROUTING, model, y, x)) {
for (i = 0; i <= 1; i++) {
rc = add_connpt_name(model, y, x, pf("GFAN%i", i));
rc = add_connpt_name(model, y, x, pf("GFAN%i", i), dup_warn);
if (rc) goto xout;
}
} else {
@ -223,10 +224,10 @@ int init_ports(struct fpga_model* model)
// to the PLL, but elsewhere? Not clear what they
// connect to...
rc = add_connpt_name(model, y, x,
logicin_s(X_A5, 1 /* routing_io */));
logicin_s(X_A5, 1 /* routing_io */), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x,
logicin_s(X_B4, 1 /* routing_io */));
logicin_s(X_B4, 1 /* routing_io */), dup_warn);
if (rc) goto xout;
}
}
@ -240,30 +241,30 @@ int init_ports(struct fpga_model* model)
// pass 0 is ramb16, pass 1 and 2 are for ramb8
for (i = 0; i <= 2; i++) {
for (j = 'A'; j <= 'B'; j++) {
rc = add_connpt_name(model, y, x, pf("%s_CLK%c", pass_str[i], j));
rc = add_connpt_name(model, y, x, pf("%s_CLK%c", pass_str[i], j), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_EN%c", pass_str[i], j));
rc = add_connpt_name(model, y, x, pf("%s_EN%c", pass_str[i], j), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_REGCE%c", pass_str[i], j));
rc = add_connpt_name(model, y, x, pf("%s_REGCE%c", pass_str[i], j), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_RST%c", pass_str[i], j));
rc = add_connpt_name(model, y, x, pf("%s_RST%c", pass_str[i], j), dup_warn);
if (rc) goto xout;
for (k = 0; k <= (!i ? 3 : 1); k++) {
rc = add_connpt_name(model, y, x, pf("%s_DIP%c%i", pass_str[i], j, k));
rc = add_connpt_name(model, y, x, pf("%s_DIP%c%i", pass_str[i], j, k), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_DOP%c%i", pass_str[i], j, k));
rc = add_connpt_name(model, y, x, pf("%s_DOP%c%i", pass_str[i], j, k), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_WE%c%i", pass_str[i], j, k));
rc = add_connpt_name(model, y, x, pf("%s_WE%c%i", pass_str[i], j, k), dup_warn);
if (rc) goto xout;
}
for (k = 0; k <= (!i ? 13 : 12); k++) {
rc = add_connpt_name(model, y, x, pf("%s_ADDR%c%i", pass_str[i], j, k));
rc = add_connpt_name(model, y, x, pf("%s_ADDR%c%i", pass_str[i], j, k), dup_warn);
if (rc) goto xout;
}
for (k = 0; k <= (!i ? 31 : 15); k++) {
rc = add_connpt_name(model, y, x, pf("%s_DI%c%i", pass_str[i], j, k));
rc = add_connpt_name(model, y, x, pf("%s_DI%c%i", pass_str[i], j, k), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_DO%c%i", pass_str[i], j, k));
rc = add_connpt_name(model, y, x, pf("%s_DO%c%i", pass_str[i], j, k), dup_warn);
if (rc) goto xout;
}
}
@ -279,54 +280,54 @@ int init_ports(struct fpga_model* model)
is_in_row(model, y, &row_num, &row_pos);
if (!row_num && row_pos == LAST_POS_IN_ROW) {
rc = add_connpt_name(model, y, x, "CARRYIN_DSP48A1_SITE");
rc = add_connpt_name(model, y, x, "CARRYIN_DSP48A1_SITE", dup_warn);
if (rc) goto xout;
for (i = 0; i <= 47; i++) {
rc = add_connpt_name(model, y, x, pf("PCIN%i_DSP48A1_SITE", i));
rc = add_connpt_name(model, y, x, pf("PCIN%i_DSP48A1_SITE", i), dup_warn);
if (rc) goto xout;
}
}
rc = add_connpt_name(model, y, x, "CLK_DSP48A1_SITE");
rc = add_connpt_name(model, y, x, "CLK_DSP48A1_SITE", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "CARRYOUT_DSP48A1_SITE");
rc = add_connpt_name(model, y, x, "CARRYOUT_DSP48A1_SITE", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "CARRYOUTF_DSP48A1_SITE");
rc = add_connpt_name(model, y, x, "CARRYOUTF_DSP48A1_SITE", dup_warn);
if (rc) goto xout;
for (i = 0; pref[i][0]; i++) {
rc = add_connpt_name(model, y, x, pf("%sCARRYIN_DSP48A1_SITE", pref[i]));
rc = add_connpt_name(model, y, x, pf("%sCARRYIN_DSP48A1_SITE", pref[i]), dup_warn);
if (rc) goto xout;
for (j = 0; seq[j][0]; j++) {
rc = add_connpt_name(model, y, x, pf("%s%s_DSP48A1_SITE", pref[i], seq[j]));
rc = add_connpt_name(model, y, x, pf("%s%s_DSP48A1_SITE", pref[i], seq[j]), dup_warn);
if (rc) goto xout;
}
}
for (i = 0; i <= 17; i++) {
rc = add_connpt_name(model, y, x, pf("A%i_DSP48A1_SITE", i));
rc = add_connpt_name(model, y, x, pf("A%i_DSP48A1_SITE", i), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("B%i_DSP48A1_SITE", i));
rc = add_connpt_name(model, y, x, pf("B%i_DSP48A1_SITE", i), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("D%i_DSP48A1_SITE", i));
rc = add_connpt_name(model, y, x, pf("D%i_DSP48A1_SITE", i), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("BCOUT%i_DSP48A1_SITE", i));
rc = add_connpt_name(model, y, x, pf("BCOUT%i_DSP48A1_SITE", i), dup_warn);
if (rc) goto xout;
}
for (i = 0; i <= 47; i++) {
rc = add_connpt_name(model, y, x, pf("C%i_DSP48A1_SITE", i));
rc = add_connpt_name(model, y, x, pf("C%i_DSP48A1_SITE", i), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("P%i_DSP48A1_SITE", i));
rc = add_connpt_name(model, y, x, pf("P%i_DSP48A1_SITE", i), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("PCOUT%i_DSP48A1_SITE", i));
rc = add_connpt_name(model, y, x, pf("PCOUT%i_DSP48A1_SITE", i), dup_warn);
if (rc) goto xout;
}
for (i = 0; i <= 35; i++) {
rc = add_connpt_name(model, y, x, pf("M%i_DSP48A1_SITE", i));
rc = add_connpt_name(model, y, x, pf("M%i_DSP48A1_SITE", i), dup_warn);
if (rc) goto xout;
}
for (i = 0; i <= 7; i++) {
rc = add_connpt_name(model, y, x, pf("OPMODE%i_DSP48A1_SITE", i));
rc = add_connpt_name(model, y, x, pf("OPMODE%i_DSP48A1_SITE", i), dup_warn);
if (rc) goto xout;
}
}
@ -340,44 +341,44 @@ int init_ports(struct fpga_model* model)
if (YX_TILE(model, y, x)->flags & TF_LOGIC_XM_DEV) {
// The first SLICEM on the bottom has a given C_IN port.
if (is_aty(Y_INNER_BOTTOM, model, y+3)) {
rc = add_connpt_name(model, y, x, "M_CIN");
rc = add_connpt_name(model, y, x, "M_CIN", dup_warn);
if (rc) goto xout;
}
rc = add_connpt_name(model, y, x, "M_COUT");
rc = add_connpt_name(model, y, x, "M_COUT", dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, "M_WE");
rc = add_connpt_name(model, y, x, "M_WE", dup_warn);
if (rc) goto xout;
for (i = 'A'; i <= 'D'; i++) {
rc = add_connpt_name(model, y, x, pf("M_%cI", i));
rc = add_connpt_name(model, y, x, pf("M_%cI", i), dup_warn);
if (rc) goto xout;
}
pref[0] = "M";
pref[1] = "X";
} else { // LOGIC_XL
rc = add_connpt_name(model, y, x, "XL_COUT");
rc = add_connpt_name(model, y, x, "XL_COUT", dup_warn);
if (rc) goto xout;
pref[0] = "L";
pref[1] = "XX";
}
for (k = 0; k <= 1; k++) {
rc = add_connpt_name(model, y, x, pf("%s_CE", pref[k]));
rc = add_connpt_name(model, y, x, pf("%s_CE", pref[k]), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_SR", pref[k]));
rc = add_connpt_name(model, y, x, pf("%s_SR", pref[k]), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_CLK", pref[k]));
rc = add_connpt_name(model, y, x, pf("%s_CLK", pref[k]), dup_warn);
if (rc) goto xout;
for (i = 'A'; i <= 'D'; i++) {
for (j = 1; j <= 6; j++) {
rc = add_connpt_name(model, y, x, pf("%s_%c%i", pref[k], i, j));
rc = add_connpt_name(model, y, x, pf("%s_%c%i", pref[k], i, j), dup_warn);
if (rc) goto xout;
}
rc = add_connpt_name(model, y, x, pf("%s_%c", pref[k], i));
rc = add_connpt_name(model, y, x, pf("%s_%c", pref[k], i), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_%cMUX", pref[k], i));
rc = add_connpt_name(model, y, x, pf("%s_%cMUX", pref[k], i), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_%cQ", pref[k], i));
rc = add_connpt_name(model, y, x, pf("%s_%cQ", pref[k], i), dup_warn);
if (rc) goto xout;
rc = add_connpt_name(model, y, x, pf("%s_%cX", pref[k], i));
rc = add_connpt_name(model, y, x, pf("%s_%cX", pref[k], i), dup_warn);
if (rc) goto xout;
}
}

View File

@ -15,10 +15,15 @@ static int init_north_south_dirwire_term(struct fpga_model* model);
static int init_iologic_switches(struct fpga_model* model);
static int init_logic_switches(struct fpga_model* model);
int init_switches(struct fpga_model* model)
int init_switches(struct fpga_model* model, int routing_sw)
{
int rc;
if (routing_sw) {
rc = init_routing_switches(model);
if (rc) goto xout;
}
rc = init_logic_switches(model);
if (rc) goto xout;
@ -34,10 +39,6 @@ int init_switches(struct fpga_model* model)
rc = init_io_switches(model);
if (rc) goto xout;
#if 0
rc = init_routing_switches(model);
if (rc) goto xout;
#endif
return 0;
xout:
return rc;
@ -1671,21 +1672,14 @@ xout:
return rc;
}
static int init_routing_switches(struct fpga_model* model)
static int init_routing_tile(struct fpga_model* model, int y, int x)
{
int x, y, i, j, routing_io, rc;
int i, j, routing_io, rc;
struct set_of_switches dir_EB_switches;
enum wire_type wire;
struct fpga_tile* tile;
const char* gfan_s, *gclk_s;
for (x = 0; x < model->x_width; x++) {
if (!is_atx(X_ROUTING_COL, model, x))
continue;
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS,
model, y))
continue;
tile = YX_TILE(model, y, x);
routing_io = (tile->type == IO_ROUTING || tile->type == ROUTING_IO_L);
gfan_s = routing_io ? "INT_IOI_GFAN%i" : "GFAN%i";
@ -1694,11 +1688,10 @@ static int init_routing_switches(struct fpga_model* model)
for (i = 0; i <= 1; i++) {
rc = add_switch(model, y, x, "GND_WIRE",
pf(gfan_s, i), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
rc = add_switch(model, y, x, "GND_WIRE", "SR1",
0 /* bidir */);
if (rc) goto xout;
rc = add_switch(model, y, x, "GND_WIRE", "SR1", 0 /* bidir */);
if (rc) FAIL(rc);
// VCC
{ int vcc_dest[] = {
@ -1709,21 +1702,18 @@ static int init_routing_switches(struct fpga_model* model)
for (i = 0; i < sizeof(vcc_dest)/sizeof(vcc_dest[0]); i++) {
rc = add_switch(model, y, x, "VCC_WIRE",
logicin_s(vcc_dest[i], routing_io),
0 /* bidir */);
if (rc) goto xout;
logicin_s(vcc_dest[i], routing_io), 0 /* bidir */);
if (rc) FAIL(rc);
}}
// KEEP1
for (i = X_A1; i <= M_WE; i++) {
rc = add_switch(model, y, x, "KEEP1_WIRE",
logicin_s(i, routing_io),
0 /* bidir */);
if (rc) goto xout;
logicin_s(i, routing_io), 0 /* bidir */);
if (rc) FAIL(rc);
}
rc = add_switch(model, y, x, "KEEP1_WIRE", "FAN_B",
0 /* bidir */);
if (rc) goto xout;
rc = add_switch(model, y, x, "KEEP1_WIRE", "FAN_B", 0 /* bidir */);
if (rc) FAIL(rc);
// VCC and KEEP1 to CLK0:1, SR0:1, GFAN0:1
{ static const char* src[] = {"VCC_WIRE", "KEEP1_WIRE"};
@ -1731,15 +1721,13 @@ static int init_routing_switches(struct fpga_model* model)
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, src[i],
pf("CLK%i", j), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
rc = add_switch(model, y, x, src[i],
pf("SR%i", j), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
rc = add_switch(model, y, x,
src[i],
pf(gfan_s, j),
0 /* bidir */);
if (rc) goto xout;
src[i], pf(gfan_s, j), 0 /* bidir */);
if (rc) FAIL(rc);
}
}
@ -1751,18 +1739,14 @@ static int init_routing_switches(struct fpga_model* model)
gclk_s = "GCLK%i";
for (i = 0; i <= 15; i++) {
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, pf(gclk_s, i),
pf("CLK%i", j), 0 /* bidir */);
if (rc) FAIL(rc);
rc = add_switch(model, y, x,
pf(gclk_s, i),
pf("CLK%i", j),
(i < 8) ? pf(gfan_s, j) : pf("SR%i", j),
0 /* bidir */);
if (rc) goto xout;
rc = add_switch(model, y, x,
pf(gclk_s, i),
(i < 8)
? pf(gfan_s, j)
: pf("SR%i", j),
0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
}
@ -1770,31 +1754,32 @@ static int init_routing_switches(struct fpga_model* model)
for (i = 0; i <= 1; i++) {
rc = add_switch(model, y, x, "FAN_B",
pf("SR%i", i), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
// some logicin wires are singled out
{ int logic_singles[] = {X_CE, X_CX, X_DX,
M_AI, M_BI, M_CX, M_DX, M_WE};
for (i = 0; i < sizeof(logic_singles)/sizeof(logic_singles[0]); i++) {
rc = add_switch(model, y, x, pf("LOGICIN_B%i", logic_singles[i]),
rc = add_switch(model, y, x,
pf("LOGICIN_B%i", logic_singles[i]),
pf("LOGICIN%i", logic_singles[i]), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}}
// connecting directional wires endpoints to logicin
rc = add_logicin_switches(model, y, x);
if (rc) goto xout;
if (rc) FAIL(rc);
// connecting logicout back to directional wires
// beginning points (and some back to logicin)
rc = add_logicout_switches(model, y, x, routing_io);
if (rc) goto xout;
if (rc) FAIL(rc);
// there are extra wires to send signals to logicin, or
// to share/multiply logicin signals
rc = add_logicio_extra(model, y, x, routing_io);
if (rc) goto xout;
if (rc) FAIL(rc);
// extra wires going to SR, CLK and GFAN
{ int to_sr[] = {X_BX, M_BX, M_DI};
@ -1803,7 +1788,7 @@ static int init_routing_switches(struct fpga_model* model)
rc = add_switch(model, y, x,
pf("LOGICIN_B%i", to_sr[i]),
pf("SR%i", j), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
}}
{ int to_clk[] = {M_BX, M_CI};
@ -1812,7 +1797,7 @@ static int init_routing_switches(struct fpga_model* model)
rc = add_switch(model, y, x,
pf("LOGICIN_B%i", to_clk[i]),
pf("CLK%i", j), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
}}
{ int to_gf[] = {M_AX, X_AX, M_CE, M_CI};
@ -1823,7 +1808,7 @@ static int init_routing_switches(struct fpga_model* model)
rc = add_switch(model, y, x,
pf("LOGICIN_B%i", to_gf[i]),
pf(gfan_s, j), bidir);
if (rc) goto xout;
if (rc) FAIL(rc);
}
}}
@ -1832,30 +1817,30 @@ static int init_routing_switches(struct fpga_model* model)
wire = W_NN2;
do {
rc = build_dirwire_switches(&dir_EB_switches, W_TO_LEN1(wire));
if (rc) goto xout;
if (rc) FAIL(rc);
for (i = 0; i < dir_EB_switches.num_s; i++) {
rc = add_switch(model, y, x,
dir_EB_switches.s[i].from,
dir_EB_switches.s[i].to, 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
rc = build_dirwire_switches(&dir_EB_switches, W_TO_LEN2(wire));
if (rc) goto xout;
if (rc) FAIL(rc);
for (i = 0; i < dir_EB_switches.num_s; i++) {
rc = add_switch(model, y, x,
dir_EB_switches.s[i].from,
dir_EB_switches.s[i].to, 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
rc = build_dirwire_switches(&dir_EB_switches, W_TO_LEN4(wire));
if (rc) goto xout;
if (rc) FAIL(rc);
for (i = 0; i < dir_EB_switches.num_s; i++) {
rc = add_switch(model, y, x,
dir_EB_switches.s[i].from,
dir_EB_switches.s[i].to, 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
wire = W_CLOCKWISE(wire);
@ -1867,10 +1852,10 @@ static int init_routing_switches(struct fpga_model* model)
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, from[i],
pf("CLK%i", j), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
rc = add_switch(model, y, x, from[i],
pf("SR%i", j), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
}}
{ static const char* from[] = {"ER1E1", "SR1E1"};
@ -1878,10 +1863,10 @@ static int init_routing_switches(struct fpga_model* model)
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, from[i],
pf("CLK%i", j), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
rc = add_switch(model, y, x, from[i],
pf(gfan_s, j), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
}}
{ static const char* from[] = {"NR1E1", "WR1E1"};
@ -1889,7 +1874,7 @@ static int init_routing_switches(struct fpga_model* model)
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, from[i],
pf(gfan_s, j), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
}}
{ static const char* from[] = {"ER1E2", "SR1E2"};
@ -1897,12 +1882,69 @@ static int init_routing_switches(struct fpga_model* model)
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, from[i],
pf("SR%i", j), 0 /* bidir */);
if (rc) goto xout;
if (rc) FAIL(rc);
}
}}
return 0;
fail:
return rc;
}
static int init_routing_switches(struct fpga_model* model)
{
int x, y, rc;
for (x = 0; x < model->x_width; x++) {
if (!is_atx(X_ROUTING_COL, model, x))
continue;
for (y = TOP_IO_TILES; y < model->y_height-BOT_IO_TILES; y++) {
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS,
model, y))
continue;
rc = init_routing_tile(model, y, x);
if (rc) FAIL(rc);
}
}
return 0;
xout:
fail:
return rc;
}
int replicate_routing_switches(struct fpga_model* model)
{
struct fpga_tile* tile;
int x, y, first_y, first_x, rc;
first_y = -1;
for (x = 0; x < model->x_width; x++) {
if (!is_atx(X_ROUTING_COL, model, x))
continue;
for (y = TOP_IO_TILES; y < model->y_height-BOT_IO_TILES; y++) {
if (is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS,
model, y))
continue;
tile = YX_TILE(model, y, x);
// Some tiles are different so we cannot include
// them in the high-speed replication scheme.
if (tile->type == IO_ROUTING || tile->type == ROUTING_IO_L
|| tile->type == ROUTING_BRK || tile->type == BRAM_ROUTING_BRK) {
rc = init_routing_tile(model, y, x);
if (rc) FAIL(rc);
continue;
}
if (first_y == -1) {
first_y = y;
first_x = x;
rc = init_routing_tile(model, y, x);
if (rc) FAIL(rc);
continue;
}
rc = replicate_switches_and_names(model,
first_y, first_x, y, x);
if (rc) FAIL(rc);
}
}
return 0;
fail:
return rc;
}