diff options
Diffstat (limited to 'ice40')
| -rw-r--r-- | ice40/arch.cc | 108 | ||||
| -rw-r--r-- | ice40/arch.h | 9 | ||||
| -rw-r--r-- | ice40/bitstream.cc | 10 | ||||
| -rw-r--r-- | ice40/cells.cc | 3 | ||||
| -rw-r--r-- | ice40/chipdb.py | 216 | ||||
| -rw-r--r-- | ice40/family.cmake | 4 | ||||
| -rw-r--r-- | ice40/gfx.cc | 319 | ||||
| -rw-r--r-- | ice40/gfx.h | 202 | ||||
| -rw-r--r-- | ice40/pack.cc | 37 | ||||
| -rw-r--r-- | ice40/pcf.cc | 2 | ||||
| -rw-r--r-- | ice40/project.cc | 4 |
11 files changed, 839 insertions, 75 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc index 7e2dd7f7..3983a24e 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -226,6 +226,15 @@ PortType Arch::getBelPinType(BelId bel, IdString pin) const return PORT_INOUT; } +std::vector<std::pair<IdString, std::string>> Arch::getBelAttrs(BelId bel) const +{ + std::vector<std::pair<IdString, std::string>> ret; + + ret.push_back(std::make_pair(id("INDEX"), stringf("%d", bel.index))); + + return ret; +} + WireId Arch::getBelPinWire(BelId bel, IdString pin) const { WireId ret; @@ -331,6 +340,28 @@ IdString Arch::getWireType(WireId wire) const return IdString(); } +std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) const +{ + std::vector<std::pair<IdString, std::string>> ret; + auto &wi = chip_info->wire_data[wire.index]; + + ret.push_back(std::make_pair(id("INDEX"), stringf("%d", wire.index))); + + ret.push_back(std::make_pair(id("GRID_X"), stringf("%d", wi.x))); + ret.push_back(std::make_pair(id("GRID_Y"), stringf("%d", wi.y))); + ret.push_back(std::make_pair(id("GRID_Z"), stringf("%d", wi.z))); + +#if 0 + for (int i = 0; i < wi.num_segments; i++) { + auto &si = wi.segments[i]; + ret.push_back(std::make_pair(id(stringf("segment[%d]", i)), + stringf("X%d/Y%d/%s", si.x, si.y, chip_info->tile_wire_names[si.index].get()))); + } +#endif + + return ret; +} + // ----------------------------------------------------------------------- PipId Arch::getPipByName(IdString name) const @@ -372,6 +403,18 @@ IdString Arch::getPipName(PipId pip) const #endif } +IdString Arch::getPipType(PipId pip) const { return IdString(); } + +std::vector<std::pair<IdString, std::string>> Arch::getPipAttrs(PipId pip) const +{ + std::vector<std::pair<IdString, std::string>> ret; + + ret.push_back(std::make_pair(id("INDEX"), stringf("%d", pip.index))); + + return ret; +} + + // ----------------------------------------------------------------------- BelId Arch::getPackagePinBel(const std::string &pin) const @@ -565,18 +608,9 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay // ----------------------------------------------------------------------- -bool Arch::place() -{ - Placer1Cfg cfg; - cfg.constraintWeight = placer_constraintWeight; - return placer1(getCtx(), cfg); -} +bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); } -bool Arch::route() -{ - Router1Cfg cfg; - return router1(getCtx(), cfg); -} +bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); } // ----------------------------------------------------------------------- @@ -695,13 +729,29 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; for (int i = 0; i < n; i++) - gfxTileWire(ret, p[i].x, p[i].y, GfxTileWireId(p[i].index), style); + gfxTileWire(ret, p[i].x, p[i].y, chip_info->width, chip_info->height, GfxTileWireId(p[i].index), style); + +#if 0 + if (ret.empty()) { + WireId wire; + wire.index = decal.index; + log_warning("No gfx decal for wire %s (%d).\n", getWireName(wire).c_str(getCtx()), decal.index); + } +#endif } if (decal.type == DecalId::TYPE_PIP) { const PipInfoPOD &p = chip_info->pip_data[decal.index]; GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_HIDDEN; gfxTilePip(ret, p.x, p.y, GfxTileWireId(p.src_seg), GfxTileWireId(p.dst_seg), style); + +#if 0 + if (ret.empty()) { + PipId pip; + pip.index = decal.index; + log_warning("No gfx decal for pip %s (%d).\n", getPipName(pip).c_str(getCtx()), decal.index); + } +#endif } if (decal.type == DecalId::TYPE_BEL) { @@ -727,7 +777,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const GraphicElement el; el.type = GraphicElement::TYPE_BOX; el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; - el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1; + el.x1 = chip_info->bel_data[bel.index].x + lut_swbox_x1; el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2; el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1 + (4 * chip_info->bel_data[bel.index].z) * logic_cell_pitch; @@ -741,13 +791,43 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const GraphicElement el; el.type = GraphicElement::TYPE_BOX; el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; - el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1; + el.x1 = chip_info->bel_data[bel.index].x + lut_swbox_x1; el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2; el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1 + i; el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + i + 7 * logic_cell_pitch; ret.push_back(el); } } + + if (bel_type == id_SB_GB) { + GraphicElement el; + el.type = GraphicElement::TYPE_BOX; + el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; + el.x1 = chip_info->bel_data[bel.index].x + local_swbox_x1 + 0.05; + el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2 - 0.05; + el.y1 = chip_info->bel_data[bel.index].y + main_swbox_y2 - 0.05; + el.y2 = chip_info->bel_data[bel.index].y + main_swbox_y2 - 0.10; + ret.push_back(el); + } + + if (bel_type == id_ICESTORM_PLL || bel_type == id_SB_WARMBOOT) { + GraphicElement el; + el.type = GraphicElement::TYPE_BOX; + el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; + el.x1 = chip_info->bel_data[bel.index].x + local_swbox_x1 + 0.05; + el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2 - 0.05; + el.y1 = chip_info->bel_data[bel.index].y + main_swbox_y2; + el.y2 = chip_info->bel_data[bel.index].y + main_swbox_y2 + 0.05; + ret.push_back(el); + } + +#if 0 + if (ret.empty()) { + BelId bel; + bel.index = decal.index; + log_warning("No gfx decal for bel %s (%d).\n", getBelName(bel).c_str(getCtx()), decal.index); + } +#endif } return ret; diff --git a/ice40/arch.h b/ice40/arch.h index 8fd1af23..37f663d9 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -225,6 +225,7 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD { RelPtr<BelConfigPOD> bel_config; RelPtr<PackageInfoPOD> packages_data; RelPtr<CellTimingPOD> cell_timing; + RelPtr<RelPtr<char>> tile_wire_names; }); #if defined(_MSC_VER) @@ -502,6 +503,8 @@ struct Arch : BaseCtx return IdString(chip_info->bel_data[bel.index].type); } + std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId bel) const; + WireId getBelPinWire(BelId bel, IdString pin) const; PortType getBelPinType(BelId bel, IdString pin) const; std::vector<IdString> getBelPins(BelId bel) const; @@ -517,6 +520,7 @@ struct Arch : BaseCtx } IdString getWireType(WireId wire) const; + std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const; uint32_t getWireChecksum(WireId wire) const { return wire.index; } @@ -692,7 +696,8 @@ struct Arch : BaseCtx IdString getPipName(PipId pip) const; - IdString getPipType(PipId pip) const { return IdString(); } + IdString getPipType(PipId pip) const; + std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const; uint32_t getPipChecksum(PipId pip) const { return pip.index; } @@ -832,8 +837,6 @@ struct Arch : BaseCtx } NPNR_ASSERT_FALSE("Expected PLL pin to share an output with an SB_IO D_IN_{0,1}"); } - - float placer_constraintWeight = 10; }; void ice40DelayFuzzerMain(Context *ctx); diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index ee276e49..4ea91011 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -870,10 +870,12 @@ bool read_asc(Context *ctx, std::istream &in) }
if (isUsed) {
NetInfo *net = ctx->wire_to_net[pi.dst];
- WireId wire;
- wire.index = pi.dst;
- ctx->unbindWire(wire);
- ctx->bindPip(pip, net, STRENGTH_WEAK);
+ if (net!=nullptr) {
+ WireId wire;
+ wire.index = pi.dst;
+ ctx->unbindWire(wire);
+ ctx->bindPip(pip, net, STRENGTH_WEAK);
+ }
}
}
for (auto bel : ctx->getBels()) {
diff --git a/ice40/cells.cc b/ice40/cells.cc index 5bdc7990..e79a1fda 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -28,6 +28,7 @@ NEXTPNR_NAMESPACE_BEGIN void add_port(const Context *ctx, CellInfo *cell, std::string name, PortType dir) { IdString id = ctx->id(name); + NPNR_ASSERT(cell->ports.count(id) == 0); cell->ports[id] = PortInfo{id, nullptr, dir}; } @@ -237,7 +238,7 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri add_port(ctx, new_cell.get(), "SCLK", PORT_IN); add_port(ctx, new_cell.get(), "SDI", PORT_IN); - add_port(ctx, new_cell.get(), "SDI", PORT_OUT); + add_port(ctx, new_cell.get(), "SDO", PORT_OUT); add_port(ctx, new_cell.get(), "LOCK", PORT_OUT); add_port(ctx, new_cell.get(), "PLLOUT_A", PORT_OUT); diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 7bdf82f0..5b2f3e57 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -50,6 +50,7 @@ tiletypes = dict() wiretypes = dict() gfx_wire_ids = dict() +gfx_wire_names = list() wire_segments = dict() fast_timings = None @@ -93,6 +94,136 @@ with open(args.gfxh) as f: idx = len(gfx_wire_ids) name = line.strip().rstrip(",") gfx_wire_ids[name] = idx + gfx_wire_names.append(name) + +def gfx_wire_alias(old, new): + assert old in gfx_wire_ids + assert new not in gfx_wire_ids + gfx_wire_ids[new] = gfx_wire_ids[old] + +# GFX aliases for RAM tiles + +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_0", "TILE_WIRE_RAM_RADDR_0") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_1", "TILE_WIRE_RAM_RADDR_1") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_2", "TILE_WIRE_RAM_RADDR_2") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_3", "TILE_WIRE_RAM_RADDR_3") + +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_0", "TILE_WIRE_RAM_RADDR_4") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_1", "TILE_WIRE_RAM_RADDR_5") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_2", "TILE_WIRE_RAM_RADDR_6") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_3", "TILE_WIRE_RAM_RADDR_7") + +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_0", "TILE_WIRE_RAM_RADDR_8") +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_1", "TILE_WIRE_RAM_RADDR_9") +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_2", "TILE_WIRE_RAM_RADDR_10") + +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_0", "TILE_WIRE_RAM_WADDR_0") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_1", "TILE_WIRE_RAM_WADDR_1") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_2", "TILE_WIRE_RAM_WADDR_2") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_3", "TILE_WIRE_RAM_WADDR_3") + +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_0", "TILE_WIRE_RAM_WADDR_4") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_1", "TILE_WIRE_RAM_WADDR_5") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_2", "TILE_WIRE_RAM_WADDR_6") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_3", "TILE_WIRE_RAM_WADDR_7") + +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_0", "TILE_WIRE_RAM_WADDR_8") +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_1", "TILE_WIRE_RAM_WADDR_9") +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_2", "TILE_WIRE_RAM_WADDR_10") + +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_0", "TILE_WIRE_RAM_MASK_0") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_1", "TILE_WIRE_RAM_MASK_1") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_2", "TILE_WIRE_RAM_MASK_2") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_3", "TILE_WIRE_RAM_MASK_3") + +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_0", "TILE_WIRE_RAM_MASK_4") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_1", "TILE_WIRE_RAM_MASK_5") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_2", "TILE_WIRE_RAM_MASK_6") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_3", "TILE_WIRE_RAM_MASK_7") + +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_0", "TILE_WIRE_RAM_MASK_8") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_1", "TILE_WIRE_RAM_MASK_9") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_2", "TILE_WIRE_RAM_MASK_10") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_3", "TILE_WIRE_RAM_MASK_11") + +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_0", "TILE_WIRE_RAM_MASK_12") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_1", "TILE_WIRE_RAM_MASK_13") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_2", "TILE_WIRE_RAM_MASK_14") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_3", "TILE_WIRE_RAM_MASK_15") + +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_0", "TILE_WIRE_RAM_WDATA_0") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_1", "TILE_WIRE_RAM_WDATA_1") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_2", "TILE_WIRE_RAM_WDATA_2") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_3", "TILE_WIRE_RAM_WDATA_3") + +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_0", "TILE_WIRE_RAM_WDATA_4") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_1", "TILE_WIRE_RAM_WDATA_5") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_2", "TILE_WIRE_RAM_WDATA_6") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_3", "TILE_WIRE_RAM_WDATA_7") + +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_0", "TILE_WIRE_RAM_WDATA_8") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_1", "TILE_WIRE_RAM_WDATA_9") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_2", "TILE_WIRE_RAM_WDATA_10") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_3", "TILE_WIRE_RAM_WDATA_11") + +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_0", "TILE_WIRE_RAM_WDATA_12") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_1", "TILE_WIRE_RAM_WDATA_13") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_2", "TILE_WIRE_RAM_WDATA_14") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_3", "TILE_WIRE_RAM_WDATA_15") + +gfx_wire_alias("TILE_WIRE_LUTFF_0_OUT", "TILE_WIRE_RAM_RDATA_0") +gfx_wire_alias("TILE_WIRE_LUTFF_1_OUT", "TILE_WIRE_RAM_RDATA_1") +gfx_wire_alias("TILE_WIRE_LUTFF_2_OUT", "TILE_WIRE_RAM_RDATA_2") +gfx_wire_alias("TILE_WIRE_LUTFF_3_OUT", "TILE_WIRE_RAM_RDATA_3") +gfx_wire_alias("TILE_WIRE_LUTFF_4_OUT", "TILE_WIRE_RAM_RDATA_4") +gfx_wire_alias("TILE_WIRE_LUTFF_5_OUT", "TILE_WIRE_RAM_RDATA_5") +gfx_wire_alias("TILE_WIRE_LUTFF_6_OUT", "TILE_WIRE_RAM_RDATA_6") +gfx_wire_alias("TILE_WIRE_LUTFF_7_OUT", "TILE_WIRE_RAM_RDATA_7") + +gfx_wire_alias("TILE_WIRE_LUTFF_0_OUT", "TILE_WIRE_RAM_RDATA_8") +gfx_wire_alias("TILE_WIRE_LUTFF_1_OUT", "TILE_WIRE_RAM_RDATA_9") +gfx_wire_alias("TILE_WIRE_LUTFF_2_OUT", "TILE_WIRE_RAM_RDATA_10") +gfx_wire_alias("TILE_WIRE_LUTFF_3_OUT", "TILE_WIRE_RAM_RDATA_11") +gfx_wire_alias("TILE_WIRE_LUTFF_4_OUT", "TILE_WIRE_RAM_RDATA_12") +gfx_wire_alias("TILE_WIRE_LUTFF_5_OUT", "TILE_WIRE_RAM_RDATA_13") +gfx_wire_alias("TILE_WIRE_LUTFF_6_OUT", "TILE_WIRE_RAM_RDATA_14") +gfx_wire_alias("TILE_WIRE_LUTFF_7_OUT", "TILE_WIRE_RAM_RDATA_15") + +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CEN", "TILE_WIRE_RAM_RCLKE") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CEN", "TILE_WIRE_RAM_WCLKE") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CLK", "TILE_WIRE_RAM_RCLK") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CLK", "TILE_WIRE_RAM_WCLK") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_S_R", "TILE_WIRE_RAM_RE") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_S_R", "TILE_WIRE_RAM_WE") + +# GFX aliases for IO tiles + +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_0", "TILE_WIRE_IO_0_D_OUT_0") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_1", "TILE_WIRE_IO_0_D_OUT_1") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_3", "TILE_WIRE_IO_0_OUT_ENB") + +gfx_wire_alias("TILE_WIRE_LUTFF_0_OUT", "TILE_WIRE_IO_0_D_IN_0") +gfx_wire_alias("TILE_WIRE_LUTFF_1_OUT", "TILE_WIRE_IO_0_D_IN_1") + +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_0", "TILE_WIRE_IO_1_D_OUT_0") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_1", "TILE_WIRE_IO_1_D_OUT_1") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_3", "TILE_WIRE_IO_1_OUT_ENB") + +gfx_wire_alias("TILE_WIRE_LUTFF_4_OUT", "TILE_WIRE_IO_1_D_IN_0") +gfx_wire_alias("TILE_WIRE_LUTFF_5_OUT", "TILE_WIRE_IO_1_D_IN_1") + +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CEN", "TILE_WIRE_IO_GLOBAL_CEN") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CLK", "TILE_WIRE_IO_GLOBAL_INCLK") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_S_R", "TILE_WIRE_IO_GLOBAL_OUTCLK") + +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_G0", "TILE_WIRE_IO_GLOBAL_LATCH") + +for neigh in "BNL BNR BOT LFT RGT TNL TNR TOP".split(): + for i in range(8): + gfx_wire_alias("TILE_WIRE_NEIGH_OP_%s_%d" % (neigh, i), "TILE_WIRE_LOGIC_OP_%s_%d" % (neigh, i)) + +# End of GFX aliases + def read_timings(filename): db = dict() @@ -165,6 +296,18 @@ def maj_wire_name(name): return name[2] in ("sp12_v_b_0", "sp12_v_b_1") return False +def norm_wire_xy(x, y, name): + if name.startswith("glb_netwk_"): + return None + if name.startswith("neigh_op_"): + return None + if name.startswith("logic_op_"): + return None + if name.startswith("io_global/latch"): + return None + return None # FIXME + return (x, y) + def cmp_wire_names(newname, oldname): if maj_wire_name(newname): return True @@ -508,11 +651,13 @@ with open(args.filename, "r") as f: wire_names_r[mode[1]] = wname if mode[1] not in wire_xy: wire_xy[mode[1]] = list() - wire_xy[mode[1]].append((int(line[0]), int(line[1]))) + wire_xy[mode[1]].append(wname) if mode[1] not in wire_segments: wire_segments[mode[1]] = dict() if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids: - wire_segments[mode[1]][(wname[0], wname[1])] = wname[2] + if (wname[0], wname[1]) not in wire_segments[mode[1]]: + wire_segments[mode[1]][(wname[0], wname[1])] = list() + wire_segments[mode[1]][(wname[0], wname[1])].append(wname[2]) continue if mode[0] in ("buffer", "routing"): @@ -561,7 +706,9 @@ def add_wire(x, y, name): 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] + if (wname[0], wname[1]) not in wire_segments[wire_idx]: + wire_segments[wire_idx][(wname[0], wname[1])] = list() + wire_segments[wire_idx][(wname[0], wname[1])].append(wname[2]) return wire_idx def add_switch(x, y, bel=-1): @@ -580,10 +727,6 @@ def add_pip(src, dst, flags=0): pip_xy[(src, dst)] = (x, y, 0, len(switches) - 1, flags) -# Add virtual padin wires -for i in range(8): - add_wire(0, 0, "padin_%d" % i) - def add_bel_input(bel, wire, port): if wire not in wire_belports: wire_belports[wire] = set() @@ -932,6 +1075,10 @@ bba.post('NEXTPNR_NAMESPACE_END') bba.push("chipdb_blob_%s" % dev_name) bba.r("chip_info_%s" % dev_name, "chip_info") +bba.l("tile_wire_names") +for name in gfx_wire_names: + bba.s(name, name) + for bel in range(len(bel_name)): bba.l("bel_wires_%d" % bel, "BelWirePOD") for data in sorted(bel_wires[bel]): @@ -1028,20 +1175,32 @@ for wire in range(num_wires): info["num_bel_pins"] = num_bel_pins info["list_bel_pins"] = ("wire%d_bels" % wire) if num_bel_pins > 0 else None - if wire in wire_xy: - avg_x, avg_y = 0, 0 + pos_xy = None + first = None - for x, y in wire_xy[wire]: - avg_x += x - avg_y += y - avg_x /= len(wire_xy[wire]) - avg_y /= len(wire_xy[wire]) + if wire in wire_xy: + for x, y, n in wire_xy[wire]: + norm_xy = norm_wire_xy(x, y, n) + if norm_xy is None: + continue + if pos_xy is None: + pos_xy = norm_xy + first = (x, y, n) + elif pos_xy != norm_xy: + print("Conflicting positions for wire %s: (%d, %d, %s) -> (%d, %d), (%d, %d, %s) -> (%d, %d)" % \ + ((info["name"],) + first + pos_xy + (x, y, n) + norm_xy), file=sys.stderr) + assert 0 + if (pos_xy is None) and (len(wire_xy[wire]) > 1): + # print("Only 'None' positions for wire %s." % info["name"], file=sys.stderr) + # assert 0 + pass - info["x"] = int(round(avg_x)) - info["y"] = int(round(avg_y)) - else: + if pos_xy is None: info["x"] = wire_names_r[wire][0] info["y"] = wire_names_r[wire][1] + else: + info["x"] = pos_xy[0] + info["y"] = pos_xy[1] wireinfo.append(info) @@ -1108,8 +1267,13 @@ for wire, info in enumerate(wireinfo): bba.r(info["list_downhill"], "pips_downhill") bba.u32(info["num_bel_pins"], "num_bel_pins") bba.r(info["list_bel_pins"], "bel_pins") - bba.u32(len(wire_segments[wire]), "num_segments") - if len(wire_segments[wire]): + + num_segments = 0 + for segs in wire_segments[wire].values(): + num_segments += len(segs) + bba.u32(num_segments, "num_segments") + + if num_segments: bba.r("wire_segments_%d" % wire, "segments") else: bba.u32(0, "segments") @@ -1125,24 +1289,25 @@ for wire, info in enumerate(wireinfo): for wire in range(num_wires): if len(wire_segments[wire]): bba.l("wire_segments_%d" % wire, "WireSegmentPOD") - for xy, seg in sorted(wire_segments[wire].items()): - bba.u8(xy[0], "x") - bba.u8(xy[1], "y") - bba.u16(gfx_wire_ids["TILE_WIRE_" + seg.upper().replace("/", "_")], "index") + for xy, segs in sorted(wire_segments[wire].items()): + for seg in segs: + bba.u8(xy[0], "x") + bba.u8(xy[1], "y") + bba.u16(gfx_wire_ids["TILE_WIRE_" + seg.upper().replace("/", "_")], "index") bba.l("pip_data_%s" % dev_name, "PipInfoPOD") for info in pipinfo: src_seg = -1 src_segname = wire_names_r[info["src"]] if (info["x"], info["y"]) in wire_segments[info["src"]]: - src_segname = wire_segments[info["src"]][(info["x"], info["y"])] + src_segname = wire_segments[info["src"]][(info["x"], info["y"])][0] src_seg = gfx_wire_ids["TILE_WIRE_" + src_segname.upper().replace("/", "_")] src_segname = src_segname.replace("/", ".") dst_seg = -1 dst_segname = wire_names_r[info["dst"]] if (info["x"], info["y"]) in wire_segments[info["dst"]]: - dst_segname = wire_segments[info["dst"]][(info["x"], info["y"])] + dst_segname = wire_segments[info["dst"]][(info["x"], info["y"])][0] dst_seg = gfx_wire_ids["TILE_WIRE_" + dst_segname.upper().replace("/", "_")] dst_segname = dst_segname.replace("/", ".") @@ -1276,5 +1441,6 @@ bba.r("bits_info_%s" % dev_name, "bits_info") bba.r("bel_config_%s" % dev_name if len(extra_cell_config) > 0 else None, "bel_config") bba.r("package_info_%s" % dev_name, "packages_data") bba.r("cell_timings_%s" % dev_name, "cell_timing") +bba.r("tile_wire_names", "tile_wire_names") bba.pop() diff --git a/ice40/family.cmake b/ice40/family.cmake index f558a14d..0e1d36e6 100644 --- a/ice40/family.cmake +++ b/ice40/family.cmake @@ -36,7 +36,7 @@ if (MSVC) set(DEV_GFXH ${CMAKE_CURRENT_SOURCE_DIR}/ice40/gfx.h) add_custom_command(OUTPUT ${DEV_CC_BBA_DB} COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -p ${DEV_CONSTIDS_INC} -g ${DEV_GFXH} ${OPT_FAST} ${OPT_SLOW} ${DEV_TXT_DB} > ${DEV_CC_BBA_DB} - DEPENDS ${DEV_TXT_DB} ${DB_PY} + DEPENDS ${DEV_CONSTIDS_INC} ${DEV_GFXH} ${DEV_TXT_DB} ${DB_PY} ) add_custom_command(OUTPUT ${DEV_CC_DB} COMMAND bbasm ${DEV_CC_BBA_DB} ${DEV_CC_DB} @@ -69,7 +69,7 @@ else() add_custom_command(OUTPUT ${DEV_CC_BBA_DB} COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -p ${DEV_CONSTIDS_INC} -g ${DEV_GFXH} ${OPT_FAST} ${OPT_SLOW} ${DEV_TXT_DB} > ${DEV_CC_BBA_DB}.new COMMAND mv ${DEV_CC_BBA_DB}.new ${DEV_CC_BBA_DB} - DEPENDS ${DEV_TXT_DB} ${DB_PY} + DEPENDS ${DEV_CONSTIDS_INC} ${DEV_GFXH} ${DEV_TXT_DB} ${DB_PY} ) add_custom_command(OUTPUT ${DEV_CC_DB} COMMAND bbasm --c ${DEV_CC_BBA_DB} ${DEV_CC_DB}.new diff --git a/ice40/gfx.cc b/ice40/gfx.cc index 1ab2fb3c..74338b8d 100644 --- a/ice40/gfx.cc +++ b/ice40/gfx.cc @@ -21,7 +21,7 @@ NEXTPNR_NAMESPACE_BEGIN -void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, GraphicElement::style_t style) +void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, int w, int h, GfxTileWireId id, GraphicElement::style_t style) { GraphicElement el; el.type = GraphicElement::TYPE_LINE; @@ -339,6 +339,168 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, g.push_back(el); } + // IO Span-4 Wires connecting to fabric + + if (id >= TILE_WIRE_SPAN4_HORZ_0 && id <= TILE_WIRE_SPAN4_HORZ_47) { + int idx = id - TILE_WIRE_SPAN4_HORZ_0; + float y1 = y + 1.0 - (0.03 + 0.0025 * (48 - (idx ^ 1))); + + el.x1 = x; + el.x2 = x + 1.0; + el.y1 = y1; + el.y2 = y1; + g.push_back(el); + + el.x1 = x + main_swbox_x1 + 0.0025 * ((idx ^ 1) + 35); + el.x2 = el.x1; + el.y1 = y1; + el.y2 = y + main_swbox_y2; + g.push_back(el); + } + + if (id >= TILE_WIRE_SPAN4_VERT_0 && id <= TILE_WIRE_SPAN4_VERT_47) { + int idx = id - TILE_WIRE_SPAN4_VERT_0; + float x1 = x + 0.03 + 0.0025 * (48 - (idx ^ 1)); + + el.x1 = x1; + el.x2 = x1; + el.y1 = y; + el.y2 = y + 1.0; + g.push_back(el); + + el.y1 = y + 1.0 - (0.03 + 0.0025 * (270 - (idx ^ 1))); + el.y2 = el.y1; + el.x1 = x1; + el.x2 = x + main_swbox_x1; + g.push_back(el); + } + + // IO Span-12 Wires connecting to fabric + + if (id >= TILE_WIRE_SPAN12_HORZ_0 && id <= TILE_WIRE_SPAN12_HORZ_23) { + int idx = id - TILE_WIRE_SPAN12_HORZ_0; + float y1 = y + 1.0 - (0.03 + 0.0025 * (88 - (idx ^ 1))); + + el.x1 = x; + el.x2 = x + 1.0; + el.y1 = y1; + el.y2 = y1; + g.push_back(el); + + el.x1 = x + main_swbox_x1 + 0.0025 * ((idx ^ 1) + 5); + el.x2 = el.x1; + el.y1 = y1; + el.y2 = y + main_swbox_y2; + g.push_back(el); + } + + if (id >= TILE_WIRE_SPAN12_VERT_0 && id <= TILE_WIRE_SPAN12_VERT_23) { + int idx = id - TILE_WIRE_SPAN12_VERT_0; + float x1 = x + 0.03 + 0.0025 * (88 - (idx ^ 1)); + + el.x1 = x1; + el.x2 = x1; + el.y1 = y; + el.y2 = y + 1.0; + g.push_back(el); + + el.y1 = y + 1.0 - (0.03 + 0.0025 * (300 - (idx ^ 1))); + el.y2 = el.y1; + el.x1 = x1; + el.x2 = x + main_swbox_x1; + g.push_back(el); + } + + // Horizontal IO Span-4 Wires + + if (id >= TILE_WIRE_SPAN4_HORZ_R_0 && id <= TILE_WIRE_SPAN4_HORZ_L_15) { + int idx = id - TILE_WIRE_SPAN4_HORZ_R_0; + + float y1 = y + 1.0 - (0.03 + 0.0025 * (60 - idx)); + float y2 = y + 1.0 - (0.03 + 0.0025 * (60 - idx - 4)); + + el.x1 = x; + el.x2 = x + 0.9; + el.y1 = y1; + el.y2 = y1; + g.push_back(el); + + if (idx <= 15) { + el.x1 = x + 0.9; + el.x2 = x + 1.0; + el.y1 = y1; + el.y2 = y2; + g.push_back(el); + } + + el.x1 = x + main_swbox_x1 + 0.0025 * (idx + 35); + el.x2 = el.x1; + el.y1 = y1; + el.y2 = y + main_swbox_y2; + g.push_back(el); + } + + // Vertical IO Span-4 Wires + + if (id >= TILE_WIRE_SPAN4_VERT_B_0 && id <= TILE_WIRE_SPAN4_VERT_T_15) { + int idx = id - TILE_WIRE_SPAN4_VERT_B_0; + + float x1 = x + 0.03 + 0.0025 * (60 - idx); + float x2 = x + 0.03 + 0.0025 * (60 - idx - 4); + + el.y1 = y + 1.00; + el.y2 = y + 0.10; + el.x1 = x1; + el.x2 = x1; + g.push_back(el); + + if (idx <= 15) { + el.y1 = y + 0.10; + el.y2 = y; + el.x1 = x1; + el.x2 = x2; + g.push_back(el); + } + + if (idx <= 15 && (x == 0 || x == w-1) && y == 1) { + float y1 = y - (0.03 + 0.0025 * (60 - idx - 4)); + + el.x1 = x2; + el.y1 = y; + el.x2 = x2; + el.y2 = y1; + g.push_back(el); + + el.x1 = x2; + el.y1 = y1; + el.x2 = x + (x == 0); + el.y2 = y1; + g.push_back(el); + } + + if (idx >= 4 && (x == 0 || x == w-1) && y == h-2) { + float y1 = y + 2.0 - (0.03 + 0.0025 * (60 - idx)); + + el.x1 = x1; + el.y1 = y + 1.0; + el.x2 = x1; + el.y2 = y1; + g.push_back(el); + + el.x1 = x1; + el.y1 = y1; + el.x2 = x + (x == 0); + el.y2 = y1; + g.push_back(el); + } + + el.y1 = y + 1.0 - (0.03 + 0.0025 * (270 - idx)); + el.y2 = el.y1; + el.x1 = x1; + el.x2 = x + main_swbox_x1; + g.push_back(el); + } + // Global2Local if (id >= TILE_WIRE_GLB2LOCAL_0 && id <= TILE_WIRE_GLB2LOCAL_3) { @@ -392,7 +554,7 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, 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.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); } @@ -403,7 +565,7 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, 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.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); } @@ -457,6 +619,42 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, } } + // LC Control for IO and BRAM + + if (id >= TILE_WIRE_FUNC_GLOBAL_CEN && id <= TILE_WIRE_FUNC_GLOBAL_S_R) { + int idx = id - TILE_WIRE_FUNC_GLOBAL_CEN; + + el.x1 = x + main_swbox_x2 - 0.005 * (idx + 5); + el.x2 = el.x1; + el.y1 = y + main_swbox_y1; + el.y2 = el.y1 - 0.005 * (idx + 2); + g.push_back(el); + + el.y1 = el.y2; + el.x2 = x + logic_cell_x2 - 0.005 * (2 - idx + 5); + g.push_back(el); + + el.y2 = y + logic_cell_y1; + el.x1 = el.x2; + g.push_back(el); + } + + if (id == TILE_WIRE_FABOUT) { + el.y1 = y + main_swbox_y1; + el.y2 = el.y1 - 0.005 * 4; + el.x1 = x + main_swbox_x2 - 0.005 * 9; + el.x2 = el.x1; + g.push_back(el); + } + + if (id == TILE_WIRE_FUNC_GLOBAL_G0) { + el.y1 = y + logic_cell_y1; + el.y2 = el.y1 - 0.005 * 4; + el.x1 = x + logic_cell_x2 - 0.005 * 3; + el.x2 = el.x1; + g.push_back(el); + } + // LC Cascade if (id >= TILE_WIRE_LUTFF_0_LOUT && id <= TILE_WIRE_LUTFF_6_LOUT) { @@ -571,6 +769,54 @@ static bool getWireXY_main(GfxTileWireId id, float &x, float &y) return true; } + // IO Span-4 Wires connecting to fabric + + if (id >= TILE_WIRE_SPAN4_HORZ_0 && id <= TILE_WIRE_SPAN4_HORZ_47) { + int idx = id - TILE_WIRE_SPAN4_HORZ_0; + x = main_swbox_x1 + 0.0025 * ((idx ^ 1) + 35); + y = main_swbox_y2; + return true; + } + + if (id >= TILE_WIRE_SPAN4_VERT_0 && id <= TILE_WIRE_SPAN4_VERT_47) { + int idx = id - TILE_WIRE_SPAN4_VERT_0; + y = 1.0 - (0.03 + 0.0025 * (270 - (idx ^ 1))); + x = main_swbox_x1; + return true; + } + + // IO Span-12 Wires connecting to fabric + + if (id >= TILE_WIRE_SPAN12_HORZ_0 && id <= TILE_WIRE_SPAN12_HORZ_23) { + int idx = id - TILE_WIRE_SPAN12_HORZ_0; + x = main_swbox_x1 + 0.0025 * ((idx ^ 1) + 5); + y = main_swbox_y2; + return true; + } + + if (id >= TILE_WIRE_SPAN12_VERT_0 && id <= TILE_WIRE_SPAN12_VERT_23) { + int idx = id - TILE_WIRE_SPAN12_VERT_0; + y = 1.0 - (0.03 + 0.0025 * (300 - (idx ^ 1))); + x = main_swbox_x1; + return true; + } + + // IO Span-4 Wires + + if (id >= TILE_WIRE_SPAN4_HORZ_R_0 && id <= TILE_WIRE_SPAN4_HORZ_L_15) { + int idx = id - TILE_WIRE_SPAN4_HORZ_R_0; + y = main_swbox_y2; + x = main_swbox_x1 + 0.0025 * (idx + 35); + return true; + } + + if (id >= TILE_WIRE_SPAN4_VERT_B_0 && id <= TILE_WIRE_SPAN4_VERT_T_15) { + int idx = id - TILE_WIRE_SPAN4_VERT_B_0; + y = 1.0 - (0.03 + 0.0025 * (270 - idx)); + x = main_swbox_x1; + return true; + } + // Global2Local if (id >= TILE_WIRE_GLB2LOCAL_0 && id <= TILE_WIRE_GLB2LOCAL_3) { @@ -626,6 +872,19 @@ static bool getWireXY_main(GfxTileWireId id, float &x, float &y) return true; } + if (id >= TILE_WIRE_FUNC_GLOBAL_CEN && id <= TILE_WIRE_FUNC_GLOBAL_S_R) { + int idx = id - TILE_WIRE_FUNC_GLOBAL_CEN; + x = main_swbox_x2 - 0.005 * (idx + 5); + y = main_swbox_y1; + return true; + } + + if (id == TILE_WIRE_FABOUT) { + x = main_swbox_x2 - 0.005 * 9; + y = main_swbox_y1; + return true; + } + return false; } @@ -662,22 +921,22 @@ void pipGfx(std::vector<GraphicElement> &g, int x, int y, float x1, float y1, fl el.style = style; if (fabsf(x1 - swx1) < 0.001 && fabsf(x2 - swx1) < 0.001) { - tx = x1 + 0.25 * fabsf(y1 - y2); + tx = swx1 + 0.25 * fabsf(y1 - y2); goto edge_pip; } if (fabsf(x1 - swx2) < 0.001 && fabsf(x2 - swx2) < 0.001) { - tx = x1 - 0.25 * fabsf(y1 - y2); + tx = swx2 - 0.25 * fabsf(y1 - y2); goto edge_pip; } if (fabsf(y1 - swy1) < 0.001 && fabsf(y2 - swy1) < 0.001) { - ty = y1 + 0.25 * fabsf(x1 - x2); + ty = swy1 + 0.25 * fabsf(x1 - x2); goto edge_pip; } - if (fabsf(y1 - swy1) < 0.001 && fabsf(y2 - swy1) < 0.001) { - ty = y1 + 0.25 * fabsf(x1 - x2); + if (fabsf(y1 - swy2) < 0.001 && fabsf(y2 - swy2) < 0.001) { + ty = swy2 - 0.25 * fabsf(x1 - x2); goto edge_pip; } @@ -727,7 +986,7 @@ void gfxTilePip(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId src, 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.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; @@ -744,8 +1003,46 @@ void gfxTilePip(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId src, 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; + 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_MUX || (src >= TILE_WIRE_LUTFF_0_COUT && src <= TILE_WIRE_LUTFF_6_COUT)) && + (dst >= TILE_WIRE_LUTFF_0_IN_0 && dst <= TILE_WIRE_LUTFF_7_IN_3 && (dst - TILE_WIRE_LUTFF_0_IN_0) % 4 == 3)) { + int lut_idx = (dst - TILE_WIRE_LUTFF_0_IN_0) / 4; + + GraphicElement el; + el.type = GraphicElement::TYPE_ARROW; + el.style = style; + el.x1 = x + (local_swbox_x2 + lut_swbox_x1) / 2; + el.x2 = el.x1; + el.y1 = y + (logic_cell_y1 + logic_cell_y2) / 2 + 0.0075 - (0.005 * 3) + lut_idx * logic_cell_pitch; + el.y2 = y + (logic_cell_y1 + logic_cell_y2 - logic_cell_pitch) / 2 + lut_idx * logic_cell_pitch; + g.push_back(el); + + el.x1 = x + logic_cell_x1 + 0.005 * 3; + el.y1 = el.y2; + g.push_back(el); + return; + } + + if ((src >= TILE_WIRE_LUTFF_0_LOUT && src <= TILE_WIRE_LUTFF_6_LOUT) && + (dst >= TILE_WIRE_LUTFF_0_IN_0 && dst <= TILE_WIRE_LUTFF_7_IN_3 && (dst - TILE_WIRE_LUTFF_0_IN_0) % 4 == 2)) { + int lut_idx = (dst - TILE_WIRE_LUTFF_0_IN_0) / 4; + + GraphicElement el; + el.type = GraphicElement::TYPE_ARROW; + el.style = style; + el.x1 = x + (local_swbox_x2 + lut_swbox_x1) / 2 + 0.005; + el.x2 = el.x1; + el.y1 = y + (logic_cell_y1 + logic_cell_y2) / 2 + 0.0075 - (0.005 * 2) + lut_idx * logic_cell_pitch; + el.y2 = y + (logic_cell_y1 + logic_cell_y2 - logic_cell_pitch) / 2 + lut_idx * logic_cell_pitch + 0.003; + g.push_back(el); + + el.x1 = x + logic_cell_x1 + 0.005 * 5; + el.y1 = el.y2; g.push_back(el); return; } diff --git a/ice40/gfx.h b/ice40/gfx.h index 8ee7b0b6..4fb6e147 100644 --- a/ice40/gfx.h +++ b/ice40/gfx.h @@ -205,6 +205,13 @@ enum GfxTileWireId TILE_WIRE_LUTFF_GLOBAL_CLK, TILE_WIRE_LUTFF_GLOBAL_S_R, + TILE_WIRE_FUNC_GLOBAL_CEN, + TILE_WIRE_FUNC_GLOBAL_CLK, + TILE_WIRE_FUNC_GLOBAL_S_R, + + TILE_WIRE_FUNC_GLOBAL_G0, + TILE_WIRE_FABOUT, + TILE_WIRE_CARRY_IN, TILE_WIRE_CARRY_IN_MUX, @@ -509,12 +516,205 @@ enum GfxTileWireId TILE_WIRE_SP12_H_L_22, TILE_WIRE_SP12_H_L_23, + TILE_WIRE_SPAN4_VERT_0, + TILE_WIRE_SPAN4_VERT_1, + TILE_WIRE_SPAN4_VERT_2, + TILE_WIRE_SPAN4_VERT_3, + TILE_WIRE_SPAN4_VERT_4, + TILE_WIRE_SPAN4_VERT_5, + TILE_WIRE_SPAN4_VERT_6, + TILE_WIRE_SPAN4_VERT_7, + TILE_WIRE_SPAN4_VERT_8, + TILE_WIRE_SPAN4_VERT_9, + TILE_WIRE_SPAN4_VERT_10, + TILE_WIRE_SPAN4_VERT_11, + TILE_WIRE_SPAN4_VERT_12, + TILE_WIRE_SPAN4_VERT_13, + TILE_WIRE_SPAN4_VERT_14, + TILE_WIRE_SPAN4_VERT_15, + TILE_WIRE_SPAN4_VERT_16, + TILE_WIRE_SPAN4_VERT_17, + TILE_WIRE_SPAN4_VERT_18, + TILE_WIRE_SPAN4_VERT_19, + TILE_WIRE_SPAN4_VERT_20, + TILE_WIRE_SPAN4_VERT_21, + TILE_WIRE_SPAN4_VERT_22, + TILE_WIRE_SPAN4_VERT_23, + TILE_WIRE_SPAN4_VERT_24, + TILE_WIRE_SPAN4_VERT_25, + TILE_WIRE_SPAN4_VERT_26, + TILE_WIRE_SPAN4_VERT_27, + TILE_WIRE_SPAN4_VERT_28, + TILE_WIRE_SPAN4_VERT_29, + TILE_WIRE_SPAN4_VERT_30, + TILE_WIRE_SPAN4_VERT_31, + TILE_WIRE_SPAN4_VERT_32, + TILE_WIRE_SPAN4_VERT_33, + TILE_WIRE_SPAN4_VERT_34, + TILE_WIRE_SPAN4_VERT_35, + TILE_WIRE_SPAN4_VERT_36, + TILE_WIRE_SPAN4_VERT_37, + TILE_WIRE_SPAN4_VERT_38, + TILE_WIRE_SPAN4_VERT_39, + TILE_WIRE_SPAN4_VERT_40, + TILE_WIRE_SPAN4_VERT_41, + TILE_WIRE_SPAN4_VERT_42, + TILE_WIRE_SPAN4_VERT_43, + TILE_WIRE_SPAN4_VERT_44, + TILE_WIRE_SPAN4_VERT_45, + TILE_WIRE_SPAN4_VERT_46, + TILE_WIRE_SPAN4_VERT_47, + + TILE_WIRE_SPAN4_HORZ_0, + TILE_WIRE_SPAN4_HORZ_1, + TILE_WIRE_SPAN4_HORZ_2, + TILE_WIRE_SPAN4_HORZ_3, + TILE_WIRE_SPAN4_HORZ_4, + TILE_WIRE_SPAN4_HORZ_5, + TILE_WIRE_SPAN4_HORZ_6, + TILE_WIRE_SPAN4_HORZ_7, + TILE_WIRE_SPAN4_HORZ_8, + TILE_WIRE_SPAN4_HORZ_9, + TILE_WIRE_SPAN4_HORZ_10, + TILE_WIRE_SPAN4_HORZ_11, + TILE_WIRE_SPAN4_HORZ_12, + TILE_WIRE_SPAN4_HORZ_13, + TILE_WIRE_SPAN4_HORZ_14, + TILE_WIRE_SPAN4_HORZ_15, + TILE_WIRE_SPAN4_HORZ_16, + TILE_WIRE_SPAN4_HORZ_17, + TILE_WIRE_SPAN4_HORZ_18, + TILE_WIRE_SPAN4_HORZ_19, + TILE_WIRE_SPAN4_HORZ_20, + TILE_WIRE_SPAN4_HORZ_21, + TILE_WIRE_SPAN4_HORZ_22, + TILE_WIRE_SPAN4_HORZ_23, + TILE_WIRE_SPAN4_HORZ_24, + TILE_WIRE_SPAN4_HORZ_25, + TILE_WIRE_SPAN4_HORZ_26, + TILE_WIRE_SPAN4_HORZ_27, + TILE_WIRE_SPAN4_HORZ_28, + TILE_WIRE_SPAN4_HORZ_29, + TILE_WIRE_SPAN4_HORZ_30, + TILE_WIRE_SPAN4_HORZ_31, + TILE_WIRE_SPAN4_HORZ_32, + TILE_WIRE_SPAN4_HORZ_33, + TILE_WIRE_SPAN4_HORZ_34, + TILE_WIRE_SPAN4_HORZ_35, + TILE_WIRE_SPAN4_HORZ_36, + TILE_WIRE_SPAN4_HORZ_37, + TILE_WIRE_SPAN4_HORZ_38, + TILE_WIRE_SPAN4_HORZ_39, + TILE_WIRE_SPAN4_HORZ_40, + TILE_WIRE_SPAN4_HORZ_41, + TILE_WIRE_SPAN4_HORZ_42, + TILE_WIRE_SPAN4_HORZ_43, + TILE_WIRE_SPAN4_HORZ_44, + TILE_WIRE_SPAN4_HORZ_45, + TILE_WIRE_SPAN4_HORZ_46, + TILE_WIRE_SPAN4_HORZ_47, + + TILE_WIRE_SPAN12_VERT_0, + TILE_WIRE_SPAN12_VERT_1, + TILE_WIRE_SPAN12_VERT_2, + TILE_WIRE_SPAN12_VERT_3, + TILE_WIRE_SPAN12_VERT_4, + TILE_WIRE_SPAN12_VERT_5, + TILE_WIRE_SPAN12_VERT_6, + TILE_WIRE_SPAN12_VERT_7, + TILE_WIRE_SPAN12_VERT_8, + TILE_WIRE_SPAN12_VERT_9, + TILE_WIRE_SPAN12_VERT_10, + TILE_WIRE_SPAN12_VERT_11, + TILE_WIRE_SPAN12_VERT_12, + TILE_WIRE_SPAN12_VERT_13, + TILE_WIRE_SPAN12_VERT_14, + TILE_WIRE_SPAN12_VERT_15, + TILE_WIRE_SPAN12_VERT_16, + TILE_WIRE_SPAN12_VERT_17, + TILE_WIRE_SPAN12_VERT_18, + TILE_WIRE_SPAN12_VERT_19, + TILE_WIRE_SPAN12_VERT_20, + TILE_WIRE_SPAN12_VERT_21, + TILE_WIRE_SPAN12_VERT_22, + TILE_WIRE_SPAN12_VERT_23, + + TILE_WIRE_SPAN12_HORZ_0, + TILE_WIRE_SPAN12_HORZ_1, + TILE_WIRE_SPAN12_HORZ_2, + TILE_WIRE_SPAN12_HORZ_3, + TILE_WIRE_SPAN12_HORZ_4, + TILE_WIRE_SPAN12_HORZ_5, + TILE_WIRE_SPAN12_HORZ_6, + TILE_WIRE_SPAN12_HORZ_7, + TILE_WIRE_SPAN12_HORZ_8, + TILE_WIRE_SPAN12_HORZ_9, + TILE_WIRE_SPAN12_HORZ_10, + TILE_WIRE_SPAN12_HORZ_11, + TILE_WIRE_SPAN12_HORZ_12, + TILE_WIRE_SPAN12_HORZ_13, + TILE_WIRE_SPAN12_HORZ_14, + TILE_WIRE_SPAN12_HORZ_15, + TILE_WIRE_SPAN12_HORZ_16, + TILE_WIRE_SPAN12_HORZ_17, + TILE_WIRE_SPAN12_HORZ_18, + TILE_WIRE_SPAN12_HORZ_19, + TILE_WIRE_SPAN12_HORZ_20, + TILE_WIRE_SPAN12_HORZ_21, + TILE_WIRE_SPAN12_HORZ_22, + TILE_WIRE_SPAN12_HORZ_23, + + TILE_WIRE_SPAN4_VERT_B_0, + TILE_WIRE_SPAN4_VERT_B_1, + TILE_WIRE_SPAN4_VERT_B_2, + TILE_WIRE_SPAN4_VERT_B_3, + TILE_WIRE_SPAN4_VERT_B_4, + TILE_WIRE_SPAN4_VERT_B_5, + TILE_WIRE_SPAN4_VERT_B_6, + TILE_WIRE_SPAN4_VERT_B_7, + TILE_WIRE_SPAN4_VERT_B_8, + TILE_WIRE_SPAN4_VERT_B_9, + TILE_WIRE_SPAN4_VERT_B_10, + TILE_WIRE_SPAN4_VERT_B_11, + TILE_WIRE_SPAN4_VERT_B_12, + TILE_WIRE_SPAN4_VERT_B_13, + TILE_WIRE_SPAN4_VERT_B_14, + TILE_WIRE_SPAN4_VERT_B_15, + + TILE_WIRE_SPAN4_VERT_T_12, + TILE_WIRE_SPAN4_VERT_T_13, + TILE_WIRE_SPAN4_VERT_T_14, + TILE_WIRE_SPAN4_VERT_T_15, + + TILE_WIRE_SPAN4_HORZ_R_0, + TILE_WIRE_SPAN4_HORZ_R_1, + TILE_WIRE_SPAN4_HORZ_R_2, + TILE_WIRE_SPAN4_HORZ_R_3, + TILE_WIRE_SPAN4_HORZ_R_4, + TILE_WIRE_SPAN4_HORZ_R_5, + TILE_WIRE_SPAN4_HORZ_R_6, + TILE_WIRE_SPAN4_HORZ_R_7, + TILE_WIRE_SPAN4_HORZ_R_8, + TILE_WIRE_SPAN4_HORZ_R_9, + TILE_WIRE_SPAN4_HORZ_R_10, + TILE_WIRE_SPAN4_HORZ_R_11, + TILE_WIRE_SPAN4_HORZ_R_12, + TILE_WIRE_SPAN4_HORZ_R_13, + TILE_WIRE_SPAN4_HORZ_R_14, + TILE_WIRE_SPAN4_HORZ_R_15, + + TILE_WIRE_SPAN4_HORZ_L_12, + TILE_WIRE_SPAN4_HORZ_L_13, + TILE_WIRE_SPAN4_HORZ_L_14, + TILE_WIRE_SPAN4_HORZ_L_15, + TILE_WIRE_PLLIN, TILE_WIRE_PLLOUT_A, TILE_WIRE_PLLOUT_B }; -void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, GraphicElement::style_t style); +void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, int w, int h, GfxTileWireId id, + GraphicElement::style_t style); void gfxTilePip(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId src, GfxTileWireId dst, GraphicElement::style_t style); diff --git a/ice40/pack.cc b/ice40/pack.cc index 05338713..7c853e0e 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -733,7 +733,7 @@ static void pack_special(Context *ctx) if (pi.name == ctx->id("PACKAGEPIN")) { if (!is_pad) { - log_error(" PLL '%s' has a PACKAGEPIN but is not a PAD PLL", ci->name.c_str(ctx)); + log_error("PLL '%s' has a PACKAGEPIN but is not a PAD PLL", ci->name.c_str(ctx)); } else { // We drop this port and instead place the PLL adequately below. pad_packagepin_net = port.second.net; @@ -743,9 +743,22 @@ static void pack_special(Context *ctx) } if (pi.name == ctx->id("REFERENCECLK")) { if (!is_core) - log_error(" PLL '%s' has a REFERENCECLK but is not a CORE PLL", ci->name.c_str(ctx)); + log_error("PLL '%s' has a REFERENCECLK but is not a CORE PLL", ci->name.c_str(ctx)); } + if (packed->ports.count(ctx->id(newname)) == 0) { + if (ci->ports[pi.name].net == nullptr) { + log_warning("PLL '%s' has unknown unconnected port '%s' - ignoring\n", ci->name.c_str(ctx), pi.name.c_str(ctx)); + continue; + } else { + if (ctx->force) { + log_error("PLL '%s' has unknown connected port '%s'\n", ci->name.c_str(ctx), pi.name.c_str(ctx)); + } else { + log_warning("PLL '%s' has unknown connected port '%s' - ignoring\n", ci->name.c_str(ctx), pi.name.c_str(ctx)); + continue; + } + } + } replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); } @@ -766,7 +779,7 @@ static void pack_special(Context *ctx) auto pll_packagepin_driver = pad_packagepin_net->driver; NPNR_ASSERT(pll_packagepin_driver.cell != nullptr); if (pll_packagepin_driver.cell->type != ctx->id("SB_IO")) { - log_error(" PLL '%s' has a PACKAGEPIN driven by " + log_error("PLL '%s' has a PACKAGEPIN driven by " "an %s, should be directly connected to an input SB_IO\n", ci->name.c_str(ctx), pll_packagepin_driver.cell->type.c_str(ctx)); } @@ -774,17 +787,17 @@ static void pack_special(Context *ctx) auto packagepin_cell = pll_packagepin_driver.cell; auto packagepin_bel_name = packagepin_cell->attrs.find(ctx->id("BEL")); if (packagepin_bel_name == packagepin_cell->attrs.end()) { - log_error(" PLL '%s' PACKAGEPIN SB_IO '%s' is unconstrained\n", ci->name.c_str(ctx), + log_error("PLL '%s' PACKAGEPIN SB_IO '%s' is unconstrained\n", ci->name.c_str(ctx), packagepin_cell->name.c_str(ctx)); } auto packagepin_bel = ctx->getBelByName(ctx->id(packagepin_bel_name->second)); if (pll_sb_io_belpin.bel != packagepin_bel) { - log_error(" PLL '%s' PACKAGEPIN is connected to pin %s, can only be pin %s\n", + log_error("PLL '%s' PACKAGEPIN is connected to pin %s, can only be pin %s\n", ci->name.c_str(ctx), ctx->getBelPackagePin(packagepin_bel).c_str(), ctx->getBelPackagePin(pll_sb_io_belpin.bel).c_str()); } if (pad_packagepin_net->users.size() != 1) { - log_error(" PLL '%s' clock input '%s' can only drive PLL\n", ci->name.c_str(ctx), + log_error("PLL '%s' clock input '%s' can only drive PLL\n", ci->name.c_str(ctx), pad_packagepin_net->name.c_str(ctx)); } // Set an attribute about this PLL's PAD SB_IO. @@ -793,13 +806,13 @@ static void pack_special(Context *ctx) packagepin_cell->ports.erase(pll_packagepin_driver.port); } - log_info(" constrained '%s' to %s\n", packed->name.c_str(ctx), ctx->getBelName(bel).c_str(ctx)); + log_info(" constrained PLL '%s' to %s\n", packed->name.c_str(ctx), ctx->getBelName(bel).c_str(ctx)); packed->attrs[ctx->id("BEL")] = ctx->getBelName(bel).str(ctx); pll_bel = bel; constrained = true; } if (!constrained) { - log_error(" could not constrain '%s' to any PLL Bel\n", packed->name.c_str(ctx)); + log_error("Could not constrain PLL '%s' to any PLL Bel (too many PLLs?)\n", packed->name.c_str(ctx)); } } @@ -818,6 +831,8 @@ static void pack_special(Context *ctx) // If we have a net connected to LOCK, make sure it only drives LUTs. auto port = packed->ports[ctx->id("LOCK")]; if (port.net != nullptr) { + log_info(" PLL '%s' has LOCK output, need to pass all outputs via LUT\n", + ci->name.c_str(ctx)); bool found_lut = false; bool all_luts = true; unsigned int lut_count = 0; @@ -835,12 +850,12 @@ static void pack_special(Context *ctx) // Every user is a LUT, carry on now. } else if (found_lut && !all_luts && lut_count < 8) { // Strategy: create a pass-through LUT, move all non-LUT users behind it. - log_info(" LUT strategy for %s: move non-LUT users to new LUT\n", port.name.c_str(ctx)); + log_info(" LUT strategy for %s: move non-LUT users to new LUT\n", port.name.c_str(ctx)); auto pt = spliceLUT(ctx, packed.get(), port.name, true); new_cells.push_back(std::move(pt)); } else { // Strategy: create a pass-through LUT, move every user behind it. - log_info(" LUT strategy for %s: move all users to new LUT\n", port.name.c_str(ctx)); + log_info(" LUT strategy for %s: move all users to new LUT\n", port.name.c_str(ctx)); auto pt = spliceLUT(ctx, packed.get(), port.name, false); new_cells.push_back(std::move(pt)); } @@ -864,7 +879,7 @@ static void pack_special(Context *ctx) auto target_bel = ctx->getBelByLocation(Loc(x, y, z++)); auto target_bel_name = ctx->getBelName(target_bel).str(ctx); user.cell->attrs[ctx->id("BEL")] = target_bel_name; - log_info(" constrained '%s' to %s\n", user.cell->name.c_str(ctx), target_bel_name.c_str()); + log_info(" constrained '%s' to %s\n", user.cell->name.c_str(ctx), target_bel_name.c_str()); } } diff --git a/ice40/pcf.cc b/ice40/pcf.cc index d9fc4e68..af5b3e17 100644 --- a/ice40/pcf.cc +++ b/ice40/pcf.cc @@ -66,7 +66,7 @@ bool apply_pcf(Context *ctx, std::string filename, std::istream &in) log_error("unsupported pcf command '%s'\n", cmd.c_str()); } } - ctx->settings.emplace(ctx->id("project/input/pcf"), filename); + ctx->settings.emplace(ctx->id("input/pcf"), filename); return true; } catch (log_execution_error_exception) { return false; diff --git a/ice40/project.cc b/ice40/project.cc index 8ca10e36..47c0903d 100644 --- a/ice40/project.cc +++ b/ice40/project.cc @@ -28,8 +28,8 @@ NEXTPNR_NAMESPACE_BEGIN void ProjectHandler::saveArch(Context *ctx, pt::ptree &root, std::string path) { root.put("project.arch.package", ctx->archArgs().package); - if (ctx->settings.find(ctx->id("project/input/pcf")) != ctx->settings.end()) { - std::string fn = ctx->settings[ctx->id("project/input/pcf")]; + if (ctx->settings.find(ctx->id("input/pcf")) != ctx->settings.end()) { + std::string fn = ctx->settings[ctx->id("input/pcf")]; root.put("project.input.pcf", make_relative(fn, path).string()); } } |
