路科验证(Rocker IC)专注于验证系统思想和前沿工程资讯,拥有一支活跃的技术原创团队,著有《芯片验证漫游指南》一书,致力为高校微电子相关专业学生与IC从业人员提供技术食粮。 您可以在手机移动端同步关注微信订阅号“路科验证”或是登录网页www.rockeric.com了解更多资讯。如果您需要联系我们,请发送邮件至 bin.rocker.liu@intel.com 。

SV及UVM高级话题篇之三:SV单元测试方法SVUnit

上一篇 / 下一篇  2018-06-12 21:04:30 / 个人分类:验证系统思想

  

正如我们上一节介绍到了目前还不算丰富的第三方SV的开源库,在svlib库的开发过程中,开发者提到了用于SV单元测试的插件SVUnit。单元测试在软件敏捷(agile)开发领域已经很普遍了,而随着SV开发的软件特性越来越浓,这使得软件开发领域的一些思想西风东渐不再稀奇。


单元测试(Unit testing)是将一个完整的模块(module、class、function)从原有的系统中隔离出来进行测试。对于verifier们,他们一般会忽略了单元测试、组件测试(Component testing,测试设计多个类),甚至跳过集成测试(Integration testing,对多个类、包、组件和子系统进行联合测试),直接利用构建的环境(系统)来对DUT进行测试。测试的概念在软件开发中是针对软件设计而言的,那么在硬件环境中如果实现概念的迁移呢?我们认为有必要对硬件本身和验证环境分别进行小范围的测试(例如单元测试),在更底层来保证硬件设计和验证环境的基本功能正确。

在以往的测试方式中,我们一般会通过这些方法来保证硬件设计和验证环境的基本功能:

  • 在硬件设计中内建断言,来保证底层功能和时序的检查。

  • 在验证环境中通过函数的返回值来判断是否成功,继而报告错误信息。


但不幸的第一个事实是,在我们验证的过程中占据三分之一时间的调试,不仅仅是在调试设计功能,而且也在调试验证环境。所以,当verifier们在抱怨designer在发布新的设计版本之前没有经过基本的测试时,verifier自己的验证环境(软件部分)也是面临着同样的问题。在验证领域中,测试的部分包括了硬件测试和验证环境测试两部分。而不幸的第二个事实是,designer没有习惯写硬件的单元测试,或者也不会在修改了设计之后自己跑验证环境检查基本测试是否通过;verifier也一样没有习惯写验证环境的单元测试。


什么?验证环境自己也要测试自己吗?当然!不然一个鸡生蛋蛋生鸡的问题会让你对自己的验证环境不再那么有信心——你如何保证你的验证环境本身没有问题?你的激励是否满足协议时序?你的采样是否按照协议进行?你的参考模型功能本身是否正确?你的计分板是否不会漏掉任何一个错误?verifier怎么来保证验证环境自身的正确呢?


另外,考虑到UVM验证环境是一个高度结构化的软件设计,那么在完成环境集成之前,是否有必要对各个环境组件完成基本测试保证它们自身的功能正确呢?而有经验的验证工程师伴随着经验,会对自己的环境集成越来越保持审慎的态度,在他们眼里,没有完美无瑕的环境。一个环境、一个组件、一个用户自定义的类,在工作之前应该需要进行单元测试。单元测试是一个低级别的,关注到类或者模块基本功能的方法,通过将目标模块进行隔离,创建单独的环境进行测试,使得每一个由单元测试历练过的模块有着更好的品质,而在后期集成中会减少更多的低级错误。


“出来混迟早是要还的”,对于验证的新人,这句话还需要更多的时间去体会。而经历过几次UVM环境调试的工程师,对于UVM这种“道可道非常道”的难以名状的验证包就会怀起敬畏之心来。没有几年的经验,verifier在完成环境集成之后,即便是完成编译之后,要加载验证环境时的心情,只能是“自己的心情自己感受”了。那么用什么来拯救一个将来要调试的庞大复杂的UVM系统呢?SVUnit的分而克之理念,或者说贯穿于软件测试领域的单元测试理念,就是要开发者在软件面前变得更谦卑一点,承认自己容易犯错,继而就开发的验证组件首先进行单个测试,再进行集成和整体的运行。


