路科验证的个人空间 https://blog.eetop.cn/1561828 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

SystemVerilog如何支持使用参数化类编写通用代码的模板?

已有 3388 次阅读| 2020-2-7 19:35 |个人分类:验证系统思想|系统分类:芯片设计

小编语:近些天,想必你和小编一样,心情也是跌宕起伏。一觉醒来,被疫情的实时动态所增加的人数又吓到,被爆出的各种负面新闻又要气炸,被一批批又加入援鄂大军的医疗队员所暖到...... anyway, 在这共克时艰之时,我们要保持理性,更要相信科学,保护好自己,路科会陪你一起永远向着光亮那方!只希望所有人都平安!像路桑所说,疫情面前我们能做好的就是平静下来,修炼内功。那静下心来看看今日份儿的推送,跟随小编一起康康如何在OOP设计模式中使用参数化类?什么是OOP的单例模式和工厂模式?


·  正  ·  文  ·  来  ·  啦  ·
SystemVerilog支持使用参数化类编写通用代码的模板。本文将阐明组成UVM基类库的代码中的一些设计模式,并传授一些使用SystemVerilog通用验证方法学(Universal Verification Methodology,UVM)或任何基于类的方法编写测试平台的经验。设计模式是针对常见编程问题进行优化的可复用解决方案。它们不仅仅是类定义或程序包,而是独立于语言的代码编写模板。1994年,SystemVerilog OOP(Object Oriented Programming,OOP,面向对象编程)语言的设计模式经由《Design Patterns: Elements of Reusable Object-Oriented Software》(该书中文译名为《设计模式:可复用面向对象软件的基础》)一书得到了推广。OOP支持编写可复用代码。这使得OOP的设计模式又向前迈出了一大步。OOP有非常多的设计模式。本文中仅列举两个重要的类别:<1>单例模式-将类的实例化限制为一个对象;<2>工厂模式-提供用于创建相关族或从属对象族的界面,并指定用于创建这些对象的策略。在更详细地阐述这些内容之前,我们需要了解SystemVerilog如何支持使用参数化类编写通用代码的模板。 参数化类参数是表示值或数据类型的常量类型。一旦仿真开始就不能对参数进行更改。在仿真开始前,编译器会将参数表达式作为结构描述和代码生成阶段的一部分进行编译。因此,用户可以将参数用作其他类型声明的一部分,也可以直接使用参数的值。例如,在声明数组范围时就可以使用参数。SystemVerilog使用符号“#”和类标题中的参数名称列表来定义通用类。当引用通用类时,还可以使用符号“#”来提供参数分配或替代列表。


图1 参数化类的声明和引用在图1的例子中,参数T是没有默认值的。因此,在使用时必须提供参数T的具体值。相对的,参数W设置了默认值5,那么就可以根据实际情况来决定是否提供具体值。使用具体参数值的通用类称为具体类。在类变量或另一种类型的声明中引用通用的参数化类时,通用的参数化类将被赋予具体的参数值。通用类的每种组合及其最终的参数覆盖都将使它成为唯一的特定:一种新的类类型(new class type)。静态类属性需要在0时刻之前分配并初始化但是只要声明了一个带有参数的通用类,这种情况就不再成立了。一个作为通用模板的参数化类和该类的特定化之间的区别是非常重要的。除非封装静态类属性的类被特定化,否则静态类属性是不会被分配的。每一个特定类都有一个唯一的实例及其静态属性的初始化


图2 具有静态属性的参数化类一旦引用了特定化的通用类,SystemVerilog就会为该通用类分配静态属性。这一过程不需要构造该类的对象。图2中的两个“typedef”创建了两个静态“counter”变量的实例。两个类变量S1和S2的声明与构造都与类型“stack_byte”共享一个静态“count”变量。与未参数化的类一样,用户可以使用类作用域运算符引用静态属性和方法。用户可以使用一个唯一的特定类来引用用户想要的唯一成员。就像定义一个新的特定类一样,必须为每个没有默认值的参数提供相应的具体参数。否则,将无法编译。 单例模式单例模式用于确定只构造一个类类型的实例。假如用户正在尝试构建树型结构并想要定义该结构,那么对于树型结构而言只有一个根对象。为了控制构造对象的个数,用户需要使类的构造函数成为本地的方法。这意味着其他任何类都不能调用这个构造函数,并且由于扩展类需要调用super.new(),因此也无法构建扩展类。 


