diff options
author | Sylvain Munaut <tnt@246tNt.com> | 2018-11-17 18:02:31 +0100 |
---|---|---|
committer | Sylvain Munaut <tnt@246tNt.com> | 2018-11-19 18:20:20 +0100 |
commit | e8556aff372c77c1e14a4378b43b47f8ba1e75ec (patch) | |
tree | 40d8a30b0d1d30bf84df1fd47b0c8d38e594b7f2 | |
parent | de8de6304f6905525fd5774d30851c0cc9fe4e37 (diff) | |
download | nextpnr-e8556aff372c77c1e14a4378b43b47f8ba1e75ec.tar.gz nextpnr-e8556aff372c77c1e14a4378b43b47f8ba1e75ec.tar.bz2 nextpnr-e8556aff372c77c1e14a4378b43b47f8ba1e75ec.zip |
ice40: Add support for SB_RGBA_DRV
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
-rw-r--r-- | ice40/arch.cc | 4 | ||||
-rw-r--r-- | ice40/bitstream.cc | 5 | ||||
-rw-r--r-- | ice40/cells.cc | 14 | ||||
-rw-r--r-- | ice40/cells.h | 2 | ||||
-rw-r--r-- | ice40/pack.cc | 35 |
5 files changed, 58 insertions, 2 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc index 259eec67..02e5515b 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -946,6 +946,10 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in return TMG_COMB_INPUT; } else if (cell->type == id_SB_WARMBOOT) { return TMG_ENDPOINT; + } else if (cell->type == id_SB_RGBA_DRV) { + if (port == id_RGB0 || port == id_RGB1 || port == id_RGB2) + return TMG_IGNORE; + return TMG_ENDPOINT; } log_error("no timing info for port '%s' of cell type '%s'\n", port.c_str(this), cell->type.c_str(this)); } diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 44d385e4..ecb26753 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -586,6 +586,11 @@ void write_asc(const Context *ctx, std::ostream &out) set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_1", write_mode & 0x2); set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_2", 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_RGBA_DRV")) { + const std::vector<std::pair<std::string, int>> rgba_params = { + {"CURRENT_MODE", 1}, {"RGB0_CURRENT", 6}, {"RGB1_CURRENT", 6}, {"RGB2_CURRENT", 6}}; + configure_extra_cell(config, ctx, cell.second.get(), rgba_params, true, std::string("IpConfig.")); + set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "RGBA_DRV_EN", true, "IpConfig."); } 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")) { diff --git a/ice40/cells.cc b/ice40/cells.cc index 53f2e10c..dbb75c2c 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -246,6 +246,20 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri add_port(ctx, new_cell.get(), "PLLOUT_B", PORT_OUT); add_port(ctx, new_cell.get(), "PLLOUT_A_GLOBAL", PORT_OUT); add_port(ctx, new_cell.get(), "PLLOUT_B_GLOBAL", PORT_OUT); + } else if (type == ctx->id("SB_RGBA_DRV")) { + new_cell->params[ctx->id("CURRENT_MODE")] = "0b0"; + new_cell->params[ctx->id("RGB0_CURRENT")] = "0b000000"; + new_cell->params[ctx->id("RGB1_CURRENT")] = "0b000000"; + new_cell->params[ctx->id("RGB2_CURRENT")] = "0b000000"; + + add_port(ctx, new_cell.get(), "CURREN", PORT_IN); + add_port(ctx, new_cell.get(), "RGBLEDEN", PORT_IN); + add_port(ctx, new_cell.get(), "RGB0PWM", PORT_IN); + add_port(ctx, new_cell.get(), "RGB1PWM", PORT_IN); + add_port(ctx, new_cell.get(), "RGB2PWM", PORT_IN); + add_port(ctx, new_cell.get(), "RGB0", PORT_OUT); + add_port(ctx, new_cell.get(), "RGB1", PORT_OUT); + add_port(ctx, new_cell.get(), "RGB2", PORT_OUT); } 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 270292ed..1fbd9073 100644 --- a/ice40/cells.h +++ b/ice40/cells.h @@ -74,6 +74,8 @@ inline bool is_sb_spram(const BaseCtx *ctx, const CellInfo *cell) { return cell- inline bool is_sb_mac16(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_MAC16"); } +inline bool is_sb_rgba_drv(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_RGBA_DRV"); } + inline bool is_sb_pll40(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_PLL40_PAD") || cell->type == ctx->id("SB_PLL40_2_PAD") || diff --git a/ice40/pack.cc b/ice40/pack.cc index c0970735..dae19b2d 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -431,12 +431,15 @@ static void pack_io(Context *ctx) for (auto cell : sorted(ctx->cells)) { CellInfo *ci = cell.second; if (is_nextpnr_iob(ctx, ci)) { - CellInfo *sb = nullptr; + CellInfo *sb = nullptr, *rgb = nullptr; if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) { sb = net_only_drives(ctx, ci->ports.at(ctx->id("O")).net, is_ice_iob, ctx->id("PACKAGE_PIN"), true, ci); } else if (ci->type == ctx->id("$nextpnr_obuf")) { - sb = net_only_drives(ctx, ci->ports.at(ctx->id("I")).net, is_ice_iob, ctx->id("PACKAGE_PIN"), true, ci); + NetInfo *net = ci->ports.at(ctx->id("I")).net; + sb = net_only_drives(ctx, net, is_ice_iob, ctx->id("PACKAGE_PIN"), true, ci); + if (net && net->driver.cell && is_sb_rgba_drv(ctx, net->driver.cell)) + rgb = net->driver.cell; } if (sb != nullptr) { // Trivial case, SB_IO used. Just destroy the net and the @@ -460,6 +463,11 @@ static void pack_io(Context *ctx) delete_nets.insert(net2->name); } } + } else if (rgb != nullptr) { + log_info("%s use by SB_RGBA_DRV %s, not creating SB_IO\n", ci->name.c_str(ctx), rgb->name.c_str(ctx)); + disconnect_port(ctx, ci, ctx->id("I")); + packed_cells.insert(ci->name); + continue; } else { // Create a SB_IO buffer std::unique_ptr<CellInfo> ice_cell = @@ -787,6 +795,29 @@ static void pack_special(Context *ctx) replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); } new_cells.push_back(std::move(packed)); + } else if (is_sb_rgba_drv(ctx, ci)) { + /* Force placement (no choices anyway) */ + cell_place_unique(ctx, ci); + + /* Disconnect all external ports and check there is no users (they should have been + * dealth with during IO packing */ + for (auto port : ci->ports) { + PortInfo &pi = port.second; + NetInfo *net = pi.net; + + if (net == nullptr) + continue; + if ((pi.name != ctx->id("RGB0")) && (pi.name != ctx->id("RGB1")) && (pi.name != ctx->id("RGB2"))) + continue; + + if (net->users.size() > 0) + log_error("SB_RGBA_DRV port connected to more than just package pin !\n"); + + ctx->nets.erase(net->name); + } + ci->ports.erase(ctx->id("RGB0")); + ci->ports.erase(ctx->id("RGB1")); + ci->ports.erase(ctx->id("RGB2")); } else if (is_sb_pll40(ctx, ci)) { bool is_pad = is_sb_pll40_pad(ctx, ci); bool is_core = !is_pad; |