added 2 switch and conn helper functions

This commit is contained in:
Wolfgang Spraul 2012-08-17 10:31:40 +02:00
parent d36a3fa6a3
commit 3be3d504d2
7 changed files with 220 additions and 61 deletions

View File

@ -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");

168
control.c
View File

@ -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];
}

View File

@ -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);

16
model.h
View File

@ -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;
};

View File

@ -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;

View File

@ -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;
}

View File

@ -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;