aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ice40/arch.cc56
-rw-r--r--ice40/arch.h59
-rw-r--r--ice40/archdefs.h15
-rw-r--r--ice40/chipdb.py178
-rw-r--r--ice40/gfx.cc34
-rw-r--r--ice40/gfx.h51
6 files changed, 310 insertions, 83 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc
index 3934e8f0..2430b7ce 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -174,6 +174,7 @@ Arch::Arch(ArchArgs args) : args(args)
if (package_info == nullptr)
log_error("Unsupported package '%s'.\n", args.package.c_str());
+ bel_carry.resize(chip_info->num_bels);
bel_to_cell.resize(chip_info->num_bels);
wire_to_net.resize(chip_info->num_wires);
pip_to_net.resize(chip_info->num_pips);
@@ -192,6 +193,7 @@ Arch::Arch(ArchArgs args) : args(args)
id_i2 = id("I2");
id_i3 = id("I3");
id_dff_en = id("DFF_ENABLE");
+ id_carry_en = id("CARRY_ENABLE");
id_neg_clk = id("NEG_CLK");
id_cin = id("CIN");
id_cout = id("COUT");
@@ -399,6 +401,45 @@ WireId Arch::getWireByName(IdString name) const
return ret;
}
+IdString Arch::getWireType(WireId wire) const
+{
+ NPNR_ASSERT(wire != WireId());
+ switch (chip_info->wire_data[wire.index].type)
+ {
+ case WireInfoPOD::WIRE_TYPE_NONE:
+ return IdString();
+ case WireInfoPOD::WIRE_TYPE_GLB2LOCAL:
+ return id("GLB2LOCAL");
+ case WireInfoPOD::WIRE_TYPE_GLB_NETWK:
+ return id("GLB_NETWK");
+ case WireInfoPOD::WIRE_TYPE_LOCAL:
+ return id("LOCAL");
+ case WireInfoPOD::WIRE_TYPE_LUTFF_IN:
+ return id("LUTFF_IN");
+ case WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT:
+ return id("LUTFF_IN_LUT");
+ case WireInfoPOD::WIRE_TYPE_LUTFF_LOUT:
+ return id("LUTFF_LOUT");
+ case WireInfoPOD::WIRE_TYPE_LUTFF_OUT:
+ return id("LUTFF_OUT");
+ case WireInfoPOD::WIRE_TYPE_LUTFF_COUT:
+ return id("LUTFF_COUT");
+ case WireInfoPOD::WIRE_TYPE_LUTFF_GLOBAL:
+ return id("LUTFF_GLOBAL");
+ case WireInfoPOD::WIRE_TYPE_CARRY_IN_MUX:
+ return id("CARRY_IN_MUX");
+ case WireInfoPOD::WIRE_TYPE_SP4_V:
+ return id("SP4_V");
+ case WireInfoPOD::WIRE_TYPE_SP4_H:
+ return id("SP4_H");
+ case WireInfoPOD::WIRE_TYPE_SP12_V:
+ return id("SP12_V");
+ case WireInfoPOD::WIRE_TYPE_SP12_H:
+ return id("SP12_H");
+ }
+ return IdString();
+}
+
// -----------------------------------------------------------------------
PipId Arch::getPipByName(IdString name) const
@@ -541,7 +582,6 @@ std::vector<GroupId> Arch::getGroups() const
group.type = GroupId::TYPE_LOCAL_SW;
ret.push_back(group);
-#if 0
if (type == TILE_LOGIC)
{
group.type = GroupId::TYPE_LC0_SW;
@@ -568,7 +608,6 @@ std::vector<GroupId> Arch::getGroups() const
group.type = GroupId::TYPE_LC7_SW;
ret.push_back(group);
}
-#endif
}
}
return ret;
@@ -768,6 +807,18 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
el.y2 = y + local_swbox_y2;
ret.push_back(el);
}
+
+ if (GroupId::TYPE_LC0_SW <= type && type <= GroupId::TYPE_LC7_SW) {
+ GraphicElement el;
+ el.type = GraphicElement::TYPE_BOX;
+ el.style = GraphicElement::STYLE_FRAME;
+
+ el.x1 = x + lut_swbox_x1;
+ el.x2 = x + lut_swbox_x2;
+ el.y1 = y + logic_cell_y1 + logic_cell_pitch * (type - GroupId::TYPE_LC0_SW);
+ el.y2 = y + logic_cell_y2 + logic_cell_pitch * (type - GroupId::TYPE_LC0_SW);
+ ret.push_back(el);
+ }
}
if (decal.type == DecalId::TYPE_WIRE) {
@@ -918,6 +969,7 @@ void Arch::assignCellInfo(CellInfo *cell)
cell->belType = belTypeFromId(cell->type);
if (cell->type == id_icestorm_lc) {
cell->lcInfo.dffEnable = bool_or_default(cell->params, id_dff_en);
+ cell->lcInfo.carryEnable = bool_or_default(cell->params, id_carry_en);
cell->lcInfo.negClk = bool_or_default(cell->params, id_neg_clk);
cell->lcInfo.clk = get_net_or_empty(cell, id_clk);
cell->lcInfo.cen = get_net_or_empty(cell, id_cen);
diff --git a/ice40/arch.h b/ice40/arch.h
index cf78088a..0be76296 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -64,6 +64,13 @@ NPNR_PACKED_STRUCT(struct BelPortPOD {
});
NPNR_PACKED_STRUCT(struct PipInfoPOD {
+ enum PipFlags : uint32_t
+ {
+ FLAG_NONE = 0,
+ FLAG_ROUTETHRU = 1,
+ FLAG_NOCARRY = 2
+ };
+
// RelPtr<char> name;
int32_t src, dst;
int32_t fast_delay;
@@ -72,6 +79,7 @@ NPNR_PACKED_STRUCT(struct PipInfoPOD {
int16_t src_seg, dst_seg;
int16_t switch_mask;
int32_t switch_index;
+ PipFlags flags;
});
NPNR_PACKED_STRUCT(struct WireSegmentPOD {
@@ -80,6 +88,25 @@ NPNR_PACKED_STRUCT(struct WireSegmentPOD {
});
NPNR_PACKED_STRUCT(struct WireInfoPOD {
+ enum WireType : int8_t
+ {
+ WIRE_TYPE_NONE = 0,
+ WIRE_TYPE_GLB2LOCAL = 1,
+ WIRE_TYPE_GLB_NETWK = 2,
+ WIRE_TYPE_LOCAL = 3,
+ WIRE_TYPE_LUTFF_IN = 4,
+ WIRE_TYPE_LUTFF_IN_LUT = 5,
+ WIRE_TYPE_LUTFF_LOUT = 6,
+ WIRE_TYPE_LUTFF_OUT = 7,
+ WIRE_TYPE_LUTFF_COUT = 8,
+ WIRE_TYPE_LUTFF_GLOBAL = 9,
+ WIRE_TYPE_CARRY_IN_MUX = 10,
+ WIRE_TYPE_SP4_V = 11,
+ WIRE_TYPE_SP4_H = 12,
+ WIRE_TYPE_SP12_V = 13,
+ WIRE_TYPE_SP12_H = 14
+ };
+
RelPtr<char> name;
int32_t num_uphill, num_downhill;
RelPtr<int32_t> pips_uphill, pips_downhill;
@@ -373,6 +400,7 @@ struct Arch : BaseCtx
mutable std::unordered_map<IdString, int> pip_by_name;
mutable std::unordered_map<Loc, int> bel_by_loc;
+ std::vector<bool> bel_carry;
std::vector<IdString> bel_to_cell;
std::vector<IdString> wire_to_net;
std::vector<IdString> pip_to_net;
@@ -414,9 +442,12 @@ struct Arch : BaseCtx
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] == IdString());
+ auto &c = cells[cell];
+
bel_to_cell[bel.index] = cell;
- cells[cell]->bel = bel;
- cells[cell]->belStrength = strength;
+ bel_carry[bel.index] = (c->type == id_icestorm_lc && c->lcInfo.carryEnable);
+ c->bel = bel;
+ c->belStrength = strength;
refreshUiBel(bel);
}
@@ -427,6 +458,7 @@ struct Arch : BaseCtx
cells[bel_to_cell[bel.index]]->bel = BelId();
cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE;
bel_to_cell[bel.index] = IdString();
+ bel_carry[bel.index] = false;
refreshUiBel(bel);
}
@@ -490,7 +522,7 @@ struct Arch : BaseCtx
return id(chip_info->wire_data[wire.index].name.get());
}
- IdString getWireType(WireId wire) const { return IdString(); }
+ IdString getWireType(WireId wire) const;
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
@@ -614,14 +646,23 @@ struct Arch : BaseCtx
bool checkPipAvail(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
- int switch_idx = chip_info->pip_data[pip.index].switch_index;
+ auto &pi = chip_info->pip_data[pip.index];
+ auto &si = chip_info->bits_info->switches[pi.switch_index];
- if (switches_locked[switch_idx] != IdString())
+ if (switches_locked[pi.switch_index] != 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;
+ if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) {
+ NPNR_ASSERT(si.bel >= 0);
+ if (bel_to_cell[si.bel] != IdString())
+ return false;
+ }
+
+ if (pi.flags & PipInfoPOD::FLAG_NOCARRY) {
+ NPNR_ASSERT(si.bel >= 0);
+ if (bel_carry[si.bel])
+ return false;
+ }
return true;
}
@@ -781,7 +822,7 @@ struct Arch : BaseCtx
IdString id_icestorm_lc, id_sb_io, id_sb_gb;
IdString id_cen, id_clk, id_sr;
IdString id_i0, id_i1, id_i2, id_i3;
- IdString id_dff_en, id_neg_clk;
+ IdString id_dff_en, id_carry_en, id_neg_clk;
IdString id_cin, id_cout;
IdString id_o, id_lo;
IdString id_icestorm_ram, id_rclk, id_wclk;
diff --git a/ice40/archdefs.h b/ice40/archdefs.h
index 9329609e..7125ba16 100644
--- a/ice40/archdefs.h
+++ b/ice40/archdefs.h
@@ -77,17 +77,6 @@ enum PortPin : int32_t
PIN_MAXIDX
};
-enum WireType : int8_t
-{
- WIRE_TYPE_NONE = 0,
- WIRE_TYPE_LOCAL = 1,
- WIRE_TYPE_GLOBAL = 2,
- WIRE_TYPE_SP4_VERT = 3,
- WIRE_TYPE_SP4_HORZ = 4,
- WIRE_TYPE_SP12_HORZ = 5,
- WIRE_TYPE_SP12_VERT = 6
-};
-
struct BelId
{
int32_t index = -1;
@@ -167,7 +156,9 @@ struct ArchCellInfo
{
struct
{
- bool dffEnable, negClk;
+ bool dffEnable;
+ bool carryEnable;
+ bool negClk;
int inputCount;
const NetInfo *clk, *cen, *sr;
} lcInfo;
diff --git a/ice40/chipdb.py b/ice40/chipdb.py
index d782013f..c1819481 100644
--- a/ice40/chipdb.py
+++ b/ice40/chipdb.py
@@ -134,12 +134,21 @@ tiletypes["DSP2"] = 7
tiletypes["DSP3"] = 8
tiletypes["IPCON"] = 9
-wiretypes["LOCAL"] = 1
-wiretypes["GLOBAL"] = 2
-wiretypes["SP4_VERT"] = 3
-wiretypes["SP4_HORZ"] = 4
-wiretypes["SP12_HORZ"] = 5
-wiretypes["SP12_VERT"] = 6
+wiretypes["NONE"] = 0
+wiretypes["GLB2LOCAL"] = 1
+wiretypes["GLB_NETWK"] = 2
+wiretypes["LOCAL"] = 3
+wiretypes["LUTFF_IN"] = 4
+wiretypes["LUTFF_IN_LUT"] = 5
+wiretypes["LUTFF_LOUT"] = 6
+wiretypes["LUTFF_OUT"] = 7
+wiretypes["LUTFF_COUT"] = 8
+wiretypes["LUTFF_GLOBAL"] = 9
+wiretypes["CARRY_IN_MUX"] = 10
+wiretypes["SP4_V"] = 11
+wiretypes["SP4_H"] = 12
+wiretypes["SP12_V"] = 13
+wiretypes["SP12_H"] = 14
def maj_wire_name(name):
if name[2].startswith("lutff_"):
@@ -179,40 +188,84 @@ def cmp_wire_names(newname, oldname):
def wire_type(name):
longname = name
- name = name.split('/')[-1]
- wt = None
-
- if name.startswith("glb_netwk_") or name.startswith("padin_"):
- wt = "GLOBAL"
- elif name.startswith("D_IN_") or name.startswith("D_OUT_"):
- wt = "LOCAL"
- elif name in ("OUT_ENB", "cen", "inclk", "latch", "outclk", "clk", "s_r", "carry_in", "carry_in_mux"):
- wt = "LOCAL"
- elif name in ("in_0", "in_1", "in_2", "in_3", "cout", "lout", "out", "fabout") or name.startswith("slf_op") or name.startswith("O_"):
- wt = "LOCAL"
- elif name.startswith("local_g") or name.startswith("glb2local_"):
- wt = "LOCAL"
- elif name.startswith("span4_horz_") or name.startswith("sp4_h_"):
- wt = "SP4_HORZ"
- elif name.startswith("span4_vert_") or name.startswith("sp4_v_") or name.startswith("sp4_r_v_"):
- wt = "SP4_VERT"
- elif name.startswith("span12_horz_") or name.startswith("sp12_h_"):
- wt = "SP12_HORZ"
- elif name.startswith("span12_vert_") or name.startswith("sp12_v_"):
- wt = "SP12_VERT"
- elif name.startswith("MASK_") or name.startswith("RADDR_") or name.startswith("WADDR_"):
- wt = "LOCAL"
- elif name.startswith("RDATA_") or name.startswith("WDATA_") or name.startswith("neigh_op_"):
- wt = "LOCAL"
- elif name in ("WCLK", "WCLKE", "WE", "RCLK", "RCLKE", "RE"):
- wt = "LOCAL"
- elif name in ("PLLOUT_A", "PLLOUT_B"):
- wt = "LOCAL"
-
- if wt is None:
- print("No type for wire: %s (%s)" % (longname, name), file=sys.stderr)
- assert 0
- return wt
+ name = name.split('/')
+
+ if name[0].startswith("X") and name[1].startswith("Y"):
+ name = name[2:]
+
+ if name[0].startswith("sp4_v_") or name[0].startswith("sp4_r_v_") or name[0].startswith("span4_vert_"):
+ return "SP4_V"
+
+ if name[0].startswith("sp4_h_") or name[0].startswith("span4_horz_"):
+ return "SP4_H"
+
+ if name[0].startswith("sp12_v_") or name[0].startswith("span12_vert_"):
+ return "SP12_V"
+
+ if name[0].startswith("sp12_h_") or name[0].startswith("span12_horz_"):
+ return "SP12_H"
+
+ if name[0].startswith("glb2local"):
+ return "GLB2LOCAL"
+
+ if name[0].startswith("glb_netwk_"):
+ return "GLB_NETWK"
+
+ if name[0].startswith("local_"):
+ return "LOCAL"
+
+ if name[0].startswith("lutff_"):
+ if name[1].startswith("in_"):
+ return "LUTFF_IN_LUT" if name[1].endswith("_lut") else "LUTFF_IN"
+
+ if name[1] == "lout":
+ return "LUTFF_LOUT"
+ if name[1] == "out":
+ return "LUTFF_OUT"
+ if name[1] == "cout":
+ return "LUTFF_COUT"
+
+ if name[0] == "ram":
+ if name[1].startswith("RADDR_"):
+ return "LUTFF_IN"
+ if name[1].startswith("WADDR_"):
+ return "LUTFF_IN"
+ if name[1].startswith("WDATA_"):
+ return "LUTFF_IN"
+ if name[1].startswith("MASK_"):
+ return "LUTFF_IN"
+ if name[1].startswith("RDATA_"):
+ return "LUTFF_OUT"
+ if name[1] in ("WCLK", "WCLKE", "WE", "RCLK", "RCLKE", "RE"):
+ return "LUTFF_GLOBAL"
+
+ if name[0].startswith("io_"):
+ if name[1].startswith("D_IN_") or name[1] == "OUT_ENB":
+ return "LUTFF_IN"
+ if name[1].startswith("D_OUT_"):
+ return "LUTFF_OUT"
+ if name[0] == "fabout":
+ return "LUTFF_IN"
+
+ if name[0] == "lutff_global" or name[0] == "io_global":
+ return "LUTFF_GLOBAL"
+
+ if name[0] == "carry_in_mux":
+ return "CARRY_IN_MUX"
+
+ if name[0] == "carry_in":
+ return "LUTFF_COUT"
+
+ if name[0].startswith("neigh_op_"):
+ return "NONE"
+
+ if name[0].startswith("padin_"):
+ return "NONE"
+
+ # print("No type for wire: %s (%s)" % (longname, name), file=sys.stderr)
+ # assert 0
+
+ return "NONE"
def pipdelay(src_idx, dst_idx, db):
if db is None:
@@ -265,9 +318,12 @@ def pipdelay(src_idx, dst_idx, db):
if src[2].startswith("local_") and dst[2] in ("io_0/D_OUT_0", "io_0/D_OUT_1", "io_0/OUT_ENB", "io_1/D_OUT_0", "io_1/D_OUT_1", "io_1/OUT_ENB"):
return db["IoInMux.I.O"]
- if re.match(r"lutff_\d+/in_\d+", dst[2]):
+ if re.match(r"lutff_\d+/in_\d+$", dst[2]):
return db["InMux.I.O"]
+ if re.match(r"lutff_\d+/in_\d+_lut", dst[2]):
+ return 0
+
if re.match(r"ram/(MASK|RADDR|WADDR|WDATA)_", dst[2]):
return db["InMux.I.O"]
@@ -472,7 +528,7 @@ with open(args.filename, "r") as f:
wire_uphill[wire_b] = set()
wire_downhill[wire_a].add(wire_b)
wire_uphill[wire_b].add(wire_a)
- pip_xy[(wire_a, wire_b)] = (mode[2], mode[3], int(line[0], 2), len(switches) - 1)
+ pip_xy[(wire_a, wire_b)] = (mode[2], mode[3], int(line[0], 2), len(switches) - 1, 0)
continue
if mode[0] == "bits":
@@ -508,11 +564,14 @@ def add_wire(x, y, name):
wire_names[wname] = wire_idx
wire_names_r[wire_idx] = wname
wire_segments[wire_idx] = dict()
+ if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids:
+ wire_segments[wire_idx][(wname[0], wname[1])] = wname[2]
+ return wire_idx
def add_switch(x, y, bel=-1):
switches.append((x, y, [], bel))
-def add_pip(src, dst):
+def add_pip(src, dst, flags=0):
x, y, _, _ = switches[-1]
if src not in wire_downhill:
@@ -523,7 +582,7 @@ def add_pip(src, dst):
wire_uphill[dst] = set()
wire_uphill[dst].add(src)
- pip_xy[(src, dst)] = (x, y, 0, len(switches) - 1)
+ pip_xy[(src, dst)] = (x, y, 0, len(switches) - 1, flags)
# Add virtual padin wires
for i in range(8):
@@ -557,10 +616,11 @@ def add_bel_lc(x, y, z):
else:
wire_cin = wire_names[(x, y, "lutff_%d/cout" % (z-1))]
- wire_in_0 = wire_names[(x, y, "lutff_%d/in_0" % z)]
- wire_in_1 = wire_names[(x, y, "lutff_%d/in_1" % z)]
- wire_in_2 = wire_names[(x, y, "lutff_%d/in_2" % z)]
- wire_in_3 = wire_names[(x, y, "lutff_%d/in_3" % z)]
+ wire_in_0 = add_wire(x, y, "lutff_%d/in_0_lut" % z)
+ wire_in_1 = add_wire(x, y, "lutff_%d/in_1_lut" % z)
+ wire_in_2 = add_wire(x, y, "lutff_%d/in_2_lut" % z)
+ wire_in_3 = add_wire(x, y, "lutff_%d/in_3_lut" % z)
+
wire_out = wire_names[(x, y, "lutff_%d/out" % z)]
wire_cout = wire_names[(x, y, "lutff_%d/cout" % z)]
wire_lout = wire_names[(x, y, "lutff_%d/lout" % z)] if z < 7 else None
@@ -583,10 +643,21 @@ def add_bel_lc(x, y, z):
# 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)
+ add_pip(wire_in_0, wire_out, 1)
+ add_pip(wire_in_1, wire_out, 1)
+ add_pip(wire_in_2, wire_out, 1)
+ add_pip(wire_in_3, wire_out, 1)
+
+ # LUT permutation pips
+ for i in range(4):
+ add_switch(x, y, bel)
+ for j in range(4):
+ if (i == j) or ((i, j) == (1, 2)) or ((i, j) == (2, 1)):
+ flags = 0
+ else:
+ flags = 2
+ add_pip(wire_names[(x, y, "lutff_%d/in_%d" % (z, i))],
+ wire_names[(x, y, "lutff_%d/in_%d_lut" % (z, j))], flags)
def add_bel_io(x, y, z):
bel = len(bel_name)
@@ -902,6 +973,7 @@ for wire in range(num_wires):
pi["y"] = pip_xy[(src, wire)][1]
pi["switch_mask"] = pip_xy[(src, wire)][2]
pi["switch_index"] = pip_xy[(src, wire)][3]
+ pi["flags"] = pip_xy[(src, wire)][4]
pipinfo.append(pi)
pips.append(pipcache[(src, wire)])
num_uphill = len(pips)
@@ -927,6 +999,7 @@ for wire in range(num_wires):
pi["y"] = pip_xy[(wire, dst)][1]
pi["switch_mask"] = pip_xy[(wire, dst)][2]
pi["switch_index"] = pip_xy[(wire, dst)][3]
+ pi["flags"] = pip_xy[(wire, dst)][4]
pipinfo.append(pi)
pips.append(pipcache[(wire, dst)])
num_downhill = len(pips)
@@ -1084,6 +1157,7 @@ for info in pipinfo:
bba.u16(dst_seg, "dst_seg")
bba.u16(info["switch_mask"], "switch_mask")
bba.u32(info["switch_index"], "switch_index")
+ bba.u32(info["flags"], "flags")
switchinfo = []
for switch in switches:
diff --git a/ice40/gfx.cc b/ice40/gfx.cc
index d5c6e77f..6eda6913 100644
--- a/ice40/gfx.cc
+++ b/ice40/gfx.cc
@@ -391,6 +391,17 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id,
int z = idx / 4;
int input = idx % 4;
el.x1 = x + local_swbox_x2;
+ el.x2 = x + lut_swbox_x1;
+ el.y1 = y + (logic_cell_y1 + logic_cell_y2) / 2 - 0.0075 + (0.005 * input) + z * logic_cell_pitch;
+ el.y2 = el.y1;
+ g.push_back(el);
+ }
+
+ if (id >= TILE_WIRE_LUTFF_0_IN_0_LUT && id <= TILE_WIRE_LUTFF_7_IN_3_LUT) {
+ int idx = id - TILE_WIRE_LUTFF_0_IN_0_LUT;
+ int z = idx / 4;
+ int input = idx % 4;
+ el.x1 = x + lut_swbox_x2;
el.x2 = x + logic_cell_x1;
el.y1 = y + (logic_cell_y1 + logic_cell_y2) / 2 - 0.0075 + (0.005 * input) + z * logic_cell_pitch;
el.y2 = el.y1;
@@ -706,10 +717,9 @@ void gfxTilePip(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId src,
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;
+ if (TILE_WIRE_LUTFF_0_IN_0_LUT <= src && src <= TILE_WIRE_LUTFF_7_IN_3_LUT && TILE_WIRE_LUTFF_0_OUT <= dst && dst <= TILE_WIRE_LUTFF_7_OUT) {
+ int lut_idx = (src - TILE_WIRE_LUTFF_0_IN_0_LUT) / 4;
+ int in_idx = (src - TILE_WIRE_LUTFF_0_IN_0_LUT) % 4;
GraphicElement el;
el.type = GraphicElement::TYPE_ARROW;
@@ -722,6 +732,22 @@ void gfxTilePip(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId src,
return;
}
+ if (TILE_WIRE_LUTFF_0_IN_0 <= src && src <= TILE_WIRE_LUTFF_7_IN_3 && TILE_WIRE_LUTFF_0_IN_0_LUT <= dst && dst <= TILE_WIRE_LUTFF_7_IN_3_LUT) {
+ int lut_idx = (src - TILE_WIRE_LUTFF_0_IN_0) / 4;
+ int in_idx = (src - TILE_WIRE_LUTFF_0_IN_0) % 4;
+ int out_idx = (dst - TILE_WIRE_LUTFF_0_IN_0_LUT) % 4;
+
+ GraphicElement el;
+ el.type = GraphicElement::TYPE_ARROW;
+ el.style = style;
+ el.x1 = x + lut_swbox_x1;
+ el.x2 = x + lut_swbox_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 - 0.0075 + (0.005 * out_idx) + lut_idx * logic_cell_pitch;
+ g.push_back(el);
+ return;
+ }
+
if (src == TILE_WIRE_CARRY_IN && dst == TILE_WIRE_CARRY_IN_MUX) {
GraphicElement el;
el.type = GraphicElement::TYPE_ARROW;
diff --git a/ice40/gfx.h b/ice40/gfx.h
index 7eeaccf1..8ee7b0b6 100644
--- a/ice40/gfx.h
+++ b/ice40/gfx.h
@@ -34,7 +34,10 @@ const float local_swbox_x2 = 0.73;
const float local_swbox_y1 = 0.05;
const float local_swbox_y2 = 0.55;
-const float logic_cell_x1 = 0.76;
+const float lut_swbox_x1 = 0.76;
+const float lut_swbox_x2 = 0.80;
+
+const float logic_cell_x1 = 0.83;
const float logic_cell_x2 = 0.95;
const float logic_cell_y1 = 0.05;
const float logic_cell_y2 = 0.10;
@@ -92,9 +95,6 @@ enum GfxTileWireId
TILE_WIRE_LOCAL_G3_6,
TILE_WIRE_LOCAL_G3_7,
- TILE_WIRE_CARRY_IN,
- TILE_WIRE_CARRY_IN_MUX,
-
TILE_WIRE_LUTFF_0_IN_0,
TILE_WIRE_LUTFF_0_IN_1,
TILE_WIRE_LUTFF_0_IN_2,
@@ -135,6 +135,46 @@ enum GfxTileWireId
TILE_WIRE_LUTFF_7_IN_2,
TILE_WIRE_LUTFF_7_IN_3,
+ TILE_WIRE_LUTFF_0_IN_0_LUT,
+ TILE_WIRE_LUTFF_0_IN_1_LUT,
+ TILE_WIRE_LUTFF_0_IN_2_LUT,
+ TILE_WIRE_LUTFF_0_IN_3_LUT,
+
+ TILE_WIRE_LUTFF_1_IN_0_LUT,
+ TILE_WIRE_LUTFF_1_IN_1_LUT,
+ TILE_WIRE_LUTFF_1_IN_2_LUT,
+ TILE_WIRE_LUTFF_1_IN_3_LUT,
+
+ TILE_WIRE_LUTFF_2_IN_0_LUT,
+ TILE_WIRE_LUTFF_2_IN_1_LUT,
+ TILE_WIRE_LUTFF_2_IN_2_LUT,
+ TILE_WIRE_LUTFF_2_IN_3_LUT,
+
+ TILE_WIRE_LUTFF_3_IN_0_LUT,
+ TILE_WIRE_LUTFF_3_IN_1_LUT,
+ TILE_WIRE_LUTFF_3_IN_2_LUT,
+ TILE_WIRE_LUTFF_3_IN_3_LUT,
+
+ TILE_WIRE_LUTFF_4_IN_0_LUT,
+ TILE_WIRE_LUTFF_4_IN_1_LUT,
+ TILE_WIRE_LUTFF_4_IN_2_LUT,
+ TILE_WIRE_LUTFF_4_IN_3_LUT,
+
+ TILE_WIRE_LUTFF_5_IN_0_LUT,
+ TILE_WIRE_LUTFF_5_IN_1_LUT,
+ TILE_WIRE_LUTFF_5_IN_2_LUT,
+ TILE_WIRE_LUTFF_5_IN_3_LUT,
+
+ TILE_WIRE_LUTFF_6_IN_0_LUT,
+ TILE_WIRE_LUTFF_6_IN_1_LUT,
+ TILE_WIRE_LUTFF_6_IN_2_LUT,
+ TILE_WIRE_LUTFF_6_IN_3_LUT,
+
+ TILE_WIRE_LUTFF_7_IN_0_LUT,
+ TILE_WIRE_LUTFF_7_IN_1_LUT,
+ TILE_WIRE_LUTFF_7_IN_2_LUT,
+ TILE_WIRE_LUTFF_7_IN_3_LUT,
+
TILE_WIRE_LUTFF_0_LOUT,
TILE_WIRE_LUTFF_1_LOUT,
TILE_WIRE_LUTFF_2_LOUT,
@@ -165,6 +205,9 @@ enum GfxTileWireId
TILE_WIRE_LUTFF_GLOBAL_CLK,
TILE_WIRE_LUTFF_GLOBAL_S_R,
+ TILE_WIRE_CARRY_IN,
+ TILE_WIRE_CARRY_IN_MUX,
+
TILE_WIRE_NEIGH_OP_BNL_0,
TILE_WIRE_NEIGH_OP_BNL_1,
TILE_WIRE_NEIGH_OP_BNL_2,