那么,具体来讲,SVUnit可以为验证环境带来什么好处呢?

  • SVUnit对于一个UVM组件的主要功能都会测试它的正确性。这种测试方法可以为后期功能的修改、添加提供支援。譬如我们在后期开发中更新了原有的功能、或者添加了原有的功能之后,运行与这个组件配套的测试套件之后,就不用担心对于组件类的更新会破坏原有的功能。

  • UVM组件在要求高复用性的前提下,就要求自身提供清晰方便的方法。在编写测试的过程中,会让verifier自己采用不同的视点,来从第三方验证IP集成者的角度来考虑我们自己写的组件,关注它提供的方法接口。这样就会让我们实现便于复用、结构清晰的组件。

  • 通过编写测试,会让verifier对软件的接口隔离原则(ISP Interface Segregation Principle),即让组件的使用者可以应用多个专用的接口,而不是一个处理庞大功能的总接口上。测试的好习惯使得verifier会有意思地将组件设计为易于调用和可测试的,并且将它与周围的环境解耦,降低对其它环境的依赖性。

  • 同时编写测试也是一个重要的文档。这个文档有些时候要胜过文本文档的实时性和应用参考,因为后期的组件集成者对于组件使用方法不单通过文档,也可以通过单元测试来理解如何创建一个对象和调用组件的方法。


接下来关于SVUnit,我们就它如何快速实现对于UVM component的测试和自动化来介绍。SVUnit也可以Verilog模块进行测试,而且测试方式很接近于之前的直接测试,只不过它将各个测试场景都分块,而且通过自定义的宏实现了单元测试的执行和报告。之前我们也已经谈到,SVUnit的测试理念并不新颖,在软件开发世界中已经有成功的单元测试框架例如JUnit。验证世界希望通过引入单元测试的理念,可以使得硬件设计和验证环境两部分在开始的时候都可以有条不紊,在每一个节点都有交付标准,因此从源头上控制代码质量,而不是直到设计在集成、验证环境在集成之后才着手测试,有经验的verifier们都知道将这些没有做早期单元测试工作模块延展到后期集成阶段做测试,他们都遭遇了什么。


下面的例子,我们围绕着SVUnit安装包中的examples目录下的一个简单的例子来介绍如何使用SVUnit。


首先我们下载了SVUnit压缩包之后解压到Unix环境中,并且执行Setup.csh或者Setup.bsh来完成环境变量的设置。接下来进入examples/uvm/simple_model目录,按照README文件中的指令,执行runSVUnit -uvm -s <simulator>。这里<simulator>的命令参数可以选择ius、questa或者vcs的任何一种。这个命令可以帮助用户完成编译、仿真的工作,其后将仿真结果报告出来。


那么假如读者一开始希望测试一个UVM组件,那么如何实现呢?这里我们还是将例子中的组件simple_model作为UUT(Unit Under Test)。



这个模块是从下面的验证环境中抽取出来的一个reference model,它通过从get_port来获取原始数据,而经过简单计算之后将数据从put_port送出。


接下来我们需要利用SVUnit来生成对simple_model的测试模板,这一步可以通过create_unit_test.pl来帮助自动生成所需要的测试框架。

create_unit_test.pl -uvm simple_model.sv


这样便可以对uvm_component类自动生成测试框架simple_module_unit_test.sv。生成的框架代码如下:



从生成的框架来看,会有一个uvm_component类simple_model_uvm_wrapper生成,这个类继承于simple_model,它的目的是为测试simple_model类,而在其内部定义更多需要的成员。随后会有一个module simple_module_unit_test,它的作用在于例化软件类simple_model_uvm_wrapper、完成SVUnit的测试环境结构,同时由单元测试者自定义一些可以用来测试的用例。从这个自动化生成的框架来看,用户无需再额外考虑如何导入SVUnit包、初始化测试框架、构建基本测试环境,这些可以通过SVUnit的Perl脚本完成,对于verifier他只需要考虑如何针对UUT构建测试环境元素和测试用例。


