mirror of
https://github.com/YosysHQ/yosys
synced 2026-08-10 08:01:14 +00:00
ice40_opt: retire the wrapper's ports before reinterpreting it as $lut
A port's direction is read off the cell type, so assigning type_impl = $lut while the $__ICE40_CARRY_WRAPPER ports are still connected makes every following unsetPort consult the wrong type: \B was an input under the wrapper and is not a port of $lut at all, so the teardown takes the output branch and trips `log_assert(w->driverCell_ == this)` in signorm mode (arch/ice40/counter, arch/ice40/bug1598). Disconnect everything under the old type, switch, then connect \A and \Y under the new one. Retiring \O first also leaves that wire undriven, so it comes back as \Y on the same wire rather than behind a freshly interposed alias. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQU5XCqDYY8MbivGkNRrDo
This commit is contained in:
parent
b495d653b4
commit
77baad0082
1 changed files with 13 additions and 3 deletions
|
|
@ -138,16 +138,26 @@ static void run_ice40_opts(Module *module)
|
|||
module->design->scratchpad_set_bool("opt.did_something", true);
|
||||
log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",
|
||||
module, cell, log_signal(replacement_output));
|
||||
cell->type_impl = TW($lut);
|
||||
// A port's direction is read off the cell type, so every
|
||||
// port has to be disconnected while the old type still
|
||||
// explains it and reconnected once the new one does --
|
||||
// otherwise the indices are updated against the wrong
|
||||
// direction. Retiring \O before it comes back as \Y also
|
||||
// leaves that wire undriven, so it can be reused rather
|
||||
// than aliased behind a fresh one.
|
||||
auto I3 = get_bit_or_zero(cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? TW::CI : TW::I3));
|
||||
cell->setPort(TW::A, { I3, inbit[1], inbit[0], get_bit_or_zero(cell->getPort(TW::I0)) });
|
||||
cell->setPort(TW::Y, cell->getPort(TW::O));
|
||||
RTLIL::SigSpec sig_a { I3, inbit[1], inbit[0], get_bit_or_zero(cell->getPort(TW::I0)) };
|
||||
RTLIL::SigSpec sig_y = cell->getPort(TW::O);
|
||||
cell->unsetPort(TW::A);
|
||||
cell->unsetPort(TW::B);
|
||||
cell->unsetPort(TW::CI);
|
||||
cell->unsetPort(TW::I0);
|
||||
cell->unsetPort(TW::I3);
|
||||
cell->unsetPort(TW::CO);
|
||||
cell->unsetPort(TW::O);
|
||||
cell->type_impl = TW($lut);
|
||||
cell->setPort(TW::A, std::move(sig_a));
|
||||
cell->setPort(TW::Y, std::move(sig_y));
|
||||
cell->setParam(ID::WIDTH, 4);
|
||||
cell->unsetParam(ID(I3_IS_CI));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue