better routing from and to logic block

This commit is contained in:
Wolfgang Spraul 2012-08-28 09:23:52 +02:00
parent 9b059ec9b5
commit 3e5b83ed07
8 changed files with 351 additions and 208 deletions

View File

@ -136,7 +136,7 @@ static int test_net(struct test_state* tstate, net_idx_t net_i)
net->el[2].y, net->el[2].x, net->el[2].y, net->el[2].x,
fpga_switch_str_i(tstate->model, fpga_switch_str_i(tstate->model,
net->el[2].y, net->el[2].x, net->el[2].y, net->el[2].x,
net->el[2].idx, SW_TO), 1, SW_TO); net->el[2].idx, SW_TO), SW_TO, 1);
same_len = sizeof(same_sw)/sizeof(*same_sw); same_len = sizeof(same_sw)/sizeof(*same_sw);
rc = fpga_switch_same_fromto(tstate->model, rc = fpga_switch_same_fromto(tstate->model,
net->el[2].y, net->el[2].x, net->el[2].y, net->el[2].x,
@ -174,7 +174,7 @@ static int test_net2(struct test_state* tstate, net_idx_t net_i)
net->el[i-1].y, net->el[i-1].x, net->el[i-1].y, net->el[i-1].x,
fpga_switch_str_i(tstate->model, fpga_switch_str_i(tstate->model,
net->el[i-1].y, net->el[i-1].x, net->el[i-1].y, net->el[i-1].x,
net->el[i-1].idx, SW_FROM), 1, SW_FROM); net->el[i-1].idx, SW_FROM), SW_FROM, 1);
same_len = sizeof(same_sw)/sizeof(*same_sw); same_len = sizeof(same_sw)/sizeof(*same_sw);
rc = fpga_switch_same_fromto(tstate->model, rc = fpga_switch_same_fromto(tstate->model,
net->el[i-1].y, net->el[i-1].x, net->el[i-1].y, net->el[i-1].x,
@ -195,37 +195,13 @@ fail:
return rc; return rc;
} }
static void fdev_print_required_pins(struct fpga_model* model, int y, int x,
int type, int type_idx)
{
struct fpga_device* dev;
int i;
dev = fdev_p(model, y, x, type, type_idx);
if (!dev) { HERE(); return; }
printf("y%02i x%02i %s %i inpin", y, x, fdev_type2str(type), type_idx);
if (!dev->pinw_req_in)
printf(" -\n");
else {
for (i = 0; i < dev->pinw_req_in; i++)
printf(" %s", fdev_pinw_idx2str(type, dev->pinw_req_for_cfg[i]));
printf("\n");
}
printf("y%02i x%02i %s %i outpin", y, x, fdev_type2str(type), type_idx);
if (dev->pinw_req_total <= dev->pinw_req_in)
printf(" -\n");
else {
for (i = dev->pinw_req_in; i < dev->pinw_req_total; i++)
printf(" %s", fdev_pinw_idx2str(type, dev->pinw_req_for_cfg[i]));
printf("\n");
}
}
static int test_all_logic_configs(struct test_state* tstate) static int test_all_logic_configs(struct test_state* tstate)
{ {
int y, x, rc; struct fpga_device* dev;
struct switch_to_yx switch_to;
struct sw_chain chain;
net_idx_t net_idx;
int y, x, i, from_to, rc;
// todo: goal: configure valid logic with as many possible in and out // todo: goal: configure valid logic with as many possible in and out
// pins, for M and X device // pins, for M and X device
@ -238,10 +214,54 @@ static int test_all_logic_configs(struct test_state* tstate)
rc = fdev_set_required_pins(tstate->model, y, x, DEV_LOGIC, DEV_LOGX); rc = fdev_set_required_pins(tstate->model, y, x, DEV_LOGIC, DEV_LOGX);
if (rc) FAIL(rc); if (rc) FAIL(rc);
// fdev_print_required_pins(tstate->model, y, x, DEV_LOGIC, DEV_LOGX);
fdev_print_required_pins(tstate->model, y, x, DEV_LOGIC, DEV_LOGX); dev = fdev_p(tstate->model, y, x, DEV_LOGIC, DEV_LOGX);
rc = diff_printf(tstate); if (!dev) FAIL(EINVAL);
if (rc) FAIL(rc); for (i = 0; i < dev->pinw_req_total; i++) {
from_to = (i < dev->pinw_req_in) ? SW_TO : SW_FROM;
switch_to.yx_req = YX_ROUTING_TILE;
switch_to.flags = SWTO_YX_DEF;
switch_to.model = tstate->model;
switch_to.y = y;
switch_to.x = x;
switch_to.start_switch = dev->pinw[dev->pinw_req_for_cfg[i]];
switch_to.from_to = from_to;
rc = fpga_switch_to_yx(&switch_to);
if (rc) FAIL(rc);
// printf_switch_to_result(&switch_to);
chain.model = tstate->model;
chain.y = switch_to.dest_y;
chain.x = switch_to.dest_x;
chain.start_switch = switch_to.dest_connpt;
chain.from_to = from_to;
chain.max_chain_size = 1;
while (fpga_switch_chain(&chain) != NO_SWITCH) {
rc = fpga_net_new(tstate->model, &net_idx);
if (rc) FAIL(rc);
// add port
rc = fpga_net_add_port(tstate->model, net_idx,
y, x, fpga_dev_idx(tstate->model, y, x,
DEV_LOGIC, DEV_LOGX), dev->pinw_req_for_cfg[i]);
if (rc) FAIL(rc);
// add (one) switch in logic tile
rc = fpga_net_add_switches(tstate->model, net_idx,
y, x, &switch_to.set);
if (rc) FAIL(rc);
// add switches in routing tile
rc = fpga_net_add_switches(tstate->model, net_idx,
switch_to.dest_y, switch_to.dest_x, &chain.set);
if (rc) FAIL(rc);
// fprintf_net(stdout, tstate->model, net_idx);
rc = diff_printf(tstate);
if (rc) FAIL(rc);
fpga_net_delete(tstate->model, net_idx);
}
}
return 0; return 0;
fail: fail:
return rc; return rc;
@ -349,6 +369,7 @@ int main(int argc, char** argv)
switch_to.y = P46_y; switch_to.y = P46_y;
switch_to.x = P46_x; switch_to.x = P46_x;
switch_to.start_switch = P46_dev->pinw[IOB_OUT_I]; switch_to.start_switch = P46_dev->pinw[IOB_OUT_I];
switch_to.from_to = SW_FROM;
rc = fpga_switch_to_yx(&switch_to); rc = fpga_switch_to_yx(&switch_to);
if (rc) FAIL(rc); if (rc) FAIL(rc);
rc = fpga_net_add_switches(&model, P46_net, switch_to.y, rc = fpga_net_add_switches(&model, P46_net, switch_to.y,
@ -357,9 +378,11 @@ int main(int argc, char** argv)
switch_to.yx_req = YX_ROUTING_TILE; switch_to.yx_req = YX_ROUTING_TILE;
switch_to.flags = SWTO_YX_DEF; switch_to.flags = SWTO_YX_DEF;
switch_to.model = &model;
switch_to.y = switch_to.dest_y; switch_to.y = switch_to.dest_y;
switch_to.x = switch_to.dest_x; switch_to.x = switch_to.dest_x;
switch_to.start_switch = switch_to.dest_connpt; switch_to.start_switch = switch_to.dest_connpt;
switch_to.from_to = SW_FROM;
rc = fpga_switch_to_yx(&switch_to); rc = fpga_switch_to_yx(&switch_to);
if (rc) FAIL(rc); if (rc) FAIL(rc);
rc = fpga_net_add_switches(&model, P46_net, switch_to.y, rc = fpga_net_add_switches(&model, P46_net, switch_to.y,
@ -368,9 +391,11 @@ int main(int argc, char** argv)
switch_to.yx_req = YX_ROUTING_TO_FABLOGIC; switch_to.yx_req = YX_ROUTING_TO_FABLOGIC;
switch_to.flags = SWTO_YX_CLOSEST; switch_to.flags = SWTO_YX_CLOSEST;
switch_to.model = &model;
switch_to.y = switch_to.dest_y; switch_to.y = switch_to.dest_y;
switch_to.x = switch_to.dest_x; switch_to.x = switch_to.dest_x;
switch_to.start_switch = switch_to.dest_connpt; switch_to.start_switch = switch_to.dest_connpt;
switch_to.from_to = SW_FROM;
rc = fpga_switch_to_yx(&switch_to); rc = fpga_switch_to_yx(&switch_to);
if (rc) FAIL(rc); if (rc) FAIL(rc);
rc = fpga_net_add_switches(&model, P46_net, switch_to.y, rc = fpga_net_add_switches(&model, P46_net, switch_to.y,
@ -379,9 +404,11 @@ int main(int argc, char** argv)
switch_to.yx_req = YX_DEV_LOGIC; switch_to.yx_req = YX_DEV_LOGIC;
switch_to.flags = SWTO_YX_TARGET_CONNPT|SWTO_YX_MAX_SWITCH_DEPTH; switch_to.flags = SWTO_YX_TARGET_CONNPT|SWTO_YX_MAX_SWITCH_DEPTH;
switch_to.model = &model;
switch_to.y = switch_to.dest_y; switch_to.y = switch_to.dest_y;
switch_to.x = switch_to.dest_x; switch_to.x = switch_to.dest_x;
switch_to.start_switch = switch_to.dest_connpt; switch_to.start_switch = switch_to.dest_connpt;
switch_to.from_to = SW_FROM;
switch_to.max_switch_depth = 1; switch_to.max_switch_depth = 1;
{ {
struct sw_chain c = { struct sw_chain c = {

View File

@ -165,15 +165,6 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits)
continue; continue;
} }
// any logic block will enable r0ma17mi22b980
if (!get_bit(bits, /*row*/ 0, /*major*/ 17,
/*minor*/ 22, /*bit_i*/ 980)) {
HERE();
continue;
}
clear_bit(bits, /*row*/ 0, /*major*/ 17,
/*minor*/ 22, /*bit_i*/ 980);
dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGX); dev_idx = fpga_dev_idx(model, y, x, DEV_LOGIC, DEV_LOGX);
if (dev_idx == NO_DEV) FAIL(EINVAL); if (dev_idx == NO_DEV) FAIL(EINVAL);
dev = FPGA_DEV(model, y, x, dev_idx); dev = FPGA_DEV(model, y, x, dev_idx);
@ -216,6 +207,36 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits)
*(uint32_t*)(u8_p+29*FRAME_SIZE+byte_off) = 0; *(uint32_t*)(u8_p+29*FRAME_SIZE+byte_off) = 0;
*(uint32_t*)(u8_p+30*FRAME_SIZE+byte_off) = 0; *(uint32_t*)(u8_p+30*FRAME_SIZE+byte_off) = 0;
} }
#if 0
// M-LUTs
lut64 = read_lut64(&maj_bits[24*130], frame_off+32);
{ int logic_base[6] = {0,1,0,0,1,0};
lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s0_A6LUT \"%s\"\n",
row, major, i-start, lut_str);
lut64 = read_lut64(&maj_bits[21*130], frame_off+32);
{ int logic_base[6] = {1,1,0,1,0,1};
lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s0_B6LUT \"%s\"\n",
row, major, i-start, lut_str);
lut64 = read_lut64(&maj_bits[24*130], frame_off);
{ int logic_base[6] = {0,1,0,0,1,0};
lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s0_C6LUT \"%s\"\n",
row, major, i-start, lut_str);
lut64 = read_lut64(&maj_bits[21*130], frame_off);
{ int logic_base[6] = {1,1,0,1,0,1};
lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s0_D6LUT \"%s\"\n",
row, major, i-start, lut_str);
#endif
} }
} }
} }