图3 具有局部限定的单例模式在图3的例子中,创建了一个局部静态属性“m_root”,该属性具有单例对象的句柄。由于无法直接调用构造函数,因此定义了一个强制执行单例模式的静态方法“get()”。“get()”仅在“new()”为“null”时可以调用,在调用的同时会检查“m_root”。“m_root”禁止了其他类的访问,所以“new()”不可能被多次调用。“get()”方法还演示了“首次使用时创建”的模式。当很多人第一次接触到单例时,他们会想象定义一个“恒定的”静态变量:在0时刻之前,该变量可以在调用“new()”进行初始化时被写入唯一的一次。但存在的问题是,只要 “new()”没有设置访问限制,任何用户都可以定义另一个根变量,并且仍然可以构造多个根对象。另一个问题就是所谓的“静态变量初始化顺序失败”。设计中所有静态变量都在0时刻之前初始化。由于没有相应的程序流进行说明,因此无法得知以何种顺序进行静态变量的初始化。这些静态变量的初始化可能分布在整个代码中。为了避免初始化顺序的失败,用户可以采用访问方法,该方法是在静态变量被第一次引用时进行初始化,而不是直接引用静态变量。这样一来,初始化的顺序问题就迎刃而解了。 工厂模式工厂模式使对象构造具有多态性这允许用户将构造委托给另一个对象,这个对象可以决定要创建何种对象。工厂模式还提供了一个策略,该策略用于确定工厂返回的对象类型如果使用了工厂模式创建类,用户可以将构造对象的类类型与要构造的实际类类型分离。这是如何工作的呢?假设现在有一个类A构造一个类B对象,和一个类B构造一个类C对象。在之后的某个时刻,用户希望将类C扩展到类D中。这时需要通过修改或扩展类B来构造D对象,而不是C对象。如果用户想要扩展B,那么还需要更改或扩展A。若是不想修改A或B,怎么办?这一问题的解决方案是,让用户使用一个特定的方法替换构造B对象的B类中对“new()”的调用。这个特定的方法通常是返回C对象,但也可以返回任何从C派生的对象因此,当用户想要改变类的构造时,不再需要修改类A或类B。

图4 工厂模式多态结构工厂模式涉及许多不同的概念。有很多工厂生产不同种类的东西。例如,工厂可以用于从一个抽象库生成单个对象。工厂使用另一种抽象类,称为代理类。它有一个虚拟方法可以返回所需类类型的对象句柄。对于使用工厂创建的每个类,用户需要扩展代理类并实现一个创造对象方法。这个方法会构造一个所需类型的对象。而后,用户构造扩展对象代理类并获取一个代理对象的句柄。这个句柄可用于构造所请求的对象。 

图5 工厂代理对象因此,代理对象是一个具有请求对象的所有属性和方法的轻量级替代对象。用户可以通过传递代理对象句柄或在数据库中存储许多不同的代理对象句柄。例如在图5中,名为“factory”的关联数组。而后用户可以调用虚拟创建对象方法,该方法可以根据数组中存储的句柄类型选择实现。用户还可以实现自动化的工厂注册过程。工厂模式可以利用特定类的静态属性初始化来实现工厂注册用户也可以设置特定化的代理类为单例模式,即“me”,如图6。如此一来,用户就可以将工厂的关联数组索引从字符串类型更改为代理基类类型。

图6 静态工厂注册一旦完成了创建对象注册表类的所有工作,这个工厂注册的实际使用就变得非常简单了。只要使用“typedef”引用特定类,“objectRegistry”类中的静态属性就会被分配和初始化。所以用户需要做的就是在想要注册到工厂的类中设置一个“typedef”就如同之前对C和D类所为的那样。

图7 用户的注册和覆盖现在,除了调用“new()”外,用户还可以使用静态方法创造一个名为“typeId”的特定类。这个类包含在请求的C类类型中。这就是“C::typeId::create()”所完成的工作。用户不需要使用动态的$cast。原因是静态creat()方法返回的类型被参数化为请求的C类型。最终,用户通过将C代理对象替换为D代理对象单例来完成了覆盖。现在,只要用户在调用创造方法时需要一个C对象,就可以使用D对象代替。
原文出处:https://www.edn.com/design/systems-design/4461513/Design-patterns-in-SystemVerilog-OOP-for-UVM-verification
系列回顾:当工程师说"class"时,到底在说什么?如何有效而正确的使用继承和多态性?


点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 253

    粉丝
  • 25

    好友
  • 33

    获赞
  • 45

    评论
  • 访问数
关闭

站长推荐 上一条 /2 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-20 17:02 , Processed in 0.106428 second(s), 12 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部