Systemverilog中$cast()的使用

news/2024/5/19 19:50:28 标签: systemverilog

Systemverilog中$cast()的使用

1 静态转换

SV类型转换分两种方法,一种叫静态类型转换,另一种称之为动态类型转换。静态类型转换的语法类似为:

int a = 2;  
real b;  
b = real'(a);  

这种类型`()的静态类型转换,一般不检查转换是否合法,因此具有一定的危险性。

2 动态转换

2.1 动态转换

c a s t 的 t a s k 却 不 是 这 样 , cast的task却不是这样, casttaskcast是systemverilog中的内建方法,它会进行类型检查。如果转换失败,会产生运行时错误。

cast在system veilog中被称为向下类型转换(downcasting),类型向下转化是指将 一个指向基类的指针转化为指向派生类的指针。

$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;

2.2 动态转换与copy

对于两个具有继承关系的class,若对应父类的instance为father_tr,而子类的instance为child_tr,那么​如果只是让子类的指针指向父类,有以下几种操作方法:

1、简单赋值:fathrer_tr = child_tr;​

2、使用copy函数:father_tr = child_tr.copy();

3、使用 c a s t 函 数 : cast函数: castcast(father_tr, child_tr);​

以上3种方法均可实现数据的传递,但有本质区别:(1)通过简单赋值操作,使两个handle father_tr和child_tr指向了同一块memory,因此,father_tr的类型也会变成子类的类型。(2)使用copy函数​,是将数值进行简单的copy,即将child_tr对应的memory中的数据放入father_tr对应的memory中,这种数据的copy方式,不会带来类型的变化,因此,father_tr仍然是父类的类型,但使用copy函数要求father_tr得先new一块memory, 如果没有memory,则需要使用clone函数。(3)此处的$cast操作与(1)中的简单赋值很类似,father_tr的类型也会变为子类的类型。

上面子类向父类进行数据传递时,显示不出cast操作向下类型转换的优势,但父类向子类传递数据时,无法使用child_tr = father_tr,则必须要使用$cast操作。

使用 c a s t 操 作 , 直 接 使 用 cast操作,直接使用 cast使cast(child_tr, father_tr)是非法的,此时则要求基类的handle必须指向派生类的对象,即father_tr必须指向child_tr类型的对象​,因此一般会有如下几步操作:

1、定义一个派生类类型的对象:child1_tr = new;

2、​father_tr = child1_tr;

3、$cast(child_tr, father_tr);

以上第(3)步,$cast会做类型检查,若类型兼容返回1,否则返回0。​

3 clone()

clone是基类uvm_object的方法,clone = new + copy,返回的是uvm_object的handle,常用于对原实体进行复制到本地进行修改。
e.g.

my_trans  trans_a;
my_trans  trans_b;
$cast(trans_a, trans_b.clone());

由于clone()后,返回的句柄是父类类型,而不在是my_trans类型,直接用trans_a = trans_b.clone()是错误的。所以需要cast给子类。

参考

1.SystemVerilog中$cast方法的作用是什么.
2.UVM 之 $cast.
3.System verilog中 $cast.
4.verifcation academy.
5.What is copy-on-write?


http://www.niftyadmin.cn/n/1458777.html

相关文章

DDRC中的write exclusive

DDRC中的write exclusive为了在硬件层面支持读写互斥,就需要判断一个地址是否已被其他处理器或核心修改,在 ARM 处理器中包含了被称为 Exclusive Monitor 的状态机来维护内存的互斥状态,从而保证读写一致性。 状态机的起始状态为 Open&#x…

sv中并行语句

sv中并行语句sv中有fork-join、fork-join_none、fork-join_any三种并行语句,拿一个栗子说明三者的区别。有三个子线程同时运行 ,只要有任何一个线程结束,就退出并行块,以下是三种实现方法。 task test();fork:tagbegi…

vim常用指令

1.跳转到上次操作光标位置:ctrlo 2.列操作:ctrlv 3.粘贴复制:yp 4.行选中:shiftv 5.高亮:gd 6.上下左右:hjkl 7.单个字母选中:v 8.快速查找文件:gf 9. 移动光标 Vi中的光标键是h, j,…

svn 问题之右键没有checkout 选项

svn 问题之右键没有checkout 选项1.原因2.解决办法3.参考1.原因 之所以出现这种问题,是因为曾经在当前地址checkout 过文件,当前地址受到svn的控制,svn不允许在当前地址下再嵌套另外一个svn库。 换个不受控的文件夹点右键,就会发…

uvm_event 的使用

uvm_event 的使用 uvm_event可以用来在不同的组件里实现同步的作用。 class exm_driver extends uvm_driver #(data_transaction)uvm_event frame_event...function void build_phase(uvm_phase phase)super.build_phase(phase);frame_event uvm_e…

VCS+Verdi 安装过程遇到的问题-CentOS7

VCSVerdi 安装过程遇到的问题-CentOS71.安装流程1.1文件结构1.2 创建文件目录1.3 解压SynopsysInstaller.rar1.4 安装instller1.5 安装VCS等1.6 生成license1.7 设置环境变量1.8 激活1.9 查看是否激活成功1.10 开机自动激活2.问题记录2.1 问题一2.2 问题二2.3 激活不成功3.引用…

systemverilog中的参数传递——ref、input、output

systemverilog中的参数传递——ref、input、output1 静态数组作为参数1.1 input1.2 output1.3 ref2 动态数组或队列作为参数3 类作为参数4 原文链接1 静态数组作为参数 sv中的静态数组、动态数组、队列都是用一块内存存放,而他们的名字作为该内存的地址&#xff0c…

verilog中函数用法

verilog中函数用法读写文件常用1.1打开文件1.2读写文件2执行系统命令读写文件常用 1.1打开文件 $fopen打开文件&#xff0c;用法如下&#xff1a; 1. $fopen("<文件名>")&#xff1b; 2. <句柄>$fopen(“<文件名>”)&#xff1b;用法1自然无须多…