[SV]使用SystemVerilog参数化类编写通用代码模板

                使用SystemVerilog参数化类编写通用代码模板

 

       SystemVerilog支持使用参数化类编写泛型代码的模板。在这里,我们将描述组成UVM基类库的代码中的一些设计模式。使用SystemVerilog Universal Verification Methodology (UVM)或任何基于类的方法论编写测试工作台的用户可以从这些技术中学习。

       设计模式是针对常见编程问题的优化的、可重用的解决方案。它们不仅仅是类定义或一组例程——它们是用于编写代码的与语言无关的模板。

       专门用于SystemVerilog面向对象编程(OOP)语言的设计模式的概念在1994年因《设计模式:可重用的面向对象软件的元素》一书而流行起来。OOP支持编写可重用代码。面向对象设计模式的重用是另一个步骤。

       设计模式有很多种。这篇文章包括两个重要的类别:

  • 单例模式——将类的实例化限制为一个对象。
  • 工厂模式——为创建一系列相关或依赖对象提供接口,并为创建这些对象指定策略。

       在更详细地解释这些之前,我们需要了解SystemVerilog如何支持使用参数化类编写泛型代码的模板。

 

一、参数化的类

       参数是一种表示值或数据类型的常量类型。一旦仿真开始,您就不能更改参数。在仿真开始之前,编译器将计算参数表达式作为其细化和代码生成阶段的一部分。因此,您可以将参数用作另一类型声明的一部分,或者在数组声明的范围内使用参数的值。

       SystemVerilog在类头中使用带有参数名称列表的井号(#)来定义泛型类。在引用泛型类时,还可以使用井号来提供参数赋值或覆盖的列表。

class stack #(type T, int W = 5);

  bit [W:0]                data;

endclass : stack

stack #(bit [1:10]);        //W为默认值5

                                          Figure 1 Parameterized class declaration and reference

 

       在这个例子中,我们必须提供一个类型参数T,因为它没有默认值;值参数W是可选的,因为我们提供了默认值5。

       用其实际参数值引用的泛型类称为专门化。当在类变量的声明中或在另一类型的声明中引用泛型参数化类时,我们修复泛型类的参数化。泛型类的每个组合及其最后的参数重写都成为惟一的类专门化:新的类类型。

       静态类属性需要在0时刻之前分配并初始化但是只要声明了一个带有参数的通用类,这种情况就不再成立了。一个作为通用模板的参数化类和该类的特定化之间的区别是非常重要的。除非封装静态类属性的类被特定化,否则静态类属性是不会被分配的。每一个特定类都有一个唯一的实例及其静态属性的初始化

class stack #(type T = int);

  static int               counter = 1;
  int                      m_cnt;

  function new(string name = "stack");
    super.new(new);
    m_cnt = counter++;
  endfunction
endclass : stack

typedef stack #(byte)        stack_byte;

typedef stack #()            stack_int;

stack_byte    S1 = new(), S2 = new();

$display(stack#(byte)::counter);
$display(stack#(bit)::counter);

                                             Figure 2 Parameterized classes with static properties 

 

       一旦引用了泛型类的专门化,SystemVerilog就会分配该泛型类的静态属性。不需要构造该类的对象。图2中的两个typedef创建了静态计数器变量的两个实例。两个类变量S1和S2的声明和构造都与typedef count_byte共享同一个静态计数变量。

       与未参数化的类一样,我们可以使用类作用域操作符来引用静态属性和方法。我们使用唯一的专门化来引用我们想要的唯一成员。就像定义新的专门化一样,必须为每个没有默认值的参数提供参数覆盖,否则将无法编译。

 

二、单例模式

        单例设计模式用于保证只构造类类型的一个实例。假设我们试图构建一个树结构,并且我们希望定义这个结构,以便树中只有一个根对象。为了控制构造的对象数量,我们需要将类构造函数设置为一个本地方法。这意味着这个类之外的人不能调用它,也不能构造扩展类,因为扩展的类需要调用super.new()。

        

        我们还创建了一个本地静态属性m_root,它持有singleton对象的句柄。由于我们不能直接调用构造函数,所以我们定义了一个静态方法get()来执行singleton模式。调用get()检查m_root,只有在它为空时才调用new()。因为没有其他人可以访问m_root,所以new()不可能被多次调用。get()方法演示了“第一次使用就创建”的模式。

       当许多人第一次想到单例时,他们想象定义一个“const”静态变量,该变量只能通过在时间0之前的初始化调用new()来写入一次,并且再也不能写入。这样做的问题是,只要new()没有本地限定符,任何人都可以定义另一个根变量,并且仍然可以构造多个根对象。

       另一个问题是所谓的“静态变量初始化顺序失败”。设计中的所有静态变量都会在时间0之前初始化。但是没有办法知道静态变量初始化的顺序,因为还没有过程式的语句流。这些静态变量初始化可能分散在代码的各个地方。

       为了避免初始化顺序混乱,我们使用访问方法来获取本地静态变量的值,该值在第一次引用时对其进行初始化,而不是直接引用静态变量。现在,先初始化哪个变量不再重要了。

 

三、工厂模式

        工厂模式使对象构造具有多态性。这允许您将构造委托给另一个对象,该对象可以决定要创建什么类型的对象。工厂还提供了一个策略来确定工厂返回的对象类型。如果我们在创建类时使用工厂模式,我们可以将构造对象的类类型与我们想要构造的实际类类型解耦。

       这是如何运作的呢?假设我们有一个构造类B对象的类a,和一个构造类C对象的类B。在以后的某个时候,我们可能想要将类C扩展到类D,但是随后我们需要修改或扩展类B来构造一个D对象而不是C对象。如果我们延长B,那么我们也需要改变或扩展A。但是我们不希望修改一个或B .工厂模式来救援,让我们更换新()调用C B类,构造一个对象的方法通常会返回一个对象,但是可以返回任何类型的一个对象来自C . A类或B不再有要修改的,当我们想要改变结构。

        

 

       工厂模式涉及许多不同的概念一起工作。有许多生产不同产品的工厂。

 

       例如,工厂可用于从抽象基生成单个对象。工厂使用另一种抽象类,称为代理类,它有一个虚拟方法,返回您想要的类类型的对象的句柄。对于希望使用工厂创建的每个类,我们需要扩展代理类并实现一个create object方法,该方法构造请求类型的对象。然后构造扩展的对象代理类,并获得一个代理对象的句柄,该代理对象可用于构造所请求的对象。

        

       因此,代理对象是完整请求对象及其所有属性和方法的轻量级替代品。我们可以传递代理对象句柄,或者在数据库中存储许多不同的代理对象句柄,例如在图5中的关联数组factory中。然后我们可以调用virtual create object方法,该方法根据存储在数组中的句柄的类型选择实现。

 

       我们还可以做一些事情来实现工厂登记过程的自动化。工厂模式可以利用特定类的静态属性初始化为我们完成工厂注册。我们还可以将专用代理对象设置为单例模式me,这允许我们将工厂的关联数组索引从字符串类型更改为代理基类类型。

        

       一旦您完成了创建对象注册表类的所有工作,这个工厂注册的实际使用就会变得非常简单。只要在typedef中引用一个专门化,objectRegistry类中的静态属性就会被分配和初始化。所以我们所需要做的就是在我们想要注册到工厂的类中放入一个类型定义,就像我们在类C和D中所做的那样。

        

       现在,我们不是调用new(),而是调用名为typeId的专门化类内部的静态方法create,这个类位于被请求的类类型C的内部。在这里,我们不需要使用动态$转换,因为静态create()方法的返回类型被参数化为所请求的类型C。最后,我们通过用一个D代理对象singleton替换C代理对象来覆盖工厂。现在,每当有人调用create方法期望得到一个C对象时,他们会得到一个D对象。

 

四、补充阅读

       这就完成了我们关于UVM的SV OOP的三部分系列文章(请阅读第1部分和第2部分)。要获得更多信息,我推荐《使用参数化类和工厂:面向对象验证的阴阳》这篇论文,并确保查看验证学院的SystemVerilog和UVM的论文和文章库。Dave Rich是Mentor Graphics公司咨询部的高级验证顾问。

 

五、相关文献

 

 

 

 

 

 

 

 

 

 

 

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值