slow day
This commit is contained in:
parent
9fdfef088b
commit
dc1a40805f
93
autotest.c
93
autotest.c
|
@ -103,12 +103,61 @@ fail:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static const char* s_spaces = " ";
|
||||
|
||||
static int printf_switchtree(struct fpga_model* model, int y, int x,
|
||||
const char* start, int indent)
|
||||
{
|
||||
int i, idx, conn_to_y, conn_to_x, rc;
|
||||
const char* to_str;
|
||||
|
||||
printf("%.*sy%02i x%02i %s\n", indent, s_spaces, y, x, start);
|
||||
for (i = 0;; i++) {
|
||||
idx = fpga_conn_dest(model, y, x, start, i);
|
||||
if (idx == NO_CONN)
|
||||
break;
|
||||
if (!i)
|
||||
printf("%.*s| connects to:\n", indent, s_spaces);
|
||||
to_str = fpga_conn_to(model, y, x,
|
||||
idx, &conn_to_y, &conn_to_x);
|
||||
printf("%.*s y%02i x%02i %s\n", indent, s_spaces,
|
||||
conn_to_y, conn_to_x, to_str);
|
||||
}
|
||||
|
||||
idx = fpga_switch_first(model, y, x, start, SW_TO);
|
||||
if (idx != NO_SWITCH)
|
||||
printf("%.*s| can be switched from:\n", indent, s_spaces);
|
||||
while (idx != NO_SWITCH) {
|
||||
to_str = fpga_switch_str(model, y, x, idx, SW_FROM);
|
||||
printf("%.*s %s %s\n", indent, s_spaces,
|
||||
fpga_switch_is_bidir(model, y, x, idx) ? "<->" : "<-",
|
||||
to_str);
|
||||
idx = fpga_switch_next(model, y, x, idx, SW_TO);
|
||||
}
|
||||
|
||||
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) {
|
||||
to_str = fpga_switch_str(model, y, x, idx, SW_TO);
|
||||
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);
|
||||
if (rc) FAIL(rc);
|
||||
idx = fpga_switch_next(model, y, x, idx, SW_FROM);
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
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, i, j, sw_idx, rc;
|
||||
int P46_y, P46_x, P46_idx, P48_y, P48_x, P48_idx, i, sw_idx, rc;
|
||||
const char* str;
|
||||
char tmp_str[128];
|
||||
struct test_state tstate;
|
||||
const char* conn_to_str;
|
||||
int conn_idx, conn_to_y, conn_to_x;
|
||||
|
@ -170,21 +219,45 @@ int main(int argc, char** argv)
|
|||
if (rc) goto fail;
|
||||
|
||||
printf("P46 I pinw %s\n", P46_dev->iob.pinw_out_I);
|
||||
for (i = 0;; i++) {
|
||||
sw_idx = fpga_switch_dest(&model, P46_y, P46_x, P46_dev->iob.pinw_out_I, i);
|
||||
if (sw_idx == NO_SWITCH)
|
||||
break;
|
||||
str = fpga_switch_to(&model, P46_y, P46_x, sw_idx, /*bidir*/ 0);
|
||||
printf(" from %s to %s\n", P46_dev->iob.pinw_out_I, str);
|
||||
for (j = 0;; j++) {
|
||||
conn_idx = fpga_conn_dest(&model, P46_y, P46_x, str, j);
|
||||
sw_idx = fpga_switch_first(&model, P46_y, P46_x,
|
||||
P46_dev->iob.pinw_out_I, SW_FROM);
|
||||
while (sw_idx != NO_SWITCH) {
|
||||
str = fpga_switch_str(&model, P46_y, P46_x, sw_idx, SW_TO);
|
||||
if (!str) FAIL(EINVAL);
|
||||
strcpy(tmp_str, str); // ringbuffer too small for long use
|
||||
printf(" from %s to %s\n", P46_dev->iob.pinw_out_I, tmp_str);
|
||||
for (i = 0;; i++) {
|
||||
conn_idx = fpga_conn_dest(&model, P46_y, P46_x, tmp_str, i);
|
||||
if (conn_idx == NO_CONN)
|
||||
break;
|
||||
conn_to_str = fpga_conn_to(&model, P46_y, P46_x,
|
||||
conn_idx, &conn_to_y, &conn_to_x);
|
||||
printf(" %s goes to y%02i x%02i %s\n",
|
||||
str, conn_to_y, conn_to_x, conn_to_str);
|
||||
tmp_str, conn_to_y, conn_to_x, conn_to_str);
|
||||
if (is_aty(Y_TOP_INNER_IO|Y_BOT_INNER_IO, &model, conn_to_y)) {
|
||||
rc = printf_switchtree(&model, conn_to_y,
|
||||
conn_to_x, conn_to_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
|
||||
{ swidx_t idx;
|
||||
swidx_t* parents; int num_parents;
|
||||
|
||||
idx = fpga_switch_tree(&model, conn_to_y, conn_to_x,
|
||||
conn_to_str, SW_FROM, &parents, &num_parents);
|
||||
while (idx != NO_SWITCH) {
|
||||
printf("idx %i num_parents %i from %s to %s\n",
|
||||
idx, num_parents,
|
||||
fpga_switch_str(&model, conn_to_y, conn_to_x, idx, SW_FROM),
|
||||
fpga_switch_str(&model, conn_to_y, conn_to_x, idx, SW_TO));
|
||||
idx = fpga_switch_tree(&model, conn_to_y, conn_to_x,
|
||||
SW_TREE_NEXT, SW_FROM, &parents, &num_parents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sw_idx = fpga_switch_next(&model, P46_y, P46_x, sw_idx, SW_FROM);
|
||||
}
|
||||
printf("P48 O pinw %s\n", P48_dev->iob.pinw_in_O);
|
||||
|
||||
|
|
185
control.c
185
control.c
|
@ -31,17 +31,17 @@ static const struct iob_site xc6slx9_iob_top[] =
|
|||
|
||||
static const struct iob_site xc6slx9_iob_bottom[] =
|
||||
{
|
||||
{ 5, {"P38", "P39", "P40", "P41"}},
|
||||
{ 7, {"UNB140", "UNB139", "P43", "P44"}},
|
||||
{12, {"P45", "P46", "P47", "P48"}},
|
||||
{14, {"UNB132", "UNB131", "UNB130", "UNB129"}},
|
||||
{19, {"UNB128", "UNB127", "UNB126", "UNB125"}},
|
||||
{21, {"UNB124", "UNB123", "P50", "P51"}},
|
||||
{25, {"P55", "P56", "UNB118", "UNB117"}},
|
||||
{29, {"UNB116", "UNB115", "UNB114", "UNB113"}},
|
||||
{31, {"P57", "P58", "P59", "P60"}},
|
||||
{36, {"P61", "P62", "P64", "P65"}},
|
||||
{38, {"P66", "P67", "P69", "P70"}},
|
||||
{ 5, {"P39", "P38", "P40", "P41"}},
|
||||
{ 7, {"UNB139", "UNB140", "P43", "P44"}},
|
||||
{12, {"P46", "P45", "P47", "P48"}},
|
||||
{14, {"UNB131", "UNB132", "UNB130", "UNB129"}},
|
||||
{19, {"UNB127", "UNB128", "UNB126", "UNB125"}},
|
||||
{21, {"UNB123", "UNB124", "P50", "P51"}},
|
||||
{25, {"P56", "P55", "UNB118", "UNB117"}},
|
||||
{29, {"UNB115", "UNB116", "UNB114", "UNB113"}},
|
||||
{31, {"P58", "P57", "P59", "P60"}},
|
||||
{36, {"P62", "P61", "P64", "P65"}},
|
||||
{38, {"P67", "P66", "P69", "P70"}},
|
||||
};
|
||||
|
||||
static const struct iob_site xc6slx9_iob_left[] =
|
||||
|
@ -323,65 +323,156 @@ const char* fpga_conn_to(struct fpga_model* model, int y, int x,
|
|||
return conn_dest_buf[last_buf];
|
||||
}
|
||||
|
||||
int fpga_switch_dest(struct fpga_model* model, int y, int x,
|
||||
const char* name, int dest_idx)
|
||||
swidx_t fpga_switch_first(struct fpga_model* model, int y, int x,
|
||||
const char* name, int from_to)
|
||||
{
|
||||
struct fpga_tile* tile;
|
||||
int rc, i, connpt_o, from_name_i, dest_idx_counter;
|
||||
int rc, i, connpt_o, name_i;
|
||||
|
||||
rc = strarray_find(&model->str, name, &from_name_i);
|
||||
rc = strarray_find(&model->str, name, &name_i);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// counts how many switches from the same source (name)
|
||||
// we have already encountered - to find the dest_idx'th
|
||||
// entry in that series
|
||||
dest_idx_counter = 0;
|
||||
// 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 = SWITCH_FROM(tile->switches[i]);
|
||||
if (tile->conn_point_names[connpt_o*2+1] == from_name_i) {
|
||||
if (dest_idx_counter >= dest_idx)
|
||||
break;
|
||||
dest_idx_counter++;
|
||||
}
|
||||
connpt_o = (from_to == SW_FROM)
|
||||
? SWITCH_FROM(tile->switches[i])
|
||||
: SWITCH_TO(tile->switches[i]);
|
||||
if (tile->conn_point_names[connpt_o*2+1] == name_i)
|
||||
break;
|
||||
}
|
||||
if (i >= tile->num_switches)
|
||||
return NO_SWITCH;
|
||||
if (dest_idx_counter > dest_idx) FAIL(EINVAL);
|
||||
return i;
|
||||
return (i >= tile->num_switches) ? NO_SWITCH : i;
|
||||
fail:
|
||||
return NO_SWITCH;
|
||||
}
|
||||
|
||||
#define NUM_SWITCH_TO_BUFS 16
|
||||
#define SWITCH_TO_BUF_SIZE 128
|
||||
swidx_t fpga_switch_next(struct fpga_model* model, int y, int x, swidx_t last, int from_to)
|
||||
{
|
||||
struct fpga_tile* tile;
|
||||
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]);
|
||||
name_i = tile->conn_point_names[connpt_o*2+1];
|
||||
|
||||
const char* fpga_switch_to(struct fpga_model* model, int y, int x,
|
||||
int swidx, int* is_bidir)
|
||||
for (i = last+1; i < tile->num_switches; i++) {
|
||||
connpt_o = (from_to == SW_FROM)
|
||||
? SWITCH_FROM(tile->switches[i])
|
||||
: SWITCH_TO(tile->switches[i]);
|
||||
if (tile->conn_point_names[connpt_o*2+1] == name_i)
|
||||
break;
|
||||
}
|
||||
return (i >= tile->num_switches) ? NO_SWITCH : i;
|
||||
}
|
||||
|
||||
#define MAX_SW_PARENTS 32
|
||||
|
||||
swidx_t fpga_switch_tree(struct fpga_model* model, int y, int x,
|
||||
const char* name, int from_to, swidx_t** parents, int* num_parents)
|
||||
{
|
||||
// the static 'parents' always contain the current
|
||||
// (last) member as their last element, which is
|
||||
// not reported back as a parent.
|
||||
static swidx_t s_parents[MAX_SW_PARENTS];
|
||||
static int s_num_parents = 0;
|
||||
|
||||
swidx_t idx;
|
||||
|
||||
*parents = s_parents;
|
||||
if (name != SW_TREE_NEXT) {
|
||||
idx = fpga_switch_first(model, y, x, name, from_to);
|
||||
if (idx == NO_SWITCH) return NO_SWITCH;
|
||||
s_parents[0] = idx;
|
||||
s_num_parents = 1;
|
||||
*num_parents = 0;
|
||||
return idx;
|
||||
}
|
||||
if (!s_num_parents) {
|
||||
HERE();
|
||||
return NO_SWITCH;
|
||||
}
|
||||
// first check whether there are children
|
||||
idx = fpga_switch_first(model, y, x,
|
||||
fpga_switch_str(model, y, x, s_parents[s_num_parents-1], !from_to),
|
||||
from_to);
|
||||
if (idx != NO_SWITCH) {
|
||||
if (s_num_parents >= MAX_SW_PARENTS) {
|
||||
HERE();
|
||||
return NO_SWITCH;
|
||||
}
|
||||
s_parents[s_num_parents] = idx;
|
||||
s_num_parents++;
|
||||
*num_parents = s_num_parents - 1;
|
||||
return idx;
|
||||
}
|
||||
do {
|
||||
// then check whether there are more members at the same level
|
||||
idx = fpga_switch_next(model, y, x, s_parents[s_num_parents-1],
|
||||
from_to);
|
||||
if (idx != NO_SWITCH) {
|
||||
s_parents[s_num_parents-1] = idx;
|
||||
*num_parents = s_num_parents - 1;
|
||||
return idx;
|
||||
}
|
||||
// and finally go one level up
|
||||
} while (s_num_parents--); // post-decrement
|
||||
return NO_SWITCH;
|
||||
}
|
||||
|
||||
#define NUM_CONNPT_BUFS 16
|
||||
#define CONNPT_BUF_SIZE 128
|
||||
|
||||
static const char* connpt_str(struct fpga_model* model, int y, int x, int connpt_o)
|
||||
{
|
||||
// We have a little local ringbuffer to make passing
|
||||
// around pointers with unknown lifetime and possible
|
||||
// overlap with writing functions more stable.
|
||||
static char switch_to_buf[NUM_SWITCH_TO_BUFS][SWITCH_TO_BUF_SIZE];
|
||||
static char switch_get_buf[NUM_CONNPT_BUFS][CONNPT_BUF_SIZE];
|
||||
static int last_buf = 0;
|
||||
|
||||
struct fpga_tile* tile;
|
||||
const char* hash_str;
|
||||
int connpt_o, str_i;
|
||||
int str_i;
|
||||
|
||||
tile = YX_TILE(model, y, x);
|
||||
if (is_bidir)
|
||||
*is_bidir = (tile->switches[swidx] & SWITCH_BIDIRECTIONAL) != 0;
|
||||
|
||||
connpt_o = SWITCH_TO(tile->switches[swidx]);
|
||||
str_i = tile->conn_point_names[connpt_o*2+1];
|
||||
str_i = YX_TILE(model, y, x)->conn_point_names[connpt_o*2+1];
|
||||
hash_str = strarray_lookup(&model->str, str_i);
|
||||
if (!hash_str || (strlen(hash_str) >= SWITCH_TO_BUF_SIZE)) {
|
||||
if (!hash_str || (strlen(hash_str) >= CONNPT_BUF_SIZE)) {
|
||||
HERE();
|
||||
return 0;
|
||||
}
|
||||
last_buf = (last_buf+1)%NUM_SWITCH_TO_BUFS;
|
||||
strcpy(switch_to_buf[last_buf], hash_str);
|
||||
|
||||
return switch_to_buf[last_buf];
|
||||
last_buf = (last_buf+1)%NUM_CONNPT_BUFS;
|
||||
return strcpy(switch_get_buf[last_buf], hash_str);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
int fpga_switch_is_bidir(struct fpga_model* model, int y, int x,
|
||||
swidx_t swidx)
|
||||
{
|
||||
return (YX_TILE(model, y, x)->switches[swidx] & SWITCH_BIDIRECTIONAL) != 0;
|
||||
}
|
||||
|
||||
int fpga_switch_is_enabled(struct fpga_model* model, int y, int x,
|
||||
swidx_t swidx)
|
||||
{
|
||||
return (YX_TILE(model, y, x)->switches[swidx] & SWITCH_ON) != 0;
|
||||
}
|
||||
|
||||
void fpga_switch_enable(struct fpga_model* model, int y, int x,
|
||||
swidx_t swidx)
|
||||
{
|
||||
YX_TILE(model, y, x)->switches[swidx] |= SWITCH_ON;
|
||||
}
|
||||
|
||||
void fpga_switch_disable(struct fpga_model* model, int y, int x,
|
||||
swidx_t swidx)
|
||||
{
|
||||
YX_TILE(model, y, x)->switches[swidx] &= ~SWITCH_ON;
|
||||
}
|
||||
|
|
30
control.h
30
control.h
|
@ -37,8 +37,30 @@ int fpga_conn_dest(struct fpga_model* model, int y, int x,
|
|||
const char* fpga_conn_to(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
|
||||
|
||||
// returns a switch index, or -1 (NO_SWITCH) if no switch was found
|
||||
int fpga_switch_dest(struct fpga_model* model, int y, int x,
|
||||
const char* name, int dest_idx);
|
||||
const char* fpga_switch_to(struct fpga_model* model, int y, int x,
|
||||
int swidx, int* is_bidir);
|
||||
swidx_t fpga_switch_first(struct fpga_model* model, int y, int x,
|
||||
const char* name, int from_to);
|
||||
swidx_t fpga_switch_next(struct fpga_model* model, int y, int x,
|
||||
swidx_t last, int from_to);
|
||||
|
||||
#define SW_TREE_NEXT 0 // use for name
|
||||
// returns -1 (NO_SWITCH) when there are no more switches in the tree
|
||||
swidx_t fpga_switch_tree(struct fpga_model* model, int y, int x,
|
||||
const char* name, int from_to, swidx_t** parents, int* num_parents);
|
||||
|
||||
const char* fpga_switch_str(struct fpga_model* model, int y, int x,
|
||||
swidx_t swidx, int from_to);
|
||||
int fpga_switch_is_bidir(struct fpga_model* model, int y, int x,
|
||||
swidx_t swidx);
|
||||
int fpga_switch_is_enabled(struct fpga_model* model, int y, int x,
|
||||
swidx_t swidx);
|
||||
void fpga_switch_enable(struct fpga_model* model, int y, int x,
|
||||
swidx_t swidx);
|
||||
void fpga_switch_disable(struct fpga_model* model, int y, int x,
|
||||
swidx_t swidx);
|
||||
|
|
4
model.h
4
model.h
|
@ -215,6 +215,10 @@ enum fpga_tile_type
|
|||
// Y_TOPBOT_IO_RANGE checks if y points to the top or bottom outer or
|
||||
// inner rows.
|
||||
#define Y_TOPBOT_IO_RANGE 0x0080
|
||||
#define Y_TOP_OUTER_IO 0x0100
|
||||
#define Y_TOP_INNER_IO 0x0200
|
||||
#define Y_BOT_INNER_IO 0x0400
|
||||
#define Y_BOT_OUTER_IO 0x0800
|
||||
|
||||
// multiple checks are combined with OR logic
|
||||
int is_aty(int check, struct fpga_model* model, int y);
|
||||
|
|
|
@ -346,9 +346,9 @@ int init_devices(struct fpga_model* model)
|
|||
if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail;
|
||||
|
||||
y = model->y_height-BOT_OUTER_ROW;
|
||||
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;
|
||||
if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail;
|
||||
if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -502,6 +502,10 @@ int is_aty(int check, struct fpga_model* model, int y)
|
|||
if (check & Y_TOPBOT_IO_RANGE
|
||||
&& ((y > TOP_INNER_ROW && y <= TOP_INNER_ROW + TOP_IO_TILES)
|
||||
|| (y >= model->y_height - BOT_INNER_ROW - BOT_IO_TILES && y < model->y_height - BOT_INNER_ROW))) return 1;
|
||||
if (check & Y_TOP_OUTER_IO && y == TOP_OUTER_IO) return 1;
|
||||
if (check & Y_TOP_INNER_IO && y == TOP_INNER_IO) return 1;
|
||||
if (check & Y_BOT_INNER_IO && y == model->y_height-BOT_INNER_IO) return 1;
|
||||
if (check & Y_BOT_OUTER_IO && y == model->y_height-BOT_OUTER_IO) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user