From 7c89aed70e433c4d471960b07390e17f91ae3f84 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 17 Jul 2018 14:19:21 +0200 Subject: ecp5: Infrastructure for FF packing Signed-off-by: David Shah --- ecp5/cells.cc | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'ecp5/cells.cc') diff --git a/ecp5/cells.cc b/ecp5/cells.cc index 13025da9..4beaabd2 100644 --- a/ecp5/cells.cc +++ b/ecp5/cells.cc @@ -18,6 +18,7 @@ */ #include "cells.h" +#include #include "design_utils.h" #include "log.h" #include "util.h" @@ -121,4 +122,47 @@ std::unique_ptr create_ecp5_cell(Context *ctx, IdString type, std::str return new_cell; } +static void set_param_safe(bool has_ff, CellInfo *lc, IdString name, const std::string &value) +{ + NPNR_ASSERT(!has_ff || lc->params.at(name) == value); + lc->params[name] = value; +} + +static void replace_port_safe(bool has_ff, CellInfo *ff, IdString ff_port, CellInfo *lc, IdString lc_port) +{ + if (has_ff) { + assert(lc->ports.at(lc_port).net == ff->ports.at(ff_port).net); + NetInfo *ffnet = ff->ports.at(ff_port).net; + if (ffnet != nullptr) + ffnet->users.erase( + std::remove_if(ffnet->users.begin(), ffnet->users.end(), + [ff, ff_port](PortRef port) { return port.cell == ff && port.port == ff_port; }), + ffnet->users.end()); + } else { + replace_port(ff, ff_port, lc, lc_port); + } +} + +void ff_to_lc(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool driven_by_lut) +{ + bool has_ff = lc->ports.at(ctx->id("Q0")).net != nullptr || lc->ports.at(ctx->id("Q1")).net != nullptr; + std::string reg = "REG" + std::to_string(index); + set_param_safe(has_ff, lc, ctx->id("SRMODE"), str_or_default(ff->params, ctx->id("SRMODE"), "LSR_OVER_CE")); + set_param_safe(has_ff, lc, ctx->id("GSR"), str_or_default(ff->params, ctx->id("GSR"), "DISABLED")); + set_param_safe(has_ff, lc, ctx->id("CEMUX"), str_or_default(ff->params, ctx->id("CEMUX"), "1")); + set_param_safe(has_ff, lc, ctx->id("LSRMUX"), str_or_default(ff->params, ctx->id("LSRMUX"), "LSR")); + lc->params[ctx->id(reg + "_SD")] = driven_by_lut ? "1" : "0"; + lc->params[ctx->id(reg + "_REGSET")] = str_or_default(ff->params, ctx->id("REGSET"), "RESET"); + replace_port_safe(has_ff, ff, ctx->id("CLK"), lc, ctx->id("CLK")); + replace_port_safe(has_ff, ff, ctx->id("LSR"), lc, ctx->id("LSR")); + replace_port_safe(has_ff, ff, ctx->id("CE"), lc, ctx->id("CE")); + + replace_port(ff, ctx->id("Q"), lc, ctx->id("Q" + std::to_string(index))); + if (driven_by_lut) { + replace_port(ff, ctx->id("DI"), lc, ctx->id("DI" + std::to_string(index))); + } else { + replace_port(ff, ctx->id("DI"), lc, ctx->id("M" + std::to_string(index))); + } +} + NEXTPNR_NAMESPACE_END -- cgit v1.2.3