ice40: Avoid chain finder from mixing up chains by only allowing I3 chaining at end

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2022-04-11 18:46:44 +01:00
parent 9067d954f4
commit d3ba259db2

View File

@ -183,43 +183,54 @@ class ChainConstrainer
void process_carries() void process_carries()
{ {
std::vector<CellChain> carry_chains = find_chains( // Find carry roots
ctx, [](const Context *ctx, const CellInfo *cell) { return is_lc(ctx, cell); }, std::vector<CellChain> carry_chains;
[](const Context *ctx, const pool<IdString> processed;
CellInfo *cell) {
CellInfo *carry_prev = net_driven_by(ctx, cell->ports.at(id_CIN).net, is_lc, id_COUT);
if (carry_prev != nullptr)
return carry_prev;
CellInfo *i3_prev = net_driven_by(ctx, cell->ports.at(id_I3).net, is_lc, id_COUT);
if (i3_prev != nullptr)
return i3_prev;
return (CellInfo *)nullptr;
},
[](const Context *ctx, const CellInfo *cell) {
CellInfo *carry_next = net_only_drives(ctx, cell->ports.at(id_COUT).net, is_lc, id_CIN, false);
if (carry_next != nullptr)
return carry_next;
CellInfo *i3_next = net_only_drives(ctx, cell->ports.at(id_COUT).net, is_lc, id_I3, false);
if (i3_next != nullptr)
return i3_next;
return (CellInfo *)nullptr;
});
pool<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 : ctx->cells) { for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get(); CellInfo *ci = cell.second.get();
if (chained.find(cell.first) == chained.end() && is_lc(ctx, ci) && if (is_lc(ctx, ci) && bool_or_default(ci->params, id_CARRY_ENABLE)) {
bool_or_default(ci->params, id_CARRY_ENABLE)) { // possibly a non-root if CIN or I3 driven by another cout
CellChain sChain; NetInfo *cin = ci->getPort(id_CIN);
sChain.cells.push_back(ci); if (cin && cin->driver.cell && is_lc(ctx, cin->driver.cell) && cin->driver.port == id_COUT) {
chained.insert(cell.first); continue;
carry_chains.push_back(sChain); }
carry_chains.emplace_back();
auto &cc = carry_chains.back();
CellInfo *cursor = ci;
while (cursor) {
cc.cells.push_back(cursor);
processed.insert(cursor->name);
NetInfo *cout = cursor->getPort(id_COUT);
if (!cout)
break;
cursor = nullptr;
// look for CIN connectivity
for (auto &usr : cout->users) {
if (is_lc(ctx, usr.cell) && usr.port == id_CIN && !processed.count(usr.cell->name)) {
cursor = usr.cell;
break;
}
}
// look for I3 connectivity - only to a top cell with no further chaining
if (cursor)
continue;
for (auto &usr : cout->users) {
if (is_lc(ctx, usr.cell) && usr.port == id_I3 && !processed.count(usr.cell->name) &&
!usr.cell->getPort(id_COUT)) {
cursor = usr.cell;
break;
}
}
}
}
}
// anything left behind....
for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get();
if (is_lc(ctx, ci) && bool_or_default(ci->params, id_CARRY_ENABLE) && !processed.count(ci->name)) {
carry_chains.emplace_back();
carry_chains.back().cells.push_back(ci);
processed.insert(ci->name);
} }
} }
std::vector<CellChain> all_chains; std::vector<CellChain> all_chains;