前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >IC验证er一起学点设计模式(1)---单例模式

IC验证er一起学点设计模式(1)---单例模式

作者头像
IC验证
发布2021-03-08 15:38:12
6650
发布2021-03-08 15:38:12
举报
文章被收录于专栏:杰瑞IC验证

1

说两句大背景

众所周知,目前IC验证行业使用最主流的语言是SystemVerilog,这个语言有一个重要特点就是它是面向对象的语言。对于面向对象的语言,想要把代码写得更“牛逼”,其实就绕不开一个概念叫“设计模式”。

设计模式是个啥呢?

简单地说,就是在人类软件开发历史长河之中,经过一代代的程序员踩坑和迭代,总结提炼出的各种具体问题的代码解决方案

本文由“壹伴编辑器”提供技术支持

那一年,写代码的种种经验还一直是口口相传散落在江湖中;

突然一个名字叫“GOF”的4个人正式成团出道;

合著了一本名为《设计模式》的书;

在其中总结出了23种经典的软件设计模式;

至此开启了人类对软件设计模式探索的浪潮!!!

本文由“壹伴编辑器”提供技术支持

这23种经典的设计模式,可分为3大类,在此先列出他们的分类和名字,先转转混个眼熟:

1.创建型模式(5种,创建对象的不同玩法)

单例模式、建造者模式、工厂方法模式、抽象工厂模式、原型模式。

2.行为型模式(11种,类和对象交互和职责分配)

策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

3.结构型模式(7种,类和对象的组合的处理)

适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

以SystemVerilog或其他面向对象的语言为主要武器的IC验证工程师们,对设计模式的学习理解,虽然不需要像真正的软件开发工程师理解的那么多,但是稍微的简单了解一些,也许就会对你的编码思想,代码风格产生不错的收益。

今天《IC验证er一起学点设计模式》这个系列,就一起来聊聊关于设计模式在验证中应用。当然对于初学者来说,本系列话题的文章只做了解即可,可以不用关注这么多。刚开始还是要先以把需求和功能顺利实现出来为第一目标,后面有精力再慢慢地提高代码的优雅性。

2

什么是单例模式

有了大背景,今天我们就直奔主题,先说说单例模式。

见名知义,“单例”的“单”,同“单身狗”的“单”,代表独一。

“单例”的“例”,代表实例,也就是类(非抽象类)创建的对象。即创建独一无二的实例的模式。

这个模式说白了,就是在一个软件系统中,针对某个类,保证系统中有且仅有一个实例,然后再提供你一个全局访问点,谁想用就通过访问点访问即可。

直接上代码,先认识一下:

单例模式实现方法其实有很多种,有细节区别,核心思想一样,我们以如上的一种实现聊聊足矣。

我们定义的jerry_singleton这个类,就是我们想做成单例模式的类。在这个类中,除了Jerry定义出的这些方法以外,可以自定义实现具体功能的核心资源代码,这里我们就直接省略了,我们主要看单例模式实现核心。

这段代码是有“套路”的,寥寥几行,内涵丰富。

关键点如下:

1、第3行,jerry_singleton这个类,声明了自己的句柄,叫m_inst。而且修饰为static和local(只能当前类访问,儿子都不让见)。

2、第4行,定义了get() 静态函数,这个函数是单例模式的核心,里面会做一个判断:如果m_inst(我们第1步中声明的jerry_singleton类的句柄)没有指向任何实例,那么我们就通过new创建一个给m_inst,把m_inst作为函数返回值。如果判断已经指向某个实例了(第1步中m_inst声明local和仅仅在此get函数中有new的动作,就保证了这里“某个”实例只可能是jerry_singleton这个类的实例),那就不需要再new了,直接返回即可。这个函数就保证了实例不会二次创建。

3、第6行,new函数,protected类型(只自己和儿子可见,外人不可见)。堵死了外界不用get()函数,而直接使用new函数创造实例的可能性。

4、本来,到上一步可以完成了,使用时候,只需要通过“jerry_singleton::get()”即可获得单实例,进而对其中定义的资源进行调用。

