aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ice40/arch.cc4
-rw-r--r--ice40/bitstream.cc3
-rw-r--r--ice40/cells.cc14
-rw-r--r--ice40/cells.h2
-rw-r--r--ice40/pack.cc4
5 files changed, 26 insertions, 1 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc
index ddf25270..ada78020 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -950,6 +950,10 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
if (port == id_RGB0 || port == id_RGB1 || port == id_RGB2)
return TMG_IGNORE;
return TMG_ENDPOINT;
+ } else if (cell->type == id_SB_LEDDA_IP) {
+ if (port == id_CLK || port == id_CLOCK)
+ return TMG_CLOCK_INPUT;
+ return TMG_IGNORE;
}
log_error("cell type '%s' is unsupported (instantiated as '%s')\n", cell->type.c_str(this), cell->name.c_str(this));
}
diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc
index e20d372a..87d77b9d 100644
--- a/ice40/bitstream.cc
+++ b/ice40/bitstream.cc
@@ -591,7 +591,8 @@ void write_asc(const Context *ctx, std::ostream &out)
{"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") ||
+ cell.second->type == ctx->id("SB_LEDDA_IP") ) {
// No config needed
} else if (cell.second->type == ctx->id("ICESTORM_SPRAM")) {
const BelInfoPOD &beli = ci.bel_data[bel.index];
diff --git a/ice40/cells.cc b/ice40/cells.cc
index dbb75c2c..aad719b1 100644
--- a/ice40/cells.cc
+++ b/ice40/cells.cc
@@ -260,6 +260,20 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri
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 if (type == ctx->id("SB_LEDDA_IP")) {
+ add_port(ctx, new_cell.get(), "LEDDCS", PORT_IN);
+ add_port(ctx, new_cell.get(), "LEDDCLK", PORT_IN);
+ for (int i = 0; i < 8; i++)
+ add_port(ctx, new_cell.get(), "LEDDDAT" + std::to_string(i), PORT_IN);
+ for (int i = 0; i < 3; i++)
+ add_port(ctx, new_cell.get(), "LEDDADDR" + std::to_string(i), PORT_IN);
+ add_port(ctx, new_cell.get(), "LEDDDEN", PORT_IN);
+ add_port(ctx, new_cell.get(), "LEDDEXE", PORT_IN);
+ add_port(ctx, new_cell.get(), "LEDDRST", PORT_IN); //doesn't actually exist, for icecube code compatibility only
+ add_port(ctx, new_cell.get(), "PWMOUT0", PORT_OUT);
+ add_port(ctx, new_cell.get(), "PWMOUT1", PORT_OUT);
+ add_port(ctx, new_cell.get(), "PWMOUT2", PORT_OUT);
+ add_port(ctx, new_cell.get(), "LEDDON", 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 1fbd9073..93ef3db4 100644
--- a/ice40/cells.h
+++ b/ice40/cells.h
@@ -76,6 +76,8 @@ inline bool is_sb_mac16(const BaseCtx *ctx, const CellInfo *cell) { return cell-
inline bool is_sb_rgba_drv(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_RGBA_DRV"); }
+inline bool is_sb_ledda_ip(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LEDDA_IP"); }
+
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 523a2642..17d2df8b 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -1044,6 +1044,10 @@ static void pack_special(Context *ctx)
ci->ports.erase(ctx->id("RGB0"));
ci->ports.erase(ctx->id("RGB1"));
ci->ports.erase(ctx->id("RGB2"));
+ } else if (is_sb_ledda_ip(ctx, ci)) {
+ /* Force placement (no choices anyway) */
+ cell_place_unique(ctx, ci);
+
} else if (is_sb_pll40(ctx, ci)) {
bool is_pad = is_sb_pll40_pad(ctx, ci);
bool is_core = !is_pad;