UVM中的cast

类型转换$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只会将句柄复制到对象,而不是对象本身。 大多数情况下,我们创建一个对象,分配或随机化该对象中的值,然后传递句柄。 但有时我们想修改对象的本地副本,所以我们将其克隆(构造+复制=克隆)。 如果我们没有克隆对象,那么与对象具有相同句柄的其他人都会看到我们正在对它进行的修改。

  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值