aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/pack.cc
diff options
context:
space:
mode:
authorSimon Schubert <2@0x2c.org>2019-06-10 11:30:01 +0200
committerSimon Schubert <2@0x2c.org>2019-06-10 14:04:25 +0200
commit88eeafae12b78798f6b886b2d4193b5fa64bac4c (patch)
treeeaff7c02dc6db212f6b147a5193b1a1ddf2b6ab0 /ice40/pack.cc
parent187db92b0571b87360516598e88f36cdb1f33349 (diff)
downloadnextpnr-88eeafae12b78798f6b886b2d4193b5fa64bac4c.tar.gz
nextpnr-88eeafae12b78798f6b886b2d4193b5fa64bac4c.tar.bz2
nextpnr-88eeafae12b78798f6b886b2d4193b5fa64bac4c.zip
ice40: add RGB_DRV/LED_DRV_CUR support for u4k
Diffstat (limited to 'ice40/pack.cc')
-rw-r--r--ice40/pack.cc35
1 files changed, 31 insertions, 4 deletions
diff --git a/ice40/pack.cc b/ice40/pack.cc
index 390cbf57..9a77048b 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -450,7 +450,7 @@ static void pack_io(Context *ctx)
} else if (ci->type == ctx->id("$nextpnr_obuf")) {
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))
+ if (net && net->driver.cell && (is_sb_rgba_drv(ctx, net->driver.cell) || is_sb_rgb_drv(ctx, net->driver.cell)))
rgb = net->driver.cell;
}
if (sb != nullptr) {
@@ -476,7 +476,7 @@ static void pack_io(Context *ctx)
}
}
} 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));
+ log_info("%s use by SB_RGBA_DRV/SB_RGB_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;
@@ -1038,6 +1038,27 @@ static void pack_special(Context *ctx)
std::unordered_set<IdString> packed_cells;
std::vector<std::unique_ptr<CellInfo>> new_cells;
+ // Handle LED_DRV_CUR first to set the ledCurConnected flag before RGB_DRV is handled below.
+ for (auto cell : sorted(ctx->cells)) {
+ CellInfo *ci = cell.second;
+ if (is_sb_led_drv_cur(ctx, ci)) {
+ /* Force placement (no choices anyway) */
+ cell_place_unique(ctx, ci);
+
+ NetInfo *ledpu_net = ci->ports.at(ctx->id("LEDPU")).net;
+ for (auto &user : ledpu_net->users) {
+ if (!is_sb_rgb_drv(ctx, user.cell)) {
+ log_error("SB_LED_DRV_CUR LEDPU port can only be connected to SB_RGB_DRV!\n");
+ } else {
+ user.cell->ledInfo.ledCurConnected = true;
+ user.cell->ports.at(user.port).net = nullptr;
+ }
+ }
+ ci->ports.erase(ctx->id("LEDPU"));
+ ctx->nets.erase(ledpu_net->name);
+ }
+ }
+
for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (is_sb_lfosc(ctx, ci)) {
@@ -1113,7 +1134,7 @@ 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)) {
+ } else if (is_sb_rgba_drv(ctx, ci) || is_sb_rgb_drv(ctx, ci)) {
/* Force placement (no choices anyway) */
cell_place_unique(ctx, ci);
@@ -1125,14 +1146,20 @@ static void pack_special(Context *ctx)
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");
+ log_error("SB_RGB_DRV/SB_RGBA_DRV port connected to more than just package pin !\n");
ctx->nets.erase(net->name);
}
+
+ if (is_sb_rgb_drv(ctx, ci) && !ci->ledInfo.ledCurConnected)
+ log_error("Port RGBPU of SB_RGB_DRV should be driven by port LEDPU of SB_LED_DRV_CUR!\n");
+
+ ci->ports.erase(ctx->id("RGBPU"));
ci->ports.erase(ctx->id("RGB0"));
ci->ports.erase(ctx->id("RGB1"));
ci->ports.erase(ctx->id("RGB2"));