目录
一、概述
- 类型转换可以分为显式转换和隐式转换
- 显式转换即静态转换以及动态转换,静态转换为在代转换值前面加单引号,并且不对转换结果做检查,例如int'(42+1.1);动态转换使用$cast(target,source),成功返回1,失败返回0。
- 隐式转换即位数扩展,例如[3:0]a = [1:0]b或者[31:0]a = [1:0]b + 32'b0
二、静态转换
program test;
initial begin
$display("int'(42+1.1) is",int'(42+1.1));//将43.1强制转换为整型,四舍五入
$display("(42+1.1) is",(42+1.1));//SV默认为浮点型
$display("real'(42+1.1) is",real'(42+1.1));
end
endprogram
++++++++++++++++++++++++++++++++++++++++++++++++++++++
run result
++++++++++++++++++++++++++++++++++++++++++++++++++++++
int'(42+1.1) is 43
(42+1.1) is 43.1
real'(42+1.1) is 43.1
可以看出静态转换可以将浮点型数据强制转换为整形数据
三、动态转换
动态转换可以用到数据类型转换也可以用到句柄转换
3.1 数据类型转换
数据类型的动态转换与上文中静态转换结果一样
program example;
typedef enum{RED,BLUE,GREEN}COLOR_E;//0,1,2
COLOR_E color,c2;
int c;
initial begin
color=BLUE;
c=color;//可以将枚举类型的变量赋值给int类型的变量
$display("c=%0d",c);
c++;
$cast(color,c);//int类型转换成枚举类型
$display("color is %0s",color.name);
c2=COLOR_E'(c);
$display("c2 is %0d/%0s",c2,color.name);
end
endprogram
——————————————————————————————————————————————————————————
run result
——————————————————————————————————————————————————————————
c=1
color is GREEN
c2 is 2/GREEN
3.2 句柄类型转换
分为两种转换,一种为子类向父类的向上类型转换,一种为父类向子类的向下类型转换
3.2.1 向上类型转换
即fanther f = child c1,父类句柄指向子类句柄
class father;
string m_name;
function new (string name);//有参数的new函数
m_name = name;
endfunction
function void print ();
$display("Hello %s", m_name);
endfunction
endclass
class child0 extends father;
string car = "car";
function new (string name);
super.new(name);//因为父类new有参数,这里必须用super new
endfunction
endclass
class child1 extends father;
string plane = "plane";
function new (string name);
super.new(name);//因为父类new有参数,这里必须用super new
endfunction
endclass
module top;
father f;
child0 c0;
child1 c1;
initial begin
f = new("father");//为父类的
f.print();//调用父类的方法,father
c0 = new("child0");
f = c0;//使父类句柄指向子类c0
f.print();//调用的还是父类方法,但是被子类传参,child0
c1 = new("child1");
f = c1;//使父类句柄指向子类c1
f.print();//调用的还是父类方法,但是被子类传参,child1
end
endmodule
————————————————————————————————————————————————————————————
run result
————————————————————————————————————————————————————————————
hello father
hello child0
hello child1
此时第二个以及第三个print函数中,父类对象中的print函数不为虚函数且子类未重写该函数,因此未构成override以及overwrite,但此时print函数的参数由子类更新后传入,实现了子类向父类传参。
3.2.2 向下类型的转换
父类向子类的转换,即fanther a;child b1,b2; a = b1;$cast(b2,f);
class father;
string m_name;
function new (string name);//有参数的new函数
m_name = name;
endfunction
function void print ();
$display("Hello %s", m_name);
endfunction
endclass
class child0 extends father;
string car = "car";
function new (string name);
super.new(name);//因为父类new有参数,这里必须用super new
endfunction
endclass
class child1 extends father;
string plane = "plane";
function new (string name);
super.new(name);//因为父类new有参数,这里必须用super new
endfunction
endclass
module top;
father f;
child0 c0;
child1 c1;
child1 c2;
initial begin
f = new("father");
f.print();
c0 = new("child0");
f = c0;
f.print();
c1 = new("child1");
f = c1;
f.print();//以上和2.2.1没差别
c1.plane="big_plane";//更改c1对象的变量
$cast(c2,f);//强制c2->f,而f->c1,所以导致c2->c1,这就是向下类型的转换
f.print();//此时f->c1,所以打印的还是c1传的参数
$write(", has %s",c2.plane)//由于c2->f->c1,所以c2->c1,所以c2.plane是c1的plane名字
end
endmodule
________________________________________________________________________________________
run result
________________________________________________________________________________________
hello father
hello child0
hello child1
, has big_plane
需要注意最后一种情况,此时f的句柄被转换成了c2完成了父类句柄向子类转换,切记此时需要先将父类句柄f指向与c2类型一致的c1子类,不然转换会报错,此时c2->f->c1,由于此时未构成override,因此f.print依然调用父类的print函数,而c2指向了c1,此时指向c1中的变量