improving hello_world
This commit is contained in:
parent
d5bb9ceb28
commit
7339cd9cc5
|
@ -434,7 +434,7 @@ static int test_switches(struct test_state* tstate, int y, int x,
|
|||
if (switch_str[2] == '4') {
|
||||
// base for len-4 wire
|
||||
if (tstate->dry_run)
|
||||
fprintf_net(stdout, tstate->model, net);
|
||||
fnet_printf(stdout, tstate->model, net);
|
||||
rc = diff_printf(tstate);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
|
@ -472,7 +472,7 @@ static int test_switches(struct test_state* tstate, int y, int x,
|
|||
|
||||
// base for len-4 target
|
||||
if (tstate->dry_run)
|
||||
fprintf_net(stdout, tstate->model, net);
|
||||
fnet_printf(stdout, tstate->model, net);
|
||||
rc = diff_printf(tstate);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
|
@ -482,7 +482,7 @@ static int test_switches(struct test_state* tstate, int y, int x,
|
|||
if (rc) FAIL(rc);
|
||||
|
||||
if (tstate->dry_run)
|
||||
fprintf_net(stdout, tstate->model, net);
|
||||
fnet_printf(stdout, tstate->model, net);
|
||||
rc = diff_printf(tstate);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
|
@ -652,7 +652,7 @@ static int test_routing_sw_from_logic(struct test_state* tstate,
|
|||
swto.dest_x, conns.chain.set.sw, conns.chain.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
if (tstate->dry_run)
|
||||
fprintf_net(stdout, tstate->model, net);
|
||||
fnet_printf(stdout, tstate->model, net);
|
||||
|
||||
rc = test_switches(tstate, conns.dest_y, conns.dest_x,
|
||||
conns.dest_str_i, net, done_list, done_list_len);
|
||||
|
|
89
bit_frames.c
89
bit_frames.c
|
@ -378,6 +378,43 @@ fail:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int bitpos_set_bits(struct fpga_bits* bits, struct fpga_model* model,
|
||||
int y, int x, struct xc6_routing_bitpos* swpos)
|
||||
{
|
||||
int row_num, row_pos, start_in_frame, rc;
|
||||
|
||||
is_in_row(model, y, &row_num, &row_pos);
|
||||
if (row_num == -1 || row_pos == -1
|
||||
|| row_pos == HCLK_POS) FAIL(EINVAL);
|
||||
if (row_pos > HCLK_POS)
|
||||
start_in_frame = (row_pos-1)*64 + 16;
|
||||
else
|
||||
start_in_frame = row_pos*64;
|
||||
|
||||
if (swpos->minor == 20) {
|
||||
if (swpos->two_bits_val & 0x02)
|
||||
set_bit(bits, row_num, model->x_major[x], swpos->minor,
|
||||
start_in_frame + swpos->two_bits_o);
|
||||
if (swpos->two_bits_val & 0x01)
|
||||
set_bit(bits, row_num, model->x_major[x], swpos->minor,
|
||||
start_in_frame + swpos->two_bits_o+1);
|
||||
set_bit(bits, row_num, model->x_major[x], swpos->minor,
|
||||
start_in_frame + swpos->one_bit_o);
|
||||
} else {
|
||||
if (swpos->two_bits_val & 0x02)
|
||||
set_bit(bits, row_num, model->x_major[x], swpos->minor,
|
||||
start_in_frame + swpos->two_bits_o/2);
|
||||
if (swpos->two_bits_val & 0x01)
|
||||
set_bit(bits, row_num, model->x_major[x], swpos->minor + 1,
|
||||
start_in_frame + swpos->two_bits_o/2);
|
||||
set_bit(bits, row_num, model->x_major[x], swpos->minor + (swpos->one_bit_o&1),
|
||||
start_in_frame + swpos->one_bit_o/2);
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int extract_routing_switches(struct extract_state* es, int y, int x)
|
||||
{
|
||||
struct fpga_tile* tile;
|
||||
|
@ -392,8 +429,8 @@ static int extract_routing_switches(struct extract_state* es, int y, int x)
|
|||
if (!is_set) continue;
|
||||
|
||||
sw_idx = fpga_switch_lookup(es->model, y, x,
|
||||
fpga_wirestr_i(es->model, es->model->sw_bitpos[i].from),
|
||||
fpga_wirestr_i(es->model, es->model->sw_bitpos[i].to));
|
||||
fpga_wire2str_i(es->model, es->model->sw_bitpos[i].from),
|
||||
fpga_wire2str_i(es->model, es->model->sw_bitpos[i].to));
|
||||
if (sw_idx == NO_SWITCH) FAIL(EINVAL);
|
||||
// todo: es->model->sw_bitpos[i].bidir handling
|
||||
|
||||
|
@ -499,18 +536,50 @@ int printf_swbits(struct fpga_model* model)
|
|||
bit_str[model->sw_bitpos[i].two_bits_o+1] = '1';
|
||||
bit_str[model->sw_bitpos[i].one_bit_o] = '1';
|
||||
printf("mi%02i %s %s %s %s\n", model->sw_bitpos[i].minor,
|
||||
fpga_wirestr(model, model->sw_bitpos[i].to),
|
||||
fpga_wire2str(model->sw_bitpos[i].to),
|
||||
bit_str,
|
||||
fpga_wirestr(model, model->sw_bitpos[i].from),
|
||||
fpga_wire2str(model->sw_bitpos[i].from),
|
||||
model->sw_bitpos[i].bidir ? "<->" : "->");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_bitpos(struct fpga_model* model, int y, int x, swidx_t sw)
|
||||
{
|
||||
enum extra_wires from_w, to_w;
|
||||
const char* from_str, *to_str;
|
||||
int i;
|
||||
|
||||
from_str = fpga_switch_str(model, y, x, sw, SW_FROM);
|
||||
to_str = fpga_switch_str(model, y, x, sw, SW_TO);
|
||||
from_w = fpga_str2wire(from_str);
|
||||
to_w = fpga_str2wire(to_str);
|
||||
|
||||
if (from_w == NO_WIRE || to_w == NO_WIRE) {
|
||||
HERE();
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < model->num_bitpos; i++) {
|
||||
if (model->sw_bitpos[i].from == from_w
|
||||
&& model->sw_bitpos[i].to == to_w)
|
||||
return i;
|
||||
if (model->sw_bitpos[i].bidir
|
||||
&& model->sw_bitpos[i].to == from_w
|
||||
&& model->sw_bitpos[i].from == to_w) {
|
||||
if (!fpga_switch_is_bidir(model, y, x, sw))
|
||||
HERE();
|
||||
return i;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "#E switch %s (%i) to %s (%i) not in model\n",
|
||||
from_str, from_w, to_str, to_w);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int write_switches(struct fpga_bits* bits, struct fpga_model* model)
|
||||
{
|
||||
int x, y, i;
|
||||
struct fpga_tile* tile;
|
||||
int x, y, i, bit_pos, rc;
|
||||
|
||||
for (x = 0; x < model->x_width; x++) {
|
||||
for (y = 0; y < model->y_height; y++) {
|
||||
|
@ -524,10 +593,20 @@ static int write_switches(struct fpga_bits* bits, struct fpga_model* model)
|
|||
// go through enabled switches, lookup in sw_bitpos
|
||||
// and set bits
|
||||
for (i = 0; i < tile->num_switches; i++) {
|
||||
if (!(tile->switches[i] & SWITCH_USED))
|
||||
continue;
|
||||
bit_pos = find_bitpos(model, y, x, i);
|
||||
if (bit_pos == -1)
|
||||
continue;
|
||||
rc = bitpos_set_bits(bits, model, y, x,
|
||||
&model->sw_bitpos[bit_pos]);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int write_model(struct fpga_bits* bits, struct fpga_model* model)
|
||||
|
|
289
control.c
289
control.c
|
@ -728,6 +728,31 @@ void fpga_conn_dest(struct fpga_model* model, int y, int x,
|
|||
*str_i = tile->conn_point_dests[connpt_dest_idx*3+2];
|
||||
}
|
||||
|
||||
int fpga_find_conn(struct fpga_model* model, int search_y, int search_x,
|
||||
str16_t* pt, int target_y, int target_x, str16_t target_pt)
|
||||
{
|
||||
struct fpga_tile* tile;
|
||||
int i, j, dests_end;
|
||||
|
||||
tile = YX_TILE(model, search_y, search_x);
|
||||
for (i = 0; i < tile->num_conn_point_names; i++) {
|
||||
dests_end = (i < tile->num_conn_point_names-1)
|
||||
? tile->conn_point_names[(i+1)*2]
|
||||
: tile->num_conn_point_dests;
|
||||
for (j = tile->conn_point_names[i*2]; j < dests_end; j++) {
|
||||
if (tile->conn_point_dests[j*3] == target_x
|
||||
&& tile->conn_point_dests[j*3+1] == target_y
|
||||
&& tile->conn_point_dests[j*3+2] == target_pt) {
|
||||
*pt = tile->conn_point_names[i*2+1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
*pt = STRIDX_NO_ENTRY;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
swidx_t fpga_switch_first(struct fpga_model* model, int y, int x,
|
||||
str16_t name_i, int from_to)
|
||||
{
|
||||
|
@ -894,6 +919,17 @@ void fpga_swset_print(struct fpga_model* model, int y, int x,
|
|||
}
|
||||
}
|
||||
|
||||
int fpga_swset_is_used(struct fpga_model* model, int y, int x,
|
||||
swidx_t* sw, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (fpga_switch_is_used(model, y, x, sw[i]))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fpga_switch_same_fromto(struct fpga_model* model, int y, int x,
|
||||
swidx_t sw, int from_to, swidx_t* same_sw, int *same_len)
|
||||
{
|
||||
|
@ -1181,7 +1217,7 @@ int fpga_switch_chain(struct sw_chain* ch)
|
|||
{
|
||||
swidx_t idx;
|
||||
struct fpga_tile* tile;
|
||||
int child_from_to, loop_detect, block_detect, i;
|
||||
int child_from_to, level_down, i;
|
||||
|
||||
if (!ch->set.len)
|
||||
{ HERE(); goto internal_error; }
|
||||
|
@ -1193,7 +1229,8 @@ int fpga_switch_chain(struct sw_chain* ch)
|
|||
if (idx == NO_SWITCH)
|
||||
break;
|
||||
ch->set.sw[ch->set.len-1] = idx;
|
||||
if (switch_list_contains(ch->model, ch->y, ch->x,
|
||||
if (!fpga_switch_is_used(ch->model, ch->y, ch->x, idx)
|
||||
&& switch_list_contains(ch->model, ch->y, ch->x,
|
||||
ch->block_list, ch->block_list_len, idx)
|
||||
== NO_SWITCH)
|
||||
return 0;
|
||||
|
@ -1229,8 +1266,14 @@ int fpga_switch_chain(struct sw_chain* ch)
|
|||
ch->model, ch->y, ch->x, idx));
|
||||
#endif
|
||||
if (idx != NO_SWITCH) {
|
||||
// If we have the same from-switch already among the
|
||||
// parents, don't enter into a loop.
|
||||
// There are four reasons why we don't want to
|
||||
// go down one level:
|
||||
// 1) switch is used
|
||||
// 2) switch loop back to parent of chain
|
||||
// 3) switch is blocked
|
||||
// 4) max depth reached
|
||||
level_down = 1;
|
||||
|
||||
child_from_to = SW_I(tile->switches[ch->set.sw[
|
||||
ch->set.len-1]], !ch->from_to);
|
||||
#ifdef DBG_ENUM_SWITCH
|
||||
|
@ -1238,7 +1281,12 @@ int fpga_switch_chain(struct sw_chain* ch)
|
|||
ch->model, ch->y, ch->x,
|
||||
child_from_to));
|
||||
#endif
|
||||
loop_detect = 0;
|
||||
if (fpga_switch_is_used(ch->model, ch->y, ch->x, idx))
|
||||
level_down = 0;
|
||||
|
||||
if (level_down) {
|
||||
// If we have the same from-switch already
|
||||
// among the parents, don't enter into a loop.
|
||||
for (i = 0; i < ch->set.len; i++) {
|
||||
int parent_connpt = SW_I(tile->switches[
|
||||
ch->set.sw[i]], ch->from_to);
|
||||
|
@ -1249,14 +1297,18 @@ int fpga_switch_chain(struct sw_chain* ch)
|
|||
== child_from_to ? " (match)" : "");
|
||||
#endif
|
||||
if (parent_connpt == child_from_to) {
|
||||
loop_detect = 1;
|
||||
level_down = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
block_detect = switch_list_contains(ch->model,
|
||||
}
|
||||
if (level_down) {
|
||||
// only go down if not blocked
|
||||
level_down = switch_list_contains(ch->model,
|
||||
ch->y, ch->x, ch->block_list,
|
||||
ch->block_list_len, idx) != NO_SWITCH;
|
||||
if (!loop_detect && !block_detect) {
|
||||
ch->block_list_len, idx) == NO_SWITCH;
|
||||
}
|
||||
if (level_down) {
|
||||
if (ch->set.len >= SW_SET_SIZE)
|
||||
{ HERE(); goto internal_error; }
|
||||
if (ch->max_depth < 1
|
||||
|
@ -1294,6 +1346,8 @@ int fpga_switch_chain(struct sw_chain* ch)
|
|||
idx = fpga_switch_next(ch->model, ch->y, ch->x,
|
||||
ch->set.sw[ch->set.len-1], ch->from_to);
|
||||
if (idx != NO_SWITCH) {
|
||||
if (fpga_switch_is_used(ch->model, ch->y, ch->x, idx))
|
||||
continue;
|
||||
#ifdef DBG_ENUM_SWITCH
|
||||
printf(" found %s\n", fpga_switch_print(
|
||||
ch->model, ch->y, ch->x, idx));
|
||||
|
@ -1731,7 +1785,7 @@ static void fprintf_inout_pin(FILE* f, struct fpga_model* model,
|
|||
fprintf(f, buf);
|
||||
}
|
||||
|
||||
void fprintf_net(FILE* f, struct fpga_model* model, net_idx_t net_i)
|
||||
void fnet_printf(FILE* f, struct fpga_model* model, net_idx_t net_i)
|
||||
{
|
||||
struct fpga_net* net;
|
||||
int i;
|
||||
|
@ -1750,3 +1804,218 @@ void fprintf_net(FILE* f, struct fpga_model* model, net_idx_t net_i)
|
|||
net->el[i].x, net->el[i].idx));
|
||||
}
|
||||
}
|
||||
|
||||
int fnet_autoroute(struct fpga_model* model, net_idx_t net_i)
|
||||
{
|
||||
struct fpga_net* net_p;
|
||||
struct fpga_device* dev_p, *out_dev, *in_dev;
|
||||
struct switch_to_yx switch_to;
|
||||
struct sw_set logic_route_set, iologic_route_set;
|
||||
struct switch_to_rel switch_to_rel;
|
||||
int i, out_i, in_i, rc;
|
||||
|
||||
// todo: gnd and vcc nets are special and have no outpin
|
||||
// but lots of inpins
|
||||
|
||||
net_p = fnet_get(model, net_i);
|
||||
if (!net_p) FAIL(EINVAL);
|
||||
out_i = -1;
|
||||
in_i = -1;
|
||||
for (i = 0; i < net_p->len; i++) {
|
||||
if (!(net_p->el[i].idx & NET_IDX_IS_PINW)) {
|
||||
// net already routed?
|
||||
FAIL(EINVAL);
|
||||
}
|
||||
dev_p = FPGA_DEV(model, net_p->el[i].y,
|
||||
net_p->el[i].x, net_p->el[i].dev_idx);
|
||||
if ((net_p->el[i].idx & NET_IDX_MASK) < dev_p->num_pinw_in) {
|
||||
// todo: right now we only support 1 inpin
|
||||
if (in_i != -1) FAIL(ENOTSUP);
|
||||
in_i = i;
|
||||
continue;
|
||||
}
|
||||
if (out_i != -1) FAIL(EINVAL); // at most 1 outpin
|
||||
out_i = i;
|
||||
}
|
||||
// todo: vcc and gnd have no outpin?
|
||||
if (out_i == -1 || in_i == -1)
|
||||
FAIL(EINVAL);
|
||||
out_dev = FPGA_DEV(model, net_p->el[out_i].y,
|
||||
net_p->el[out_i].x, net_p->el[out_i].dev_idx);
|
||||
in_dev = FPGA_DEV(model, net_p->el[in_i].y,
|
||||
net_p->el[in_i].x, net_p->el[in_i].dev_idx);
|
||||
if (out_dev->type == DEV_IOB) {
|
||||
if (in_dev->type != DEV_LOGIC)
|
||||
FAIL(ENOTSUP);
|
||||
|
||||
// switch to ilogic
|
||||
switch_to.yx_req = YX_DEV_ILOGIC;
|
||||
switch_to.flags = SWTO_YX_DEF;
|
||||
switch_to.model = model;
|
||||
switch_to.y = net_p->el[out_i].y;
|
||||
switch_to.x = net_p->el[out_i].x;
|
||||
switch_to.start_switch = out_dev->pinw[net_p->el[out_i].idx
|
||||
& NET_IDX_MASK];
|
||||
switch_to.from_to = SW_FROM;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.y, switch_to.x,
|
||||
switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// switch to ilogic routing
|
||||
switch_to.yx_req = YX_ROUTING_TILE;
|
||||
switch_to.flags = SWTO_YX_DEF;
|
||||
switch_to.model = model;
|
||||
switch_to.y = switch_to.dest_y;
|
||||
switch_to.x = switch_to.dest_x;
|
||||
switch_to.start_switch = switch_to.dest_connpt;
|
||||
switch_to.from_to = SW_FROM;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.y, switch_to.x,
|
||||
switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// switch from logic tile to logic routing tile
|
||||
switch_to_rel.model = model;
|
||||
switch_to_rel.start_y = net_p->el[in_i].y;
|
||||
switch_to_rel.start_x = net_p->el[in_i].x;
|
||||
switch_to_rel.start_switch =
|
||||
in_dev->pinw[net_p->el[in_i].idx & NET_IDX_MASK];
|
||||
switch_to_rel.from_to = SW_TO;
|
||||
switch_to_rel.rel_y = 0;
|
||||
switch_to_rel.rel_x = -1;
|
||||
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
|
||||
rc = fpga_switch_to_rel(&switch_to_rel);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to_rel.start_y,
|
||||
switch_to_rel.start_x, switch_to_rel.set.sw,
|
||||
switch_to_rel.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// route from ilogic routing to logic routing
|
||||
rc = froute_direct(model, switch_to.dest_y, switch_to.dest_x,
|
||||
switch_to.dest_connpt,
|
||||
switch_to_rel.dest_y, switch_to_rel.dest_x,
|
||||
switch_to_rel.dest_connpt,
|
||||
&iologic_route_set, &logic_route_set);
|
||||
if (rc) FAIL(rc);
|
||||
if (!iologic_route_set.len || !logic_route_set.len) FAIL(EINVAL);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.dest_y, switch_to.dest_x,
|
||||
iologic_route_set.sw, iologic_route_set.len);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, net_p->el[in_i].y, net_p->el[in_i].x-1,
|
||||
logic_route_set.sw, logic_route_set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (out_dev->type == DEV_LOGIC) {
|
||||
if (in_dev->type != DEV_IOB)
|
||||
FAIL(ENOTSUP);
|
||||
|
||||
// switch from ologic to iob
|
||||
switch_to.yx_req = YX_DEV_OLOGIC;
|
||||
switch_to.flags = SWTO_YX_DEF;
|
||||
switch_to.model = model;
|
||||
switch_to.y = net_p->el[in_i].y;
|
||||
switch_to.x = net_p->el[in_i].x;
|
||||
switch_to.start_switch = in_dev->pinw[net_p->el[in_i].idx
|
||||
& NET_IDX_MASK];
|
||||
switch_to.from_to = SW_TO;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.y, switch_to.x,
|
||||
switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// switches inside ologic to ologic routing
|
||||
switch_to.yx_req = YX_ROUTING_TILE;
|
||||
switch_to.flags = SWTO_YX_DEF;
|
||||
switch_to.model = model;
|
||||
switch_to.y = switch_to.dest_y;
|
||||
switch_to.x = switch_to.dest_x;
|
||||
switch_to.start_switch = switch_to.dest_connpt;
|
||||
switch_to.from_to = SW_TO;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.y, switch_to.x,
|
||||
switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// switch inside logic tile
|
||||
switch_to_rel.model = model;
|
||||
switch_to_rel.start_y = net_p->el[out_i].y;
|
||||
switch_to_rel.start_x = net_p->el[out_i].x;
|
||||
switch_to_rel.start_switch =
|
||||
out_dev->pinw[net_p->el[out_i].idx & NET_IDX_MASK];
|
||||
switch_to_rel.from_to = SW_FROM;
|
||||
switch_to_rel.rel_y = 0;
|
||||
switch_to_rel.rel_x = -1;
|
||||
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
|
||||
rc = fpga_switch_to_rel(&switch_to_rel);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to_rel.start_y,
|
||||
switch_to_rel.start_x, switch_to_rel.set.sw,
|
||||
switch_to_rel.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// route from logic routing to ilogic routing
|
||||
rc = froute_direct(model, switch_to_rel.dest_y,
|
||||
switch_to_rel.dest_x, switch_to_rel.dest_connpt,
|
||||
switch_to.dest_y, switch_to.dest_x, switch_to.dest_connpt,
|
||||
&logic_route_set, &iologic_route_set);
|
||||
if (rc) FAIL(rc);
|
||||
if (!iologic_route_set.len || !logic_route_set.len) FAIL(EINVAL);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.dest_y, switch_to.dest_x,
|
||||
iologic_route_set.sw, iologic_route_set.len);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to_rel.dest_y,
|
||||
switch_to_rel.dest_x, logic_route_set.sw,
|
||||
logic_route_set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
FAIL(ENOTSUP);
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int froute_direct(struct fpga_model* model, int start_y, int start_x,
|
||||
str16_t start_pt, int end_y, int end_x, str16_t end_pt,
|
||||
struct sw_set* start_set, struct sw_set* end_set)
|
||||
{
|
||||
struct sw_conns conns;
|
||||
struct sw_set end_switches;
|
||||
int i, rc;
|
||||
|
||||
rc = fpga_swset_fromto(model, end_y, end_x, end_pt, SW_TO, &end_switches);
|
||||
if (rc) FAIL(rc);
|
||||
if (!end_switches.len) FAIL(EINVAL);
|
||||
|
||||
rc = construct_sw_conns(&conns, model, start_y, start_x, start_pt,
|
||||
SW_FROM, /*max_depth*/ 1);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
while (fpga_switch_conns(&conns) != NO_CONN) {
|
||||
if (conns.dest_y != end_y
|
||||
|| conns.dest_x != end_x) continue;
|
||||
for (i = 0; i < end_switches.len; i++) {
|
||||
if (conns.dest_str_i == fpga_switch_str_i(model, end_y,
|
||||
end_x, end_switches.sw[i], SW_FROM)) {
|
||||
*start_set = conns.chain.set;
|
||||
end_set->len = 1;
|
||||
end_set->sw[0] = end_switches.sw[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
destruct_sw_conns(&conns);
|
||||
start_set->len = 0;
|
||||
end_set->len = 0;
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
|
13
control.h
13
control.h
|
@ -131,6 +131,8 @@ int fpga_swset_level_down(struct fpga_model* model, int y, int x,
|
|||
struct sw_set* set, int from_to);
|
||||
void fpga_swset_print(struct fpga_model* model, int y, int x,
|
||||
struct sw_set* set, int from_to);
|
||||
int fpga_swset_is_used(struct fpga_model* model, int y, int x,
|
||||
swidx_t* sw, int len);
|
||||
|
||||
// When calling, same_len must contain the size of the
|
||||
// same_sw array. Upon return same_len returns how many
|
||||
|
@ -328,5 +330,14 @@ int fnet_add_sw(struct fpga_model* model, net_idx_t net_i,
|
|||
int fnet_remove_sw(struct fpga_model* model, net_idx_t net_i,
|
||||
int y, int x, const swidx_t* switches, int num_sw);
|
||||
void fnet_free_all(struct fpga_model* model);
|
||||
void fnet_printf(FILE* f, struct fpga_model* model, net_idx_t net_i);
|
||||
|
||||
void fprintf_net(FILE* f, struct fpga_model* model, net_idx_t net_i);
|
||||
int fnet_autoroute(struct fpga_model* model, net_idx_t net_i);
|
||||
|
||||
//
|
||||
// routing
|
||||
//
|
||||
|
||||
int froute_direct(struct fpga_model* model, int start_y, int start_x,
|
||||
str16_t start_pt, int end_y, int end_x, str16_t end_pt,
|
||||
struct sw_set* start_set, struct sw_set* end_set);
|
||||
|
|
|
@ -729,7 +729,7 @@ int printf_nets(FILE* f, struct fpga_model* model)
|
|||
|
||||
net_i = NO_NET;
|
||||
while (!(rc = fnet_enum(model, net_i, &net_i)) && net_i != NO_NET)
|
||||
fprintf_net(f, model, net_i);
|
||||
fnet_printf(f, model, net_i);
|
||||
if (rc) FAIL(rc);
|
||||
return 0;
|
||||
fail:
|
||||
|
|
242
hello_world.c
242
hello_world.c
|
@ -9,246 +9,6 @@
|
|||
#include "floorplan.h"
|
||||
#include "control.h"
|
||||
|
||||
int fpga_find_conn(struct fpga_model* model, int search_y, int search_x,
|
||||
str16_t* pt, int target_y, int target_x, str16_t target_pt)
|
||||
{
|
||||
struct fpga_tile* tile;
|
||||
int i, j, dests_end;
|
||||
|
||||
tile = YX_TILE(model, search_y, search_x);
|
||||
for (i = 0; i < tile->num_conn_point_names; i++) {
|
||||
dests_end = (i < tile->num_conn_point_names-1)
|
||||
? tile->conn_point_names[(i+1)*2]
|
||||
: tile->num_conn_point_dests;
|
||||
for (j = tile->conn_point_names[i*2]; j < dests_end; j++) {
|
||||
if (tile->conn_point_dests[j*3] == target_x
|
||||
&& tile->conn_point_dests[j*3+1] == target_y
|
||||
&& tile->conn_point_dests[j*3+2] == target_pt) {
|
||||
*pt = tile->conn_point_names[i*2+1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
*pt = STRIDX_NO_ENTRY;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int froute_direct(struct fpga_model* model, int start_y, int start_x,
|
||||
str16_t start_pt, int end_y, int end_x, str16_t end_pt,
|
||||
struct sw_set* start_set, struct sw_set* end_set)
|
||||
{
|
||||
struct sw_conns conns;
|
||||
struct sw_set end_switches;
|
||||
int i, rc;
|
||||
|
||||
rc = fpga_swset_fromto(model, end_y, end_x, end_pt, SW_TO, &end_switches);
|
||||
if (rc) FAIL(rc);
|
||||
if (!end_switches.len) FAIL(EINVAL);
|
||||
|
||||
rc = construct_sw_conns(&conns, model, start_y, start_x, start_pt,
|
||||
SW_FROM, /*max_depth*/ 1);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
while (fpga_switch_conns(&conns) != NO_CONN) {
|
||||
if (conns.dest_y != end_y
|
||||
|| conns.dest_x != end_x) continue;
|
||||
for (i = 0; i < end_switches.len; i++) {
|
||||
if (conns.dest_str_i == fpga_switch_str_i(model, end_y,
|
||||
end_x, end_switches.sw[i], SW_FROM)) {
|
||||
*start_set = conns.chain.set;
|
||||
end_set->len = 1;
|
||||
end_set->sw[0] = end_switches.sw[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
destruct_sw_conns(&conns);
|
||||
start_set->len = 0;
|
||||
end_set->len = 0;
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fnet_autoroute(struct fpga_model* model, net_idx_t net_i)
|
||||
{
|
||||
struct fpga_net* net_p;
|
||||
struct fpga_device* dev_p, *out_dev, *in_dev;
|
||||
struct switch_to_yx switch_to;
|
||||
struct sw_set logic_route_set, iologic_route_set;
|
||||
struct switch_to_rel switch_to_rel;
|
||||
int i, out_i, in_i, rc;
|
||||
|
||||
// todo: gnd and vcc nets are special and have no outpin
|
||||
// but lots of inpins
|
||||
|
||||
net_p = fnet_get(model, net_i);
|
||||
if (!net_p) FAIL(EINVAL);
|
||||
out_i = -1;
|
||||
in_i = -1;
|
||||
for (i = 0; i < net_p->len; i++) {
|
||||
if (!(net_p->el[i].idx & NET_IDX_IS_PINW)) {
|
||||
// net already routed?
|
||||
FAIL(EINVAL);
|
||||
}
|
||||
dev_p = FPGA_DEV(model, net_p->el[i].y,
|
||||
net_p->el[i].x, net_p->el[i].dev_idx);
|
||||
if ((net_p->el[i].idx & NET_IDX_MASK) < dev_p->num_pinw_in) {
|
||||
// todo: right now we only support 1 inpin
|
||||
if (in_i != -1) FAIL(ENOTSUP);
|
||||
in_i = i;
|
||||
continue;
|
||||
}
|
||||
if (out_i != -1) FAIL(EINVAL); // at most 1 outpin
|
||||
out_i = i;
|
||||
}
|
||||
// todo: vcc and gnd have no outpin?
|
||||
if (out_i == -1 || in_i == -1)
|
||||
FAIL(EINVAL);
|
||||
out_dev = FPGA_DEV(model, net_p->el[out_i].y,
|
||||
net_p->el[out_i].x, net_p->el[out_i].dev_idx);
|
||||
in_dev = FPGA_DEV(model, net_p->el[in_i].y,
|
||||
net_p->el[in_i].x, net_p->el[in_i].dev_idx);
|
||||
if (out_dev->type == DEV_IOB) {
|
||||
if (in_dev->type != DEV_LOGIC)
|
||||
FAIL(ENOTSUP);
|
||||
|
||||
// switch to ilogic
|
||||
switch_to.yx_req = YX_DEV_ILOGIC;
|
||||
switch_to.flags = SWTO_YX_DEF;
|
||||
switch_to.model = model;
|
||||
switch_to.y = net_p->el[out_i].y;
|
||||
switch_to.x = net_p->el[out_i].x;
|
||||
switch_to.start_switch = out_dev->pinw[net_p->el[out_i].idx
|
||||
& NET_IDX_MASK];
|
||||
switch_to.from_to = SW_FROM;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.y, switch_to.x,
|
||||
switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// switch to ilogic routing
|
||||
switch_to.yx_req = YX_ROUTING_TILE;
|
||||
switch_to.flags = SWTO_YX_DEF;
|
||||
switch_to.model = model;
|
||||
switch_to.y = switch_to.dest_y;
|
||||
switch_to.x = switch_to.dest_x;
|
||||
switch_to.start_switch = switch_to.dest_connpt;
|
||||
switch_to.from_to = SW_FROM;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.y, switch_to.x,
|
||||
switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// switch from logic tile to logic routing tile
|
||||
switch_to_rel.model = model;
|
||||
switch_to_rel.start_y = net_p->el[in_i].y;
|
||||
switch_to_rel.start_x = net_p->el[in_i].x;
|
||||
switch_to_rel.start_switch =
|
||||
in_dev->pinw[net_p->el[in_i].idx & NET_IDX_MASK];
|
||||
switch_to_rel.from_to = SW_TO;
|
||||
switch_to_rel.rel_y = 0;
|
||||
switch_to_rel.rel_x = -1;
|
||||
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
|
||||
rc = fpga_switch_to_rel(&switch_to_rel);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to_rel.start_y,
|
||||
switch_to_rel.start_x, switch_to_rel.set.sw,
|
||||
switch_to_rel.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// route from ilogic routing to logic routing
|
||||
rc = froute_direct(model, switch_to.dest_y, switch_to.dest_x,
|
||||
switch_to.dest_connpt,
|
||||
switch_to_rel.dest_y, switch_to_rel.dest_x,
|
||||
switch_to_rel.dest_connpt,
|
||||
&iologic_route_set, &logic_route_set);
|
||||
if (rc) FAIL(rc);
|
||||
if (!iologic_route_set.len || !logic_route_set.len) FAIL(EINVAL);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.dest_y, switch_to.dest_x,
|
||||
iologic_route_set.sw, iologic_route_set.len);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, net_p->el[in_i].y, net_p->el[in_i].x-1,
|
||||
logic_route_set.sw, logic_route_set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (out_dev->type == DEV_LOGIC) {
|
||||
if (in_dev->type != DEV_IOB)
|
||||
FAIL(ENOTSUP);
|
||||
|
||||
// switch from ologic to iob
|
||||
switch_to.yx_req = YX_DEV_OLOGIC;
|
||||
switch_to.flags = SWTO_YX_DEF;
|
||||
switch_to.model = model;
|
||||
switch_to.y = net_p->el[in_i].y;
|
||||
switch_to.x = net_p->el[in_i].x;
|
||||
switch_to.start_switch = in_dev->pinw[net_p->el[in_i].idx
|
||||
& NET_IDX_MASK];
|
||||
switch_to.from_to = SW_TO;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.y, switch_to.x,
|
||||
switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// switches inside ologic to ologic routing
|
||||
switch_to.yx_req = YX_ROUTING_TILE;
|
||||
switch_to.flags = SWTO_YX_DEF;
|
||||
switch_to.model = model;
|
||||
switch_to.y = switch_to.dest_y;
|
||||
switch_to.x = switch_to.dest_x;
|
||||
switch_to.start_switch = switch_to.dest_connpt;
|
||||
switch_to.from_to = SW_TO;
|
||||
rc = fpga_switch_to_yx(&switch_to);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.y, switch_to.x,
|
||||
switch_to.set.sw, switch_to.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// switch inside logic tile
|
||||
switch_to_rel.model = model;
|
||||
switch_to_rel.start_y = net_p->el[out_i].y;
|
||||
switch_to_rel.start_x = net_p->el[out_i].x;
|
||||
switch_to_rel.start_switch =
|
||||
out_dev->pinw[net_p->el[out_i].idx & NET_IDX_MASK];
|
||||
switch_to_rel.from_to = SW_FROM;
|
||||
switch_to_rel.rel_y = 0;
|
||||
switch_to_rel.rel_x = -1;
|
||||
switch_to_rel.target_connpt = STRIDX_NO_ENTRY;
|
||||
rc = fpga_switch_to_rel(&switch_to_rel);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to_rel.start_y,
|
||||
switch_to_rel.start_x, switch_to_rel.set.sw,
|
||||
switch_to_rel.set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
// route from logic routing to ilogic routing
|
||||
rc = froute_direct(model, switch_to_rel.dest_y,
|
||||
switch_to_rel.dest_x, switch_to_rel.dest_connpt,
|
||||
switch_to.dest_y, switch_to.dest_x, switch_to.dest_connpt,
|
||||
&logic_route_set, &iologic_route_set);
|
||||
if (rc) FAIL(rc);
|
||||
if (!iologic_route_set.len || !logic_route_set.len) FAIL(EINVAL);
|
||||
rc = fnet_add_sw(model, net_i, switch_to.dest_y, switch_to.dest_x,
|
||||
iologic_route_set.sw, iologic_route_set.len);
|
||||
if (rc) FAIL(rc);
|
||||
rc = fnet_add_sw(model, net_i, switch_to_rel.dest_y,
|
||||
switch_to_rel.dest_x, logic_route_set.sw,
|
||||
logic_route_set.len);
|
||||
if (rc) FAIL(rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
FAIL(ENOTSUP);
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
struct fpga_model model;
|
||||
|
@ -282,6 +42,8 @@ int main(int argc, char** argv)
|
|||
logic_type_idx = DEV_LOGX;
|
||||
if ((rc = fdev_logic_set_lut(&model, logic_y, logic_x, logic_type_idx,
|
||||
LUT_D, 6, "A3*A5", ZTERM))) FAIL(rc);
|
||||
if ((rc = fdev_logic_out_used(&model, logic_y, logic_x, logic_type_idx,
|
||||
LUT_D))) FAIL(rc);
|
||||
|
||||
if ((rc = fnet_new(&model, &inA_net))) FAIL(rc);
|
||||
if ((rc = fnet_add_port(&model, inA_net, iob_inA_y, iob_inA_x,
|
||||
|
|
6
model.h
6
model.h
|
@ -764,6 +764,7 @@ enum wire_type
|
|||
#define W_TO_LEN4(w) wire_to_len(w, FIRST_LEN4)
|
||||
|
||||
const char* wire_base(enum wire_type w);
|
||||
enum wire_type base2wire(const char* str);
|
||||
enum wire_type rotate_wire(enum wire_type cur, int off);
|
||||
enum wire_type wire_to_len(enum wire_type w, int first_len);
|
||||
|
||||
|
@ -824,7 +825,8 @@ enum extra_wires {
|
|||
LW_LAST = 1999
|
||||
};
|
||||
|
||||
const char* fpga_wirestr(struct fpga_model* model, enum extra_wires wire);
|
||||
str16_t fpga_wirestr_i(struct fpga_model* model, enum extra_wires wire);
|
||||
const char* fpga_wire2str(enum extra_wires wire);
|
||||
str16_t fpga_wire2str_i(struct fpga_model* model, enum extra_wires wire);
|
||||
enum extra_wires fpga_str2wire(const char* str);
|
||||
int fdev_logic_inbit(pinw_idx_t idx);
|
||||
int fdev_logic_outbit(pinw_idx_t idx);
|
||||
|
|
181
model_helper.c
181
model_helper.c
|
@ -743,7 +743,7 @@ const char* logicout_str(enum logicout_wire w)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char* fpga_wirestr(struct fpga_model* model, enum extra_wires wire)
|
||||
const char* fpga_wire2str(enum extra_wires wire)
|
||||
{
|
||||
enum { NUM_BUFS = 8, BUF_SIZE = 64 };
|
||||
static char buf[NUM_BUFS][BUF_SIZE];
|
||||
|
@ -807,9 +807,184 @@ const char* fpga_wirestr(struct fpga_model* model, enum extra_wires wire)
|
|||
return buf[last_buf];
|
||||
}
|
||||
|
||||
str16_t fpga_wirestr_i(struct fpga_model* model, enum extra_wires wire)
|
||||
str16_t fpga_wire2str_i(struct fpga_model* model, enum extra_wires wire)
|
||||
{
|
||||
return strarray_find(&model->str, fpga_wirestr(model, wire));
|
||||
return strarray_find(&model->str, fpga_wire2str(wire));
|
||||
}
|
||||
|
||||
enum extra_wires fpga_str2wire(const char* str)
|
||||
{
|
||||
const char* _str;
|
||||
enum wire_type wtype;
|
||||
int len, num, flags;
|
||||
|
||||
_str = str;
|
||||
if (!strncmp(_str, "INT_IOI_", 8))
|
||||
_str = &_str[8];
|
||||
|
||||
if (!strncmp(_str, "GCLK", 4)) {
|
||||
len = strlen(_str);
|
||||
if (!strcmp(&_str[len-4], "_BRK"))
|
||||
len -= 4;
|
||||
if (len > 4) {
|
||||
num = to_i(&_str[4], len-4);
|
||||
if (num >= 0 && num <= 15)
|
||||
return GCLK0 + num;
|
||||
}
|
||||
}
|
||||
if (!strncmp(_str, "LOGICIN_B", 9)) {
|
||||
len = strlen(&_str[9]);
|
||||
if (len) {
|
||||
switch (to_i(&_str[9], len)) {
|
||||
case X_A1: return LW + LI_A1;
|
||||
case X_A2: return LW + LI_A2;
|
||||
case X_A3: return LW + LI_A3;
|
||||
case X_A4: return LW + LI_A4;
|
||||
case X_A5: return LW + LI_A5;
|
||||
case X_A6: return LW + LI_A6;
|
||||
case X_AX: return LW + LI_AX;
|
||||
case X_B1: return LW + LI_B1;
|
||||
case X_B2: return LW + LI_B2;
|
||||
case X_B3: return LW + LI_B3;
|
||||
case X_B4: return LW + LI_B4;
|
||||
case X_B5: return LW + LI_B5;
|
||||
case X_B6: return LW + LI_B6;
|
||||
case X_BX: return LW + LI_BX;
|
||||
case X_C1: return LW + LI_C1;
|
||||
case X_C2: return LW + LI_C2;
|
||||
case X_C3: return LW + LI_C3;
|
||||
case X_C4: return LW + LI_C4;
|
||||
case X_C5: return LW + LI_C5;
|
||||
case X_C6: return LW + LI_C6;
|
||||
case X_CE: return LW + LI_CE;
|
||||
case X_CX: return LW + LI_CX;
|
||||
case X_D1: return LW + LI_D1;
|
||||
case X_D2: return LW + LI_D2;
|
||||
case X_D3: return LW + LI_D3;
|
||||
case X_D4: return LW + LI_D4;
|
||||
case X_D5: return LW + LI_D5;
|
||||
case X_D6: return LW + LI_D6;
|
||||
case X_DX: return LW + LI_DX;
|
||||
case M_A1: return LW + (LI_A1|LD1);
|
||||
case M_A2: return LW + (LI_A2|LD1);
|
||||
case M_A3: return LW + (LI_A3|LD1);
|
||||
case M_A4: return LW + (LI_A4|LD1);
|
||||
case M_A5: return LW + (LI_A5|LD1);
|
||||
case M_A6: return LW + (LI_A6|LD1);
|
||||
case M_AX: return LW + (LI_AX|LD1);
|
||||
case M_AI: return LW + (LI_AI|LD1);
|
||||
case M_B1: return LW + (LI_B1|LD1);
|
||||
case M_B2: return LW + (LI_B2|LD1);
|
||||
case M_B3: return LW + (LI_B3|LD1);
|
||||
case M_B4: return LW + (LI_B4|LD1);
|
||||
case M_B5: return LW + (LI_B5|LD1);
|
||||
case M_B6: return LW + (LI_B6|LD1);
|
||||
case M_BX: return LW + (LI_BX|LD1);
|
||||
case M_BI: return LW + (LI_BI|LD1);
|
||||
case M_C1: return LW + (LI_C1|LD1);
|
||||
case M_C2: return LW + (LI_C2|LD1);
|
||||
case M_C3: return LW + (LI_C3|LD1);
|
||||
case M_C4: return LW + (LI_C4|LD1);
|
||||
case M_C5: return LW + (LI_C5|LD1);
|
||||
case M_C6: return LW + (LI_C6|LD1);
|
||||
case M_CE: return LW + (LI_CE|LD1);
|
||||
case M_CX: return LW + (LI_CX|LD1);
|
||||
case M_CI: return LW + (LI_CI|LD1);
|
||||
case M_D1: return LW + (LI_D1|LD1);
|
||||
case M_D2: return LW + (LI_D2|LD1);
|
||||
case M_D3: return LW + (LI_D3|LD1);
|
||||
case M_D4: return LW + (LI_D4|LD1);
|
||||
case M_D5: return LW + (LI_D5|LD1);
|
||||
case M_D6: return LW + (LI_D6|LD1);
|
||||
case M_DX: return LW + (LI_DX|LD1);
|
||||
case M_DI: return LW + (LI_DI|LD1);
|
||||
case M_WE: return LW + (LI_WE|LD1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!strncmp(_str, "LOGICOUT", 8)) {
|
||||
len = strlen(&_str[8]);
|
||||
if (len) {
|
||||
switch (to_i(&_str[8], len)) {
|
||||
case M_A: return LW + (LO_A|LD1);
|
||||
case M_AMUX: return LW + (LO_AMUX|LD1);
|
||||
case M_AQ: return LW + (LO_AQ|LD1);
|
||||
case M_B: return LW + (LO_B|LD1);
|
||||
case M_BMUX: return LW + (LO_BMUX|LD1);
|
||||
case M_BQ: return LW + (LO_BQ|LD1);
|
||||
case M_C: return LW + (LO_C|LD1);
|
||||
case M_CMUX: return LW + (LO_CMUX|LD1);
|
||||
case M_CQ: return LW + (LO_CQ|LD1);
|
||||
case M_D: return LW + (LO_D|LD1);
|
||||
case M_DMUX: return LW + (LO_DMUX|LD1);
|
||||
case M_DQ: return LW + (LO_DQ|LD1);
|
||||
case X_A: return LW + LO_A;
|
||||
case X_AMUX: return LW + LO_AMUX;
|
||||
case X_AQ: return LW + LO_AQ;
|
||||
case X_B: return LW + LO_B;
|
||||
case X_BMUX: return LW + LO_BMUX;
|
||||
case X_BQ: return LW + LO_BQ;
|
||||
case X_C: return LW + LO_C;
|
||||
case X_CMUX: return LW + LO_CMUX;
|
||||
case X_CQ: return LW + LO_CQ;
|
||||
case X_D: return LW + LO_D;
|
||||
case X_DMUX: return LW + LO_DMUX;
|
||||
case X_DQ: return LW + LO_DQ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((wtype = base2wire(_str))) {
|
||||
flags = 0;
|
||||
if (_str[3] == 'B')
|
||||
flags |= DIR_BEG;
|
||||
if (_str[3] != 'B' && _str[3] != 'E')
|
||||
HERE();
|
||||
else {
|
||||
if (!strcmp(&_str[4], "_S0")) {
|
||||
num = 0;
|
||||
flags |= DIR_S0;
|
||||
} else if (!strcmp(&_str[4], "_N3")) {
|
||||
num = 3;
|
||||
flags |= DIR_N3;
|
||||
} else switch (_str[4]) {
|
||||
case '0': num = 0; break;
|
||||
case '1': num = 1; break;
|
||||
case '2': num = 2; break;
|
||||
case '3': num = 3; break;
|
||||
default:
|
||||
HERE();
|
||||
num = -1;
|
||||
break;
|
||||
}
|
||||
if (num != -1)
|
||||
return DW + ((wtype*4 + num)|flags);
|
||||
}
|
||||
}
|
||||
if (!strcmp(_str, "GFAN0")) return GFAN0;
|
||||
if (!strcmp(_str, "GFAN1")) return GFAN1;
|
||||
if (!strcmp(_str, "CLK0")) return CLK0;
|
||||
if (!strcmp(_str, "CLK1")) return CLK1;
|
||||
if (!strcmp(_str, "SR0")) return SR0;
|
||||
if (!strcmp(_str, "SR1")) return SR1;
|
||||
if (!strcmp(_str, "GND_WIRE")) return GND_WIRE;
|
||||
if (!strcmp(_str, "VCC_WIRE")) return VCC_WIRE;
|
||||
if (!strcmp(_str, "FAN_B")) return FAN_B;
|
||||
if (!strncmp(_str, "LOGICIN", 7)) {
|
||||
if (!strcmp(&_str[7], "20")) return LOGICIN20;
|
||||
if (!strcmp(&_str[7], "21")) return LOGICIN21;
|
||||
if (!strcmp(&_str[7], "44")) return LOGICIN44;
|
||||
if (!strcmp(&_str[7], "52")) return LOGICIN52;
|
||||
if (!strcmp(&_str[7], "_N21")) return LOGICIN_N21;
|
||||
if (!strcmp(&_str[7], "_N28")) return LOGICIN_N28;
|
||||
if (!strcmp(&_str[7], "_N52")) return LOGICIN_N52;
|
||||
if (!strcmp(&_str[7], "_N60")) return LOGICIN_N60;
|
||||
if (!strcmp(&_str[7], "_S20")) return LOGICIN_S20;
|
||||
if (!strcmp(&_str[7], "_S36")) return LOGICIN_S36;
|
||||
if (!strcmp(&_str[7], "_S44")) return LOGICIN_S44;
|
||||
if (!strcmp(&_str[7], "_S62")) return LOGICIN_S62;
|
||||
}
|
||||
HERE();
|
||||
return NO_WIRE;
|
||||
}
|
||||
|
||||
int fdev_logic_inbit(pinw_idx_t idx)
|
||||
|
|
|
@ -908,6 +908,38 @@ const char* wire_base(enum wire_type w)
|
|||
EXIT(1);
|
||||
}
|
||||
|
||||
enum wire_type base2wire(const char* str)
|
||||
{
|
||||
if (!strncmp(str, "NL1", 3)) return W_NL1;
|
||||
if (!strncmp(str, "NR1", 3)) return W_NR1;
|
||||
if (!strncmp(str, "EL1", 3)) return W_EL1;
|
||||
if (!strncmp(str, "ER1", 3)) return W_ER1;
|
||||
if (!strncmp(str, "SL1", 3)) return W_SL1;
|
||||
if (!strncmp(str, "SR1", 3)) return W_SR1;
|
||||
if (!strncmp(str, "WL1", 3)) return W_WL1;
|
||||
if (!strncmp(str, "WR1", 3)) return W_WR1;
|
||||
|
||||
if (!strncmp(str, "NN2", 3)) return W_NN2;
|
||||
if (!strncmp(str, "NE2", 3)) return W_NE2;
|
||||
if (!strncmp(str, "EE2", 3)) return W_EE2;
|
||||
if (!strncmp(str, "SE2", 3)) return W_SE2;
|
||||
if (!strncmp(str, "SS2", 3)) return W_SS2;
|
||||
if (!strncmp(str, "SW2", 3)) return W_SW2;
|
||||
if (!strncmp(str, "WW2", 3)) return W_WW2;
|
||||
if (!strncmp(str, "NW2", 3)) return W_NW2;
|
||||
|
||||
if (!strncmp(str, "NN4", 3)) return W_NN4;
|
||||
if (!strncmp(str, "NE4", 3)) return W_NE4;
|
||||
if (!strncmp(str, "EE4", 3)) return W_EE4;
|
||||
if (!strncmp(str, "SE4", 3)) return W_SE4;
|
||||
if (!strncmp(str, "SS4", 3)) return W_SS4;
|
||||
if (!strncmp(str, "SW4", 3)) return W_SW4;
|
||||
if (!strncmp(str, "WW4", 3)) return W_WW4;
|
||||
if (!strncmp(str, "NW4", 3)) return W_NW4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rotate_num(int cur, int off, int first, int last)
|
||||
{
|
||||
if (cur+off > last)
|
||||
|
@ -939,8 +971,8 @@ enum wire_type wire_to_len(enum wire_type w, int first_len)
|
|||
EXIT(1);
|
||||
}
|
||||
|
||||
static const char* routing_wirestr(struct fpga_model* model,
|
||||
enum extra_wires wire, int routing_io, int gclk_brk)
|
||||
static const char* routing_wirestr(enum extra_wires wire,
|
||||
int routing_io, int gclk_brk)
|
||||
{
|
||||
if (routing_io) {
|
||||
if (wire == GFAN0) return "INT_IOI_GFAN0";
|
||||
|
@ -969,7 +1001,7 @@ static const char* routing_wirestr(struct fpga_model* model,
|
|||
default: ;
|
||||
}
|
||||
}
|
||||
return fpga_wirestr(model, wire);
|
||||
return fpga_wire2str(wire);
|
||||
}
|
||||
|
||||
static int init_routing_tile(struct fpga_model* model, int y, int x)
|
||||
|
@ -997,7 +1029,7 @@ static int init_routing_tile(struct fpga_model* model, int y, int x)
|
|||
pf("SR%i", i), 0 /* bidir */);
|
||||
if (rc) FAIL(rc);
|
||||
rc = add_switch(model, y, x,
|
||||
"KEEP1_WIRE", routing_wirestr(model, GFAN0+i, routing_io, gclk_brk), 0 /* bidir */);
|
||||
"KEEP1_WIRE", routing_wirestr(GFAN0+i, routing_io, gclk_brk), 0 /* bidir */);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
|
||||
|
@ -1013,14 +1045,14 @@ static int init_routing_tile(struct fpga_model* model, int y, int x)
|
|||
is_bidir = 0;
|
||||
}
|
||||
rc = add_switch(model, y, x,
|
||||
routing_wirestr(model, from_wire, routing_io, gclk_brk),
|
||||
routing_wirestr(model, to_wire, routing_io, gclk_brk),
|
||||
routing_wirestr(from_wire, routing_io, gclk_brk),
|
||||
routing_wirestr(to_wire, routing_io, gclk_brk),
|
||||
is_bidir);
|
||||
if (rc) FAIL(rc);
|
||||
if (is_bidir) {
|
||||
rc = add_switch(model, y, x,
|
||||
routing_wirestr(model, to_wire, routing_io, gclk_brk),
|
||||
routing_wirestr(model, from_wire, routing_io, gclk_brk),
|
||||
routing_wirestr(to_wire, routing_io, gclk_brk),
|
||||
routing_wirestr(from_wire, routing_io, gclk_brk),
|
||||
/* bidir */ 1);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
|
|
23
parts.c
23
parts.c
|
@ -220,6 +220,21 @@ static int wire_decrement(int wire)
|
|||
return wire;
|
||||
}
|
||||
|
||||
static enum extra_wires clean_S0N3(enum extra_wires wire)
|
||||
{
|
||||
int flags;
|
||||
|
||||
if (wire < DW || wire > DW_LAST) return wire;
|
||||
wire -= DW;
|
||||
flags = wire & DIR_FLAGS;
|
||||
wire &= ~DIR_FLAGS;
|
||||
if (flags & DIR_S0 && wire%4 != 0)
|
||||
flags &= ~DIR_S0;
|
||||
if (flags & DIR_N3 && wire%4 != 3)
|
||||
flags &= ~DIR_N3;
|
||||
return DW + (wire | flags);
|
||||
}
|
||||
|
||||
static int src_to_bitpos(struct xc6_routing_bitpos* bitpos, int* cur_el, int max_el,
|
||||
const struct sw_mip_src* src, int src_len)
|
||||
{
|
||||
|
@ -232,8 +247,8 @@ static int src_to_bitpos(struct xc6_routing_bitpos* bitpos, int* cur_el, int max
|
|||
bidir = bidir_check(src[i].m0_sw_to, src[i].from_w[j]);
|
||||
if (bidir != -1) {
|
||||
if (*cur_el >= max_el) FAIL(EINVAL);
|
||||
bitpos[*cur_el].from = src[i].from_w[j];
|
||||
bitpos[*cur_el].to = src[i].m0_sw_to;
|
||||
bitpos[*cur_el].from = clean_S0N3(src[i].from_w[j]);
|
||||
bitpos[*cur_el].to = clean_S0N3(src[i].m0_sw_to);
|
||||
bitpos[*cur_el].bidir = bidir;
|
||||
bitpos[*cur_el].minor = src[i].minor;
|
||||
bitpos[*cur_el].two_bits_o = src[i].m0_two_bits_o;
|
||||
|
@ -245,8 +260,8 @@ static int src_to_bitpos(struct xc6_routing_bitpos* bitpos, int* cur_el, int max
|
|||
bidir = bidir_check(src[i].m1_sw_to, src[i].from_w[j]);
|
||||
if (bidir != -1) {
|
||||
if (*cur_el >= max_el) FAIL(EINVAL);
|
||||
bitpos[*cur_el].from = src[i].from_w[j];
|
||||
bitpos[*cur_el].to = src[i].m1_sw_to;
|
||||
bitpos[*cur_el].from = clean_S0N3(src[i].from_w[j]);
|
||||
bitpos[*cur_el].to = clean_S0N3(src[i].m1_sw_to);
|
||||
bitpos[*cur_el].bidir = bidir;
|
||||
bitpos[*cur_el].minor = src[i].minor;
|
||||
bitpos[*cur_el].two_bits_o = src[i].m1_two_bits_o;
|
||||
|
|
Loading…
Reference in New Issue
Block a user