Caseelim
Replace vl-casestmts with equivalent vl-ifstmts.
This rewrite rewrites case statements into if statements. It
requires that sizes have been computed that the test expressions and match
expressions agree on their sizes. If these conditions are not met, it may
issue non-fatal warnings and fail to rewrite the case statements.
This transform is practically useful for supporting designs that involve
case statements and we believe it is basically reasonable. But Verilog's case
statements have significant problems with regards to the handling of X
and Z values. There are, therefore, many cases where this translation will
change a module's simulation semantics. More information about these problems
can be found in case-statement-problems.
The basic idea of the transform is just to rewrite, e.g., for plain
case statements:
case (<test>)
<match-1>: <body-1>
<match-2>: <body-2>
...
<match-n>: <body-N>
default: <default-body>
endcase
-->
if (<test> === <match-1>) <body-1>
else if (<test> === <match-2>) <body-2>
...
else if (<test> === <body-n>) <body-n>
else <default-body>
This rewrite is intuitively correct, and appears to produce identical
results in some test simulations on NCVerilog and Verilog-XL.
This transform isn't quite correct if test can cause side-effects. The
Verilog standard says that test should be evaluated only once, before the
match expressions. In our transformed code, test may be evaluated
multiple times. This is not a problem for back-end tools like esim
where there is no such notion of evaluation.
We considered doing something more sophisticated to avoid replicating the
test expression, which would avoid this problem. It would be easy enough
to simply assign the test expression to some temporary wire, then check
temp against each match expression. But we might then need to also
include this new wire in the sensitivity list for the always block, which could
become tricky/messy. So for now, our transform really is just as naive as the
above suggests.
Our support for casex and casez statements is somewhat more
limited. Here, we require that each match expression be some simple,
atomic vl-constint-p or vl-weirdint-p expression. These
constraints allow us to carry out the following transform
e.g.,:
casez (in)
4'b001?: <body-1>
4'b01??: <body-2>
4'b1???: <body-3>
default: <default-body>
endcase
-->
if ( (in & 4'b1110) === (4'b001z & 4'b1110) ) <body-1>
else if ( (in & 4'b1100) === (4'b01zz & 4'b1100) ) <body-2>
else if ( (in & 4'b1000) === (4'b1zzz & 4'b1000) ) <body-2>
else if (in[3] === 1'b0 & in[2] === 1'b1) <body-2>
else if (in[3] === 1'b1) <body-3>
else <default-body>
That is, our if statement conditions simply mask out the x/z/? bits as
appropriate, and check that the other bits are matched.
Unfortunately, this transformation is completely wrong in the case
where data has X or Z bits, because in the Verilog semantics these bits
are not to be tested. On the other hand, these are terrible, non-conservative
semantics, and we think our behavior is about as reasonable as possible.
Subtopics
- Vl-casezx-stmt-elim
- Rewrite an casez or casex statement into if statements.
- Vl-casezx-matchexpr
- Creates, e.g., the expression (data & 4'b1100) === 4'b1000
for handling casez(data) ... 4'b10??: ... endcase.
- Vl-modulelist-caseelim
- (vl-modulelist-caseelim x ss) maps vl-module-caseelim across a list.
- Vl-casezx-match-any-expr
- Handles situations like casez(foo) ... 3'bxx1, 3'bx10:
... endcase, i.e., where we have multiple match expressions associated with
the same body.
- Vl-casestmt-elim
- Rewrite an ordinary case statement into if statements.
- Vl-casestmt-size-warnings
- Check case statements for compatible sizes, and issue warnings if we
find any incompatible sizes.
- Vl-casezx-elim-aux
- Vl-stmt-caseelim
- Recursively eliminate case, casez, and casex
statements within a statement.
- Case-statement-problems
- The official behavior of case, casez and casex is
problematic with respect to X and Z values.
- Vl-casestmt-compare-expr
- Creates, e.g., the expression foo === 3'b110 | foo === 3'b111,
for handling case(foo) ... 3'b110, 3'b111: ... endcase.
- Vl-initiallist-caseelim
- Vl-alwayslist-caseelim
- Vl-casestmt-elim-aux
- Vl-initial-caseelim
- Vl-always-caseelim
- Vl-casestmt-sizes-agreep
- Make sure all match expressions have been sized and that their sizes
are compatible with the test expression.
- Vl-module-caseelim
- Vl-design-caseelim