zoukankan      html  css  js  c++  java
  • systemverilog浅析$cast

    问题一:动态类型转换和静态类型转换的区别?

    $cast:基本语法$case(A,B)实际上是A=B;A表示目的端,B表示源端。(downcasting)类型向下转换

    • $cast 动态类型转换,转换失败会报错。
    • `静态类型转换,转换时报不报错

    问题二:$cast是function还是task?

    据语境,仿真器会自动选择执行task或是function,task在不需要返回值时执行,而function在需要返回值的语境下执行。将cast作为任务还是函数调用确定了无效赋值是如何处理的。
    cast的task function应用

    问题三:什么时候需要$cast?

    我们通过下面的一个简单的例子来进行说明一下。
    【多选题】有如下的代码,下面$cast返回值为1的有:(BCD)

    class A; endclass;
    class B extends A; endclass;
    class C extends B; endclass;
    A a = new(…);
    B b = new(…);
    C c = new(…);

    A、$cast(b, a) B、a = c; $cast(b,a);

    C、$cast(b,c) D、a = b; $cast(b, a)

    解析:

    • 在解析之前,希望大家能够通读一下绿皮书的第八章8.3.1,借用书上的一句话,将一个基类句柄赋值给一个扩展类并不总是非法的,当基类的句柄确实指向一个派生类对象时是允许的。$cast子程序会检查句柄所指向的对象类型,而不仅仅检查句柄本身。比如说$cast(B,A),会检查句柄A指向的对象是不是句柄B指向的对象的扩展类,或者是同一类型。如果满足的话,你就可以从基类的句柄A中拷贝扩展对象的地址给扩展对象的句柄B了。
      看到这里大家应该会有点晕晕的,那我们通过实际的例子来给大家展示一下,cast的实际应用场景。
       class bird;
         virtual function void hungry();
             $display("I am bird,I am hungry");
         endfuntion
         function void hungry2();
             $display("I am bird,I am hungry2");
         endfuntion
       endclass
    
       class parrot;
         virtual function void hungry();
             $display("I am parrot,I am hungry");
         endfuntion
         function void hungry2();
             $display("I am parrot,I am hungry2");
         endfuntion
        endclass
    
       program ex;
           bird A;
           parrot B;
           initial begin
             A = new();
             B = new();
             A.hungry();
             A.hungry2();
             B.hungry();
             B.hungry2();
          end
     endprogram
    

    运行结果:

    I am bird,I am hungry
    I am bird,I am hungry2
    I am parrot,I am hungry
    I am parrot,I am hungry2
    

    相信大家对这个结果够没有异议,那么接下来我将通过几种场景来深入理解cast。我们假设bird parrot的类不变,改写program的调用。

    情景一:基类 = 扩展类

       program ex;
           bird A;
           parrot B;
           initial begin
             A = new();
             B = new();
             A = B;
             A.hungry();
             A.hungry2();
             B.hungry();
             B.hungry2();
          end
     endprogram
    

    运行结果:

    I am parrot,I am hungry
    I am bird,I am hungry2
    I am parrot,I am hungry
    I am parrot,I am hungry2
    
    • 基类 = 扩展类;A句柄指向parrot的对象
    • virtual函数的特性

    场景二:扩展类 = 基类

    program ex;
           bird A;
           parrot B;
           initial begin
             A = new();
             B = new();
             B = A;
             A.hungry();
             A.hungry2();
             B.hungry();
             B.hungry2();
          end
     endprogram
    

    运行结果:

    Error-[SV-ICA] illegal class assignment
    
    • 扩展类 = 基类,直接调用会有问题

    场景三:cast用作task

    program ex;
           bird A;
           parrot B;
           initial begin
             A = new();
             B = new();
             $cast(B,A);
             A.hungry();
             A.hungry2();
             B.hungry();
             B.hungry2();
          end
     endprogram
    

    运行结果:

    Error-[DCF] Dynamic cast failed
    
    • $cast(扩展类,基类),上述代码$cast没有返回值,所以结果是做task用,根据图【cast的task function应用】我们可以知道,如果cast用作task应用的时候失败,则异常结束,直接跳出。

    场景四:cast用作function

    program ex;
           bird A;
           parrot B;
           initial begin
             A = new();
             B = new();
            if(!$cast(B,A))begin
              $display("B = A; failed");
             end
             A.hungry();
             A.hungry2();
             B.hungry();
             B.hungry2();
          end
     endprogram
    

    运行结果:

    B = A;failed
    I am bird,I am hungry
    I am bird,I am hungry2
    I am parrot,I am hungry
    I am parrot,I am hungry2
    
    • if(!$cast(扩展类,基类)),上述代码$cast有返回值,所以结果是做function用,根据图【cast的task function应用】我们可以知道,如果cast用作function应用的时候失败,返回0,继续运行。

    场景五:cast成功转换的应用,B=A,基类的句柄A指向扩展类,扩展类跟B句柄指向的类是同类型的。

    program ex;
           bird A;
           parrot B;
           initial begin
             A = new();
             B = new();
             A = B;
            if(!$cast(B,A))begin
                  $display("B = A; failed");
             end
             else begin
                   $display("B = A; OK !!!!");
             end
             A.hungry();
             A.hungry2();
             B.hungry();
             B.hungry2();
          end
     endprogram
    

    运行结果:

     B = A;OK !!!!
    I am parrot,I am hungry
    I am bird,I am hungry2
    I am parrot,I am hungry
    I am parrot,I am hungry2
    
    • B=A,基类的句柄A指向扩展类,扩展类跟B句柄指向的类是同类型的。(参考书上的那句话,这里通过例子深入理解一下)

    场景六:cast成功转换的应用,B=A,基类的句柄A指向扩展类,扩展类是B句柄指向的类的扩展类。

      class dog extends parrot;
         virtual function void hungry();
             $display("I am dog,I am hungry");
         endfuntion
         function void hungry2();
             $display("I am dog,I am hungry2");
         endfuntion
       endclass
    
    program ex;
           bird A;
           parrot B;
           dog C;
           initial begin
             A = new();
             B = new();
             C = new();
             A = C;
            if(!$cast(B,A))begin
                  $display("B = A; failed");
             end
             else begin
                   $display("B = A; OK !!!!");
             end
             A.hungry();
             A.hungry2();
             B.hungry();
             B.hungry2();
          end
     endprogram
    

    运行结果:

     B = A;OK !!!!
    I am dog,I am hungry
    I am bird,I am hungry2
    I am dog,I am hungry
    I am parrot,I am hungry2
    
    • B=A,基类的句柄A指向扩展类,扩展类是B句柄指向的类的扩展类。(参考书上的那句话,这里通过例子深入理解一下)

    相信通过上述的六种场景,大家对cast应该有了一定的了解,那么对我们最开始的那道题,大家应该都能理解了吧。

  • 相关阅读:
    N、Z、Q、R 分别代表什么
    Android常用代码-监听网络状态
    完整的android use SSL发送邮件
    android 发送邮件相关文章
    Spring RMI的实现原理
    spring+quartz配置
    Quartz配置表达式
    singleton容器
    Spring学习-框架概览
    [Shader2D]漩涡效果
  • 原文地址:https://www.cnblogs.com/xuqing125/p/14759124.html
Copyright © 2011-2022 走看看