我们考虑按照上图构建一个测试环境,在simple_model_uvm_wrapper中新引入两个数据缓存,一端用来接收测试环境中的数据,另外一端用来与simple_model的TLM端口连接。因此在simple_model_uvm_wrapper由verifer来实现新添加的FIFO的例化和连接:



在建立了测试环境之后,就可以在simple_model_unit_test中添加具体的测试用例了。



可以看到在`SVUNIT_TEST_BEGIN和`SVUNIT_TEST_END的宏中,可以添加多个测试单元,由`SVTEST和`SVTEST_END来装载每一个单元测试名。而测试的信息报告可以通过`FAILE_UNLESS、`FAIL_IF来实现,这些信息都会在稍后运行时通过SVUnit的测试框架来处理。而在通过指令“runSVUnit -uvm -s <simulator>”来执行单元测试之后,会打印出下面的这些信息:



这些报告信息中,用户需要注意这几个关键词:test、testcase和test suit。在一个测试模板中可以定义多个test,它们在测试中使按照先后顺序执行的,在测试中如果有任意一个测试失败,那么它最终的状态也是失败的,即这个模板对应的testcase的测试状态是失败的。


而为了方便用户管理多个测试模板和其中的test,SVUnit支持通过单次调用runSVUnit来实现按照先后顺序执行多个UUT的testcase。这种将多个testcase整理起来跑测试的方式,称之为test suite。


也许在SVUnit之前,verifier在开发验证环境的同时已经隐约感到应该对一些基本的UVM组件(或者module、interface)进行测试,但这种测试的方法还没有被规范化,也因此无法将这种单元测试的方法在团队内推广开来。而通过SVUnit,这样一个轻量级的应用,它既可以自动化生成测试模板,也可以在稍后的测试管理中方便测试启动、管理和报告。整个单元测试的环节被规范下来之后,使得verifier和designer就有机会在设计环境或者硬件模块的同时,也可以准备单元测试。尽管verifier也许还不适应测试驱动开发(test driven develoment)的方式,但通过SVUnit来增强自己新代码的信心这一点,对verifier还是很有吸引力的。


单元测试的另外一个帮助在于,当你作为一段有悠久历史的老代码的维护者时,测试代码是让你试图保证原有代码结构和功能的大管家。就像一座老房子,代码的注释也许都像家具的使用说明一样过期了,但单元测试的代码还是像一个有问必答的管家帮公司(而不是某一个开发者)来看管着这些代码。无论这间老房子迎来哪一位新的主人,单元测试代码都会给你一一介绍这所房子的结构、哪一处是大门、哪一处年久失修、哪一处有一个坑。

因此SVUnit对于软件世界到验证世界来的新移民,他们会本能的欢迎;对于验证世界的原住民,伴随着他们软件经验的增长,他们也逐渐认识到单元测试的重要性;而对于那些生活在一个“世外桃源”不知魏晋南北朝的硬件设计人员,如何说服他们接受单元测试的理念,恐怕还有很长的一段路要走。


下一节我们将关注如何实现《OVM到UVM的移植》。


谢谢你对路科验证的关注,也欢迎你分享和转发真正的技术价值,你的支持是我们保持前行的动力。



TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

路科验证

路科验证

路科验证(Rocker IC)专注于验证系统思想和前沿工程资讯,拥有一支活跃的技术原创团队,为高校微电子相关专业学生与IC从业人员提供技术食粮。 您可以在手机移动端同步关注微信订阅号“路科验证”。如果您需要联系我们,请发送邮件至 rocker.ic@vip.163.com 或者 bin.rocker.liu@intel.com 。

日历

« 2018-06-21  
     12
3456789
10111213141516
17181920212223
24252627282930

数据统计

  • 访问量: 115225
  • 日志数: 221
  • 建立时间: 2016-06-25
  • 更新时间: 2018-06-14

RSS订阅

Open Toolbar