ice40: Add support for SB_RGBA_DRV
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
parent
de8de6304f
commit
e8556aff37
@ -946,6 +946,10 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
|
|||||||
return TMG_COMB_INPUT;
|
return TMG_COMB_INPUT;
|
||||||
} else if (cell->type == id_SB_WARMBOOT) {
|
} else if (cell->type == id_SB_WARMBOOT) {
|
||||||
return TMG_ENDPOINT;
|
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));
|
log_error("no timing info for port '%s' of cell type '%s'\n", port.c_str(this), cell->type.c_str(this));
|
||||||
}
|
}
|
||||||
|
@ -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_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_2", read_mode & 0x1);
|
||||||
set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_3", read_mode & 0x2);
|
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")) {
|
} else if (cell.second->type == ctx->id("SB_WARMBOOT") || cell.second->type == ctx->id("ICESTORM_LFOSC")) {
|
||||||
// No config needed
|
// No config needed
|
||||||
} else if (cell.second->type == ctx->id("ICESTORM_SPRAM")) {
|
} else if (cell.second->type == ctx->id("ICESTORM_SPRAM")) {
|
||||||
|
@ -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_B", PORT_OUT);
|
||||||
add_port(ctx, new_cell.get(), "PLLOUT_A_GLOBAL", PORT_OUT);
|
add_port(ctx, new_cell.get(), "PLLOUT_A_GLOBAL", PORT_OUT);
|
||||||
add_port(ctx, new_cell.get(), "PLLOUT_B_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 {
|
} else {
|
||||||
log_error("unable to create iCE40 cell of type %s", type.c_str(ctx));
|
log_error("unable to create iCE40 cell of type %s", type.c_str(ctx));
|
||||||
}
|
}
|
||||||
|
@ -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_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)
|
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") ||
|
return cell->type == ctx->id("SB_PLL40_PAD") || cell->type == ctx->id("SB_PLL40_2_PAD") ||
|
||||||
|
@ -431,12 +431,15 @@ static void pack_io(Context *ctx)
|
|||||||
for (auto cell : sorted(ctx->cells)) {
|
for (auto cell : sorted(ctx->cells)) {
|
||||||
CellInfo *ci = cell.second;
|
CellInfo *ci = cell.second;
|
||||||
if (is_nextpnr_iob(ctx, ci)) {
|
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")) {
|
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);
|
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")) {
|
} 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) {
|
if (sb != nullptr) {
|
||||||
// Trivial case, SB_IO used. Just destroy the net and the
|
// 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);
|
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 {
|
} else {
|
||||||
// Create a SB_IO buffer
|
// Create a SB_IO buffer
|
||||||
std::unique_ptr<CellInfo> ice_cell =
|
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));
|
replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
|
||||||
}
|
}
|
||||||
new_cells.push_back(std::move(packed));
|
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)) {
|
} else if (is_sb_pll40(ctx, ci)) {
|
||||||
bool is_pad = is_sb_pll40_pad(ctx, ci);
|
bool is_pad = is_sb_pll40_pad(ctx, ci);
|
||||||
bool is_core = !is_pad;
|
bool is_core = !is_pad;
|
||||||
|
Loading…
Reference in New Issue
Block a user