ecp5: Infrastructure for FF packing
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
eb773f246d
commit
7c89aed70e
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "cells.h"
|
||||
#include <algorithm>
|
||||
#include "design_utils.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
@ -121,4 +122,47 @@ std::unique_ptr<CellInfo> 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
|
||||
|
@ -46,6 +46,8 @@ inline bool is_pfumx(const BaseCtx *ctx, const CellInfo *cell) { return cell->ty
|
||||
|
||||
inline bool is_l6mux(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("L6MUX21"); }
|
||||
|
||||
void ff_to_lc(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool driven_by_lut);
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
25
ecp5/pack.cc
25
ecp5/pack.cc
@ -52,6 +52,23 @@ class Ecp5Packer
|
||||
new_cells.clear();
|
||||
}
|
||||
|
||||
// Find FFs associated with LUTs, or LUT expansion muxes
|
||||
void find_lutff_pairs()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
if (is_lut(ctx, ci) || is_pfumx(ctx, ci) || is_l6mux(ctx, ci)) {
|
||||
NetInfo *znet = ci->ports.at(ctx->id("Z")).net;
|
||||
if (znet != nullptr) {
|
||||
CellInfo *ff = net_only_drives(ctx, znet, is_ff, ctx->id("DI"), false);
|
||||
if (ff != nullptr) {
|
||||
lutffPairs[ci->name] = ff->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Simple "packer" to remove nextpnr IOBUFs, this assumes IOBUFs are manually instantiated
|
||||
void pack_io()
|
||||
{
|
||||
@ -126,6 +143,13 @@ class Ecp5Packer
|
||||
replace_port(ci, ctx->id("Z"), packed.get(), ctx->id("OFX0"));
|
||||
ctx->nets.erase(f0->name);
|
||||
ctx->nets.erase(f1->name);
|
||||
|
||||
if (lutffPairs.find(ci->name) != lutffPairs.end()) {
|
||||
CellInfo *ff = ctx->cells.at(lutffPairs[ci->name]).get();
|
||||
ff_to_lc(ctx, ff, packed.get(), 0, true);
|
||||
packed_cells.insert(ff->name);
|
||||
}
|
||||
|
||||
new_cells.push_back(std::move(packed));
|
||||
packed_cells.insert(lc0->name);
|
||||
packed_cells.insert(lc1->name);
|
||||
@ -157,6 +181,7 @@ class Ecp5Packer
|
||||
};
|
||||
|
||||
std::unordered_map<IdString, SliceUsage> sliceUsage;
|
||||
std::unordered_map<IdString, IdString> lutffPairs;
|
||||
};
|
||||
|
||||
// Main pack function
|
||||
|
Loading…
Reference in New Issue
Block a user