SystemVerilog中$cast方法
$cast是systemverilog中的内建方法。
$cast可以对不同的内建类型进行转换,用的更多的是不同层次之间类的转换。在这种父类与子类之间的转换里, 父类站的高,子类在底下,从父类向子类的转换,称为向下类型转换,而子类向父类的转换称为向上类型转换。向上类型转换是安全的,而反之则是不安全的。原因在于子类既然继承了父类,就拥有父类的一切属性,除此之外,龙生九子,各有不同,子类还有自己独特的个性,这些是父类没有的。当进行向上类型转换时,相当于父类的句柄指向子类对象,这样的话句柄仍然能对子类对象与父类相同的属性进行访问。但是反过来,如果向下类型转换也那么自由,当试图把子类的句柄指向父类的对象会发生什么呢?父类本来划好了一小块地盘,但是因为子类含有比父类更丰富的属性,它很有可能会访问父类并不包含的资源,这时就找不到该资源,越界了,因此会有error。父类就好像上海,子类相当于长三角地区,包含但不仅仅是上海,因此父类能到的地方子类都可以到,反之不行,因此把子类的句柄给父类没关系,但反之不行,所以向下类型是需要有严格的类型检查的,阻止非法转换。
class father; string m_name; function new (string name); m_name = name; endfunction : new function void print (); $display("Hello %s", m_name); endfunction : print endclass : father class child1 extends father; string area1 = "jiangzhehu"; function new (string area1); super.new(area1); endfunction : new endclass : child1 class child2 extends father; string area2 = "shanghai"; function new (string area2); super.new(area2); endfunction : new endclass : child2 program top; father f; child1 c10,c11,c12; child2 c20,c21,c22; initial begin f = new ("shanghai"); f.print(); c10 = new("jiangzhehu"); f = c10; f.print(); c20 = new("changsanjiao"); f = c20; f.print(); c20.area2 = "zhejiang"; $cast(c21, f); c21.print(); $display("has %s", c21.area2); c22 = c20; c22.print(); $display("has %s", c22.area2); c20.area2 = "hangzhou"; c21.print(); $display("has %s", c21.area2); c22.print(); $display("has %s", c22.area2); end endprogram : top仿真结果如下:
# Hello shanghai # Hello jiangzhehu # Hello changsanjiao # Hello changsanjiao # has zhejiang # Hello changsanjiao # has zhejiang # Hello changsanjiao # has hangzhou # Hello changsanjiao # has hangzhou
请注意,不能直接把$cast(c21, f);前提是先把子类赋给父类才行。
使用cast也不能把c20给c10;
那么cast的作用可以直接在子类之间用=代替,如上述代码中所示;
千万小心这样的句柄传递,会造成两个句柄同时指向一个对象,当使用其中一个句柄对对象的内容进行修改,另一个句柄再次访问的时候就会发现值已经被改变了。同时也可以看出cast的复制效果只是个指针,只有使用copy函数才能切断联系。
那么这样的类型转换有什么好处呢?通常的类型转换是一种格式的需求,将独特的子类转换为父类的类型,更注重通用性,共性越多,重用性越好。首先子类转换为父类,可以看起来一样,通用性好,但是要处理具体的内容就需要将父类句柄类型转换为子类类型才能访问子类特有的资源。
欢迎点赞,关注,分享~~, 本文原发于微信公众号【数字ic小站】