switch cleanup - nice code savings!

This commit is contained in:
Wolfgang Spraul 2012-09-16 14:45:54 +02:00
parent 2eeedfd5c8
commit 81e9f80f55
7 changed files with 227 additions and 1023 deletions

View File

@ -439,17 +439,12 @@ fail:
return rc;
}
static int construct_extract_state(struct extract_state* es, struct fpga_model* model)
static int construct_extract_state(struct extract_state* es,
struct fpga_model* model)
{
int rc;
memset(es, 0, sizeof(*es));
es->model = model;
if (model->first_routing_y == -1)
FAIL(EINVAL);
return 0;
fail:
return rc;
}
int extract_model(struct fpga_model* model, struct fpga_bits* bits)

146
control.c
View File

@ -344,83 +344,6 @@ str16_t fdev_logic_pinstr_i(struct fpga_model* model, pinw_idx_t idx, int ld1_ty
return str_i;
}
int fdev_logic_inbit(pinw_idx_t idx)
{
if (idx & LD1) {
idx &= ~LD1;
if (idx >= LI_A1 && idx <= LI_C6)
return M_A1 + (idx/6)*8+idx%6;
if (idx >= LI_D1 && idx <= LI_D6)
return M_D1 + (idx-LI_D1);
switch (idx) {
case LI_AX: return M_AX;
case LI_BX: return M_BX;
case LI_CE: return M_CE;
case LI_CX: return M_CX;
case LI_DX: return M_DX;
case LI_AI: return M_AI;
case LI_BI: return M_BI;
case LI_CI: return M_CI;
case LI_DI: return M_DI;
case LI_WE: return M_WE;
}
HERE();
return -1;
}
if (idx >= LI_A1 && idx <= LI_C6)
return X_A1 + (idx/6)*7+idx%6;
else if (idx >= LI_D1 && idx <= LI_D6)
return X_D1 + (idx-LI_D1);
else switch (idx) {
case LI_AX: return X_AX;
case LI_BX: return X_BX;
case LI_CE: return X_CE;
case LI_CX: return X_CX;
case LI_DX: return X_DX;
}
HERE();
return -1;
}
int fdev_logic_outbit(pinw_idx_t idx)
{
if (idx & LD1) {
idx &= ~LD1;
switch (idx) {
case LO_A: return M_A;
case LO_AMUX: return M_AMUX;
case LO_AQ: return M_AQ;
case LO_B: return M_B;
case LO_BMUX: return M_BMUX;
case LO_BQ: return M_BQ;
case LO_C: return M_C;
case LO_CMUX: return M_CMUX;
case LO_CQ: return M_CQ;
case LO_D: return M_D;
case LO_DMUX: return M_DMUX;
case LO_DQ: return M_DQ;
}
HERE();
return -1;
}
switch (idx) {
case LO_A: return X_A;
case LO_AMUX: return X_AMUX;
case LO_AQ: return X_AQ;
case LO_B: return X_B;
case LO_BMUX: return X_BMUX;
case LO_BQ: return X_BQ;
case LO_C: return X_C;
case LO_CMUX: return X_CMUX;
case LO_CQ: return X_CQ;
case LO_D: return X_D;
case LO_DMUX: return X_DMUX;
case LO_DQ: return X_DQ;
}
HERE();
return -1;
}
static int reset_required_pins(struct fpga_device* dev)
{
int rc;
@ -1827,72 +1750,3 @@ void fprintf_net(FILE* f, struct fpga_model* model, net_idx_t net_i)
net->el[i].x, net->el[i].idx));
}
}
const char* fpga_wirestr(struct fpga_model* model, enum extra_wires wire)
{
enum { NUM_BUFS = 8, BUF_SIZE = 64 };
static char buf[NUM_BUFS][BUF_SIZE];
static int last_buf = 0;
switch (wire) {
case GFAN0: return "GFAN0";
case GFAN1: return "GFAN1";
case CLK0: return "CLK0";
case CLK1: return "CLK1";
case SR0: return "SR0";
case SR1: return "SR1";
case GND_WIRE: return "GND_WIRE";
case VCC_WIRE: return "VCC_WIRE";
case FAN_B: return "FAN_B";
case LOGICIN20: return "LOGICIN20";
case LOGICIN21: return "LOGICIN21";
case LOGICIN44: return "LOGICIN44";
case LOGICIN52: return "LOGICIN52";
case LOGICIN_N21: return "LOGICIN_N21";
case LOGICIN_N28: return "LOGICIN_N28";
case LOGICIN_N52: return "LOGICIN_N52";
case LOGICIN_N60: return "LOGICIN_N60";
case LOGICIN_S20: return "LOGICIN_S20";
case LOGICIN_S36: return "LOGICIN_S36";
case LOGICIN_S44: return "LOGICIN_S44";
case LOGICIN_S62: return "LOGICIN_S62";
default: ;
}
last_buf = (last_buf+1)%NUM_BUFS;
buf[last_buf][0] = 0;
if (wire >= GCLK0 && wire <= GCLK15)
snprintf(buf[last_buf], sizeof(buf[0]), "GCLK%i", wire-GCLK0);
else if (wire >= DW && wire <= DW_LAST) {
char beg_end;
int flags;
wire -= DW;
flags = wire & DIR_FLAGS;
wire &= ~DIR_FLAGS;
beg_end = (flags & DIR_BEG) ? 'B' : 'E';
if (flags & DIR_S0 && wire%4 == 0)
snprintf(buf[last_buf], sizeof(buf[0]),
"%s%c_S0", wire_base(wire/4), beg_end);
else if (flags & DIR_N3 && wire%4 == 3)
snprintf(buf[last_buf], sizeof(buf[0]),
"%s%c_N3", wire_base(wire/4), beg_end);
else
snprintf(buf[last_buf], sizeof(buf[0]),
"%s%c%i", wire_base(wire/4), beg_end, wire%4);
} else if (wire >= LW && wire <= LW_LAST) {
wire -= LW;
if ((wire&(~LD1)) >= LI_FIRST && (wire&(~LD1)) <= LI_LAST)
snprintf(buf[last_buf], sizeof(buf[0]), "LOGICIN_B%i", fdev_logic_inbit(wire));
else if ((wire&(~LD1)) >= LO_FIRST && (wire&(~LD1)) <= LO_LAST)
snprintf(buf[last_buf], sizeof(buf[0]), "LOGICOUT%i", fdev_logic_outbit(wire));
else HERE();
} else HERE();
return buf[last_buf];
}
str16_t fpga_wirestr_i(struct fpga_model* model, enum extra_wires wire)
{
return strarray_find(&model->str, fpga_wirestr(model, wire));
}

View File

