diff options
| -rw-r--r-- | ice40/arch.cc | 17 | ||||
| -rw-r--r-- | ice40/arch.h | 38 | ||||
| -rw-r--r-- | ice40/archdefs.h | 4 | ||||
| -rw-r--r-- | ice40/chipdb.py | 47 | ||||
| -rw-r--r-- | ice40/gfx.cc | 33 | ||||
| -rw-r--r-- | ice40/gfx.h | 45 | 
6 files changed, 157 insertions, 27 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc index eff1d9b9..2e790569 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"); @@ -541,7 +543,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 +569,6 @@ std::vector<GroupId> Arch::getGroups() const                  group.type = GroupId::TYPE_LC7_SW;                  ret.push_back(group);              } -#endif          }      }      return ret; @@ -763,6 +763,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) { @@ -913,6 +925,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 98361132..4a5157bd 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 { @@ -373,6 +381,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 +423,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 +439,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);      } @@ -614,14 +627,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 +803,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..84d73f5e 100644 --- a/ice40/archdefs.h +++ b/ice40/archdefs.h @@ -167,7 +167,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 a0d7f03c..d61a51bd 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -190,6 +190,8 @@ def wire_type(name):          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 in ("in_0_lut", "in_1_lut", "in_2_lut", "in_3_lut"): +        wt = "LOCAL"      elif name.startswith("local_g") or name.startswith("glb2local_"):          wt = "LOCAL"      elif name.startswith("span4_horz_") or name.startswith("sp4_h_"): @@ -265,9 +267,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 +477,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 +513,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 +531,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 +565,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 +592,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) @@ -898,6 +918,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) @@ -923,6 +944,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) @@ -1080,6 +1102,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 924fe964..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,9 +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; @@ -721,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..5a98e79d 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; @@ -135,6 +138,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,  | 
