Turns out the code for div by a power of 2 is already almost capable of
optimizing this to a shift-by-0 or and-with-0, which will be further
folded into nothingness; let's beef it up to handle div by 1 as well.
Fixes#2820.
The recent fix for case expression width detection causes the width of
the expressions to be queried before they are simplified. Because the
logic supporting module scope identifiers only existed in simplify,
looking them up would fail during width detection. This moves the logic
to a common helper used in both simplify() and detectSignWidthWorker().
Transparency is meaningless for asynchronous ports, so we assume
transparent == false to simplify the code in this case. Likewise,
enable is meaningless, and we assume it is const-1. However,
turns out that nMigen emits the former, and Verilog frontend emits
the latter, so squash these issues when ingesting a $memrd cell.
Fixes#2811.
This essentially adds wide port support for free in passes that don't
have a usefully better way of handling wide ports than just breaking
them up to narrow ports, avoiding "please run memory_narrow" annoyance.
When converting a sync transparent read port with const address to async
read port, nothing at all needs to be done other than clk_enable change,
and thus we have no FF cell to return. Handle this case correctly in
the helper and in its users.
- The case expression and case item expressions are extended to the
maximum width among them, and are only interpreted as signed if all of
them are signed
- Add overall width and sign detection for AST_CASE
- Add sign argument to genWidthRTLIL helper
- Coverage for both const and non-const case statements
When extracting read register from a transparent port that has an
enable, reset, or initial value, the usual trick of putting a register
on the address instead of data doesn't work. In this case, create soft
transparency logic instead.
When transparency masks land, this will also be used to handle ports
that are transparent to only a subset of write ports.
Like wide port support, this is still completely unusable, and support
in various passes will be gradually added later. It also has no support
at all in the cell library, so attempting to create a read port with
a reset or initial value will cause an assert failure for now.
Since the packed cell doesn't actually support wide ports yet, we just
auto-narrow them on emit. The future packed cell will add
RD_WIDE_CONTINUATION and WR_WIDE_CONTINUATION parameters so the
transform will be trivially reversible for proper serialization.