Difficulty: Easy · Puzzle 1 of 6 · Topic: String and Casting Puzzles
Predict all outputs from string methods and both `$cast` attempts.
class base_pkt; endclass
class good_pkt extends base_pkt;
int id = 42;
endclass
class bad_pkt extends base_pkt; endclass
module p1;
string s = "dv puzzle";
base_pkt b1, b2;
good_pkt g;
initial begin
b1 = good_pkt::new();
b2 = bad_pkt::new();
$display("substr=%s", s.substr(3,8));
$display("toupper=%s", s.toupper());
if ($cast(g, b1)) $display("cast1 ok id=%0d", g.id);
else $display("cast1 fail");
if ($cast(g, b2)) $display("cast2 ok id=%0d", g.id);
else $display("cast2 fail");
end
endmodule`substr(i,j)` uses inclusive indices. `$cast` checks runtime object type, not just declared handle type.
1) `substr(3,8)` on `"dv puzzle"` returns `"puzzle"` (index 3 through 8 inclusive).
2) `toupper()` returns `"DV PUZZLE"`.
3) `b1` points to a `good_pkt`, so `$cast(g,b1)` succeeds and prints id 42.
4) `b2` points to a `bad_pkt`, so the cast to `good_pkt` fails and returns 0.Answer: substr=puzzle, toupper=DV PUZZLE, cast1 ok id=42, cast2 fail
Checked by running the code in Verilator 5; the printed output supports the answer above. A failed $cast returns 0 because the object is a bad_pkt; Icarus 13 lacks toupper and class $cast.
`b2` has the static type `base_pkt` and `g` is a `good_pkt` handle, so the code compiles; only the run-time object type (`bad_pkt`) makes the second cast fail. Note that the constructor is written `good_pkt::new()` (or `new` assigned to a typed handle), never `new good_pkt()`.
What happens to `g` after the failed second cast in this code? Model answer: nothing: a failed `$cast` leaves the destination unchanged, so `g` still references the good_pkt object from the first cast and `g.id` is still 42.
I would split this into string methods and a runtime cast. The substring from 3 to 8 is puzzle and the upper case version is DV PUZZLE. The first cast works because the base handle really points to a good packet, so id is 42, and the second fails and returns 0 because that object is a bad packet. The trap is that both casts compile, since only the run-time object type decides, so I would always check the return value of the cast.