@ -44,8 +44,6 @@ const char* fdev_pinw_idx2str(int devtype, pinw_idx_t idx);
// the second logic device (L or M).
const char* fdev_logic_pinstr(pinw_idx_t idx, int ld1_type);
str16_t fdev_logic_pinstr_i(struct fpga_model* model, pinw_idx_t idx, int ld1_type);
int fdev_logic_inbit(pinw_idx_t idx);
int fdev_logic_outbit(pinw_idx_t idx);
// lut_a2d is LUT_A to LUT_D value, lut_5or6 is int 5 or int 6.
int fdev_logic_set_lut(struct fpga_model* model, int y, int x, int type_idx,
@ -327,5 +325,3 @@ void fpga_net_free_all(struct fpga_model* model);
void fprintf_net(FILE* f, struct fpga_model* model, net_idx_t net_i);
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);

View File

@ -74,7 +74,6 @@ struct fpga_model
struct xc6_routing_bitpos* sw_bitpos;
int num_bitpos;
int first_routing_y, first_routing_x;
struct fpga_tile* tiles;
struct hashed_strarray str;
@ -824,3 +823,8 @@ enum extra_wires {
// can be OR'ed to the LI or LO value.
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);
int fdev_logic_inbit(pinw_idx_t idx);
int fdev_logic_outbit(pinw_idx_t idx);

View File

@ -742,3 +742,149 @@ const char* logicout_str(enum logicout_wire w)
EXIT(1);
return 0;
}
const char* fpga_wirestr(struct fpga_model* model, enum extra_wires wire)
{
enum { NUM_BUFS = 8, BUF_SIZE = 64 };
static char buf[NUM_BUFS][BUF_SIZE];
static int last_buf = 0;
switch (wire) {
case GFAN0: return "GFAN0";
case GFAN1: return "GFAN1";
case CLK0: return "CLK0";
case CLK1: return "CLK1";
case SR0: return "SR0";
case SR1: return "SR1";
case GND_WIRE: return "GND_WIRE";
case VCC_WIRE: return "VCC_WIRE";
case FAN_B: return "FAN_B";
case LOGICIN20: return "LOGICIN20";
case LOGICIN21: return "LOGICIN21";
case LOGICIN44: return "LOGICIN44";
case LOGICIN52: return "LOGICIN52";
case LOGICIN_N21: return "LOGICIN_N21";
case LOGICIN_N28: return "LOGICIN_N28";
case LOGICIN_N52: return "LOGICIN_N52";
case LOGICIN_N60: return "LOGICIN_N60";
case LOGICIN_S20: return "LOGICIN_S20";
case LOGICIN_S36: return "LOGICIN_S36";
case LOGICIN_S44: return "LOGICIN_S44";
case LOGICIN_S62: return "LOGICIN_S62";
default: ;
}
last_buf = (last_buf+1)%NUM_BUFS;
buf[last_buf][0] = 0;
if (wire >= GCLK0 && wire <= GCLK15)
snprintf(buf[last_buf], sizeof(buf[0]), "GCLK%i", wire-GCLK0);
else if (wire >= DW && wire <= DW_LAST) {
char beg_end;
int flags;
wire -= DW;
flags = wire & DIR_FLAGS;
wire &= ~DIR_FLAGS;
beg_end = (flags & DIR_BEG) ? 'B' : 'E';
if (flags & DIR_S0 && wire%4 == 0)
snprintf(buf[last_buf], sizeof(buf[0]),
"%s%c_S0", wire_base(wire/4), beg_end);
else if (flags & DIR_N3 && wire%4 == 3)
snprintf(buf[last_buf], sizeof(buf[0]),
"%s%c_N3", wire_base(wire/4), beg_end);
else
snprintf(buf[last_buf], sizeof(buf[0]),
"%s%c%i", wire_base(wire/4), beg_end, wire%4);
} else if (wire >= LW && wire <= LW_LAST) {
wire -= LW;
if ((wire&(~LD1)) >= LI_FIRST && (wire&(~LD1)) <= LI_LAST)
snprintf(buf[last_buf], sizeof(buf[0]), "LOGICIN_B%i", fdev_logic_inbit(wire));
else if ((wire&(~LD1)) >= LO_FIRST && (wire&(~LD1)) <= LO_LAST)
snprintf(buf[last_buf], sizeof(buf[0]), "LOGICOUT%i", fdev_logic_outbit(wire));
else HERE();
} else HERE();
return buf[last_buf];
}
str16_t fpga_wirestr_i(struct fpga_model* model, enum extra_wires wire)
{
return strarray_find(&model->str, fpga_wirestr(model, wire));
}
int fdev_logic_inbit(pinw_idx_t idx)
{
if (idx & LD1) {
idx &= ~LD1;
if (idx >= LI_A1 && idx <= LI_C6)
return M_A1 + (idx/6)*8+idx%6;
if (idx >= LI_D1 && idx <= LI_D6)
return M_D1 + (idx-LI_D1);
switch (idx) {
case LI_AX: return M_AX;
case LI_BX: return M_BX;
case LI_CE: return M_CE;
case LI_CX: return M_CX;
case LI_DX: return M_DX;
case LI_AI: return M_AI;
case LI_BI: return M_BI;
case LI_CI: return M_CI;
case LI_DI: return M_DI;
case LI_WE: return M_WE;
}
HERE();
return -1;
}
if (idx >= LI_A1 && idx <= LI_C6)
return X_A1 + (idx/6)*7+idx%6;
else if (idx >= LI_D1 && idx <= LI_D6)
return X_D1 + (idx-LI_D1);
else switch (idx) {
case LI_AX: return X_AX;
case LI_BX: return X_BX;
case LI_CE: return X_CE;
case LI_CX: return X_CX;
case LI_DX: return X_DX;
}
HERE();
return -1;
}
int fdev_logic_outbit(pinw_idx_t idx)
{
if (idx & LD1) {
idx &= ~LD1;
switch (idx) {
case LO_A: return M_A;
case LO_AMUX: return M_AMUX;
case LO_AQ: return M_AQ;
case LO_B: return M_B;
case LO_BMUX: return M_BMUX;
case LO_BQ: return M_BQ;
case LO_C: return M_C;
case LO_CMUX: return M_CMUX;
case LO_CQ: return M_CQ;
case LO_D: return M_D;
case LO_DMUX: return M_DMUX;
case LO_DQ: return M_DQ;
}
HERE();
return -1;
}
switch (idx) {
case LO_A: return X_A;
case LO_AMUX: return X_AMUX;
case LO_AQ: return X_AQ;
case LO_B: return X_B;
case LO_BMUX: return X_BMUX;
case LO_BQ: return X_BQ;
case LO_C: return X_C;
case LO_CMUX: return X_CMUX;
case LO_CQ: return X_CQ;
case LO_D: return X_D;
case LO_DMUX: return X_DMUX;
case LO_DQ: return X_DQ;
}
HERE();
return -1;
}