View File

@ -713,103 +713,28 @@ static void print_ramb16_cfg(ramb16_cfg_t* cfg)
printf("}\n"); printf("}\n");
} }
static void printf_clb(uint8_t* maj_bits, int row, int major) static void printf_routing_2minors(uint8_t* bits, int row, int major,
int even_minor)
{ {
int i, j, start, max_idx, frame_off; int y, i, hclk;
const char* lut_str; uint64_t u64_0, u64_1;
uint64_t lut64; char bit_str[128];
// the first two slots on top and bottom row are not used for clb for (y = 0; y < 16; y++) {
if (!row) { hclk = (y < 8) ? 0 : 2;
start = 0; u64_0 = frame_get_u64(bits + y*8 + hclk);
max_idx = 14; u64_1 = frame_get_u64(bits + y*8 + hclk + FRAME_SIZE);
} else if (row == 3) { if (u64_0 || u64_1) {
start = 2; for (i = 0; i < sizeof(bit_str); i++)
max_idx = 16; bit_str[i] = '0';
} else { for (i = 0; i < 64; i++) {
start = 0; if (u64_0 & (1ULL << i))
max_idx = 16; bit_str[i*2] = '1';
} if (u64_1 & (1ULL << i))
bit_str[i*2+1] = '1';
for (i = start; i < max_idx; i++) { }
if (clb_empty(maj_bits, i)) printf("r%i ma%i v64_%i mip%i %s\n",
continue; row, major, y, even_minor, bit_str);
frame_off = i*64;
if (i >= 8)
frame_off += 16; // skip clock bits for idx >= 8
// LUTs
lut64 = read_lut64(&maj_bits[24*130], frame_off+32);
{ int logic_base[6] = {0,1,0,0,1,0};
lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s0_A6LUT \"%s\"\n",
row, major, i-start, lut_str);
lut64 = read_lut64(&maj_bits[21*130], frame_off+32);
{ int logic_base[6] = {1,1,0,1,0,1};
lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s0_B6LUT \"%s\"\n",
row, major, i-start, lut_str);
lut64 = read_lut64(&maj_bits[24*130], frame_off);
{ int logic_base[6] = {0,1,0,0,1,0};
lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s0_C6LUT \"%s\"\n",
row, major, i-start, lut_str);
lut64 = read_lut64(&maj_bits[21*130], frame_off);
{ int logic_base[6] = {1,1,0,1,0,1};
lut_str = lut2bool(lut64, 64, &logic_base, 1 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s0_D6LUT \"%s\"\n",
row, major, i-start, lut_str);
lut64 = read_lut64(&maj_bits[27*130], frame_off+32);
{ int logic_base[6] = {1,1,0,1,1,0};
lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s1_A6LUT \"%s\"\n",
row, major, i-start, lut_str);
lut64 = read_lut64(&maj_bits[29*130], frame_off+32);
{ int logic_base[6] = {1,1,0,1,1,0};
lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s1_B6LUT \"%s\"\n",
row, major, i-start, lut_str);
lut64 = read_lut64(&maj_bits[27*130], frame_off);
{ int logic_base[6] = {0,1,0,0,0,1};
lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s1_C6LUT \"%s\"\n",
row, major, i-start, lut_str);
lut64 = read_lut64(&maj_bits[29*130], frame_off);
{ int logic_base[6] = {0,1,0,0,0,1};
lut_str = lut2bool(lut64, 64, &logic_base, 0 /* flip_b0 */); }
if (*lut_str)
printf("r%i ma%i clb i%i s1_D6LUT \"%s\"\n",
row, major, i-start, lut_str);
// bits
for (j = 0; j < 64; j++) {
if (frame_get_bit(&maj_bits[20*130], frame_off + j))
printf("r%i ma%i clb i%i mi20 bit %i\n",
row, major, i-start, j);
}
for (j = 0; j < 64; j++) {
if (frame_get_bit(&maj_bits[23*130], frame_off + j))
printf("r%i ma%i clb i%i mi23 bit %i\n",
row, major, i-start, j);
}
for (j = 0; j < 64; j++) {
if (frame_get_bit(&maj_bits[26*130], frame_off + j))
printf("r%i ma%i clb i%i mi26 bit %i\n",
row, major, i-start, j);
} }
} }
} }
@ -823,7 +748,8 @@ static int dump_bits(struct fpga_config* cfg)
for (row = 0; row < 4; row++) { for (row = 0; row < 4; row++) {
for (major = 0; major < 18; major++) { for (major = 0; major < 18; major++) {
// todo: the macc/bram/logic special cases can be removed // todo: the macc/bram/logic special cases can be removed
if (0 && major == 7) { // MACC if (get_major_type(cfg->reg[cfg->idcode_reg].int_v,
major) == MAJ_MACC) {
int last_extra_minor; int last_extra_minor;
if (!row || row == 3) if (!row || row == 3)
@ -851,30 +777,25 @@ static int dump_bits(struct fpga_config* cfg)
} }
} }
} }
} else if (0 && (major == 2 || major == 5 || major == 8 || major == 10 } else if (get_major_type(cfg->reg[cfg->idcode_reg].int_v, major) == MAJ_LOGIC_XM) {
|| major == 12 || major == 15)) { // logic_m // clock
for (minor = 0; minor < 31; minor++)
printf_clock(
&cfg->bits.d[off+minor*130],
row, major, minor);
// bitwise
minor = 0; minor = 0;
while (minor < 20) { while (minor < 31) {
minor += printf_frames(&cfg->bits.d[off minor += printf_frames(&cfg->bits.d[off
+minor*130], 31 - minor, row, +minor*130], 31 - minor,
major, minor, /*print_empty*/ 0); row, major, minor, /*print_empty*/ 0);
} }
// clock // 0:20 routing minor pairs
for (minor = 20; minor < 31; minor++) for (i = 0; i < 10; i++)
printf_clock(&cfg->bits.d[off+minor*130], printf_routing_2minors(&cfg->bits.d[off+i*2*FRAME_SIZE], row, major, i*2);
row, major, minor); } else if (get_major_type(cfg->reg[cfg->idcode_reg].int_v, major) == MAJ_BRAM) {
// extra bits at bottom of row0 and top of row3
if (row == 3)
printf_extrabits(&cfg->bits.d[off], 20, 11,
0, 128, row, major);
else if (!row)
printf_extrabits(&cfg->bits.d[off], 20, 11,
14*64 + 16, 128, row, major);
// clbs
printf_clb(&cfg->bits.d[off], row, major);
} else if (0 && (major == 4 || major == 14)) { // bram
ramb16_cfg_t ramb16_cfg[4]; ramb16_cfg_t ramb16_cfg[4];
// minors 0..22 // minors 0..22
@ -910,7 +831,7 @@ static int dump_bits(struct fpga_config* cfg)
} }
} else { } else {
int major_minors = int major_minors =
get_major_minors(XC6SLX9, major); get_major_minors(cfg->reg[cfg->idcode_reg].int_v, major);
minor = 0; minor = 0;
while (minor < major_minors) { while (minor < major_minors) {
minor += printf_frames(&cfg->bits.d[off minor += printf_frames(&cfg->bits.d[off

169
control.c
View File

@ -312,12 +312,67 @@ const char* fdev_pinw_idx2str(int devtype, pinw_idx_t idx)
return 0; return 0;
} }
static void free_required_pins(struct fpga_device* dev) static int reset_required_pins(struct fpga_device* dev)
{ {
free(dev->pinw_req_for_cfg); int rc;
dev->pinw_req_for_cfg = 0;
if (!dev->pinw_req_for_cfg) {
dev->pinw_req_for_cfg = malloc(dev->num_pinw_total
* sizeof(*dev->pinw_req_for_cfg));
if (!dev->pinw_req_for_cfg) FAIL(ENOMEM);
}
dev->pinw_req_total = 0; dev->pinw_req_total = 0;
dev->pinw_req_in = 0; dev->pinw_req_in = 0;
return 0;
fail:
return rc;
}
void fdev_print_required_pins(struct fpga_model* model, int y, int x,
int type, int type_idx)
{
struct fpga_device* dev;
int i;
dev = fdev_p(model, y, x, type, type_idx);
if (!dev) { HERE(); return; }
printf("y%02i x%02i %s %i inpin", y, x, fdev_type2str(type), type_idx);
if (!dev->pinw_req_in)
printf(" -\n");
else {
for (i = 0; i < dev->pinw_req_in; i++)
printf(" %s", fdev_pinw_idx2str(type, dev->pinw_req_for_cfg[i]));
printf("\n");
}
printf("y%02i x%02i %s %i outpin", y, x, fdev_type2str(type), type_idx);
if (dev->pinw_req_total <= dev->pinw_req_in)
printf(" -\n");
else {
for (i = dev->pinw_req_in; i < dev->pinw_req_total; i++)
printf(" %s", fdev_pinw_idx2str(type, dev->pinw_req_for_cfg[i]));
printf("\n");
}
}
static void add_req_inpin(struct fpga_device* dev, pinw_idx_t pinw_i)
{
if (dev->pinw_req_total > dev->pinw_req_in) {
memmove(&dev->pinw_req_for_cfg[dev->pinw_req_in+1],
&dev->pinw_req_for_cfg[dev->pinw_req_in],
(dev->pinw_req_total-dev->pinw_req_in)
*sizeof(*dev->pinw_req_for_cfg));
}
dev->pinw_req_for_cfg[dev->pinw_req_in] = pinw_i;
dev->pinw_req_in++;
dev->pinw_req_total++;
}
static void add_req_outpin(struct fpga_device* dev, pinw_idx_t pinw_i)
{
dev->pinw_req_for_cfg[dev->pinw_req_total] = pinw_i;
dev->pinw_req_total++;
} }
#define MAX_LUT_LEN 512 #define MAX_LUT_LEN 512
@ -331,7 +386,8 @@ int fdev_logic_set_lut(struct fpga_model* model, int y, int x, int type_idx,
dev = fdev_p(model, y, x, DEV_LOGIC, type_idx); dev = fdev_p(model, y, x, DEV_LOGIC, type_idx);
if (!dev) FAIL(EINVAL); if (!dev) FAIL(EINVAL);
free_required_pins(dev); rc = reset_required_pins(dev);
if (rc) FAIL(rc);
luts = dev->u.logic.luts; luts = dev->u.logic.luts;
if (!luts[which_lut]) { if (!luts[which_lut]) {
@ -371,23 +427,50 @@ fail:
return rc; return rc;
} }
static void scan_lut_digits(const char* s, int* digits)
{
int i;
for (i = 0; i < 6; i++)
digits[i] = 0;
if (!s) return;
for (i = 0; s[i]; i++) {
if (s[i] >= '1' && s[i] <= '6')
digits[s[i]-'1']++;
}
}
int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type, int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type,
int type_idx) int type_idx)
{ {
struct fpga_device* dev; struct fpga_device* dev;
int rc; int digits[6];
int i, j, rc;
dev = fdev_p(model, y, x, type, type_idx); dev = fdev_p(model, y, x, type, type_idx);
if (!dev) FAIL(EINVAL); if (!dev) FAIL(EINVAL);
free_required_pins(dev); rc = reset_required_pins(dev);
if (rc) FAIL(rc);
if (type == DEV_LOGIC) { if (type == DEV_LOGIC) {
#if 0 if (dev->u.logic.A_used)
TODO: add_req_outpin(dev, LOGIC_OUT_A);
// required pinwires depend on the given config and will if (dev->u.logic.B_used)
// be deleted/invalidated on any config change. add_req_outpin(dev, LOGIC_OUT_B);
int pinw_req_total, pinw_req_in; if (dev->u.logic.C_used)
pinw_idx_t* pinw_req_for_cfg; add_req_outpin(dev, LOGIC_OUT_C);
#endif if (dev->u.logic.D_used)
add_req_outpin(dev, LOGIC_OUT_D);
for (i = 0; i < sizeof(dev->u.logic.luts)
/sizeof(dev->u.logic.luts[0]); i++) {
if (!dev->u.logic.luts[i]) continue;
scan_lut_digits(dev->u.logic.luts[i], digits);
for (j = 0; j < 6; j++) {
// i/2 because luts order is A5-A6 B5-B6, etc.
if (digits[j])
add_req_inpin(dev,
LOGIC_IN_A1+(i/2)*6+j);
}
}
} }
return 0; return 0;
fail: fail:
@ -402,7 +485,10 @@ void fdev_delete(struct fpga_model* model, int y, int x, int type, int type_idx)
dev = fdev_p(model, y, x, type, type_idx); dev = fdev_p(model, y, x, type, type_idx);
if (!dev) { HERE(); return; } if (!dev) { HERE(); return; }
if (!dev->instantiated) return; if (!dev->instantiated) return;
free_required_pins(dev); free(dev->pinw_req_for_cfg);
dev->pinw_req_for_cfg = 0;
dev->pinw_req_total = 0;
dev->pinw_req_in = 0;
if (dev->type == DEV_LOGIC) { if (dev->type == DEV_LOGIC) {
for (i = 0; i < sizeof(dev->u.logic.luts) for (i = 0; i < sizeof(dev->u.logic.luts)
/sizeof(dev->u.logic.luts[0]); i++) { /sizeof(dev->u.logic.luts[0]); i++) {
@ -825,7 +911,7 @@ int fpga_switch_conns(struct sw_conns* conns)
conns->chain.y = conns->y; conns->chain.y = conns->y;
conns->chain.x = conns->x; conns->chain.x = conns->x;
conns->chain.start_switch = conns->start_switch; conns->chain.start_switch = conns->start_switch;
conns->chain.from_to = SW_FROM; conns->chain.from_to = conns->from_to;
conns->chain.max_chain_size = conns->max_switch_depth; conns->chain.max_chain_size = conns->max_switch_depth;
conns->start_switch = STRIDX_NO_ENTRY; conns->start_switch = STRIDX_NO_ENTRY;
@ -841,7 +927,7 @@ int fpga_switch_conns(struct sw_conns* conns)
end_of_chain_str = fpga_switch_str_i(conns->model, end_of_chain_str = fpga_switch_str_i(conns->model,
conns->y, conns->x, conns->y, conns->x,
conns->chain.set.sw[conns->chain.set.len-1], conns->chain.set.sw[conns->chain.set.len-1],
SW_TO); !conns->from_to);
if (end_of_chain_str == STRIDX_NO_ENTRY) if (end_of_chain_str == STRIDX_NO_ENTRY)
{ HERE(); goto internal_error; } { HERE(); goto internal_error; }
conns->dest_i = 0; conns->dest_i = 0;
@ -865,7 +951,7 @@ internal_error:
} }
void printf_swchain(struct fpga_model* model, int y, int x, void printf_swchain(struct fpga_model* model, int y, int x,
str16_t sw, int max_depth, int from_to) str16_t sw, int from_to, int max_depth)
{ {
struct sw_chain chain = struct sw_chain chain =
{ .model = model, .y = y, .x = x, .start_switch = sw, { .model = model, .y = y, .x = x, .start_switch = sw,
@ -877,14 +963,14 @@ void printf_swchain(struct fpga_model* model, int y, int x,
} }
void printf_swconns(struct fpga_model* model, int y, int x, void printf_swconns(struct fpga_model* model, int y, int x,
str16_t sw, int max_depth) str16_t sw, int from_to, int max_depth)
{ {
struct sw_conns conns = struct sw_conns conns =
{ .model = model, .y = y, .x = x, .start_switch = sw, { .model = model, .y = y, .x = x, .start_switch = sw,
.max_switch_depth = max_depth }; .from_to = from_to, .max_switch_depth = max_depth };
while (fpga_switch_conns(&conns) != NO_CONN) { while (fpga_switch_conns(&conns) != NO_CONN) {
printf("sw %s conn y%02i x%02i %s\n", fmt_swset(model, y, x, printf("sw %s conn y%02i x%02i %s\n", fmt_swset(model, y, x,
&conns.chain.set, SW_FROM), &conns.chain.set, from_to),
conns.dest_y, conns.dest_x, conns.dest_y, conns.dest_x,
strarray_lookup(&model->str, conns.dest_str_i)); strarray_lookup(&model->str, conns.dest_str_i));
} }
@ -894,7 +980,7 @@ int fpga_switch_to_yx(struct switch_to_yx* p)
{ {
struct sw_conns conns = { struct sw_conns conns = {
.model = p->model, .y = p->y, .x = p->x, .model = p->model, .y = p->y, .x = p->x,
.start_switch = p->start_switch, .start_switch = p->start_switch, .from_to = p->from_to,
.max_switch_depth = .max_switch_depth =
(p->flags & SWTO_YX_MAX_SWITCH_DEPTH) (p->flags & SWTO_YX_MAX_SWITCH_DEPTH)
? p->max_switch_depth : MAX_SW_DEPTH }; ? p->max_switch_depth : MAX_SW_DEPTH };
@ -942,6 +1028,18 @@ int fpga_switch_to_yx(struct switch_to_yx* p)
return 0; return 0;
} }
void printf_switch_to_result(struct switch_to_yx* p)
{
printf("switch_to_yx() from y%02i x%02i connpt %s (%s)\n",
p->y, p->x, strarray_lookup(&p->model->str, p->start_switch),
p->from_to == SW_FROM ? "SW_FROM" : "SW_TO");
printf(" %s y%02i x%02i %s via %s\n",
p->from_to == SW_FROM ? "to" : "from",
p->dest_y, p->dest_x,
strarray_lookup(&p->model->str, p->dest_connpt),
fmt_swset(p->model, p->y, p->x, &p->set, p->from_to));
}
#define NET_ALLOC_INCREMENT 64 #define NET_ALLOC_INCREMENT 64
static int fpga_net_useidx(struct fpga_model* model, net_idx_t new_idx) static int fpga_net_useidx(struct fpga_model* model, net_idx_t new_idx)
@ -981,6 +1079,26 @@ int fpga_net_new(struct fpga_model* model, net_idx_t* new_idx)
return 0; return 0;
} }
void fpga_net_delete(struct fpga_model* model, net_idx_t net_idx)
{
struct fpga_net* net;
int i;
net = &model->nets[net_idx-1];
for (i = 0; i < net->len; i++) {
if (net->el[i].idx & NET_IDX_IS_PINW)
continue;
if (!fpga_switch_is_used(model, net->el[i].y, net->el[i].x,
net->el[i].idx))
HERE();
fpga_switch_disable(model, net->el[i].y, net->el[i].x,
net->el[i].idx);
}
model->nets[net_idx-1].len = 0;
if (model->highest_used_net == net_idx)
model->highest_used_net--;
}
int fpga_net_enum(struct fpga_model* model, net_idx_t last, net_idx_t* next) int fpga_net_enum(struct fpga_model* model, net_idx_t last, net_idx_t* next)
{ {
int i; int i;
@ -1029,6 +1147,15 @@ fail:
return rc; return rc;
} }
int fpga_net_add_switch(struct fpga_model* model, net_idx_t net_i,
int y, int x, swidx_t one_sw)
{
struct sw_set set;
set.sw[0] = one_sw;
set.len = 1;
return fpga_net_add_switches(model, net_i, y, x, &set);
}
int fpga_net_add_switches(struct fpga_model* model, net_idx_t net_i, int fpga_net_add_switches(struct fpga_model* model, net_idx_t net_i,
int y, int x, const struct sw_set* set) int y, int x, const struct sw_set* set)
{ {

View File

@ -43,6 +43,8 @@ int fdev_logic_set_lut(struct fpga_model* model, int y, int x, int type_idx,
int which_lut, const char* lut_str, int lut_len); int which_lut, const char* lut_str, int lut_len);
int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type, int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type,
int type_idx); int type_idx);
void fdev_print_required_pins(struct fpga_model* model, int y, int x,
int type, int type_idx);
void fdev_delete(struct fpga_model* model, int y, int x, int type, void fdev_delete(struct fpga_model* model, int y, int x, int type,
int type_idx); int type_idx);
@ -139,6 +141,7 @@ struct sw_conns
int x; int x;
// start_switch will be set to STRIDX_NO_ENTRY (0) after first call // start_switch will be set to STRIDX_NO_ENTRY (0) after first call
str16_t start_switch; str16_t start_switch;
int from_to;
int max_switch_depth; int max_switch_depth;
// return values: // return values:
@ -156,9 +159,9 @@ struct sw_conns
int fpga_switch_conns(struct sw_conns* conns); int fpga_switch_conns(struct sw_conns* conns);
void printf_swchain(struct fpga_model* model, int y, int x, void printf_swchain(struct fpga_model* model, int y, int x,
str16_t sw, int max_depth, int from_to); str16_t sw, int from_to, int max_depth);
void printf_swconns(struct fpga_model* model, int y, int x, void printf_swconns(struct fpga_model* model, int y, int x,
str16_t sw, int max_depth); str16_t sw, int from_to, int max_depth);
#define SWTO_YX_DEF 0 #define SWTO_YX_DEF 0
#define SWTO_YX_CLOSEST 0x0001 #define SWTO_YX_CLOSEST 0x0001
@ -174,6 +177,7 @@ struct switch_to_yx
int y; int y;
int x; int x;
str16_t start_switch; str16_t start_switch;
int from_to;
int max_switch_depth; // only if SWTO_YX_MAX_SWITCH_DEPTH is set int max_switch_depth; // only if SWTO_YX_MAX_SWITCH_DEPTH is set
str16_t target_connpt; // only if SWTO_YX_TARGET_CONNPT is set str16_t target_connpt; // only if SWTO_YX_TARGET_CONNPT is set
@ -185,6 +189,7 @@ struct switch_to_yx
}; };
int fpga_switch_to_yx(struct switch_to_yx* p); int fpga_switch_to_yx(struct switch_to_yx* p);
void printf_switch_to_result(struct switch_to_yx* p);
// //
// nets // nets
@ -221,11 +226,14 @@ typedef int net_idx_t; // net indices are 1-based
#define NO_NET 0 #define NO_NET 0
int fpga_net_new(struct fpga_model* model, net_idx_t* new_idx); int fpga_net_new(struct fpga_model* model, net_idx_t* new_idx);
void fpga_net_delete(struct fpga_model* model, net_idx_t net_idx);
// start a new enumeration by calling with last==NO_NET // start a new enumeration by calling with last==NO_NET
int fpga_net_enum(struct fpga_model* model, net_idx_t last, net_idx_t* next); int fpga_net_enum(struct fpga_model* model, net_idx_t last, net_idx_t* next);
struct fpga_net* fpga_net_get(struct fpga_model* model, net_idx_t net_i); struct fpga_net* fpga_net_get(struct fpga_model* model, net_idx_t net_i);
int fpga_net_add_port(struct fpga_model* model, net_idx_t net_i, int fpga_net_add_port(struct fpga_model* model, net_idx_t net_i,
int y, int x, dev_idx_t dev_idx, pinw_idx_t pinw_idx); int y, int x, dev_idx_t dev_idx, pinw_idx_t pinw_idx);
int fpga_net_add_switch(struct fpga_model* model, net_idx_t net_i,
int y, int x, swidx_t one_sw);
int fpga_net_add_switches(struct fpga_model* model, net_idx_t net_i, int fpga_net_add_switches(struct fpga_model* model, net_idx_t net_i,
int y, int x, const struct sw_set* set); int y, int x, const struct sw_set* set);
void fpga_net_free_all(struct fpga_model* model); void fpga_net_free_all(struct fpga_model* model);

10
model.h
View File

@ -348,7 +348,8 @@ typedef int dev_type_idx_t;
enum { LOGIC_M = 1, LOGIC_L, LOGIC_X }; enum { LOGIC_M = 1, LOGIC_L, LOGIC_X };
// All LOGICIN_IN A..D sequences must be exactly sequential as // All LOGICIN_IN A..D sequences must be exactly sequential as
// here to match initialization in model_device:init_logic(). // here to match initialization in model_devices.c:init_logic()
// and control.c:fdev_set_required_pins().
enum { // input: enum { // input:
LOGIC_IN_A1 = 0, LOGIC_IN_A1 = 0,
LOGIC_IN_A2, LOGIC_IN_A3, LOGIC_IN_A4, LOGIC_IN_A5, LOGIC_IN_A6, LOGIC_IN_A2, LOGIC_IN_A3, LOGIC_IN_A4, LOGIC_IN_A5, LOGIC_IN_A6,
@ -385,8 +386,11 @@ enum { // input:
"AQ", "BQ", "CQ", "DQ", \ "AQ", "BQ", "CQ", "DQ", \
"COUT" } "COUT" }
// offsets into fpgadev_logic:luts[] // offsets into fpgadev_logic:luts[], also hardcoded in
enum { A5_LUT = 0, A6_LUT, B5_LUT, B6_LUT, C5_LUT, C6_LUT, D5_LUT, D6_LUT, NUM_LUTS }; // control.c:fdev_set_required_pins(), where we assume
// that div2 will lead to A-D
enum { A5_LUT = 0, A6_LUT, B5_LUT, B6_LUT,
C5_LUT, C6_LUT, D5_LUT, D6_LUT, NUM_LUTS };
#define FP_LUT_STR \ #define FP_LUT_STR \
{ "A5_lut", "A6_lut", "B5_lut", "B6_lut", \ { "A5_lut", "A6_lut", "B5_lut", "B6_lut", \
"C5_lut", "C6_lut", "D5_lut", "D6_lut" } "C5_lut", "C6_lut", "D5_lut", "D6_lut" }

74
parts.c
View File

@ -70,30 +70,29 @@ const char* get_iob_sitename(int idcode, int idx)
return iob_xc6slx9_sitenames[idx]; return iob_xc6slx9_sitenames[idx];
} }
static const int minors_per_major[] = // for slx4 and slx9
{
/* 0 */ 4, // 505 bytes = middle 8-bit for each minor?
/* 1 */ 30, // left
/* 2 */ 31, // logic M
/* 3 */ 30, // logic L
/* 4 */ 25, // bram
/* 5 */ 31, // logic M
/* 6 */ 30, // logic L
/* 7 */ 24, // macc
/* 8 */ 31, // logic M
/* 9 */ 31, // center
/* 10 */ 31, // logic M
/* 11 */ 30, // logic L
/* 12 */ 31, // logic M
/* 13 */ 30, // logic L
/* 14 */ 25, // bram
/* 15 */ 31, // logic M
/* 16 */ 30, // logic L
/* 17 */ 30, // right
};
int get_major_minors(int idcode, int major) int get_major_minors(int idcode, int major)
{ {
static const int minors_per_major[] = // for slx9
{
/* 0 */ 4, // 505 bytes = middle 8-bit for each minor?
/* 1 */ 30, // left
/* 2 */ 31, // logic M
/* 3 */ 30, // logic L
/* 4 */ 25, // bram
/* 5 */ 31, // logic M
/* 6 */ 30, // logic L
/* 7 */ 24, // macc
/* 8 */ 31, // logic M
/* 9 */ 31, // center
/* 10 */ 31, // logic M
/* 11 */ 30, // logic L
/* 12 */ 31, // logic M
/* 13 */ 30, // logic L
/* 14 */ 25, // bram
/* 15 */ 31, // logic M
/* 16 */ 30, // logic L
/* 17 */ 30, // right
};
if ((idcode & IDCODE_MASK) != XC6SLX9) if ((idcode & IDCODE_MASK) != XC6SLX9)
EXIT(1); EXIT(1);
if (major < 0 || major if (major < 0 || major
@ -101,3 +100,34 @@ int get_major_minors(int idcode, int major)
EXIT(1); EXIT(1);
return minors_per_major[major]; return minors_per_major[major];
} }
enum major_type get_major_type(int idcode, int major)
{
static const int major_types[] = // for slx9
{
/* 0 */ MAJ_ZERO,
/* 1 */ MAJ_LEFT,
/* 2 */ MAJ_LOGIC_XM,
/* 3 */ MAJ_LOGIC_XL,
/* 4 */ MAJ_BRAM,
/* 5 */ MAJ_LOGIC_XM,
/* 6 */ MAJ_LOGIC_XL,
/* 7 */ MAJ_MACC,
/* 8 */ MAJ_LOGIC_XM,
/* 9 */ MAJ_CENTER,
/* 10 */ MAJ_LOGIC_XM,
/* 11 */ MAJ_LOGIC_XL,
/* 12 */ MAJ_LOGIC_XM,
/* 13 */ MAJ_LOGIC_XL,
/* 14 */ MAJ_BRAM,
/* 15 */ MAJ_LOGIC_XM,
/* 16 */ MAJ_LOGIC_XL,
/* 17 */ MAJ_RIGHT
};
if ((idcode & IDCODE_MASK) != XC6SLX9)
EXIT(1);
if (major < 0 || major
> sizeof(major_types)/sizeof(major_types[0]))
EXIT(1);
return major_types[major];
}

View File

@ -39,5 +39,10 @@
#define BITS_LEN (IOB_DATA_START+IOB_DATA_LEN) #define BITS_LEN (IOB_DATA_START+IOB_DATA_LEN)
int get_major_minors(int idcode, int major); int get_major_minors(int idcode, int major);
enum major_type { MAJ_ZERO, MAJ_LEFT, MAJ_RIGHT, MAJ_CENTER,
MAJ_LOGIC_XM, MAJ_LOGIC_XL, MAJ_BRAM, MAJ_MACC };
enum major_type get_major_type(int idcode, int major);
int get_num_iobs(int idcode); int get_num_iobs(int idcode);
const char* get_iob_sitename(int idcode, int idx); const char* get_iob_sitename(int idcode, int idx);