diff options
-rw-r--r-- | ice40/bitstream.cc | 3 | ||||
-rw-r--r-- | ice40/place_legaliser.cc | 17 |
2 files changed, 19 insertions, 1 deletions
diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 942c9977..1a498dd1 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -178,7 +178,8 @@ void write_asc(const Context *ctx, std::ostream &out) bool carry_const = get_param_or_def(cell.second.get(), ctx->id("CIN_CONST")); bool carry_set = get_param_or_def(cell.second.get(), ctx->id("CIN_SET")); if (carry_const) { - assert(z == 0); + if (!ctx->force) + assert(z == 0); set_config(ti, config.at(y).at(x), "CarryInSet", carry_set); } } else if (cell.second->type == ctx->id("SB_IO")) { diff --git a/ice40/place_legaliser.cc b/ice40/place_legaliser.cc index 1292d094..91350c2b 100644 --- a/ice40/place_legaliser.cc +++ b/ice40/place_legaliser.cc @@ -155,6 +155,22 @@ class PlacementLegaliser return i3_next;*/ return (CellInfo *)nullptr; }); + std::unordered_set<IdString> chained; + for (auto &base_chain : carry_chains) { + for (auto c : base_chain.cells) + chained.insert(c->name); + } + // Any cells not in chains, but with carry enabled, must also be put in a single-carry chain + // for correct processing + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (chained.find(cell.first) == chained.end() && is_lc(ctx, ci) && bool_or_default(ci->params, ctx->id("CARRY_ENABLE"))) { + CellChain sChain; + sChain.cells.push_back(ci); + chained.insert(cell.first); + carry_chains.push_back(sChain); + } + } bool success = true; // Find midpoints for all chains, before we start tearing them up std::vector<CellChain> all_chains; @@ -274,6 +290,7 @@ class PlacementLegaliser CellInfo *passout = make_carry_pass_out(cell->ports.at(ctx->id("COUT"))); chains.back().cells.push_back(passout); tile.push_back(passout); + start_of_chain = true; } } ++curr_cell; |