diff --git a/autotest.c b/autotest.c index 52d1cb3..2e1d575 100644 --- a/autotest.c +++ b/autotest.c @@ -104,9 +104,12 @@ fail: int main(int argc, char** argv) { struct fpga_model model; - struct fpga_device* dev; - int iob_y, iob_x, iob_idx, rc; + 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; + const char* str; struct test_state tstate; + const char* conn_to_str; + int conn_idx, conn_to_y, conn_to_x; printf("\n"); printf("O fpgatools automatic test suite. Be welcome and be " @@ -132,44 +135,58 @@ int main(int argc, char** argv) if (rc) FAIL(); // configure P46 - rc = fpga_find_iob(&model, "P46", &iob_y, &iob_x, &iob_idx); + rc = fpga_find_iob(&model, "P46", &P46_y, &P46_x, &P46_idx); if (rc) FAIL(); - dev = fpga_dev(&model, iob_y, iob_x, DEV_IOB, iob_idx); - if (!dev) { rc = -1; FAIL(); } - dev->instantiated = 1; - strcpy(dev->iob.istandard, IO_LVCMOS33); - dev->iob.bypass_mux = BYPASS_MUX_I; - dev->iob.I_mux = IMUX_I; + P46_dev = fpga_dev(&model, P46_y, P46_x, DEV_IOB, P46_idx); + if (!P46_dev) { rc = -1; FAIL(); } + P46_dev->instantiated = 1; + strcpy(P46_dev->iob.istandard, IO_LVCMOS33); + P46_dev->iob.bypass_mux = BYPASS_MUX_I; + P46_dev->iob.I_mux = IMUX_I; // configure P48 - rc = fpga_find_iob(&model, "P48", &iob_y, &iob_x, &iob_idx); + rc = fpga_find_iob(&model, "P48", &P48_y, &P48_x, &P48_idx); if (rc) FAIL(); - dev = fpga_dev(&model, iob_y, iob_x, DEV_IOB, iob_idx); - if (!dev) { rc = -1; FAIL(); } - 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; - - rc = diff_printf(&tstate); - if (rc) goto fail; + P48_dev = fpga_dev(&model, P48_y, P48_x, DEV_IOB, P48_idx); + if (!P48_dev) { rc = -1; FAIL(); } + P48_dev->instantiated = 1; + strcpy(P48_dev->iob.ostandard, IO_LVCMOS33); + P48_dev->iob.drive_strength = 12; + P48_dev->iob.O_used = 1; + P48_dev->iob.slew = SLEW_SLOW; + P48_dev->iob.suspend = SUSP_3STATE; // configure logic - dev = fpga_dev(&model, /*y*/ 68, /*x*/ 13, DEV_LOGIC, /*LOGIC_X*/ 1); - if (!dev) { rc = -1; FAIL(); } - dev->instantiated = 1; - dev->logic.D_used = 1; - rc = fpga_set_lut(&model, dev, D6_LUT, "A3", ZTERM); + logic_dev = fpga_dev(&model, /*y*/ 68, /*x*/ 13, DEV_LOGIC, /*LOGIC_X*/ 1); + if (!logic_dev) { rc = -1; FAIL(); } + logic_dev->instantiated = 1; + logic_dev->logic.D_used = 1; + rc = fpga_set_lut(&model, logic_dev, D6_LUT, "A3", ZTERM); if (rc) FAIL(); +#if 0 rc = diff_printf(&tstate); if (rc) goto fail; +#endif - // todo: start routing, step by step - // todo: after each step, printf floorplan diff (test_diff.sh) - // todo: popen/fork/pipe + 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); + 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); + } + } + printf("P48 O pinw %s\n", P48_dev->iob.pinw_in_O); printf("\n"); printf("O Test suite completed.\n"); diff --git a/control.c b/control.c index f375e45..33fdacf 100644 --- a/control.c +++ b/control.c @@ -16,32 +16,32 @@ struct iob_site static const struct iob_site xc6slx9_iob_top[] = { - { 5, {"P144", "P143", "P141", "P142"}}, - { 7, {"P140", "P139", "P137", "P138"}}, - {12, {"UNB9", "UNB10", "UNB12", "UNB11"}}, - {14, {"UNB13", "UNB14", "UNB16", "UNB15"}}, - {19, {"UNB17", "UNB18", "UNB20", "UNB19"}}, - {21, {"P134", "P133", "P131", "P132"}}, - {25, {"P127", "P126", "P123", "P124"}}, - {29, {"UNB29", "UNB30", "UNB32", "UNB31"}}, - {31, {"UNB33", "UNB34", "P120", "P121"}}, - {36, {"P119", "P118", "P116", "P117"}}, - {38, {"P115", "P114", "P111", "P112"}}, + { 5, {"P144", "P143", "P142", "P141"}}, + { 7, {"P140", "P139", "P138", "P137"}}, + {12, {"UNB9", "UNB10", "UNB11", "UNB12"}}, + {14, {"UNB13", "UNB14", "UNB15", "UNB16"}}, + {19, {"UNB17", "UNB18", "UNB19", "UNB20"}}, + {21, {"P134", "P133", "P132", "P131"}}, + {25, {"P127", "P126", "P124", "P123"}}, + {29, {"UNB29", "UNB30", "UNB31", "UNB32"}}, + {31, {"UNB33", "UNB34", "P121", "P120"}}, + {36, {"P119", "P118", "P117", "P116"}}, + {38, {"P115", "P114", "P112", "P111"}}, }; static const struct iob_site xc6slx9_iob_bottom[] = { - { 5, {"P38", "P39", "P41", "P40"}}, - { 7, {"UNB140", "UNB139", "P44", "P43"}}, - {12, {"P45", "P46", "P48", "P47"}}, - {14, {"UNB132", "UNB131", "UNB129", "UNB130"}}, - {19, {"UNB128", "UNB127", "UNB125", "UNB126"}}, - {21, {"UNB124", "UNB123", "P51", "P50"}}, - {25, {"P55", "P56", "UNB117", "UNB118"}}, - {29, {"UNB116", "UNB115", "UNB113", "UNB114"}}, - {31, {"P57", "P58", "P60", "P59"}}, - {36, {"P61", "P62", "P65", "P64"}}, - {38, {"P66", "P67", "P70", "P69"}}, + { 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[] = @@ -261,3 +261,127 @@ int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev, (*ptr)[lut_len] = 0; return 0; } + +int fpga_conn_dest(struct fpga_model* model, int y, int x, + const char* name, int dest_idx) +{ + struct fpga_tile* tile; + int i, rc, connpt_i, num_dests, conn_point_dests_o; + + rc = strarray_find(&model->str, name, &connpt_i); + if (rc) FAIL(); + tile = YX_TILE(model, y, x); + for (i = 0; i < tile->num_conn_point_names; i++) { + if (tile->conn_point_names[i*2+1] == connpt_i) + break; + } + if (i >= tile->num_conn_point_names) + FAIL(); + + conn_point_dests_o = tile->conn_point_names[i*2]; + if (i < tile->num_conn_point_names-1) + num_dests = tile->conn_point_names[(i+1)*2] - conn_point_dests_o; + else + num_dests = tile->num_conn_point_dests - conn_point_dests_o; + if (dest_idx >= num_dests) + return NO_CONN; + return conn_point_dests_o + dest_idx; +fail: + return NO_CONN; +} + +#define NUM_CONN_DEST_BUFS 16 +#define CONN_DEST_BUF_SIZE 128 + +const char* fpga_conn_to(struct fpga_model* model, int y, int x, + int connpt_dest_idx, int* dest_y, int* dest_x) +{ + static char conn_dest_buf[NUM_CONN_DEST_BUFS][CONN_DEST_BUF_SIZE]; + static int last_buf = 0; + + struct fpga_tile* tile; + const char* hash_str; + + tile = YX_TILE(model, y, x); + if (connpt_dest_idx < 0 + || connpt_dest_idx >= tile->num_conn_point_dests) { + HERE(); + return 0; + } + *dest_x = tile->conn_point_dests[connpt_dest_idx*3]; + *dest_y = tile->conn_point_dests[connpt_dest_idx*3+1]; + + hash_str = strarray_lookup(&model->str, + tile->conn_point_dests[connpt_dest_idx*3+2]); + if (!hash_str || (strlen(hash_str) >= CONN_DEST_BUF_SIZE)) { + HERE(); + return 0; + } + last_buf = (last_buf+1)%NUM_CONN_DEST_BUFS; + strcpy(conn_dest_buf[last_buf], hash_str); + + return conn_dest_buf[last_buf]; +} + +int fpga_switch_dest(struct fpga_model* model, int y, int x, + const char* name, int dest_idx) +{ + struct fpga_tile* tile; + int rc, i, connpt_o, from_name_i, dest_idx_counter; + + rc = strarray_find(&model->str, name, &from_name_i); + if (rc) FAIL(); + + // 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; + 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++; + } + } + if (i >= tile->num_switches) + return NO_SWITCH; + if (dest_idx_counter > dest_idx) FAIL(); + return i; +fail: + return NO_SWITCH; +} + +#define NUM_SWITCH_TO_BUFS 16 +#define SWITCH_TO_BUF_SIZE 128 + +const char* fpga_switch_to(struct fpga_model* model, int y, int x, + int swidx, int* is_bidir) +{ + // 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 int last_buf = 0; + + struct fpga_tile* tile; + const char* hash_str; + int connpt_o, 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]; + hash_str = strarray_lookup(&model->str, str_i); + if (!hash_str || (strlen(hash_str) >= SWITCH_TO_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]; +} diff --git a/control.h b/control.h index 46b3745..6894c56 100644 --- a/control.h +++ b/control.h @@ -30,3 +30,15 @@ enum { A6_LUT, B6_LUT, C6_LUT, D6_LUT }; // lut_len can be -1 (ZTERM) int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev, int which_lut, const char* lut_str, int lut_len); + +// returns a connpt dest index, or -1 (NO_CONN) if no connection was found +int fpga_conn_dest(struct fpga_model* model, int y, int x, + const char* name, int dest_idx); +const char* fpga_conn_to(struct fpga_model* model, int y, int x, + int connpt_dest_idx, int* dest_y, int* dest_x); + +// 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); diff --git a/model.h b/model.h index b17b0fb..75cc817 100644 --- a/model.h +++ b/model.h @@ -365,9 +365,14 @@ struct fpga_device }; }; -#define SWITCH_ON 0x80000000 -#define SWITCH_BIDIRECTIONAL 0x40000000 -#define SWITCH_MAX_CONNPT_O 0x7FFF // 15 bits +#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 NO_SWITCH -1 +#define NO_CONN -1 struct fpga_tile { @@ -382,6 +387,7 @@ struct fpga_tile // 2*16 bit per entry // - index into conn_point_dests (not multiplied by 3) (16bit) // - hashed string array index (16 bit) + // each conn point name exists only once in the array int num_conn_point_names; // conn_point_names is 2*num_conn_point_names 16-bit words uint16_t* conn_point_names; // num_conn_point_names*2 16-bit-words: 16(conn)-16(str) @@ -396,8 +402,8 @@ struct fpga_tile // expect up to 4k switches per tile // 32bit: 31 off: no connection on: connected // 30 off: unidirectional on: bidirectional - // 29:15 from, index into conn_point_names - // 14:0 to, index into conn_point_names + // 29:15 from, index into conn_point_names (not yet *2) + // 14:0 to, index into conn_point_names (not yet *2) int num_switches; uint32_t* switches; }; diff --git a/model_devices.c b/model_devices.c index 3e5e774..70325cf 100644 --- a/model_devices.c +++ b/model_devices.c @@ -63,12 +63,12 @@ static int init_iob(struct fpga_model* model, int y, int x, if (rc) FAIL(); snprintf(tile->devs[idx].iob.pinw_in_T, sizeof(tile->devs[idx].iob.pinw_in_T), - "%s_IBUF%i_PINW", prefix, type_idx); + "%s_T%i_PINW", prefix, type_idx); rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_T); if (rc) FAIL(); snprintf(tile->devs[idx].iob.pinw_out_I, sizeof(tile->devs[idx].iob.pinw_out_I), - "%s_T%i_PINW", prefix, type_idx); + "%s_IBUF%i_PINW", prefix, type_idx); rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_I); if (rc) FAIL(); snprintf(tile->devs[idx].iob.pinw_out_PADOUT, @@ -344,8 +344,8 @@ int init_devices(struct fpga_model* model) 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, 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; y = model->y_height-BOT_OUTER_ROW; if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; diff --git a/model_main.c b/model_main.c index 55f0093..edc9541 100644 --- a/model_main.c +++ b/model_main.c @@ -38,10 +38,8 @@ int fpga_build_model(struct fpga_model* model, int fpga_rows, const char* column rc = init_conns(model); if (rc) return rc; -#if 0 rc = init_switches(model); if (rc) return rc; -#endif return 0; } diff --git a/model_switches.c b/model_switches.c index 36412c7..237810c 100644 --- a/model_switches.c +++ b/model_switches.c @@ -34,8 +34,10 @@ 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;