From dc1a40805fefa53a87fb481281f8f5de4d2e5037 Mon Sep 17 00:00:00 2001 From: Wolfgang Spraul Date: Tue, 21 Aug 2012 14:46:28 +0200 Subject: [PATCH] slow day --- autotest.c | 93 +++++++++++++++++++++--- control.c | 185 ++++++++++++++++++++++++++++++++++++------------ control.h | 30 ++++++-- model.h | 4 ++ model_devices.c | 2 +- model_helper.c | 4 ++ 6 files changed, 256 insertions(+), 62 deletions(-) diff --git a/autotest.c b/autotest.c index a00e503..0c85995 100644 --- a/autotest.c +++ b/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); diff --git a/control.c b/control.c index c0c115f..9c5ce53 100644 --- a/control.c +++ b/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; } diff --git a/control.h b/control.h index 6894c56..e1cf85d 100644 --- a/control.h +++ b/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); diff --git a/model.h b/model.h index 2e62f9b..cb12874 100644 --- a/model.h +++ b/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); diff --git a/model_devices.c b/model_devices.c index 52a3845..94dce18 100644 --- a/model_devices.c +++ b/model_devices.c @@ -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; } } diff --git a/model_helper.c b/model_helper.c index 7c6f32b..3a90e0a 100644 --- a/model_helper.c +++ b/model_helper.c @@ -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; }