more clock routing
This commit is contained in:
parent
340d011f06
commit
31b4e9fe11
|
@ -734,7 +734,8 @@ static int test_iologic_switches2(struct test_state* tstate, int iob_y, int iob_
|
||||||
|
|
||||||
if (construct_sw_chain(&chain, tstate->model, switch_to.dest_y,
|
if (construct_sw_chain(&chain, tstate->model, switch_to.dest_y,
|
||||||
switch_to.dest_x, switch_to.dest_connpt, from_to,
|
switch_to.dest_x, switch_to.dest_connpt, from_to,
|
||||||
/*max_depth*/ -1, /*block_list*/ 0, /*block_list_len*/ 0))
|
/*max_depth*/ -1, SWCHAIN_DEFAULT,
|
||||||
|
/*block_list*/ 0, /*block_list_len*/ 0))
|
||||||
FAIL(EINVAL);
|
FAIL(EINVAL);
|
||||||
while (fpga_switch_chain(&chain) != NO_CONN) {
|
while (fpga_switch_chain(&chain) != NO_CONN) {
|
||||||
|
|
||||||
|
@ -1765,7 +1766,7 @@ static int test_clock_routing(struct test_state* tstate)
|
||||||
fdev_iob_input(tstate->model, iob_clk_y, iob_clk_x,
|
fdev_iob_input(tstate->model, iob_clk_y, iob_clk_x,
|
||||||
iob_clk_type_idx, IO_LVCMOS33);
|
iob_clk_type_idx, IO_LVCMOS33);
|
||||||
|
|
||||||
logic_y = 58;
|
logic_y = 65; // down from hclk at 62
|
||||||
logic_x = 13;
|
logic_x = 13;
|
||||||
logic_type_idx = DEV_LOG_M_OR_L;
|
logic_type_idx = DEV_LOG_M_OR_L;
|
||||||
|
|
||||||
|
@ -1818,7 +1819,7 @@ static int test_clock_routing(struct test_state* tstate)
|
||||||
if (!is_aty(Y_ROW_HORIZ_AXSYMM, tstate->model, y))
|
if (!is_aty(Y_ROW_HORIZ_AXSYMM, tstate->model, y))
|
||||||
continue;
|
continue;
|
||||||
logic_type_idx = DEV_LOG_M_OR_L;
|
logic_type_idx = DEV_LOG_M_OR_L;
|
||||||
logic_y = y-3;
|
logic_y = y-3; // up from hclk
|
||||||
for (logic_x = 13; logic_x <= 26; logic_x += 13) {
|
for (logic_x = 13; logic_x <= 26; logic_x += 13) {
|
||||||
fdev_logic_a2d_lut(tstate->model, logic_y, logic_x,
|
fdev_logic_a2d_lut(tstate->model, logic_y, logic_x,
|
||||||
logic_type_idx, LUT_A, 6, "A1", ZTERM);
|
logic_type_idx, LUT_A, 6, "A1", ZTERM);
|
||||||
|
|
|
@ -13,6 +13,7 @@ static uint8_t* get_first_minor(struct fpga_bits* bits, int row, int major)
|
||||||
{
|
{
|
||||||
int i, num_frames;
|
int i, num_frames;
|
||||||
|
|
||||||
|
if (row < 0) { HERE(); return 0; }
|
||||||
num_frames = 0;
|
num_frames = 0;
|
||||||
for (i = 0; i < major; i++)
|
for (i = 0; i < major; i++)
|
||||||
num_frames += get_major_minors(XC6SLX9, i);
|
num_frames += get_major_minors(XC6SLX9, i);
|
||||||
|
@ -593,6 +594,7 @@ static int extract_type2(struct extract_state* es)
|
||||||
|
|
||||||
//
|
//
|
||||||
// find and enable reg-switch for gclk_pin[i]
|
// find and enable reg-switch for gclk_pin[i]
|
||||||
|
// the writing equivalent is in write_inner_term_sw()
|
||||||
//
|
//
|
||||||
|
|
||||||
fpga_find_iob(es->model, es->model->pkg->gclk_pin[i],
|
fpga_find_iob(es->model, es->model->pkg->gclk_pin[i],
|
||||||
|
@ -1907,12 +1909,14 @@ static int extract_center_switches(struct extract_state *es)
|
||||||
RC_RETURN(es->model);
|
RC_RETURN(es->model);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int extract_hclk_switches(struct extract_state *es)
|
static int extract_gclk_center_vert_sw(struct extract_state *es)
|
||||||
{
|
{
|
||||||
int word, cur_row, cur_minor, cur_pin, i, hclk_y;
|
int word, cur_row, cur_minor, cur_pin, i, hclk_y;
|
||||||
uint8_t *ma0_bits;
|
uint8_t *ma0_bits;
|
||||||
|
|
||||||
RC_CHECK(es->model);
|
RC_CHECK(es->model);
|
||||||
|
// Switches in the vertical center column that are routing gclk
|
||||||
|
// signals to the left and right side of the chip.
|
||||||
for (cur_row = 0; cur_row < es->model->die->num_rows; cur_row++) {
|
for (cur_row = 0; cur_row < es->model->die->num_rows; cur_row++) {
|
||||||
hclk_y = row_to_hclk(cur_row, es->model);
|
hclk_y = row_to_hclk(cur_row, es->model);
|
||||||
RC_ASSERT(es->model, hclk_y != -1);
|
RC_ASSERT(es->model, hclk_y != -1);
|
||||||
|
@ -1946,13 +1950,95 @@ static int extract_hclk_switches(struct extract_state *es)
|
||||||
word &= ~(1<<cur_pin);
|
word &= ~(1<<cur_pin);
|
||||||
}
|
}
|
||||||
if (word) HERE();
|
if (word) HERE();
|
||||||
frame_set_pinword(ma0_bits + cur_minor*FRAME_SIZE + 8*8+XC6_HCLK_BYTES, word + 4);
|
frame_set_pinword(ma0_bits + cur_minor*FRAME_SIZE + 8*8+XC6_HCLK_BYTES + 4, word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RC_RETURN(es->model);
|
RC_RETURN(es->model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int extract_gclk_hclk_updown_sw(struct extract_state *es)
|
||||||
|
{
|
||||||
|
int word, cur_row, x, gclk_pin, hclk_y;
|
||||||
|
uint8_t *mi0_bits;
|
||||||
|
|
||||||
|
RC_CHECK(es->model);
|
||||||
|
// Switches in each horizontal hclk row that are routing
|
||||||
|
// gclk signals and and down to the clocked devices.
|
||||||
|
|
||||||
|
// todo: clk access in left and right IO devs, center devs,
|
||||||
|
// bram and macc devs as well as special devs not tested
|
||||||
|
// yet (only XM logic devs tested).
|
||||||
|
for (cur_row = 0; cur_row < es->model->die->num_rows; cur_row++) {
|
||||||
|
hclk_y = row_to_hclk(cur_row, es->model);
|
||||||
|
RC_ASSERT(es->model, hclk_y != -1);
|
||||||
|
for (x = LEFT_IO_ROUTING; x <= es->model->x_width-RIGHT_IO_ROUTING_O; x++) {
|
||||||
|
if (!is_atx(X_ROUTING_COL, es->model, x))
|
||||||
|
continue;
|
||||||
|
mi0_bits = get_first_minor(es->bits, cur_row, es->model->x_major[x]);
|
||||||
|
// each minor (0:15) stores the configuration bits for one gclk
|
||||||
|
// pin (in the hclk bytes of the minor)
|
||||||
|
for (gclk_pin = 0; gclk_pin <= 15; gclk_pin++) {
|
||||||
|
word = frame_get_pinword(mi0_bits + gclk_pin*FRAME_SIZE + XC6_HCLK_POS);
|
||||||
|
if (word & (1<<XC6_HCLK_GCLK_UP_PIN)) {
|
||||||
|
add_yx_switch(es, hclk_y, x,
|
||||||
|
pf("HCLK_GCLK%i_INT", gclk_pin),
|
||||||
|
pf("HCLK_GCLK_UP%i", gclk_pin));
|
||||||
|
word &= ~(1<<XC6_HCLK_GCLK_UP_PIN);
|
||||||
|
}
|
||||||
|
if (word & (1<<XC6_HCLK_GCLK_DOWN_PIN)) {
|
||||||
|
add_yx_switch(es, hclk_y, x,
|
||||||
|
pf("HCLK_GCLK%i_INT", gclk_pin),
|
||||||
|
pf("HCLK_GCLK%i", gclk_pin));
|
||||||
|
word &= ~(1<<XC6_HCLK_GCLK_DOWN_PIN);
|
||||||
|
}
|
||||||
|
if (word) HERE();
|
||||||
|
frame_set_pinword(mi0_bits + gclk_pin*FRAME_SIZE + XC6_HCLK_POS, word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RC_RETURN(es->model);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_hclk_sw(struct fpga_bits *bits, struct fpga_model *model,
|
||||||
|
int y, int x)
|
||||||
|
{
|
||||||
|
uint8_t *mi0_bits;
|
||||||
|
struct fpga_tile *tile;
|
||||||
|
const char *from_str, *to_str;
|
||||||
|
int i, j, gclk_pin_from, gclk_pin_to, up, word;
|
||||||
|
|
||||||
|
RC_CHECK(model);
|
||||||
|
|
||||||
|
mi0_bits = get_first_minor(bits, which_row(y, model), model->x_major[x]);
|
||||||
|
RC_ASSERT(model, mi0_bits);
|
||||||
|
|
||||||
|
tile = YX_TILE(model, y, x);
|
||||||
|
for (i = 0; i < tile->num_switches; i++) {
|
||||||
|
if (!(tile->switches[i] & SWITCH_USED))
|
||||||
|
continue;
|
||||||
|
from_str = fpga_switch_str(model, y, x, i, SW_FROM);
|
||||||
|
to_str = fpga_switch_str(model, y, x, i, SW_TO);
|
||||||
|
|
||||||
|
j = sscanf(from_str, "HCLK_GCLK%i_INT", &gclk_pin_from);
|
||||||
|
RC_ASSERT(model, j == 1);
|
||||||
|
j = sscanf(to_str, "HCLK_GCLK%i", &gclk_pin_to);
|
||||||
|
if (j == 1)
|
||||||
|
up = 0; // down
|
||||||
|
else {
|
||||||
|
j = sscanf(to_str, "HCLK_GCLK_UP%i", &gclk_pin_to);
|
||||||
|
RC_ASSERT(model, j == 1);
|
||||||
|
up = 1;
|
||||||
|
}
|
||||||
|
RC_ASSERT(model, gclk_pin_from == gclk_pin_to);
|
||||||
|
|
||||||
|
word = frame_get_pinword(mi0_bits + gclk_pin_from*FRAME_SIZE + XC6_HCLK_POS);
|
||||||
|
word |= 1 << (up ? XC6_HCLK_GCLK_UP_PIN : XC6_HCLK_GCLK_DOWN_PIN);
|
||||||
|
frame_set_pinword(mi0_bits + gclk_pin_from*FRAME_SIZE + XC6_HCLK_POS, word);
|
||||||
|
}
|
||||||
|
RC_RETURN(model);
|
||||||
|
}
|
||||||
|
|
||||||
static int extract_switches(struct extract_state *es)
|
static int extract_switches(struct extract_state *es)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
|
@ -1979,7 +2065,8 @@ static int extract_switches(struct extract_state *es)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extract_center_switches(es);
|
extract_center_switches(es);
|
||||||
extract_hclk_switches(es);
|
extract_gclk_center_vert_sw(es);
|
||||||
|
extract_gclk_hclk_updown_sw(es);
|
||||||
RC_RETURN(es->model);
|
RC_RETURN(es->model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2245,12 +2332,99 @@ fail:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int write_inner_term_sw(struct fpga_bits *bits,
|
||||||
|
struct fpga_model *model, int y, int x)
|
||||||
|
{
|
||||||
|
struct fpga_tile *tile;
|
||||||
|
const char *from_str, *from_found, *to_str, *to_found;
|
||||||
|
int i, j, from_idx, to_idx;
|
||||||
|
|
||||||
|
RC_CHECK(model);
|
||||||
|
|
||||||
|
tile = YX_TILE(model, y, x);
|
||||||
|
for (i = 0; i < tile->num_switches; i++) {
|
||||||
|
if (!(tile->switches[i] & SWITCH_USED))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
from_str = fpga_switch_str(model, y, x, i, SW_FROM);
|
||||||
|
to_str = fpga_switch_str(model, y, x, i, SW_TO);
|
||||||
|
RC_ASSERT(model, from_str && to_str);
|
||||||
|
|
||||||
|
if (strstr(from_str, "IBUF")
|
||||||
|
&& strstr(to_str, "CLKPIN"))
|
||||||
|
continue;
|
||||||
|
if ((from_found = strstr(from_str, "CLKPIN"))
|
||||||
|
&& (to_found = strstr(to_str, "CKPIN"))) {
|
||||||
|
struct switch_to_yx_l2 switch_to_yx_l2;
|
||||||
|
int iob_y, iob_x, iob_idx;
|
||||||
|
struct fpga_device *iob_dev;
|
||||||
|
|
||||||
|
from_idx = atoi(&from_found[6]);
|
||||||
|
to_idx = atoi(&to_found[5]);
|
||||||
|
RC_ASSERT(model, from_idx == to_idx);
|
||||||
|
|
||||||
|
// follow switches backwards to IOB
|
||||||
|
switch_to_yx_l2.l1.yx_req = YX_DEV_IOB;
|
||||||
|
switch_to_yx_l2.l1.flags = SWTO_YX_DEF;
|
||||||
|
switch_to_yx_l2.l1.model = model;
|
||||||
|
switch_to_yx_l2.l1.y = y;
|
||||||
|
switch_to_yx_l2.l1.x = x;
|
||||||
|
switch_to_yx_l2.l1.start_switch = fpga_switch_str_i(model, y, x, i, SW_TO);
|
||||||
|
switch_to_yx_l2.l1.from_to = SW_TO;
|
||||||
|
fpga_switch_to_yx_l2(&switch_to_yx_l2);
|
||||||
|
RC_ASSERT(model, switch_to_yx_l2.l1.set.len);
|
||||||
|
|
||||||
|
// find matching gclk pin
|
||||||
|
for (j = 0; j < model->pkg->num_gclk_pins; j++) {
|
||||||
|
if (!model->pkg->gclk_pin[j])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fpga_find_iob(model, model->pkg->gclk_pin[j],
|
||||||
|
&iob_y, &iob_x, &iob_idx);
|
||||||
|
RC_CHECK(model);
|
||||||
|
if (iob_y != switch_to_yx_l2.l1.dest_y
|
||||||
|
|| iob_x != switch_to_yx_l2.l1.dest_x)
|
||||||
|
continue;
|
||||||
|
iob_dev = fdev_p(model, iob_y, iob_x, DEV_IOB, iob_idx);
|
||||||
|
RC_ASSERT(model, iob_dev);
|
||||||
|
|
||||||
|
if (fpga_switch_lookup(model, iob_y, iob_x,
|
||||||
|
iob_dev->pinw[IOB_OUT_I],
|
||||||
|
switch_to_yx_l2.l1.dest_connpt) != NO_SWITCH)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// set bit
|
||||||
|
if (j < model->pkg->num_gclk_pins) {
|
||||||
|
uint16_t u16;
|
||||||
|
int bits_off;
|
||||||
|
|
||||||
|
bits_off = IOB_DATA_START
|
||||||
|
+ model->pkg->gclk_type2_o[j]*XC6_WORD_BYTES
|
||||||
|
+ XC6_TYPE2_GCLK_REG_SW/XC6_WORD_BITS;
|
||||||
|
u16 = frame_get_u16(&bits->d[bits_off]);
|
||||||
|
u16 |= 1<<(XC6_TYPE2_GCLK_REG_SW%XC6_WORD_BITS);
|
||||||
|
frame_set_u16(&bits->d[bits_off], u16);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// fall-through to unsupported
|
||||||
|
}
|
||||||
|
fprintf(stderr, "#E %s:%i unsupported switch "
|
||||||
|
"y%i x%i %s -> %s\n", __FILE__, __LINE__,
|
||||||
|
y, x, from_str, to_str);
|
||||||
|
}
|
||||||
|
RC_RETURN(model);
|
||||||
|
}
|
||||||
|
|
||||||
static int write_switches(struct fpga_bits* bits, struct fpga_model* model)
|
static int write_switches(struct fpga_bits* bits, struct fpga_model* model)
|
||||||
{
|
{
|
||||||
struct fpga_tile* tile;
|
struct fpga_tile* tile;
|
||||||
int x, y, i, rc;
|
int x, y, i;
|
||||||
|
|
||||||
RC_CHECK(model);
|
RC_CHECK(model);
|
||||||
|
// We need to identify and take out each enabled switch, whether it
|
||||||
|
// leads to enabled bits or not. That way we can print unsupported
|
||||||
|
// switches at the end and keep our model alive and maintainable
|
||||||
|
// over time.
|
||||||
for (x = 0; x < model->x_width; x++) {
|
for (x = 0; x < model->x_width; x++) {
|
||||||
for (y = 0; y < model->y_height; y++) {
|
for (y = 0; y < model->y_height; y++) {
|
||||||
if (is_atx(X_ROUTING_COL, model, x)
|
if (is_atx(X_ROUTING_COL, model, x)
|
||||||
|
@ -2258,20 +2432,25 @@ static int write_switches(struct fpga_bits* bits, struct fpga_model* model)
|
||||||
&& y < model->y_height-BOT_IO_TILES
|
&& y < model->y_height-BOT_IO_TILES
|
||||||
&& !is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS,
|
&& !is_aty(Y_ROW_HORIZ_AXSYMM|Y_CHIP_HORIZ_REGS,
|
||||||
model, y)) {
|
model, y)) {
|
||||||
rc = write_routing_sw(bits, model, y, x);
|
write_routing_sw(bits, model, y, x);
|
||||||
if (rc) FAIL(rc);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (is_atyx(YX_DEV_ILOGIC, model, y, x)) {
|
if (is_atyx(YX_DEV_ILOGIC, model, y, x)) {
|
||||||
rc = write_iologic_sw(bits, model, y, x);
|
write_iologic_sw(bits, model, y, x);
|
||||||
if (rc) FAIL(rc);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// todo: there are probably switches in logic and
|
|
||||||
// iob that need bits, and switches in other
|
|
||||||
// tiles that need no bits...
|
|
||||||
if (is_atyx(YX_DEV_LOGIC|YX_DEV_IOB, model, y, x))
|
if (is_atyx(YX_DEV_LOGIC|YX_DEV_IOB, model, y, x))
|
||||||
continue;
|
continue;
|
||||||
|
if (is_atx(X_ROUTING_COL, model, x)
|
||||||
|
&& is_aty(Y_ROW_HORIZ_AXSYMM, model, y)) {
|
||||||
|
write_hclk_sw(bits, model, y, x);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_atyx(YX_INNER_TERM, model, y, x)) {
|
||||||
|
write_inner_term_sw(bits, model, y, x);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// print unsupported switches
|
||||||
tile = YX_TILE(model, y, x);
|
tile = YX_TILE(model, y, x);
|
||||||
for (i = 0; i < tile->num_switches; i++) {
|
for (i = 0; i < tile->num_switches; i++) {
|
||||||
if (!(tile->switches[i] & SWITCH_USED))
|
if (!(tile->switches[i] & SWITCH_USED))
|
||||||
|
@ -2283,9 +2462,7 @@ static int write_switches(struct fpga_bits* bits, struct fpga_model* model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
RC_RETURN(model);
|
||||||
fail:
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_logic(struct fpga_bits* bits, struct fpga_model* model)
|
static int write_logic(struct fpga_bits* bits, struct fpga_model* model)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
|
|
||||||
#undef DBG_ENUM_SWITCH
|
#undef DBG_ENUM_SWITCH
|
||||||
|
#undef DBG_SWITCH_CONNS
|
||||||
#undef DBG_SWITCH_TO_YX
|
#undef DBG_SWITCH_TO_YX
|
||||||
#undef DBG_SWITCH_TO_REL
|
#undef DBG_SWITCH_TO_REL
|
||||||
|
|
||||||
|
@ -1580,13 +1581,14 @@ const char* fmt_swset(struct fpga_model* model, int y, int x,
|
||||||
|
|
||||||
int construct_sw_chain(struct sw_chain* chain, struct fpga_model* model,
|
int construct_sw_chain(struct sw_chain* chain, struct fpga_model* model,
|
||||||
int y, int x, str16_t start_switch, int from_to, int max_depth,
|
int y, int x, str16_t start_switch, int from_to, int max_depth,
|
||||||
swidx_t* block_list, int block_list_len)
|
int flags, swidx_t* block_list, int block_list_len)
|
||||||
{
|
{
|
||||||
RC_CHECK(model);
|
RC_CHECK(model);
|
||||||
#ifdef DBG_ENUM_SWITCH
|
#ifdef DBG_ENUM_SWITCH
|
||||||
printf("construct_sw_chain() %s (%s)\n",
|
printf("construct_sw_chain() %s (%s) flags %Xh\n",
|
||||||
strarray_lookup(&model->str, start_switch),
|
strarray_lookup(&model->str, start_switch),
|
||||||
(from_to == SW_FROM) ? "SW_FROM" : "SW_TO");
|
(from_to == SW_FROM) ? "SW_FROM" : "SW_TO",
|
||||||
|
flags);
|
||||||
#endif
|
#endif
|
||||||
memset(chain, 0, sizeof(*chain));
|
memset(chain, 0, sizeof(*chain));
|
||||||
chain->model = model;
|
chain->model = model;
|
||||||
|
@ -1594,6 +1596,7 @@ int construct_sw_chain(struct sw_chain* chain, struct fpga_model* model,
|
||||||
chain->x = x;
|
chain->x = x;
|
||||||
chain->from_to = from_to;
|
chain->from_to = from_to;
|
||||||
chain->max_depth = (max_depth < 0) ? SW_SET_SIZE : max_depth;
|
chain->max_depth = (max_depth < 0) ? SW_SET_SIZE : max_depth;
|
||||||
|
chain->flags = flags;
|
||||||
if (block_list) {
|
if (block_list) {
|
||||||
chain->block_list = block_list;
|
chain->block_list = block_list;
|
||||||
chain->block_list_len = block_list_len;
|
chain->block_list_len = block_list_len;
|
||||||
|
@ -1665,7 +1668,8 @@ int fpga_switch_chain(struct sw_chain* ch)
|
||||||
if (idx == NO_SWITCH)
|
if (idx == NO_SWITCH)
|
||||||
break;
|
break;
|
||||||
ch->set.sw[ch->set.len-1] = idx;
|
ch->set.sw[ch->set.len-1] = idx;
|
||||||
if (!fpga_switch_is_used(ch->model, ch->y, ch->x, idx)
|
if ((!(ch->flags & SWCHAIN_EXCLUDING_USED)
|
||||||
|
|| !fpga_switch_is_used(ch->model, ch->y, ch->x, idx))
|
||||||
&& switch_list_contains(ch->model, ch->y, ch->x,
|
&& switch_list_contains(ch->model, ch->y, ch->x,
|
||||||
ch->block_list, ch->block_list_len, idx)
|
ch->block_list, ch->block_list_len, idx)
|
||||||
== NO_SWITCH)
|
== NO_SWITCH)
|
||||||
|
@ -1718,7 +1722,8 @@ int fpga_switch_chain(struct sw_chain* ch)
|
||||||
ch->model, ch->y, ch->x,
|
ch->model, ch->y, ch->x,
|
||||||
child_from_to));
|
child_from_to));
|
||||||
#endif
|
#endif
|
||||||
if (fpga_switch_is_used(ch->model, ch->y, ch->x, idx))
|
if (ch->flags & SWCHAIN_EXCLUDING_USED
|
||||||
|
&& fpga_switch_is_used(ch->model, ch->y, ch->x, idx))
|
||||||
level_down = 0;
|
level_down = 0;
|
||||||
|
|
||||||
if (level_down) {
|
if (level_down) {
|
||||||
|
@ -1784,7 +1789,8 @@ int fpga_switch_chain(struct sw_chain* ch)
|
||||||
ch->model, ch->y, ch->x,
|
ch->model, ch->y, ch->x,
|
||||||
ch->set.sw[ch->set.len-1], ch->from_to);
|
ch->set.sw[ch->set.len-1], ch->from_to);
|
||||||
if (ch->set.sw[ch->set.len-1] != NO_SWITCH) {
|
if (ch->set.sw[ch->set.len-1] != NO_SWITCH) {
|
||||||
if (fpga_switch_is_used(ch->model, ch->y,
|
if (ch->flags & SWCHAIN_EXCLUDING_USED
|
||||||
|
&& fpga_switch_is_used(ch->model, ch->y,
|
||||||
ch->x, ch->set.sw[ch->set.len-1])) {
|
ch->x, ch->set.sw[ch->set.len-1])) {
|
||||||
#ifdef DBG_ENUM_SWITCH
|
#ifdef DBG_ENUM_SWITCH
|
||||||
printf(" skipping used %s\n",
|
printf(" skipping used %s\n",
|
||||||
|
@ -1822,7 +1828,8 @@ int construct_sw_conns(struct sw_conns* conns, struct fpga_model* model,
|
||||||
RC_CHECK(model);
|
RC_CHECK(model);
|
||||||
memset(conns, 0, sizeof(*conns));
|
memset(conns, 0, sizeof(*conns));
|
||||||
construct_sw_chain(&conns->chain, model, y, x, start_switch,
|
construct_sw_chain(&conns->chain, model, y, x, start_switch,
|
||||||
from_to, max_depth, /*block_list*/ 0, /*block_list_len*/ 0);
|
from_to, max_depth, SWCHAIN_DEFAULT,
|
||||||
|
/*block_list*/ 0, /*block_list_len*/ 0);
|
||||||
RC_RETURN(model);
|
RC_RETURN(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1838,11 +1845,18 @@ int fpga_switch_conns(struct sw_conns* conns)
|
||||||
|
|
||||||
if (!conns->chain.set.len) { HERE(); goto internal_error; }
|
if (!conns->chain.set.len) { HERE(); goto internal_error; }
|
||||||
|
|
||||||
|
#ifdef DBG_SWITCH_TO_YX
|
||||||
|
printf("fpga_switch_conns() dest_i %i num_dests %i\n", conns->dest_i, conns->num_dests);
|
||||||
|
#endif
|
||||||
// on the first call, both dest_i and num_dests are 0
|
// on the first call, both dest_i and num_dests are 0
|
||||||
while (conns->dest_i >= conns->num_dests) {
|
while (conns->dest_i >= conns->num_dests) {
|
||||||
fpga_switch_chain(&conns->chain);
|
fpga_switch_chain(&conns->chain);
|
||||||
if (conns->chain.set.len == 0)
|
if (conns->chain.set.len == 0) {
|
||||||
|
#ifdef DBG_SWITCH_TO_YX
|
||||||
|
printf(" no more switches\n");
|
||||||
|
#endif
|
||||||
return NO_CONN;
|
return NO_CONN;
|
||||||
|
}
|
||||||
end_of_chain_str = fpga_switch_str_i(conns->chain.model,
|
end_of_chain_str = fpga_switch_str_i(conns->chain.model,
|
||||||
conns->chain.y, conns->chain.x,
|
conns->chain.y, conns->chain.x,
|
||||||
conns->chain.set.sw[conns->chain.set.len-1],
|
conns->chain.set.sw[conns->chain.set.len-1],
|
||||||
|
@ -1853,8 +1867,17 @@ int fpga_switch_conns(struct sw_conns* conns)
|
||||||
fpga_connpt_find(conns->chain.model, conns->chain.y,
|
fpga_connpt_find(conns->chain.model, conns->chain.y,
|
||||||
conns->chain.x, end_of_chain_str,
|
conns->chain.x, end_of_chain_str,
|
||||||
&conns->connpt_dest_start, &conns->num_dests);
|
&conns->connpt_dest_start, &conns->num_dests);
|
||||||
if (conns->num_dests)
|
if (conns->num_dests) {
|
||||||
|
#ifdef DBG_SWITCH_TO_YX
|
||||||
|
printf(" %s: %i conns\n", strarray_lookup(&conns->chain.model->str,
|
||||||
|
end_of_chain_str), conns->num_dests);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
#ifdef DBG_SWITCH_TO_YX
|
||||||
|
printf(" %s: no conns\n", strarray_lookup(
|
||||||
|
&conns->chain.model->str, end_of_chain_str));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
fpga_conn_dest(conns->chain.model, conns->chain.y, conns->chain.x,
|
fpga_conn_dest(conns->chain.model, conns->chain.y, conns->chain.x,
|
||||||
conns->connpt_dest_start + conns->dest_i,
|
conns->connpt_dest_start + conns->dest_i,
|
||||||
|
@ -1880,6 +1903,7 @@ void printf_swchain(struct fpga_model* model, int y, int x,
|
||||||
y, x, strarray_lookup(&model->str, sw),
|
y, x, strarray_lookup(&model->str, sw),
|
||||||
block_list_len ? *block_list_len : 0);
|
block_list_len ? *block_list_len : 0);
|
||||||
if (construct_sw_chain(&chain, model, y, x, sw, from_to, max_depth,
|
if (construct_sw_chain(&chain, model, y, x, sw, from_to, max_depth,
|
||||||
|
SWCHAIN_DEFAULT,
|
||||||
block_list, block_list_len ? *block_list_len : 0))
|
block_list, block_list_len ? *block_list_len : 0))
|
||||||
{ HERE(); return; }
|
{ HERE(); return; }
|
||||||
while (fpga_switch_chain(&chain) != NO_CONN) {
|
while (fpga_switch_chain(&chain) != NO_CONN) {
|
||||||
|
|
|
@ -203,6 +203,9 @@ const char* fmt_swset(struct fpga_model* model, int y, int x,
|
||||||
// of switches in a tile, currently 3459 in a slx9 routing tile.
|
// of switches in a tile, currently 3459 in a slx9 routing tile.
|
||||||
#define MAX_SWITCHBOX_SIZE 4000
|
#define MAX_SWITCHBOX_SIZE 4000
|
||||||
|
|
||||||
|
#define SWCHAIN_DEFAULT 0
|
||||||
|
#define SWCHAIN_EXCLUDING_USED 0x0001
|
||||||
|
|
||||||
struct sw_chain
|
struct sw_chain
|
||||||
{
|
{
|
||||||
// start and recurring values:
|
// start and recurring values:
|
||||||
|
@ -211,6 +214,7 @@ struct sw_chain
|
||||||
int x;
|
int x;
|
||||||
int from_to;
|
int from_to;
|
||||||
int max_depth;
|
int max_depth;
|
||||||
|
int flags;
|
||||||
//
|
//
|
||||||
// block_list works as if all switches from or to the ones
|
// block_list works as if all switches from or to the ones
|
||||||
// on the block list are blocked, that is the recursion will
|
// on the block list are blocked, that is the recursion will
|
||||||
|
@ -233,7 +237,7 @@ struct sw_chain
|
||||||
|
|
||||||
int construct_sw_chain(struct sw_chain* chain, struct fpga_model* model,
|
int construct_sw_chain(struct sw_chain* chain, struct fpga_model* model,
|
||||||
int y, int x, str16_t start_switch, int from_to, int max_depth,
|
int y, int x, str16_t start_switch, int from_to, int max_depth,
|
||||||
swidx_t* block_list, int block_list_len);
|
int flags, swidx_t* block_list, int block_list_len);
|
||||||
void destruct_sw_chain(struct sw_chain* chain);
|
void destruct_sw_chain(struct sw_chain* chain);
|
||||||
|
|
||||||
// Returns 0 if another switchset is returned in chain, or
|
// Returns 0 if another switchset is returned in chain, or
|
||||||
|
|
|
@ -292,10 +292,9 @@ int is_atx(int check, struct fpga_model* model, int x);
|
||||||
// outside_of_routing is true for anything outside of the outer
|
// outside_of_routing is true for anything outside of the outer
|
||||||
// boundary of the regular routing area.
|
// boundary of the regular routing area.
|
||||||
#define YX_OUTSIDE_OF_ROUTING 0x0400
|
#define YX_OUTSIDE_OF_ROUTING 0x0400
|
||||||
#define YX_ROUTING_BOUNDARY 0x0800
|
#define YX_X_CENTER_CMTPLL 0x0800
|
||||||
#define YX_X_CENTER_CMTPLL 0x1000
|
#define YX_Y_CENTER 0x1000
|
||||||
#define YX_Y_CENTER 0x2000
|
#define YX_CENTER 0x2000
|
||||||
#define YX_CENTER 0x4000
|
|
||||||
|
|
||||||
int is_atyx(int check, struct fpga_model* model, int y, int x);
|
int is_atyx(int check, struct fpga_model* model, int y, int x);
|
||||||
|
|
||||||
|
|
|
@ -732,10 +732,6 @@ int is_atyx(int check, struct fpga_model* model, int y, int x)
|
||||||
|| x > model->x_width-RIGHT_IO_ROUTING_O
|
|| x > model->x_width-RIGHT_IO_ROUTING_O
|
||||||
|| y <= TOP_INNER_ROW
|
|| y <= TOP_INNER_ROW
|
||||||
|| y >= model->y_height-BOT_INNER_ROW )) return 1;
|
|| y >= model->y_height-BOT_INNER_ROW )) return 1;
|
||||||
if (check & YX_ROUTING_BOUNDARY
|
|
||||||
&& is_atyx(YX_ROUTING_TILE, model, y, x)
|
|
||||||
&& (x == LEFT_IO_ROUTING || x == model->x_width-RIGHT_IO_ROUTING_O
|
|
||||||
|| y == TOP_FIRST_REGULAR || y == model->y_height-BOT_LAST_REGULAR_O)) return 1;
|
|
||||||
if (check & YX_X_CENTER_CMTPLL
|
if (check & YX_X_CENTER_CMTPLL
|
||||||
&& is_atx(X_CENTER_CMTPLL_COL, model, x)) return 1;
|
&& is_atx(X_CENTER_CMTPLL_COL, model, x)) return 1;
|
||||||
if (check & YX_Y_CENTER
|
if (check & YX_Y_CENTER
|
||||||
|
@ -1905,6 +1901,29 @@ enum extra_wires fpga_str2wire(const char* str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
if ((wtype = base2wire(_str))) {
|
if ((wtype = base2wire(_str))) {
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (_str[3] == 'B')
|
if (_str[3] == 'B')
|
||||||
|
@ -1932,29 +1951,6 @@ enum extra_wires fpga_str2wire(const char* str)
|
||||||
return DW + ((wtype*4 + num)|flags);
|
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();
|
HERE();
|
||||||
return NO_WIRE;
|
return NO_WIRE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1308,7 +1308,7 @@ enum wire_type base2wire(const char* str)
|
||||||
if (!strncmp(str, "WW4", 3)) return W_WW4;
|
if (!strncmp(str, "WW4", 3)) return W_WW4;
|
||||||
if (!strncmp(str, "NW4", 3)) return W_NW4;
|
if (!strncmp(str, "NW4", 3)) return W_NW4;
|
||||||
|
|
||||||
HERE();
|
fprintf(stderr, "#E %s:%i base2wire() %s unknown\n", __FILE__, __LINE__, str);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,9 +130,13 @@ const struct xc6_pkg_info *xc6_pkg_info(enum xc6_pkg pkg);
|
||||||
#define XC6_WORD_BYTES 2
|
#define XC6_WORD_BYTES 2
|
||||||
#define XC6_WORD_BITS (XC6_WORD_BYTES*8)
|
#define XC6_WORD_BITS (XC6_WORD_BYTES*8)
|
||||||
|
|
||||||
|
#define XC6_HCLK_POS 64
|
||||||
#define XC6_HCLK_BYTES 2
|
#define XC6_HCLK_BYTES 2
|
||||||
#define XC6_HCLK_BITS (XC6_HCLK_BYTES*8)
|
#define XC6_HCLK_BITS (XC6_HCLK_BYTES*8)
|
||||||
|
|
||||||
|
#define XC6_HCLK_GCLK_UP_PIN 0
|
||||||
|
#define XC6_HCLK_GCLK_DOWN_PIN 1
|
||||||
|
|
||||||
#define XC6_NULL_MAJOR 0
|
#define XC6_NULL_MAJOR 0
|
||||||
|
|
||||||
#define XC6_IOB_MASK_IO 0x00FF00FFFF000000
|
#define XC6_IOB_MASK_IO 0x00FF00FFFF000000
|
||||||
|
|
Loading…
Reference in New Issue
Block a user