SystemVerilog 类对象,变量和句柄

本文介绍SystemVerilog中的类对象与句柄概念。详细解释了类对象的创建及句柄的应用,通过实例展示了如何使用句柄引用类对象中的成员。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类对象是你在调用其构造函数 new()时创建的类定义的实例。 在SystemVerilog中,所有类对象都是动态创建的; 在时间0之后或之后.LRM不指定如何或何时可以销毁对象 - 只有当它不能被销毁时。
类变量是变量的值表示对类对象的引用。 像任何其他变量一样,类变量的生命周期取决于它的定义方式和位置(静态,自动或动态)。

类句柄表示对类对象的引用的值。 您永远无法查看或表示句柄的文字值(除特殊句柄:null外)。 您必须在表达式中使用类变量,以便使用存储在变量中的类句柄来引用类对象中的成员或方法。

举例如下:

module top;
   class class_name
      int i;
   endclass
   class_name class_variable;;
   initial $display("Hello World");
endmodule

你将创建一个静态变量class_name但不包含类对象。 所以没有句柄存在class_name。 现在调用构造函数。

module top;
   class class_name
      int i;
   endclass
   class_name class_variable;;
   initial $display("Hello World");
   initial begin
      class_variable = new();
      class_variable.i = 1;
      $display(class_variable.i);
   end   
endmodule

new()是一个返回句柄给class_name对象的函数。 class_variable.i表示使用存储在class_variable中的句柄来引用对象,并选择该对象的变量i。 在C / C ++中,这看起来像指针引用class_name-> i; 在SystemVerilog中,你永远不会直接使用这个对象,你总是引用使用存储在类变量中的句柄。

关于句柄的通俗解释(什么是句柄?为什么会有句柄?):

从广义上,能够从一个数值拎起一大堆数据的东西都可以叫做句柄。句柄的英文是"Handle",本义就是"柄",只是在计算机科学中,被特别地翻译成"句柄",其实还是个"柄"。从一个小东西拎起一大堆东西,这难道不像是个"柄"吗?

然后,指针其实也是一种"句柄",只是由于指针同时拥有更特殊的含义——实实在在地对应内存里地一个地址——所以,通常不把指针说成是"句柄"。但指针也有着能从一个32位的值引用到一大堆数据的作用,这不是句柄又是什么?

Windows系统中有许多内核对象(这里的对象不完全等价于"面向对象程序设计"一词中的"对象",虽然实质上还真差不多),比如打开的文件,创建的线程,程序的窗口,等等。这些重要的对象肯定不是4个字节或者8个字节足以完全描述的,他们拥有大量的属性。为了保存这样一个"对象"的状态,往往需要上百甚至上千字节的内存空间,那么怎么在程序间或程序内部的子过程(函数)之间传递这些数据呢?拖着这成百上千的字节拷贝来拷贝去吗?显然会浪费效率。那么怎么办?当然传递这些对象的首地址是一个办法,但这至少有两个缺点:

  1. 暴露了内核对象本身,使得程序(而不是操作系统内核)也可以任意地修改对象地内部状态(首地址都知道了,还有什么不能改的?),这显然是操作系统内核所不允许的;
  2. 操作系统有定期整理内存的责任,如果一些内存整理过一次后,对象被搬走了怎么办?

所以,Windows操作系统就采用进一步的间接:在进程的地址空间中设一张表,表里头专门保存一些编号和由这个编号对应一个地址,而由那个地址去引用实际的对象,这个编号跟那个地址在数值上没有任何规律性的联系,纯粹是个映射而已。

在Windows系统中,这个编号就叫做"句柄"。


SystemVerilog 中,随机化枚举变量句柄的过程涉及几个重要概念:定义枚举类型、声明随机化的枚举变量以及利用类的机制完成实例化随机化。以下是详细的说明。 ### 定义枚举类型 首先需要定义一个枚举类型。例如: ```systemverilog typedef enum {RED, GREEN, BLUE} color_e; ``` 这段代码定义了一个名为 `color_e` 的枚举类型,其中包含三个可能的值:`RED`, `GREEN`, `BLUE`[^1]。 ### 创建带有枚举变量的类并声明其为随机变量 接着,在类中声明该枚举类型的随机变量。假设我们希望这个枚举变量是一个句柄形式(即它可以通过对象实例访问),那么我们可以这样设计: ```systemverilog class EnumHandleClass; rand color_e color_handle; function new(); // 初始化逻辑可以放在这里 endfunction constraint c_color { color_handle dist { RED := 1, GREEN := 2, BLUE := 3 }; // 设置不同颜色的选择权重 } endclass ``` 在这个例子中,`EnumHandleClass` 类包含了作为随机变量的枚举类型 `color_handle`。还增加了一个约束条件 `c_color`,用于调整各个颜色被选中的概率[^4]。 ### 实例化随机化过程 为了对枚举变量进行随机化,我们需要创建此类的一个实例,并调用它的 `randomize()` 方法。下面是如何实现这一点的例子: ```systemverilog program test_random_enum_handle; EnumHandleClass eh_instance; initial begin eh_instance = new(); // 创建类的新实例 repeat (5) begin // 进行五次随机化演示 if (!eh_instance.randomize()) $fatal("Randomization failed"); case(eh_instance.color_handle) RED: $display("The randomized handle points to RED."); GREEN: $display("The randomized handle points to GREEN."); BLUE: $display("The randomized handle points to BLUE."); endcase end end endprogram ``` 这里展示了如何通过循环多次调用 `randomize()` 函数来获取不同的随机结果,并根据每次的结果采取相应的行动[^2]。 --- #### 注意事项 - **约束的有效性**:确保所加上的任何约束不会使解决方案空间变得为空集,否则可能导致无法完成随机化。 - **性能考虑**:对于复杂的大规模验证环境中频繁使用的随机化操作,应关注其实现效率及其对整体仿真时间的影响[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值