第18行是一种经常锦上添花的写法:

A、首先,一定要想清楚,J_SIG是什么?

J_SIG不是一个字符串,它是一个jerry_singleton类型的句柄!

这句话让这个句柄直接指向了那个通过get函数返回的实例。

B、然后,大家注意,这句话,写在class外边!也即是我们之前讲的$unit空间,可看作J_SIG全局可见,可依照名字直接调用!(前文回顾:人人都会用到,但是大部分人不清楚是什么的“神秘空间”

C、最后,神来之笔,顺手写上了一个const,把句柄J_SIG进行了常量限制,也就是只读变量。这样这个J_SIG句柄就不能再指向其他的对象了!

这样简单的一句话下来,你便可以在验证平台任何地方(相同编译单元域),直接使用J_SIG这个句柄, 就可以方便访问到jerry_singleton类的唯一实例!

说到这里忍不住顺便来一嘴子,UVM源代码中有这么一句:

const uvm_root uvm_top = uvm_root::get();

是不是很熟悉呢!我们平时使用的“uvm_top”和今天的“J_SIG”一样的玩法。

看完例子3句话再总结下实现单例的核心:

类内部自new对象

new的时候保证唯一性

提供全局访问点

3

单例模式优劣

有人问了,这个玩意有什么用?

优秀的推销人员,一般先不会直接给你说产品有什么用,而是先甩出已经拿下的一堆大客户再说。

所以,你问我单例模式有什么用?我希望你先别问我,请你在UVM源代码目录下grep一下例如“::get()”或者 "function .* get();"等类似的关键词,只是随便追一追,看看是不是大把的单例模式?

看看他们怎么用,再来问我有没有用?

如同下面录屏视频中Jerry在uvm1.2源代码里grep的简单操作,可以大体看出例如uvm各种phase、uvm_reg_cbs和uvm_callback相关的一些类、uvm_resource_pool、uvm_root,等等都用了单例模式。

值得一提的是,在UVM1.2中更是单独设计了一个单例类uvm_coreserice_t,把uvm_factory、report_server等重要的共享的信息都带上。

哈哈,当然,我们也简单地聊聊单例有什么好处。

1.唯一性

验证平台中,有的信息我们希望是唯一存在的,比如想收集到不同组件的关键信息进行统一存放或管理,如果存在多个对象,就不能得到一个完整唯一的信息,存在风险。此时可以考虑用单例方式优雅地解决。比如uvm_root、各种phase,这些实例如果不全局唯一,就会存在风险和麻烦。

2.省内存

假如你的验证平台,有一个类里面的内容很多很庞大,偏偏许多组件都想使用它里面的东西,用的时候每个组件都需要把这个组件声明和new一下,创建了这么多对象,显然是非常浪费内存空间,用单例就可以很好地节省。

3.全局访问更方便

从上一小节的代码中可以看出,我们要访问单例中的内容变得非常简单,不需要在任何组件类中声明例化,随用即可。

4.资源和数据共享

因为全局的访问方便和唯一性,通过单例,不同的组件可以在不关联的情况下,直接实现资源的共享或通信。这在搭建更高层次的验证平台和统一的时候可以提高很多效率。例如你的验证平台中有一些通用功能的公共函数,这些函数甚至可以在不同级别的验证平台中公用,那完全可以考虑为单例模式。

本文由“壹伴编辑器”提供技术支持

话说回来,盐好吃也不能多吃,单例也是有缺点的,不是啥情况都能用的,比如说虽然你想资源共享你的某个类,但是需要根据不同的参数例化不同的对象,在这种情况下,单例模式就不是很友好了,即便是节省了内存或方便了访问,无法满足实际应用需求也是徒劳。

大家可以结合前面提到的UVM源代码中单例的应用进行其优劣思考,但是也不要局限在其中,多想想自己设计的验证平台中哪些更适合用单例模式,然后应用之。

好了,时光如水,又到了说再见的时候了,祝大家天天开心,吃好喝好,越来越牛逼~

——The End——

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 杰瑞IC验证 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档