我注意到,当源表达式求值为null时,不同的模拟器(甚至同一模拟器的不同版本)显示有关动态强制转换的不同行为。以下是LRM(IEEE 1800-2012)所述的内容:
8.16施法
... 当$ cast应用于类句柄时,它仅在三种情况下成功:
1)源表达式和目标类型是赋值兼容的,即目标是源表达式的相同类型或超类。
2)源表达式的类型与目标类型转换兼容,即:
- 源表达式的类型是目标类型的超类,或
- 源表达式的类型是接口类(见8.26)
,源是与目标类型兼容的对象。这种类型的赋值需要由$ cast提供的运行时检查。
3)源表达式是文字常量null。
在所有其他情况下,$ cast将失败,特别是当源和目标类型不兼容时,即使源表达式求值为null。 ...
这是一个简单的测试案例,可以解决所有可能的情况:
interface class ifc;
pure virtual function void test();
endclass : ifc
class typeA implements ifc;
bit A;
string s = "typeA";
function new();
A = 1'b1;
endfunction : new
virtual function void test();
$display("%t: %s", $time, s);
endfunction : test
static function void null_test(string s);
$display("%t: %s - $cast succeeded", $time, s);
endfunction : null_test
endclass: typeA
class typeA_ext extends typeA;
function new();
super.new();
A = 1'b0;
s = "typeA_ext";
endfunction : new
endclass: typeA_ext
class typeB;
int B;
function new();
B = 69;
endfunction : new
endclass: typeB
module test_case;
ifc i, i_null;
typeA A0, A1, A_null;
typeA_ext A0_ext, A1_ext;
typeB B, B_null;
// Case 1
initial begin
#1;
$display("Case 1");
A1 = new();
A1_ext = new();
$cast(A0, A1); // It succeeds according to case 1 (same as A0 = A1 - the destination is same type as the source expression)
A0.test();
$cast(A0, A1_ext); // It succeeds according to case 1 (same as A0 = A1_ext - the destination is a superclass of the source expression)
A0.test();
end
// Case 2
initial begin
#2;
$display("Case 2");
A1 = new();
A1_ext = new();
A0 = A1_ext;
i = A1;
$cast(A0_ext, A0); // It succeeds according to case 2a - in fact, A0 (typeA) is holding an object (A1_ext) of type typeA_ext
A0.test();
$cast(A0, i); // It succeeds according to case 2b - in fact, i (interface class) is holding A1 (typeA)
A0.test();
end
// Case 3
initial begin
#3;
$display("Case 3");
$cast(A0, null); // It succeeds according to case 3
A0.null_test("$cast(A0, null)");
end
// In all other cases $cast shall fail - Let's use $cast as a function to catch the run-time error
initial begin
#4;
$display("All other cases");
B = new();
B_null = null;
if ($cast(A0, B)) // source and destination types are not cast compatible
$display("%t: $cast(A0, B) - Not expected to succeed", $time);
else if ($cast(A0, B_null)) // even if the source expression evaluates to null
$display("%t: $cast(A0, B_null) - Not expected to succeed", $time);
else
$display("%t: $cast fails as expected", $time);
end
// Debatable? Do they fall in "all other cases"? Shall $cast fail?
initial begin
#5;
$display("Debatable?");
A_null = null;
i_null = A_null;
$cast(A0, A_null); // Shouldn't it match case 1 and/or 3?
A0.null_test("$cast(A0, A_null)");
$cast(A0, i_null); // Shouldn't it match case 2b and/or 3?
A0.null_test("$cast(A0, i_null)");
end
endmodule
以下是EDA游乐场中相同测试用例的链接:
Dynamic cast when source expression is null
我想知道当源表达式在每种可能的" flavor"中评估为null时,哪个模拟器正确解释LRM。
有没有"步行LRM"在那里? ; - )