Merge pull request #22 from YosysHQ/routethru
Add iCE40 LUT route-through pips
This commit is contained in:
commit
e673d9d2db
12
ice40/arch.h
12
ice40/arch.h
@ -141,6 +141,7 @@ static const int max_switch_bits = 5;
|
||||
|
||||
NPNR_PACKED_STRUCT(struct SwitchInfoPOD {
|
||||
int32_t num_bits;
|
||||
int32_t bel;
|
||||
int8_t x, y;
|
||||
ConfigBitPOD cbits[max_switch_bits];
|
||||
});
|
||||
@ -613,7 +614,16 @@ struct Arch : BaseCtx
|
||||
bool checkPipAvail(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
return switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString();
|
||||
int switch_idx = chip_info->pip_data[pip.index].switch_index;
|
||||
|
||||
if (switches_locked[switch_idx] != IdString())
|
||||
return false;
|
||||
|
||||
int bel_idx = chip_info->bits_info->switches[switch_idx].bel;
|
||||
if (bel_idx >= 0 && bel_to_cell[bel_idx] != IdString())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IdString getBoundPipNet(PipId pip) const
|
||||
|
@ -221,8 +221,21 @@ std::string tagTileType(TileType &tile)
|
||||
NPNR_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
static BelPin get_one_bel_pin(const Context *ctx, WireId wire)
|
||||
{
|
||||
auto pins = ctx->getWireBelPins(wire);
|
||||
NPNR_ASSERT(pins.begin() != pins.end());
|
||||
return *pins.begin();
|
||||
}
|
||||
|
||||
void write_asc(const Context *ctx, std::ostream &out)
|
||||
{
|
||||
|
||||
static const std::vector<int> lut_perm = {
|
||||
4, 14, 15, 5, 6, 16, 17, 7, 3, 13, 12, 2, 1, 11, 10, 0,
|
||||
};
|
||||
|
||||
// [y][x][row][col]
|
||||
const ChipInfoPOD &ci = *ctx->chip_info;
|
||||
const BitstreamInfoPOD &bi = *ci.bits_info;
|
||||
@ -262,12 +275,50 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
if (ctx->pip_to_net[pip.index] != IdString()) {
|
||||
const PipInfoPOD &pi = ci.pip_data[pip.index];
|
||||
const SwitchInfoPOD &swi = bi.switches[pi.switch_index];
|
||||
for (int i = 0; i < swi.num_bits; i++) {
|
||||
bool val = (pi.switch_mask & (1 << ((swi.num_bits - 1) - i))) != 0;
|
||||
int8_t &cbit = config.at(swi.y).at(swi.x).at(swi.cbits[i].row).at(swi.cbits[i].col);
|
||||
if (bool(cbit) != 0)
|
||||
NPNR_ASSERT(false);
|
||||
cbit = val;
|
||||
int sw_bel_idx = swi.bel;
|
||||
if (sw_bel_idx >= 0) {
|
||||
const BelInfoPOD &beli = ci.bel_data[sw_bel_idx];
|
||||
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC];
|
||||
BelId sw_bel;
|
||||
sw_bel.index = sw_bel_idx;
|
||||
NPNR_ASSERT(ctx->getBelType(sw_bel) == TYPE_ICESTORM_LC);
|
||||
BelPin input = get_one_bel_pin(ctx, ctx->getPipSrcWire(pip));
|
||||
BelPin output = get_one_bel_pin(ctx, ctx->getPipDstWire(pip));
|
||||
NPNR_ASSERT(input.bel == sw_bel);
|
||||
NPNR_ASSERT(output.bel == sw_bel && output.pin == PIN_O);
|
||||
unsigned lut_init;
|
||||
switch (input.pin) {
|
||||
case PIN_I0:
|
||||
lut_init = 2;
|
||||
break;
|
||||
case PIN_I1:
|
||||
lut_init = 4;
|
||||
break;
|
||||
case PIN_I2:
|
||||
lut_init = 16;
|
||||
break;
|
||||
case PIN_I3:
|
||||
lut_init = 256;
|
||||
break;
|
||||
default:
|
||||
NPNR_ASSERT_FALSE("bad feedthru LUT input");
|
||||
}
|
||||
std::vector<bool> lc(20, false);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((lut_init >> i) & 0x1)
|
||||
lc.at(lut_perm.at(i)) = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
set_config(ti, config.at(beli.y).at(beli.x), "LC_" + std::to_string(beli.z), lc.at(i), i);
|
||||
} else {
|
||||
for (int i = 0; i < swi.num_bits; i++) {
|
||||
bool val = (pi.switch_mask & (1 << ((swi.num_bits - 1) - i))) != 0;
|
||||
int8_t &cbit = config.at(swi.y).at(swi.x).at(swi.cbits[i].row).at(swi.cbits[i].col);
|
||||
if (bool(cbit) != 0)
|
||||
NPNR_ASSERT(false);
|
||||
cbit = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -295,9 +346,7 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
bool carry_enable = get_param_or_def(cell.second.get(), ctx->id("CARRY_ENABLE"));
|
||||
std::vector<bool> lc(20, false);
|
||||
// From arachne-pnr
|
||||
static std::vector<int> lut_perm = {
|
||||
4, 14, 15, 5, 6, 16, 17, 7, 3, 13, 12, 2, 1, 11, 10, 0,
|
||||
};
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((lut_init >> i) & 0x1)
|
||||
lc.at(lut_perm.at(i)) = true;
|
||||
|
@ -271,6 +271,16 @@ def pipdelay(src_idx, dst_idx, db):
|
||||
if re.match(r"ram/(MASK|RADDR|WADDR|WDATA)_", dst[2]):
|
||||
return db["InMux.I.O"]
|
||||
|
||||
if re.match(r"lutff_\d+/out", dst[2]):
|
||||
if re.match(r"lutff_\d+/in_0", src[2]):
|
||||
return db["LogicCell40.in0.lcout"]
|
||||
if re.match(r"lutff_\d+/in_1", src[2]):
|
||||
return db["LogicCell40.in1.lcout"]
|
||||
if re.match(r"lutff_\d+/in_2", src[2]):
|
||||
return db["LogicCell40.in2.lcout"]
|
||||
if re.match(r"lutff_\d+/in_3", src[2]):
|
||||
return db["LogicCell40.in3.lcout"]
|
||||
|
||||
print(src, dst, src_idx, dst_idx, src_type, dst_type, file=sys.stderr)
|
||||
assert 0
|
||||
|
||||
@ -316,12 +326,12 @@ with open(args.filename, "r") as f:
|
||||
|
||||
if line[0] == ".buffer":
|
||||
mode = ("buffer", int(line[3]), int(line[1]), int(line[2]))
|
||||
switches.append((line[3], int(line[1]), int(line[2]), line[4:]))
|
||||
switches.append((int(line[1]), int(line[2]), line[4:], -1))
|
||||
continue
|
||||
|
||||
if line[0] == ".routing":
|
||||
mode = ("routing", int(line[3]), int(line[1]), int(line[2]))
|
||||
switches.append((line[3], int(line[1]), int(line[2]), line[4:]))
|
||||
switches.append((int(line[1]), int(line[2]), line[4:], -1))
|
||||
continue
|
||||
|
||||
if line[0] == ".io_tile":
|
||||
@ -499,6 +509,22 @@ def add_wire(x, y, name):
|
||||
wire_names_r[wire_idx] = wname
|
||||
wire_segments[wire_idx] = dict()
|
||||
|
||||
def add_switch(x, y, bel=-1):
|
||||
switches.append((x, y, [], bel))
|
||||
|
||||
def add_pip(src, dst):
|
||||
x, y, _, _ = switches[-1]
|
||||
|
||||
if src not in wire_downhill:
|
||||
wire_downhill[src] = set()
|
||||
wire_downhill[src].add(dst)
|
||||
|
||||
if dst not in wire_uphill:
|
||||
wire_uphill[dst] = set()
|
||||
wire_uphill[dst].add(src)
|
||||
|
||||
pip_xy[(src, dst)] = (x, y, 0, len(switches) - 1)
|
||||
|
||||
# Add virtual padin wires
|
||||
for i in range(8):
|
||||
add_wire(0, 0, "padin_%d" % i)
|
||||
@ -555,6 +581,13 @@ def add_bel_lc(x, y, z):
|
||||
if wire_lout is not None:
|
||||
add_bel_output(bel, wire_lout, "LO")
|
||||
|
||||
# route-through LUTs
|
||||
add_switch(x, y, bel)
|
||||
add_pip(wire_in_0, wire_out)
|
||||
add_pip(wire_in_1, wire_out)
|
||||
add_pip(wire_in_2, wire_out)
|
||||
add_pip(wire_in_3, wire_out)
|
||||
|
||||
def add_bel_io(x, y, z):
|
||||
bel = len(bel_name)
|
||||
bel_name.append("X%d/Y%d/io%d" % (x, y, z))
|
||||
@ -1050,7 +1083,7 @@ for info in pipinfo:
|
||||
|
||||
switchinfo = []
|
||||
for switch in switches:
|
||||
dst, x, y, bits = switch
|
||||
x, y, bits, bel = switch
|
||||
bitlist = []
|
||||
for b in bits:
|
||||
m = cbit_re.match(b)
|
||||
@ -1060,11 +1093,13 @@ for switch in switches:
|
||||
si["x"] = x
|
||||
si["y"] = y
|
||||
si["bits"] = bitlist
|
||||
si["bel"] = bel
|
||||
switchinfo.append(si)
|
||||
|
||||
bba.l("switch_data_%s" % dev_name, "SwitchInfoPOD")
|
||||
for info in switchinfo:
|
||||
bba.u32(len(info["bits"]), "num_bits")
|
||||
bba.u32(info["bel"], "bel")
|
||||
bba.u8(info["x"], "x")
|
||||
bba.u8(info["y"], "y")
|
||||
for i in range(5):
|
||||
|
24
ice40/gfx.cc
24
ice40/gfx.cc
@ -696,11 +696,30 @@ void gfxTilePip(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId src,
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
if (getWireXY_main(src, x1, y1) && getWireXY_main(dst, x2, y2))
|
||||
if (getWireXY_main(src, x1, y1) && getWireXY_main(dst, x2, y2)) {
|
||||
pipGfx(g, x, y, x1, y1, x2, y2, main_swbox_x1, main_swbox_y1, main_swbox_x2, main_swbox_y2, style);
|
||||
return;
|
||||
}
|
||||
|
||||
if (getWireXY_local(src, x1, y1) && getWireXY_local(dst, x2, y2))
|
||||
if (getWireXY_local(src, x1, y1) && getWireXY_local(dst, x2, y2)) {
|
||||
pipGfx(g, x, y, x1, y1, x2, y2, local_swbox_x1, local_swbox_y1, local_swbox_x2, local_swbox_y2, style);
|
||||
return;
|
||||
}
|
||||
|
||||
if (TILE_WIRE_LUTFF_0_IN_0 <= src && src <= TILE_WIRE_LUTFF_7_IN_3 && TILE_WIRE_LUTFF_0_OUT <= dst && dst <= TILE_WIRE_LUTFF_7_OUT) {
|
||||
int lut_idx = (src - TILE_WIRE_LUTFF_0_IN_0) / 4;
|
||||
int in_idx = (src - TILE_WIRE_LUTFF_0_IN_0) % 4;
|
||||
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::TYPE_ARROW;
|
||||
el.style = style;
|
||||
el.x1 = x + logic_cell_x1;
|
||||
el.x2 = x + logic_cell_x2;
|
||||
el.y1 = y + (logic_cell_y1 + logic_cell_y2) / 2 - 0.0075 + (0.005 * in_idx) + lut_idx * logic_cell_pitch;
|
||||
el.y2 = y + (logic_cell_y1 + logic_cell_y2) / 2 + lut_idx * logic_cell_pitch;
|
||||
g.push_back(el);
|
||||
return;
|
||||
}
|
||||
|
||||
if (src == TILE_WIRE_CARRY_IN && dst == TILE_WIRE_CARRY_IN_MUX) {
|
||||
GraphicElement el;
|
||||
@ -711,6 +730,7 @@ void gfxTilePip(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId src,
|
||||
el.y1 = y + 0.01;
|
||||
el.y2 = y + 0.02;
|
||||
g.push_back(el);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user