类型转换$cast
1. $cast做枚举类型转换:
枚举类型的缺省类型为双状态int,可以使用简单的赋值表达式把枚举类型变量的值直接赋值给非枚举变量 如int,但SV不允许在没有进行显示类型转换的情况下把int变量直接赋值给枚举变量。SV要求显式的类型转换的目的在于让你意识到可能的数据越界情况。
typedef enum bit[1:0] {RED=0,BLUE,GREEN} COLOR_E;
COLOR_E color,c2;
int c;
initial begin
color = BLUE; // 赋值一个已知的合法的值
c = color; // 将枚举变量赋值给int,此时为 1
c = c+1; // int型变量递增
if(!$cast(color,c)) // 将整型显示转换回枚举类型,如果越界会报错
$display("cast failed for c=%0d",c); // c的值此时为2
$display("Color is %0d/%s",color,color.name());
c++; // c的值为3,对于枚举类型已然越界
c2 = COLOR_E'(c); // 不做类型检查,下句c2.name()由于越界而打印不出
$display("c2 is %0d/$s",c2,c2.name()); // 打印:c2 is 3/
end
主要查看有无越界!!!
2. $cast 做句柄类型转换(重点):
这里涉及到类型转换,向上类型转换和向下类型转换:
- 向上类型转换:向上类型转换没问题,总是合法的,即将子类句柄赋值给父类,如
base_clase bc; //父类句柄
sub_class sc //子类句柄
sc = new(); //实例化子类
bc = sc; //直接将子类句柄赋值给父类句柄,这是正确的
$display(bc); //调用父类函数
bc.display; //相当于运行sc.display
- **向下类型转换:**将父类句柄指向子类句柄是非法的
base_class bc; //父类句柄
sub_class sc; //子类句柄
bc = new(); //实例化父类
sc = bc; // 非法,试图将父类句柄赋值给子类句柄,这是错误的
$cast(sc,bc); // 此时通过cast方式仍然不行;
base_class bc;
sub_class sc1,sc2;
sc2 = new();
bc = sc2;
sc1 = bc; // 非法
$cast(sc1,bc); // 通过cast方式可以实现,可以看到bc的句柄类型虽然是父类,但其指的对象类型是子类
只有子类句柄赋值给父类句柄时,可以用$cast使新的子类句柄指向该父类对象,调用其函数。
下面是详细的例子
module test_cast;
class h_amba;
int ii = 5;
virtual function display();
$display("ii in h_amba is : %d",ii);
endfunction
endclass
class h_ahb extends h_amba;
int ii = 15;
function display();
$display("ii in h_ahb is : %d",ii);
endfunction
endclass
class h_apb extends h_amba;
int ii = 25;
function display();
$display("ii in h_apb is : %d",ii);
endfunction
endclass
function display(h_amba amba);
amba.display();
endfunction
initial begin
h_amba amba;
h_ahb ahb_0,ahb_1;
h_apb apb_0,apb_1;
ahb_0 = new();
apb_0 = new();
apb_1 = new();
amba = ahb_0; //向上转换,合法的,ahb_0借用amba的句柄
display(amba); // 相当于运行ahb_0的display函数,间接使用其方法
$display("amba.ii = %d",amba.ii); // 函数固定住了
$cast(ahb_1,amba); //amba的句柄赋值给ahb_1
display(ahb_1); //ahb_1完全替代了amba的位置,可以直接使用其方法
$display("ahb_1.ii = %d",ahb_1.ii); //函数固定
amba = apb_0; //合法
display(amba); //apb_0间接使用amba方法
$display("amba.ii = %d",amba.ii);
amba = apb_1; //合法
//apb_1 = amba; //非法的
display(amba);
//若用$cast(apb_1,amba),s=上面不需要实例化,且这点使用display(apb_1),是等效的
//apb_1已经在上面实例化
$finish;
end
endmodule
仿真结果如下:
在SystemVerilog中,类变量的赋值或$cast只会将句柄复制到对象,而不是对象本身。 大多数情况下,我们创建一个对象,分配或随机化该对象中的值,然后传递句柄。 但有时我们想修改对象的本地副本,所以我们将其克隆(构造+复制=克隆)。 如果我们没有克隆对象,那么与对象具有相同句柄的其他人都会看到我们正在对它进行的修改。