ecp5: Fixing packer bugs

Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
David Shah 2018-07-17 16:45:39 +02:00
parent f62f04e376
commit 2eb783d626
4 changed files with 29 additions and 10 deletions

View File

@ -214,6 +214,18 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
cc.tiles[tname].add_enum(slice + ".REG1.REGSET", cc.tiles[tname].add_enum(slice + ".REG1.REGSET",
str_or_default(ci->params, ctx->id("REG1_REGSET"), "RESET")); str_or_default(ci->params, ctx->id("REG1_REGSET"), "RESET"));
cc.tiles[tname].add_enum(slice + ".CEMUX", str_or_default(ci->params, ctx->id("CEMUX"), "1")); cc.tiles[tname].add_enum(slice + ".CEMUX", str_or_default(ci->params, ctx->id("CEMUX"), "1"));
IdString lsrnet;
if (ci->ports.find(ctx->id("LSR")) != ci->ports.end() && ci->ports.at(ctx->id("LSR")).net != nullptr)
lsrnet = ci->ports.at(ctx->id("LSR")).net->name;
if (ctx->getBoundWireNet(ctx->getWireByName(
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR0")))) == lsrnet) {
cc.tiles[tname].add_enum("LSR0.SRMODE", str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
cc.tiles[tname].add_enum("LSR0.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
} else if (ctx->getBoundWireNet(ctx->getWireByName(ctx->id(
fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR1")))) == lsrnet) {
cc.tiles[tname].add_enum("LSR1.SRMODE", str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
cc.tiles[tname].add_enum("LSR1.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
}
// TODO: CLKMUX, CEMUX, carry // TODO: CLKMUX, CEMUX, carry
} else if (ci->type == ctx->id("TRELLIS_IO")) { } else if (ci->type == ctx->id("TRELLIS_IO")) {
std::string pio = ctx->locInfo(bel)->bel_data[bel.index].name.get(); std::string pio = ctx->locInfo(bel)->bel_data[bel.index].name.get();

View File

@ -41,7 +41,7 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str
new_cell->name = ctx->id(name); new_cell->name = ctx->id(name);
} }
new_cell->type = type; new_cell->type = type;
if (type == ctx->id("TRELLIS_LC")) { if (type == ctx->id("TRELLIS_SLICE")) {
new_cell->params[ctx->id("MODE")] = "LOGIC"; new_cell->params[ctx->id("MODE")] = "LOGIC";
new_cell->params[ctx->id("GSR")] = "DISABLED"; new_cell->params[ctx->id("GSR")] = "DISABLED";
new_cell->params[ctx->id("SRMODE")] = "LSR_OVER_CE"; new_cell->params[ctx->id("SRMODE")] = "LSR_OVER_CE";
@ -131,7 +131,7 @@ static void set_param_safe(bool has_ff, CellInfo *lc, IdString name, const std::
static void replace_port_safe(bool has_ff, CellInfo *ff, IdString ff_port, CellInfo *lc, IdString lc_port) static void replace_port_safe(bool has_ff, CellInfo *ff, IdString ff_port, CellInfo *lc, IdString lc_port)
{ {
if (has_ff) { if (has_ff) {
assert(lc->ports.at(lc_port).net == ff->ports.at(ff_port).net); NPNR_ASSERT(lc->ports.at(lc_port).net == ff->ports.at(ff_port).net);
NetInfo *ffnet = ff->ports.at(ff_port).net; NetInfo *ffnet = ff->ports.at(ff_port).net;
if (ffnet != nullptr) if (ffnet != nullptr)
ffnet->users.erase( ffnet->users.erase(
@ -154,8 +154,10 @@ void ff_to_slice(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool drive
lc->params[ctx->id(reg + "_SD")] = driven_by_lut ? "1" : "0"; 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"); 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("CLK"), lc, ctx->id("CLK"));
replace_port_safe(has_ff, ff, ctx->id("LSR"), lc, ctx->id("LSR")); if (ff->ports.find(ctx->id("LSR")) != ff->ports.end())
replace_port_safe(has_ff, ff, ctx->id("CE"), lc, ctx->id("CE")); replace_port_safe(has_ff, ff, ctx->id("LSR"), lc, ctx->id("LSR"));
if (ff->ports.find(ctx->id("CE")) != ff->ports.end())
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))); replace_port(ff, ctx->id("Q"), lc, ctx->id("Q" + std::to_string(index)));
if (driven_by_lut) { if (driven_by_lut) {

View File

@ -119,7 +119,8 @@ class Ecp5Packer
NetInfo *znet = ci->ports.at(ctx->id("Z")).net; NetInfo *znet = ci->ports.at(ctx->id("Z")).net;
if (znet != nullptr) { if (znet != nullptr) {
for (auto user : znet->users) { for (auto user : znet->users) {
if (is_lut(ctx, user.cell) && procdLuts.find(user.cell->name) == procdLuts.end()) { if (is_lut(ctx, user.cell) && user.cell != ci &&
procdLuts.find(user.cell->name) == procdLuts.end()) {
if (can_pack_lutff(ci->name, user.cell->name)) { if (can_pack_lutff(ci->name, user.cell->name)) {
procdLuts.insert(ci->name); procdLuts.insert(ci->name);
procdLuts.insert(user.cell->name); procdLuts.insert(user.cell->name);
@ -137,7 +138,8 @@ class Ecp5Packer
NetInfo *qnet = ctx->cells.at(lutffPairs[ci->name])->ports.at(ctx->id("Q")).net; NetInfo *qnet = ctx->cells.at(lutffPairs[ci->name])->ports.at(ctx->id("Q")).net;
if (qnet != nullptr) { if (qnet != nullptr) {
for (auto user : qnet->users) { for (auto user : qnet->users) {
if (is_lut(ctx, user.cell) && procdLuts.find(user.cell->name) == procdLuts.end()) { if (is_lut(ctx, user.cell) && user.cell != ci &&
procdLuts.find(user.cell->name) == procdLuts.end()) {
if (can_pack_lutff(ci->name, user.cell->name)) { if (can_pack_lutff(ci->name, user.cell->name)) {
procdLuts.insert(ci->name); procdLuts.insert(ci->name);
procdLuts.insert(user.cell->name); procdLuts.insert(user.cell->name);
@ -152,11 +154,11 @@ class Ecp5Packer
} }
} }
} }
for (char inp : "ABCD") { for (const char *inp : {"A", "B", "C", "D"}) {
NetInfo *innet = ci->ports.at(ctx->id(std::string("") + inp)).net; NetInfo *innet = ci->ports.at(ctx->id(inp)).net;
if (innet != nullptr && innet->driver.cell != nullptr) { if (innet != nullptr && innet->driver.cell != nullptr) {
CellInfo *drv = innet->driver.cell; CellInfo *drv = innet->driver.cell;
if (is_lut(ctx, drv) && innet->driver.port == ctx->id("Z")) { if (is_lut(ctx, drv) && drv != ci && innet->driver.port == ctx->id("Z")) {
if (procdLuts.find(drv->name) == procdLuts.end()) { if (procdLuts.find(drv->name) == procdLuts.end()) {
if (can_pack_lutff(ci->name, drv->name)) { if (can_pack_lutff(ci->name, drv->name)) {
procdLuts.insert(ci->name); procdLuts.insert(ci->name);
@ -167,7 +169,8 @@ class Ecp5Packer
} }
} else if (is_ff(ctx, drv) && innet->driver.port == ctx->id("Q")) { } else if (is_ff(ctx, drv) && innet->driver.port == ctx->id("Q")) {
auto fflut = fflutPairs.find(drv->name); auto fflut = fflutPairs.find(drv->name);
if (fflut != fflutPairs.end() && procdLuts.find(fflut->second) == procdLuts.end()) { if (fflut != fflutPairs.end() && fflut->second != ci->name &&
procdLuts.find(fflut->second) == procdLuts.end()) {
if (can_pack_lutff(ci->name, fflut->second)) { if (can_pack_lutff(ci->name, fflut->second)) {
procdLuts.insert(ci->name); procdLuts.insert(ci->name);
procdLuts.insert(fflut->second); procdLuts.insert(fflut->second);

View File

@ -0,0 +1,2 @@
read_verilog blinky.v
synth_ecp5 -noccu2 -nomux -nodram -json blinky.json