Difficulty: Medium · Puzzle 4 of 6 · Topic: String and Casting Puzzles
Predict the cast success bit and the enum value after each attempt.
typedef enum int {IDLE=0, BUSY=1, DONE=2} state_e;
module p4;
int raw1 = 2;
int raw2 = 3;
state_e s = IDLE;
bit ok;
initial begin
ok = $cast(s, raw1);
$display("c1=%0d s=%s", ok, s.name());
ok = $cast(s, raw2);
$display("c2=%0d s=%s", ok, s.name());
end
endmodule`$cast` to enum succeeds only for legal enumerator values. On failure, destination keeps previous value.
1) `raw1=2` is the legal enum value DONE, so the first cast returns 1 and `s` becomes DONE.
2) `raw2=3` is not a legal enumerator, so the second cast returns 0.
3) A failed cast does not modify the destination, so `s` stays DONE.
(The cast and the use of `s` are in separate statements on purpose: reading `s` in the same `$display` argument list as the `$cast` that writes it would depend on argument evaluation order, which the LRM does not define.)Answer: c1=1 s=DONE, then c2=0 s=DONE
Checked by running the code in Verilator 5; the printed output supports the answer above. A failed $cast leaves the enum unchanged; Icarus 13 does not implement $cast.
People assume a failed `$cast` zeroes the destination or sets it to the first enum literal (IDLE), but it leaves DONE untouched.
How would a static cast `state_e'(raw2)` behave differently? Model answer: it performs no legality check and raises no error: s becomes 3, which matches no enumerator, so `s.name()` returns an empty string (run in Verilator; some tools warn).
I would check whether each raw number is a legal enum value. The value 2 is DONE, so the first cast returns 1, and the value 3 is not a legal enumerator, so the second cast returns 0. A failed cast leaves the destination alone, so the state stays DONE. The trap is thinking it resets to the first literal, and I would also keep the cast and the display in separate statements, because the argument evaluation order is not defined.