From 302ccc14cfa4344aeefa413e4d686e1c279552fa Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 29 Jun 2018 19:58:08 +0200 Subject: ice40: UltraPlus SPRAM working Signed-off-by: David Shah --- common/place_sa.cc | 2 +- dummy/place_legaliser.cc | 4 +--- ice40/arch.cc | 8 ++++---- ice40/arch.h | 2 +- ice40/bitstream.cc | 23 +++++++++++++++++++++++ ice40/cells.cc | 18 ++++++++++++++++++ ice40/cells.h | 2 ++ ice40/pack.cc | 22 ++++++++++++++++++---- 8 files changed, 68 insertions(+), 13 deletions(-) diff --git a/common/place_sa.cc b/common/place_sa.cc index b773bb68..ab161c57 100644 --- a/common/place_sa.cc +++ b/common/place_sa.cc @@ -39,8 +39,8 @@ #include "log.h" #include "place_common.h" #include "place_legaliser.h" -#include "util.h" #include "timing.h" +#include "util.h" NEXTPNR_NAMESPACE_BEGIN class SAPlacer diff --git a/dummy/place_legaliser.cc b/dummy/place_legaliser.cc index 610a9681..0d23f15b 100644 --- a/dummy/place_legaliser.cc +++ b/dummy/place_legaliser.cc @@ -21,8 +21,6 @@ NEXTPNR_NAMESPACE_BEGIN -bool legalise_design(Context *ctx) { - return true; -} +bool legalise_design(Context *ctx) { return true; } NEXTPNR_NAMESPACE_END diff --git a/ice40/arch.cc b/ice40/arch.cc index 6bca62e4..b16a9f43 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -56,8 +56,8 @@ IdString Arch::belTypeToId(BelType type) const return id("SB_LEDDA_IP"); if (type == TYPE_SB_RGBA_DRV) return id("SB_RGBA_DRV"); - if (type == TYPE_SB_SPRAM256KA) - return id("SB_SPRAM256KA"); + if (type == TYPE_ICESTORM_SPRAM) + return id("ICESTORM_SPRAM"); return IdString(); } @@ -91,8 +91,8 @@ BelType Arch::belTypeFromId(IdString type) const return TYPE_SB_LEDDA_IP; if (type == id("SB_RGBA_DRV")) return TYPE_SB_RGBA_DRV; - if (type == id("SB_SPRAM256KA")) - return TYPE_SB_SPRAM256KA; + if (type == id("ICESTORM_SPRAM")) + return TYPE_ICESTORM_SPRAM; return TYPE_NONE; } diff --git a/ice40/arch.h b/ice40/arch.h index 2906cad7..044a81f1 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -62,7 +62,7 @@ enum BelType : int32_t TYPE_IO_I3C, TYPE_SB_LEDDA_IP, TYPE_SB_RGBA_DRV, - TYPE_SB_SPRAM256KA, + TYPE_ICESTORM_SPRAM, }; enum PortPin : int32_t diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 1a498dd1..0b6e0d35 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -241,6 +241,29 @@ void write_asc(const Context *ctx, std::ostream &out) 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") || cell.second->type == ctx->id("ICESTORM_LFOSC")) { // No config needed + } else if (cell.second->type == ctx->id("ICESTORM_SPRAM")) { + const BelInfoPOD &beli = ci.bel_data[bel.index]; + int x = beli.x, y = beli.y, z = beli.z; + assert(ctx->args.type == ArchArgs::UP5K); + if (x == 0 && y == 0) { + const TileInfoPOD &ti_ipcon = bi.tiles_nonrouting[TILE_IPCON]; + if (z == 1) { + set_config(ti_ipcon, config.at(1).at(0), "IpConfig.CBIT_0", true); + } else if (z == 2) { + set_config(ti_ipcon, config.at(1).at(0), "IpConfig.CBIT_1", true); + } else { + assert(false); + } + } else if (x == 25 && y == 0) { + const TileInfoPOD &ti_ipcon = bi.tiles_nonrouting[TILE_IPCON]; + if (z == 3) { + set_config(ti_ipcon, config.at(1).at(25), "IpConfig.CBIT_0", true); + } else if (z == 4) { + set_config(ti_ipcon, config.at(1).at(25), "IpConfig.CBIT_1", true); + } else { + assert(false); + } + } } else { assert(false); } diff --git a/ice40/cells.cc b/ice40/cells.cc index 27277e4e..7f690930 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -124,6 +124,24 @@ std::unique_ptr create_ice_cell(Context *ctx, IdString type, std::stri } else if (type == ctx->id("SB_GB")) { add_port(ctx, new_cell.get(), "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN); add_port(ctx, new_cell.get(), "GLOBAL_BUFFER_OUTPUT", PORT_OUT); + } else if (type == ctx->id("ICESTORM_SPRAM")) { + add_port(ctx, new_cell.get(), "WREN", PORT_IN); + add_port(ctx, new_cell.get(), "CHIPSELECT", PORT_IN); + add_port(ctx, new_cell.get(), "CLOCK", PORT_IN); + add_port(ctx, new_cell.get(), "STANDBY", PORT_IN); + add_port(ctx, new_cell.get(), "SLEEP", PORT_IN); + add_port(ctx, new_cell.get(), "POWEROFF", PORT_IN); + + for (int i = 0; i < 16; i++) { + add_port(ctx, new_cell.get(), "DATAIN_" + std::to_string(i), PORT_IN); + add_port(ctx, new_cell.get(), "DATAOUT_" + std::to_string(i), PORT_OUT); + } + for (int i = 0; i < 14; i++) { + add_port(ctx, new_cell.get(), "ADDRESS_" + std::to_string(i), PORT_IN); + } + for (int i = 0; i < 4; i++) { + add_port(ctx, new_cell.get(), "MASKWREN_" + std::to_string(i), PORT_IN); + } } else { log_error("unable to create iCE40 cell of type %s", type.c_str(ctx)); } diff --git a/ice40/cells.h b/ice40/cells.h index eb0007aa..9f99835d 100644 --- a/ice40/cells.h +++ b/ice40/cells.h @@ -67,6 +67,8 @@ inline bool is_sb_lfosc(const BaseCtx *ctx, const CellInfo *cell) { return cell- inline bool is_sb_hfosc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_HFOSC"); } +inline bool is_sb_spram(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_SPRAM256KA"); } + // 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 253e3fa8..2484aa53 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -528,10 +528,10 @@ static void promote_globals(Context *ctx) } } -// Pack internal oscillators -static void pack_intosc(Context *ctx) +// Pack special functions +static void pack_special(Context *ctx) { - log_info("Packing oscillators..\n"); + log_info("Packing special functions..\n"); std::unordered_set packed_cells; std::vector> new_cells; @@ -550,6 +550,20 @@ static void pack_intosc(Context *ctx) replace_port(ci, ctx->id("CLKLF"), packed.get(), ctx->id("CLKLF")); } new_cells.push_back(std::move(packed)); + } else if (is_sb_spram(ctx, ci)) { + std::unique_ptr packed = + create_ice_cell(ctx, ctx->id("ICESTORM_SPRAM"), ci->name.str(ctx) + "_RAM"); + packed_cells.insert(ci->name); + for (auto port : ci->ports) { + PortInfo &pi = port.second; + std::string newname = pi.name.str(ctx); + size_t bpos = newname.find('['); + if (bpos != std::string::npos) { + newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2); + } + replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); + } + new_cells.push_back(std::move(packed)); } } @@ -573,7 +587,7 @@ bool pack_design(Context *ctx) pack_nonlut_ffs(ctx); pack_carries(ctx); pack_ram(ctx); - pack_intosc(ctx); + pack_special(ctx); log_info("Checksum: 0x%08x\n", ctx->checksum()); return true; } catch (log_execution_error_exception) { -- cgit v1.2.3