diff options
-rw-r--r-- | ice40/arch.h | 5 | ||||
-rw-r--r-- | ice40/bitstream.cc | 41 | ||||
-rw-r--r-- | ice40/cells.cc | 19 | ||||
-rw-r--r-- | ice40/cells.h | 10 | ||||
-rw-r--r-- | ice40/pack.cc | 34 |
5 files changed, 94 insertions, 15 deletions
diff --git a/ice40/arch.h b/ice40/arch.h index 74a1efcc..07c2582b 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -692,11 +692,6 @@ struct Arch : BaseCtx bool checkPipAvail(PipId pip) const { assert(pip != PipId()); - if (args.type == ArchArgs::UP5K) { - int x = chip_info->pip_data[pip.index].x; - if (x == 0 || x == (chip_info->width - 1)) - return false; - } return switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString(); } diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 6e6ebabd..8e34335c 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -267,7 +267,8 @@ void write_asc(const Context *ctx, std::ostream &out) read_mode & 0x1); set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_3", read_mode & 0x2); - } else if (cell.second->type == ctx->id("SB_WARMBOOT")) { + } else if (cell.second->type == ctx->id("SB_WARMBOOT") || + cell.second->type == ctx->id("ICESTORM_LFOSC")) { // No config needed } else { assert(false); @@ -323,13 +324,8 @@ void write_asc(const Context *ctx, std::ostream &out) ctx->args.type == ArchArgs::HX8K) { setColBufCtrl = (y == 8 || y == 9 || y == 24 || y == 25); } else if (ctx->args.type == ArchArgs::UP5K) { - if (tile == TILE_LOGIC || tile == TILE_RAMB || - tile == TILE_RAMT) { - setColBufCtrl = (y == 4 || y == 5 || y == 14 || y == 15 || - y == 26 || y == 27); - } else { - setColBufCtrl = false; - } + setColBufCtrl = (y == 4 || y == 5 || y == 14 || y == 15 || + y == 26 || y == 27); } if (setColBufCtrl) { set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_0", @@ -349,6 +345,35 @@ void write_asc(const Context *ctx, std::ostream &out) set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_7", true); } + + // Weird UltraPlus bits + if (tile == TILE_DSP0 || tile == TILE_DSP1 || tile == TILE_DSP2 || + tile == TILE_IPCON) { + for (int lc_idx = 0; lc_idx < 8; lc_idx++) { + static const std::vector<int> ip_dsp_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++) + set_config(ti, config.at(y).at(x), + "LC_" + std::to_string(lc_idx), + ((i % 8) >= 4), ip_dsp_lut_perm.at(i)); + if (tile == TILE_IPCON) + set_config(ti, config.at(y).at(x), + "Cascade.IPCON_LC0" + + std::to_string(lc_idx) + + "_inmux02_5", + true); + else + set_config( + ti, config.at(y).at(x), + "Cascade.MULT" + + std::to_string(int(tile - TILE_DSP0)) + + "_LC0" + std::to_string(lc_idx) + + "_inmux02_5", + true); + } + } } } diff --git a/ice40/cells.cc b/ice40/cells.cc index 3f94d4ba..0ae25e12 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -106,11 +106,26 @@ CellInfo *create_ice_cell(Context *ctx, IdString type, std::string name) add_port(ctx, new_cell, "RADDR_" + std::to_string(i), PORT_IN); add_port(ctx, new_cell, "WADDR_" + std::to_string(i), PORT_IN); } + } else if (type == ctx->id("ICESTORM_LFOSC")) { + add_port(ctx, new_cell, "CLKLFEN", PORT_IN); + add_port(ctx, new_cell, "CLKLFPU", PORT_IN); + add_port(ctx, new_cell, "CLKLF", PORT_OUT); + add_port(ctx, new_cell, "CLKLF_FABRIC", PORT_OUT); + } else if (type == ctx->id("ICESTORM_HFOSC")) { + new_cell->params[ctx->id("CLKHF_DIV")] = "0"; + new_cell->params[ctx->id("TRIM_EN")] = "0"; + + add_port(ctx, new_cell, "CLKHFEN", PORT_IN); + add_port(ctx, new_cell, "CLKHFPU", PORT_IN); + add_port(ctx, new_cell, "CLKHF", PORT_OUT); + add_port(ctx, new_cell, "CLKHF_FABRIC", PORT_OUT); + for (int i = 0; i < 10; i++) + add_port(ctx, new_cell, "TRIM" + std::to_string(i), PORT_IN); } else if (type == ctx->id("SB_GB")) { add_port(ctx, new_cell, "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN); add_port(ctx, new_cell, "GLOBAL_BUFFER_OUTPUT", PORT_OUT); } else { - log_error("unable to create iCE40 cell of type %s", type.c_str()); + log_error("unable to create iCE40 cell of type %s", type.c_str(ctx)); } return new_cell; } @@ -124,7 +139,7 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff) replace_port(lut, "I3", lc, "I3"); if (no_dff) { replace_port(lut, "O", lc, "O"); - lc->params["DFF_ENABLE"] = "0"; + lc->params[ctx->id("DFF_ENABLE")] = "0"; } } diff --git a/ice40/cells.h b/ice40/cells.h index b1f3d516..3e5f6ebd 100644 --- a/ice40/cells.h +++ b/ice40/cells.h @@ -91,6 +91,16 @@ inline bool is_ram(const Context *ctx, const CellInfo *cell) cell->type == ctx->id("SB_RAM40_4KNRNW"); } +inline bool is_sb_lfosc(const Context *ctx, const CellInfo *cell) +{ + return cell->type == ctx->id("SB_LFOSC"); +} + +inline bool is_sb_hfosc(const Context *ctx, const CellInfo *cell) +{ + return cell->type == ctx->id("SB_HFOSC"); +} + // Convert a SB_LUT primitive to (part of) an ICESTORM_LC, swapping ports // as needed. Set no_dff if a DFF is not being used, so that the output // can be reconnected diff --git a/ice40/pack.cc b/ice40/pack.cc index e9f02ddf..5022fc59 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -485,6 +485,39 @@ static void promote_globals(Context *ctx) } } +// Pack internal oscillators +static void pack_intosc(Context *ctx) +{ + log_info("Packing oscillators..\n"); + + std::unordered_set<IdString> packed_cells; + std::vector<CellInfo *> new_cells; + + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (is_sb_lfosc(ctx, ci)) { + CellInfo *packed = create_ice_cell(ctx, "ICESTORM_LFOSC", + ci->name.str(ctx) + "_OSC"); + packed_cells.insert(ci->name); + new_cells.push_back(packed); + replace_port(ci, "CLKLFEN", packed, "CLKLFEN"); + replace_port(ci, "CLKLFPU", packed, "CLKLFPU"); + if (bool_or_default(ci->attrs, "ROUTE_THROUGH_FABRIC")) { + replace_port(ci, "CLKLF", packed, "CLKLF_FABRIC"); + } else { + replace_port(ci, "CLKLF", packed, "CLKLF"); + } + } + } + + for (auto pcell : packed_cells) { + ctx->cells.erase(pcell); + } + for (auto ncell : new_cells) { + ctx->cells[ncell->name] = ncell; + } +} + // Main pack function bool pack_design(Context *ctx) { @@ -496,6 +529,7 @@ bool pack_design(Context *ctx) pack_lut_lutffs(ctx); pack_nonlut_ffs(ctx); pack_ram(ctx); + pack_intosc(ctx); log_info("Checksum: 0x%08x\n", ctx->checksum()); return true; } catch (log_execution_error_exception) { |