View File

@ -26,8 +26,6 @@ int fpga_build_model(struct fpga_model* model, int fpga_rows,
strarray_init(&model->str, STRIDX_64K);
rc = get_xc6_routing_bitpos(&model->sw_bitpos, &model->num_bitpos);
if (rc) FAIL(rc);
model->first_routing_y = -1;
model->first_routing_x = -1;
// The order of tiles, then devices, then ports, then
// connections and finally switches is important so

View File

@ -7,6 +7,7 @@
#include <stdarg.h>
#include "model.h"
#include "parts.h"
static int init_ce_clk_switches(struct fpga_model* model);
static int init_io_switches(struct fpga_model* model);
@ -938,724 +939,47 @@ enum wire_type wire_to_len(enum wire_type w, int first_len)
EXIT(1);
}
static enum wire_type wire_to_NESW4(enum wire_type w)
static const char* routing_wirestr(struct fpga_model* model,
enum extra_wires wire, int routing_io, int gclk_brk)
{
// normalizes any of the 8 directions to just N/E/S/W
// by going back to an even number.
w = W_TO_LEN4(w);
return w - (w-FIRST_LEN4)%2;
}
// longest should be something like "WW2E_N3"?
typedef char WIRE_NAME[8];
struct one_switch
{
WIRE_NAME from;
WIRE_NAME to;
};
struct set_of_switches
{
int num_s;
struct one_switch s[64];
};
static void add_switch_range(struct set_of_switches* dest,
enum wire_type end_wire, int end_from, int end_to,
enum wire_type beg_wire, int beg_from)
{
int i;
for (i = end_from; i <= end_to; i++) {
sprintf(dest->s[dest->num_s].from, "%sE%i", wire_base(end_wire), i);
sprintf(dest->s[dest->num_s].to, "%sB%i", wire_base(beg_wire), beg_from + (i-end_from));
dest->num_s++;
if (routing_io) {
if (wire == GFAN0) return "INT_IOI_GFAN0";
if (wire == GFAN1) return "INT_IOI_GFAN1";
if (wire == LW + LI_A5) return "INT_IOI_LOGICIN_B4";
if (wire == LW + LI_B4) return "INT_IOI_LOGICIN_B10";
}
}
static void add_switch_E3toB0(struct set_of_switches* dest,
enum wire_type end_wire, enum wire_type beg_wire)
{
const char* end_wire_s = wire_base(end_wire);
const char* beg_wire_s = wire_base(beg_wire);
sprintf(dest->s[dest->num_s].from, "%sE3", end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB0", beg_wire_s);
dest->num_s++;
add_switch_range(dest, end_wire, 0, 2, beg_wire, 1);
}
static void add_switch_E0toB3(struct set_of_switches* dest,
enum wire_type end_wire, enum wire_type beg_wire)
{
const char* end_wire_s = wire_base(end_wire);
const char* beg_wire_s = wire_base(beg_wire);
sprintf(dest->s[dest->num_s].from, "%sE0", end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB3", beg_wire_s);
dest->num_s++;
add_switch_range(dest, end_wire, 1, 3, beg_wire, 0);
}
static int add_switches(struct set_of_switches* dest,
enum wire_type end_wire, enum wire_type beg_wire)
{
const char* end_wire_s, *beg_wire_s;
int i;
end_wire_s = wire_base(end_wire);
beg_wire_s = wire_base(beg_wire);
//
// First the directional routing at the end of len-1 wires.
//
if (W_IS_LEN1(end_wire)) {
if (end_wire == W_WL1) {
if (beg_wire == W_NL1) {
sprintf(dest->s[dest->num_s].from, "%sE_N3",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB3",
beg_wire_s);
dest->num_s++;
add_switch_range(dest, end_wire,
0, 2, beg_wire, 0);
return 0;
}
if (beg_wire == W_WR1) {
add_switch_range(dest, end_wire,
0, 1, beg_wire, 2);
sprintf(dest->s[dest->num_s].from, "%sE_N3",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB1",
beg_wire_s);
dest->num_s++;
sprintf(dest->s[dest->num_s].from, "%sE2",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB0",
beg_wire_s);
dest->num_s++;
return 0;
}
if (beg_wire == W_NN2 || beg_wire == W_NW2) {
sprintf(dest->s[dest->num_s].from, "%sE_N3",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB0",
beg_wire_s);
dest->num_s++;
add_switch_range(dest, end_wire,
0, 2, beg_wire, 1);
return 0;
}
if (beg_wire == W_SR1) {
add_switch_E3toB0(dest, end_wire, beg_wire);
return 0;
}
if (beg_wire == W_WL1) {
add_switch_E0toB3(dest, end_wire, beg_wire);
return 0;
}
add_switch_range(dest, end_wire, 0, 3, beg_wire, 0);
return 0;
}
if (end_wire == W_WR1) {
if (beg_wire == W_SW2 || beg_wire == W_WW2) {
add_switch_range(dest, end_wire,
1, 3, beg_wire, 0);
sprintf(dest->s[dest->num_s].from, "%sE_S0",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB3",
beg_wire_s);
dest->num_s++;
return 0;
}
if (beg_wire == W_SR1) {
sprintf(dest->s[dest->num_s].from, "%sE_S0",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB0",
beg_wire_s);
dest->num_s++;
add_switch_range(dest, end_wire,
1, 3, beg_wire, 1);
return 0;
}
if (beg_wire == W_WL1) {
add_switch_range(dest, end_wire,
2, 3, beg_wire, 0);
sprintf(dest->s[dest->num_s].from, "%sE_S0",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB2",
beg_wire_s);
dest->num_s++;
sprintf(dest->s[dest->num_s].from, "%sE1",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB3",
beg_wire_s);
dest->num_s++;
return 0;
}
if (beg_wire == W_WR1) {
add_switch_E3toB0(dest, end_wire, beg_wire);
return 0;
}
if (beg_wire == W_NL1) {
add_switch_E0toB3(dest, end_wire, beg_wire);
return 0;
}
add_switch_range(dest, end_wire, 0, 3, beg_wire, 0);
return 0;
}
if (beg_wire == W_WR1 || beg_wire == W_ER1
|| beg_wire == W_SR1) {
add_switch_E3toB0(dest, end_wire, beg_wire);
return 0;
}
if (beg_wire == W_NL1 || beg_wire == W_EL1
|| beg_wire == W_WL1) {
add_switch_E0toB3(dest, end_wire, beg_wire);
return 0;
}
add_switch_range(dest, end_wire, 0, 3, beg_wire, 0);
return 0;
}
//
// The rest of the function is for directional routing
// at the end of len-2 and len-4 wires.
//
if (end_wire == W_WW2) {
if (beg_wire == W_NL1) {
add_switch_range(dest, end_wire, 0, 2, beg_wire, 0);
sprintf(dest->s[dest->num_s].from, "%sE_N3",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB3",
beg_wire_s);
dest->num_s++;
return 0;
}
if (beg_wire == W_WR1) {
add_switch_range(dest, end_wire, 0, 1, beg_wire, 2);
sprintf(dest->s[dest->num_s].from, "%sE_N3",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB1",
beg_wire_s);
dest->num_s++;
sprintf(dest->s[dest->num_s].from, "%sE2",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB0",
beg_wire_s);
dest->num_s++;
return 0;
}
if (beg_wire == W_WL1) {
add_switch_E0toB3(dest, end_wire, beg_wire);
return 0;
}
if (beg_wire == W_SR1) {
add_switch_E3toB0(dest, end_wire, beg_wire);
return 0;
}
if (beg_wire == W_WW4 || beg_wire == W_NN2
|| beg_wire == W_NW2 || beg_wire == W_NE4
|| beg_wire == W_NN4 || beg_wire == W_NW4) {
add_switch_range(dest, end_wire, 0, 2, beg_wire, 1);
sprintf(dest->s[dest->num_s].from, "%sE_N3",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB0",
beg_wire_s);
dest->num_s++;
return 0;
}
add_switch_range(dest, end_wire, 0, 3, beg_wire, 0);
return 0;
}
if (end_wire == W_NW2 || end_wire == W_NW4
|| end_wire == W_WW4) {
if (beg_wire == W_NL1) {
add_switch_E0toB3(dest, end_wire, beg_wire);
return 0;
}
if (beg_wire == W_WR1) {
add_switch_E3toB0(dest, end_wire, beg_wire);
return 0;
}
if (beg_wire == W_SR1) {
sprintf(dest->s[dest->num_s].from, "%sE_S0",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB0",
beg_wire_s);
dest->num_s++;
add_switch_range(dest, end_wire, 1, 3, beg_wire, 1);
return 0;
}
if (beg_wire == W_WL1) {
sprintf(dest->s[dest->num_s].from, "%sE_S0",
end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB2",
beg_wire_s);
dest->num_s++;
sprintf(dest->s[dest->num_s].from, "%sE1", end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB3", beg_wire_s);
dest->num_s++;
add_switch_range(dest, end_wire, 2, 3, beg_wire, 0);
return 0;
}
if (beg_wire == W_SS4 || beg_wire == W_SW2
|| beg_wire == W_SW4 || beg_wire == W_WW2) {
add_switch_range(dest, end_wire, 1, 3, beg_wire, 0);
sprintf(dest->s[dest->num_s].from, "%sE_S0", end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB3", beg_wire_s);
dest->num_s++;
return 0;
}
add_switch_range(dest, end_wire, 0, 3, beg_wire, 0);
return 0;
}
if ((end_wire == W_SS2 || end_wire == W_SS4
|| end_wire == W_SW2 || end_wire == W_SW4)
&& (beg_wire == W_NW4 || beg_wire == W_WW4)) {
for (i = 0; i <= 2; i++) {
sprintf(dest->s[dest->num_s].from, "%sE%i",
end_wire_s, i);
sprintf(dest->s[dest->num_s].to, "%sB%i",
beg_wire_s, i+1);
dest->num_s++;
}
sprintf(dest->s[dest->num_s].from, "%sE_N3", end_wire_s);
sprintf(dest->s[dest->num_s].to, "%sB0", beg_wire_s);
dest->num_s++;
return 0;
}
if (beg_wire == W_WR1 || beg_wire == W_ER1 || beg_wire == W_SR1) {
add_switch_E3toB0(dest, end_wire, beg_wire);
return 0;
}
if (beg_wire == W_WL1 || beg_wire == W_EL1 || beg_wire == W_NL1) {
add_switch_E0toB3(dest, end_wire, beg_wire);
return 0;
}
add_switch_range(dest, end_wire, 0, 3, beg_wire, 0);
return 0;
}
// todo: should try to rewrite this using groups...
static int build_dirwire_switches(struct set_of_switches* dest,
enum wire_type src_wire)
{
enum wire_type cur;
int i, rc;
dest->num_s = 0;
if (W_IS_LEN2(src_wire) || W_IS_LEN4(src_wire)) {
cur = W_COUNTER_CLOCKWISE_2(wire_to_NESW4(src_wire));
for (i = 0; i < 6; i++) {
rc = add_switches(dest, src_wire, cur);
if (rc) goto xout;
cur = W_CLOCKWISE(cur);
if (gclk_brk) {
switch (wire) {
case GCLK0: return "GCLK0_BRK";
case GCLK1: return "GCLK1_BRK";
case GCLK2: return "GCLK2_BRK";
case GCLK3: return "GCLK3_BRK";
case GCLK4: return "GCLK4_BRK";
case GCLK5: return "GCLK5_BRK";
case GCLK6: return "GCLK6_BRK";
case GCLK7: return "GCLK7_BRK";
case GCLK8: return "GCLK8_BRK";
case GCLK9: return "GCLK9_BRK";
case GCLK10: return "GCLK10_BRK";
case GCLK11: return "GCLK11_BRK";
case GCLK12: return "GCLK12_BRK";
case GCLK13: return "GCLK13_BRK";
case GCLK14: return "GCLK14_BRK";
case GCLK15: return "GCLK15_BRK";
default: ;
}
}
cur = W_COUNTER_CLOCKWISE(W_TO_LEN2(wire_to_NESW4(src_wire)));
for (i = 0; i < 4; i++) {
rc = add_switches(dest, src_wire, cur);
if (rc) goto xout;
cur = W_CLOCKWISE(cur);
}
cur = W_COUNTER_CLOCKWISE(W_TO_LEN1(wire_to_NESW4(src_wire)));
for (i = 0; i < 4; i++) {
rc = add_switches(dest, src_wire, cur);
if (rc) goto xout;
cur = W_CLOCKWISE(cur);
}
return 0;
xout:
return rc;
}
// See this as an array of groups of 4 wires, the order inside
// the groups is significant as well. It's how the wire structure
// is expressed best - several places build their logic on this,
// search for logicin_g4.
// todo: not sure this is deal. vcc goes to 0/1 and 6/7, and logicio_extra
// seems to have groups also corresponding to 0/1/6/7 and 2-5
static int logicin_g4[] = {
/* g00 mip16-3 */ M_B6, X_A6, M_C1, X_AX, /* g01 mip18-3 */ M_AI, X_B1, M_D3, X_C3,
/* g02 mip12-3 */ M_C3, X_D3, M_B2, M_WE, /* g03 mip14-3 */ M_AX, X_C2, M_A6, X_B6,
/* g04 mip16-2 */ M_B5, X_A5, M_BX, X_D2, /* g05 mip18-2 */ M_A2, M_BI, M_D4, X_C4,
/* g06 mip12-2 */ M_C4, X_D4, X_A1, X_CE, /* g07 mip14-2 */ M_D1, X_BX, M_A5, X_B5,
/* g08 mip16-1 */ M_B4, X_A4, X_CX, X_D1, /* g09 mip18-1 */ M_A1, M_CE, M_D5, X_C5,
/* g10 mip12-1 */ M_C5, X_D5, M_CI, X_A2, /* g11 mip14-1 */ M_CX, M_D2, M_A4, X_B4,
/* g12 mip16-0 */ M_B3, X_A3, M_C2, M_DX, /* g13 mip18-0 */ X_B2, FAN_B, M_D6, X_C6,
/* g14 mip12-0 */ M_C6, X_D6, M_B1, M_DI, /* g15 mip14-0 */ X_C1, X_DX, M_A3, X_B3,
};
static int add_logicio_extra(struct fpga_model* model,
int y, int x, int routing_io)
{
// 16 groups of 4. The order inside the group does not matter,
// but the order of the groups must match the order in src_w.
static int dest_w[] = {
/* group 0 */ M_D1, X_A1, X_CE, X_BX | LWF_BIDIR,
/* group 1 */ M_B2, M_WE, X_C2, M_AX | LWF_BIDIR,
/* group 2 */ M_C1, M_AI, X_B1, X_AX | LWF_BIDIR,
/* group 3 */ M_A2, M_BI, X_D2, M_BX | LWF_BIDIR,
/* group 4 */ M_C2, M_DX, X_B2, FAN_B | LWF_BIDIR,
/* group 5 */ M_A1, X_CX, X_D1, M_CE | LWF_BIDIR,
/* group 6 */ M_CX, M_D2, X_A2, M_CI | LWF_BIDIR,
/* group 7 */ M_B1, X_C1, X_DX, M_DI | LWF_BIDIR,
/* group 8 */ M_A5, M_C4, X_B5, X_D4,
/* group 9 */ M_A6, M_C3, X_B6, X_D3,
/* group 10 */ M_B5, M_D4, X_A5, X_C4,
/* group 11 */ M_B6, M_D3, X_A6, X_C3,
/* group 12 */ M_B4, M_D5, X_A4, X_C5,
/* group 13 */ M_B3, M_D6, X_A3, X_C6,
/* group 14 */ M_A3, M_C6, X_B3, X_D6,
/* group 15 */ M_A4, M_C5, X_B4, X_D5,
};
// 16 groups of 5. Order of groups in sync with dest_w.
// Each dest_w group can only have 1 bidir wire, which is
// flagged there. The flag in src_w signals whether that one
// bidir line in dest_w is to be driven as bidir or not.
static int src_w[] = {
/* group 0 */ GFAN0, M_AX, M_CI | LWF_BIDIR, M_DI | LWF_BIDIR, LOGICIN_N28,
/* group 1 */ GFAN0 | LWF_BIDIR, LOGICIN20, M_CI | LWF_BIDIR, LOGICIN_N52, LOGICIN_N28,
/* group 2 */ GFAN0 | LWF_BIDIR, M_CE | LWF_BIDIR, LOGICIN_N21, LOGICIN44, LOGICIN_N60,
/* group 3 */ GFAN0, FAN_B | LWF_BIDIR, X_AX, M_CE | LWF_BIDIR, LOGICIN_N60,
/* group 4 */ GFAN1, M_BX | LWF_BIDIR, LOGICIN21, LOGICIN_S44, LOGICIN_S36,
/* group 5 */ GFAN1 | LWF_BIDIR, FAN_B, M_BX | LWF_BIDIR, X_AX | LWF_BIDIR, LOGICIN_S36,
/* group 6 */ GFAN1 | LWF_BIDIR, M_AX | LWF_BIDIR, X_BX | LWF_BIDIR, M_DI, LOGICIN_S62,
/* group 7 */ GFAN1, LOGICIN52, X_BX | LWF_BIDIR, LOGICIN_S20, LOGICIN_S62,
/* group 8 */ M_AX, M_CI, M_DI, LOGICIN_N28, UNDEF,
/* group 9 */ LOGICIN20, M_CI, LOGICIN_N52, LOGICIN_N28, UNDEF,
/* group 10 */ FAN_B, X_AX, M_CE, LOGICIN_N60, UNDEF,
/* group 11 */ M_CE, LOGICIN_N21, LOGICIN44, LOGICIN_N60, UNDEF,
/* group 12 */ FAN_B, M_BX, X_AX, LOGICIN_S36, UNDEF,
/* group 13 */ M_BX, LOGICIN21, LOGICIN_S44, LOGICIN_S36, UNDEF,
/* group 14 */ LOGICIN52, X_BX, LOGICIN_S20, LOGICIN_S62, UNDEF,
/* group 15 */ M_AX, X_BX, M_DI, LOGICIN_S62, UNDEF
};
char from_str[32], to_str[32];
int i, j, cur_dest_w, is_bidir, rc;
for (i = 0; i < sizeof(src_w)/sizeof(src_w[0]); i++) {
for (j = 0; j < 4; j++) {
cur_dest_w = dest_w[(i/5)*4 + j];
is_bidir = (cur_dest_w & LWF_BIDIR) && (src_w[i] & LWF_BIDIR);
if ((cur_dest_w & LWF_WIRE_MASK) == FAN_B)
strcpy(to_str, "FAN_B");
else
strcpy(to_str, logicin_s(cur_dest_w, routing_io));
switch (src_w[i] & LWF_WIRE_MASK) {
case UNDEF: continue;
default:
snprintf(from_str, sizeof(from_str), "LOGICIN_B%i",
src_w[i] & LWF_WIRE_MASK);
break;
case GFAN0:
case GFAN1:
if (routing_io) {
is_bidir = 0;
strcpy(from_str, "VCC_WIRE");
} else {
strcpy(from_str, (src_w[i] & LWF_WIRE_MASK)
== GFAN0 ? "GFAN0" : "GFAN1");
}
break;
case FAN_B: strcpy(from_str, "FAN_B"); break;
case LOGICIN20: strcpy(from_str, "LOGICIN20"); break;
case LOGICIN21: strcpy(from_str, "LOGICIN21"); break;
case LOGICIN44: strcpy(from_str, "LOGICIN44"); break;
case LOGICIN52: strcpy(from_str, "LOGICIN52"); break;
case LOGICIN_N21: strcpy(from_str, "LOGICIN_N21"); break;
case LOGICIN_N28: strcpy(from_str, "LOGICIN_N28"); break;
case LOGICIN_N52: strcpy(from_str, "LOGICIN_N52"); break;
case LOGICIN_N60: strcpy(from_str, "LOGICIN_N60"); break;
case LOGICIN_S20: strcpy(from_str, "LOGICIN_S20"); break;
case LOGICIN_S36: strcpy(from_str, "LOGICIN_S36"); break;
case LOGICIN_S44: strcpy(from_str, "LOGICIN_S44"); break;
case LOGICIN_S62: strcpy(from_str, "LOGICIN_S62"); break;
}
rc = add_switch(model, y, x, from_str, to_str, is_bidir);
if (rc) goto xout;
}
}
return 0;
xout:
return rc;
}
// switch device:
// - position of 2-bit selector, either 2 bits in 1 minor (mi20), or 1+1
// bits in 2 minors (mip0-18)
// - array of 4 pointers to wire groups, each containing up to 6 wires
static int add_logicout_switches(struct fpga_model* model,
int y, int x, int routing_io)
{
// 8 groups of 3. The order inside the group does not matter,
// but the order of the groups does.
// TODO: these out_wires[] groups also matter in bit positions, fix positions!
static int out_wires[] = {
/* group 0 */ M_A, M_CMUX, X_AQ,
/* group 1 */ M_AQ, X_A, X_CMUX,
/* group 2 */ M_BQ, X_B, X_DMUX,
/* group 3 */ M_B, M_DMUX, X_BQ,
/* group 4 */ M_AMUX, M_C, X_CQ,
/* group 5 */ M_CQ, X_AMUX, X_C,
/* group 6 */ M_DQ, X_BMUX, X_D,
/* group 7 */ M_BMUX, M_D, X_DQ,
};
enum wire_type wire;
char from_str[32], to_str[32];
int i, j, rc;
for (i = 0; i < sizeof(out_wires)/sizeof(out_wires[0]); i++) {
// out to dirwires
snprintf(from_str, sizeof(from_str), "LOGICOUT%i",
out_wires[i]);
wire = W_NN2;
do {
// len 2
snprintf(to_str, sizeof(to_str), "%sB%i",
wire_base(wire), i/(2*3));
rc = add_switch(model, y, x, from_str, to_str,
0 /* bidir */);
if (rc) goto xout;
// len 4
snprintf(to_str, sizeof(to_str), "%sB%i",
wire_base(W_TO_LEN4(wire)), i/(2*3));
rc = add_switch(model, y, x, from_str, to_str,
0 /* bidir */);
if (rc) goto xout;
wire = W_CLOCKWISE(wire);
} while (wire != W_NN2); // one full turn
// NR1, SL1
snprintf(to_str, sizeof(to_str), "NR1B%i", i/(2*3));
rc = add_switch(model, y, x, from_str, to_str, 0 /* bidir */);
if (rc) goto xout;
snprintf(to_str, sizeof(to_str), "SL1B%i", i/(2*3));
rc = add_switch(model, y, x, from_str, to_str, 0 /* bidir */);
if (rc) goto xout;
// ER1, SR1, WR1 (+1)
// NL1, EL1, WL1 (+3)
{
static const char* plus1[] = {"ER1B%i", "SR1B%i", "WR1B%i"};
static const char* plus3[] = {"NL1B%i", "EL1B%i", "WL1B%i"};
for (j = 0; j < 3; j++) {
snprintf(to_str, sizeof(to_str), plus1[j], (i/(2*3)+1)%4);
rc = add_switch(model, y, x, from_str, to_str, 0 /* bidir */);
if (rc) goto xout;
snprintf(to_str, sizeof(to_str), plus3[j], (i/(2*3)+3)%4);
rc = add_switch(model, y, x, from_str, to_str, 0 /* bidir */);
if (rc) goto xout;
}
}
// back to logicin
for (j = 0; j < 8; j++) {
if (logicin_g4[(i/3)*8 + j] == FAN_B)
strcpy(to_str, "FAN_B");
else
strcpy(to_str, logicin_s(logicin_g4[(i/3)*8 + j], routing_io));
rc = add_switch(model, y, x, from_str, to_str,
0 /* bidir */);
if (rc) goto xout;
}
}
return 0;
xout:
return rc;
}
static int add_logicin_switch(struct fpga_model* model, int y, int x,
enum wire_type dirwire, int dirwire_num,
int logicin_num)
{
char from_str[32], to_str[32];
int rc;
if (dirwire == W_NW2 || dirwire == W_NL1) {
dirwire_num++;
if (dirwire_num > 3)
dirwire_num = 0;
}
if (dirwire_num == -1)
dirwire_num = 3;
if (dirwire_num == 0 && logicin_num & LWF_SOUTH0)
snprintf(from_str, sizeof(from_str), "%sE_S0",
wire_base(dirwire));
else if (dirwire_num == 3 && logicin_num & LWF_NORTH3)
snprintf(from_str, sizeof(from_str), "%sE_N3",
wire_base(dirwire));
else
snprintf(from_str, sizeof(from_str), "%sE%i",
wire_base(dirwire), dirwire_num);
if ((logicin_num & LWF_WIRE_MASK) == FAN_B)
strcpy(to_str, "FAN_B");
else {
struct fpga_tile* tile = YX_TILE(model, y, x);
int routing_io = (tile->type == IO_ROUTING || tile->type == ROUTING_IO_L);
strcpy(to_str, logicin_s(logicin_num, routing_io));
}
rc = add_switch(model, y, x, from_str, to_str, 0 /* bidir */);
if (rc) goto xout;
return 0;
xout:
return rc;
}
static enum wire_type dirwire_g4[] = {
W_NN2, W_NE2, W_WR1, W_EL1,
W_EE2, W_SE2, W_NR1, W_SL1,
W_SS2, W_SW2, W_ER1, W_WL1,
W_WW2, W_NW2, W_SR1, W_NL1
};
static int add_logicin_switches(struct fpga_model* model, int y, int x)
{
int logicin_wire, i, j, k, l, rc;
//
// There are probably ways to merge all 4 loops into one
// nicely by regrouping better. For now we have 4 loops
// that differ like this:
//
// 1) g4 groups: 2 6 10 14
// LWF_SOUTH0 for i == 3 (group 14)
// decrement at NN (=never), k > 3
//
// 2) g4 groups: 15 3 7 11
// LWF_SOUTH0 for i == 0 (group 15)
// decrement at EE, k > 0
//
// 3) g4 groups: 1 5 9 13
// LWF_NORTH3 for i == 0 (group 1)
// decrement at SS, k > 1
//
// 4) g4 groups: 0 4 8 12
// LWF_NORTH3 for i == 0 (group 0)
// decrement at WW, k > 2
//
// i = logicin groups (the destinations of our switches)
for (i = 0; i < 4; i++) { // we want: 2, 6, 10, 14
// j = each destination logicin wire
for (j = 0; j < 4; j++) {
logicin_wire = logicin_g4[((2+i*4)%16)*4 + j];
if (i == 3)
logicin_wire |= LWF_SOUTH0;
for (k = 0; k < 4; k++) { // k = dirwire groups/quarts
for (l = 0; l < 4; l++) { // l = each dirwire in a group/quart
rc = add_logicin_switch(model, y, x, dirwire_g4[k*4+l], k > 3 ? i-1 : i, logicin_wire);
if (rc) FAIL(rc);
}
}
}
}
// i = logicin groups (the destinations of our switches)
for (i = 0; i < 4; i++) { // we want: 15, 3, 7, 11
// j = each destination logicin wire
for (j = 0; j < 4; j++) {
logicin_wire = logicin_g4[((15+i*4)%16)*4 + j];
if (i == 0)
logicin_wire |= LWF_SOUTH0;
for (k = 0; k < 4; k++) { // k = dirwire groups/quarts
for (l = 0; l < 4; l++) { // l = each dirwire in a group/quart
rc = add_logicin_switch(model, y, x, dirwire_g4[k*4+l], k > 0 ? i-1 : i, logicin_wire);
if (rc) FAIL(rc);
}
}
}
}
// i = logicin groups (the destinations of our switches)
for (i = 0; i < 4; i++) { // we want: 1, 5, 9, 13
// j = each destination logicin wire
for (j = 0; j < 4; j++) {
logicin_wire = logicin_g4[((1+i*4)%16)*4 + j];
if (i == 0)
logicin_wire |= LWF_NORTH3;
for (k = 0; k < 4; k++) { // k = dirwire groups/quarts
for (l = 0; l < 4; l++) { // l = each dirwire in a group/quart
rc = add_logicin_switch(model, y, x, dirwire_g4[k*4+l], k > 1 ? i-1 : i, logicin_wire);
if (rc) FAIL(rc);
}
}
}
}
// i = logicin groups (the destinations of our switches)
for (i = 0; i < 4; i++) { // we want: 0, 4, 8, 12
// j = each destination logicin wire
for (j = 0; j < 4; j++) {
logicin_wire = logicin_g4[((0+i*4)%16)*4 + j];
if (i == 0)
logicin_wire |= LWF_NORTH3;
for (k = 0; k < 4; k++) { // k = dirwire groups/quarts
for (l = 0; l < 4; l++) { // l = each dirwire in a group/quart
rc = add_logicin_switch(model, y, x, dirwire_g4[k*4+l], k > 2 ? i-1 : i, logicin_wire);
if (rc) FAIL(rc);
}
}
}
}
return 0;
fail:
return rc;
return fpga_wirestr(model, wire);
}
static int init_routing_tile(struct fpga_model* model, int y, int x)
{
int i, j, routing_io, rc;
struct set_of_switches dir_EB_switches;
enum wire_type wire;
int i, routing_io, gclk_brk, from_wire, to_wire, is_bidir, rc;
struct fpga_tile* tile;
const char* gfan_s, *gclk_s;
tile = YX_TILE(model, y, x);
if (model->first_routing_y == -1
&& tile->type != IO_ROUTING && tile->type != ROUTING_IO_L
&& tile->type != ROUTING_BRK && tile->type != BRAM_ROUTING_BRK) {
model->first_routing_y = y;
model->first_routing_x = x;
}
routing_io = (tile->type == IO_ROUTING || tile->type == ROUTING_IO_L);
gfan_s = routing_io ? "INT_IOI_GFAN%i" : "GFAN%i";
// GND
for (i = 0; i <= 1; i++) {
rc = add_switch(model, y, x, "GND_WIRE",
pf(gfan_s, i), 0 /* bidir */);
if (rc) FAIL(rc);
}
rc = add_switch(model, y, x, "GND_WIRE", "SR1", 0 /* bidir */);
if (rc) FAIL(rc);
// VCC
for (i = 0; i < sizeof(logicin_g4)/sizeof(logicin_g4[0])/2; i++) {
// VCC goes to the first 2 wires of even groups, and
// last 2 wires of odd groups. In the array, it goes to:
// 0 1 .. 6 7 8 9 .. 14 15 16 17 ..
rc = add_switch(model, y, x, "VCC_WIRE",
logicin_s(logicin_g4[i + ((i+2)/4)*4],
routing_io), 0 /* bidir */);
if (rc) FAIL(rc);
}
gclk_brk = (tile->type == ROUTING_BRK || tile->type == BRAM_ROUTING_BRK);
// KEEP1
for (i = X_A1; i <= M_WE; i++) {
@ -1665,176 +989,63 @@ static int init_routing_tile(struct fpga_model* model, int y, int x)
}
rc = add_switch(model, y, x, "KEEP1_WIRE", "FAN_B", 0 /* bidir */);
if (rc) FAIL(rc);
// VCC and KEEP1 to CLK0:1, SR0:1, GFAN0:1
{ static const char* src[] = {"VCC_WIRE", "KEEP1_WIRE"};
for (i = 0; i <= 1; i++)
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, src[i],
pf("CLK%i", j), 0 /* bidir */);
if (rc) FAIL(rc);
rc = add_switch(model, y, x, src[i],
pf("SR%i", j), 0 /* bidir */);
if (rc) FAIL(rc);
rc = add_switch(model, y, x,
src[i], pf(gfan_s, j), 0 /* bidir */);
if (rc) FAIL(rc);
}
}
// GCLK0:15 -> CLK0:1, GFAN0:1/SR0:1
if (tile->type == ROUTING_BRK
|| tile->type == BRAM_ROUTING_BRK)
gclk_s = "GCLK%i_BRK";
else
gclk_s = "GCLK%i";
for (i = 0; i <= 15; i++) {
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, pf(gclk_s, i),
pf("CLK%i", j), 0 /* bidir */);
if (rc) FAIL(rc);
rc = add_switch(model, y, x,
pf(gclk_s, i),
(i < 8) ? pf(gfan_s, j) : pf("SR%i", j),
0 /* bidir */);
if (rc) FAIL(rc);
}
}
// FAN_B to SR0:1
for (i = 0; i <= 1; i++) {
rc = add_switch(model, y, x, "FAN_B",
rc = add_switch(model, y, x, "KEEP1_WIRE",
pf("CLK%i", i), 0 /* bidir */);
if (rc) FAIL(rc);
rc = add_switch(model, y, x, "KEEP1_WIRE",
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 */);
if (rc) FAIL(rc);
}
// some logicin wires are singled out
{ int logic_singles[] = {X_CE, X_CX, X_DX,
M_AI, M_BI, M_CX, M_DX, M_WE};
for (i = 0; i < sizeof(logic_singles)/sizeof(logic_singles[0]); i++) {
for (i = 0; i < model->num_bitpos; i++) {
from_wire = model->sw_bitpos[i].from;
to_wire = model->sw_bitpos[i].to;
is_bidir = model->sw_bitpos[i].bidir;
if (routing_io) {
if (from_wire == GFAN0 || from_wire == GFAN1) {
from_wire = VCC_WIRE;
is_bidir = 0;
} else if (to_wire == GFAN0 || to_wire == GFAN1)
is_bidir = 0;
}
rc = add_switch(model, y, x,
pf("LOGICIN_B%i", logic_singles[i]),
pf("LOGICIN%i", logic_singles[i]), 0 /* bidir */);
routing_wirestr(model, from_wire, routing_io, gclk_brk),
routing_wirestr(model, to_wire, routing_io, gclk_brk),
is_bidir);
if (rc) FAIL(rc);
}}
// connecting directional wires endpoints to logicin
rc = add_logicin_switches(model, y, x);
if (rc) FAIL(rc);
// connecting logicout back to directional wires
// beginning points (and some back to logicin)
rc = add_logicout_switches(model, y, x, routing_io);
if (rc) FAIL(rc);
// there are extra wires to send signals to logicin, or
// to share/multiply logicin signals
rc = add_logicio_extra(model, y, x, routing_io);
if (rc) FAIL(rc);
// extra wires going to SR, CLK and GFAN
{ int to_sr[] = {X_BX, M_BX, M_DI};
for (i = 0; i < sizeof(to_sr)/sizeof(to_sr[0]); i++) {
for (j = 0; j <= 1; j++) {
if (is_bidir) {
rc = add_switch(model, y, x,
pf("LOGICIN_B%i", to_sr[i]),
pf("SR%i", j), 0 /* bidir */);
routing_wirestr(model, to_wire, routing_io, gclk_brk),
routing_wirestr(model, from_wire, routing_io, gclk_brk),
/* bidir */ 1);
if (rc) FAIL(rc);
}
}}
{ int to_clk[] = {M_BX, M_CI};
for (i = 0; i < sizeof(to_clk)/sizeof(to_clk[0]); i++) {
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x,
pf("LOGICIN_B%i", to_clk[i]),
pf("CLK%i", j), 0 /* bidir */);
if (rc) FAIL(rc);
}
}}
{ int to_gf[] = {M_AX, X_AX, M_CE, M_CI};
for (i = 0; i < sizeof(to_gf)/sizeof(to_gf[0]); i++) {
for (j = 0; j <= 1; j++) {
int bidir = !routing_io
&& ((!j && i < 2) || (j && i >= 2));
rc = add_switch(model, y, x,
pf("LOGICIN_B%i", to_gf[i]),
pf(gfan_s, j), bidir);
if (rc) FAIL(rc);
}
}}
// connecting the directional wires from one's end
// to another one's beginning
wire = W_NN2;
do {
rc = build_dirwire_switches(&dir_EB_switches, W_TO_LEN1(wire));
}
if (routing_io) {
// These switches don't come out of the general model because
// they are bidir there and skipped on the reverse side, but
// fall back to regular unidir switches in the io tiles. Can
// be cleaned up one day.
rc = add_switch(model, y, x, "LOGICIN_B6", "INT_IOI_GFAN0", 0);
if (rc) FAIL(rc);
for (i = 0; i < dir_EB_switches.num_s; i++) {
rc = add_switch(model, y, x,
dir_EB_switches.s[i].from,
dir_EB_switches.s[i].to, 0 /* bidir */);
if (rc) FAIL(rc);
}
rc = build_dirwire_switches(&dir_EB_switches, W_TO_LEN2(wire));
rc = add_switch(model, y, x, "LOGICIN_B35", "INT_IOI_GFAN0", 0);
if (rc) FAIL(rc);
for (i = 0; i < dir_EB_switches.num_s; i++) {
rc = add_switch(model, y, x,
dir_EB_switches.s[i].from,
dir_EB_switches.s[i].to, 0 /* bidir */);
if (rc) FAIL(rc);
}
rc = build_dirwire_switches(&dir_EB_switches, W_TO_LEN4(wire));
rc = add_switch(model, y, x, "LOGICIN_B51", "INT_IOI_GFAN1", 0);
if (rc) FAIL(rc);
rc = add_switch(model, y, x, "LOGICIN_B53", "INT_IOI_GFAN1", 0);
if (rc) FAIL(rc);
}
{ const int logicin_b[] = {20, 21, 28, 36, 44, 52, 60, 62};
for (i = 0; i < sizeof(logicin_b)/sizeof(*logicin_b); i++) {
rc = add_switch(model, y, x,
pf("LOGICIN_B%i", logicin_b[i]),
pf("LOGICIN%i", logicin_b[i]),
/* bidir */ 0);
if (rc) FAIL(rc);
for (i = 0; i < dir_EB_switches.num_s; i++) {
rc = add_switch(model, y, x,
dir_EB_switches.s[i].from,
dir_EB_switches.s[i].to, 0 /* bidir */);
if (rc) FAIL(rc);
}
wire = W_CLOCKWISE(wire);
} while (wire != W_NN2); // one full turn
// and finally, some end wires go to CLK, SR and GFAN
{ static const char* from[] = {"NR1E2", "WR1E2"};
for (i = 0; i < sizeof(from)/sizeof(from[0]); i++) {
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, from[i],
pf("CLK%i", j), 0 /* bidir */);
if (rc) FAIL(rc);
rc = add_switch(model, y, x, from[i],
pf("SR%i", j), 0 /* bidir */);
if (rc) FAIL(rc);
}
}}
{ static const char* from[] = {"ER1E1", "SR1E1"};
for (i = 0; i < sizeof(from)/sizeof(from[0]); i++) {
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, from[i],
pf("CLK%i", j), 0 /* bidir */);
if (rc) FAIL(rc);
rc = add_switch(model, y, x, from[i],
pf(gfan_s, j), 0 /* bidir */);
if (rc) FAIL(rc);
}
}}
{ static const char* from[] = {"NR1E1", "WR1E1"};
for (i = 0; i < sizeof(from)/sizeof(from[0]); i++) {
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, from[i],
pf(gfan_s, j), 0 /* bidir */);
if (rc) FAIL(rc);
}
}}
{ static const char* from[] = {"ER1E2", "SR1E2"};
for (i = 0; i < sizeof(from)/sizeof(from[0]); i++) {
for (j = 0; j <= 1; j++) {
rc = add_switch(model, y, x, from[i],
pf("SR%i", j), 0 /* bidir */);
if (rc) FAIL(rc);
}
}}
return 0;
fail: