本文主要是介绍SystemVerilog学习-01-系统验证概述,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
什么是验证
无论是我们日常进行求解问题还是进行开发工程,都需要进行测试得到的结果的准确性。用来证明设计的功能正确性,确保设计符合功能描述的过程就是验证。
通常情况下,验证的工作量会大于设计的工作量,通常是占(前端设计+验证)总工作量的70%。举个例子,一双鞋子,工厂制作(使用流水线的机器)可能只需要几分钟,而对于消费者来说,首先需要确定鞋子是否合脚(确定鞋子的大小尺寸),然后要确定鞋子的薄厚,款式、样式、颜色、材质等等。把这些都确认好进行购买后,这时,可以说你完成了鞋子的验证工作。这样的一个流程也可以称为是一种 “验证的过程” 。日常生活是如此,芯片制造中更是如此。
验证中使用的硬件验证语言(HVL)和硬件描述语言(HDL)相比会有一些典型的性质:
- 受约束的随机激励生成;
- 功能覆盖率;
- 更高层次的结构(面向对象编程);
- 多线程以及线程间的通信;
- 支持HDL数据类型;
- 集成事件仿真器,便于对设计实施控制。
测试平台
测试平台的概念对于使用过FPGA进行开发设计的人来说并不陌生,在平时编写FPGA的一些小工程时,都会编写testbench进行模块的验证和测试。通常一个简单的TB包括时钟,激励,测试模块,验证模块功能的方式通常进行使用display在窗口打印输出或者观察波形。
对于验证来说,测试平台也包含上述这些部分,还进一步将这些进行细化,如下图所示:
验证测试平台包括时钟和复位,用于驱动测试平台正常运行;DUT(device under test)为待测的模块;激励用于提供给待测模块输入,对DUT创建测试序列,使得DUT正常工作;监视器部分负责监视模块的数据结果的变化,观察DUT的输入输出,然后将监视结果反馈给核查部分;核查部分对来自监视器和DUT的输出进行比对,进行报告检查结果,如功能是否正常,验证是否通过。而且测试平台(testbench)的功能更加丰富:
- 产生激励(Generate stimulus);
- 把激励输入到待测设计上(DUV,Design Under Verification);
- 产生预期(Generate Expectation);
- 捕捉响应(Capture response);
- 检验响应的正确性(Check the response for correctness);
- 根据验证目标评估验证进度(Measure the progress against the overall verification goals);
芯片开发流程
随着芯片的规模越来越大,开发的复杂度和集成度越来越高,从而需要越来越多的人专门去做验证的工作,下图是一个芯片开发的整体流程。
首先需要市场人员与客户沟通;然后由系统设计人员按照功能划分为各个子系统;子系统被进—步划分为功能模块,并由设计团队实现;验证人员对设计功能展开验证,发现设计缺陷,交由设计人员修正;验证没有出现漏洞后,交由后端人员进行综合、布局、布线;后端人员将核心数据交由FAB进行流片。
在一个芯片开发的流程设计中,验证是硅前的比较重要的一环。验证阶段每多发现一个bug,在后期会更小的概率出现灾难级别的系统漏洞。
验证和设计
硬件设计的目的在于创建一个基于设计规范并能完成特定任务的设备。作为验证工程师,主要目的就是确保该设备能够完成预期的目标任务,达到预期的效果。验证的流程可以并行于设计的流程。对于主流的验证流程,一般是不同的人承担验证和设计的工作,当一个设计者拿到功能描述文档后,开始进行功能的RTL设计,一般在晚于设计者的一到两周验证工程师也需要进行阅读功能描述文档,并且进行验证环境的搭建设计。
设计和验证都需要围绕功能描述文档,验证发现结果不符合预期时,如果漏洞明显可交由设计修正,待返回再测试;如果功能实现与设计存在分歧,则需共同回顾功能描述,决定哪一方理解正确,统—对功能的理解。
所以验证和设计都需要认真阅读功能描述文档,设计负责实现功能模块,将其翻译为RTL模型,验证会按照其功能发送激励和比较结果,从而达到功能描述的要求。
验证的工作
所以对于验证部分来说,在开始构建验证环境前,要进行编写验证计划,一般包括需要验证什么样的特性,采用那些技术等等。编写完成验证计划后,围绕项目的需求,进行检查核实设计文件是否正确地按照功能描述文档去实施;设计人员是否有遗漏边界情况(corner case) ;硬件设计是否足够稳定来处理一些错误情况(error response) 。
对于验证部分来说,他的工作就是完成分配给他的模块级(module level) 、子系统级(subsystem level)或者系统级(chip level)的任务。并且期望要求"按时保质低耗"完成目标硬件设计的验证工作。对于成本而言,在硅前验证付出的额外成本,相对是最低的。
缺陷增长曲线
通过缺陷数量在时间线上的记录,我们可以绘制出缺陷数量的增长曲线。一般来讲,缺陷数量的增长曲线是逐渐逼近趋于缓慢的。功能验证需要保证的就是将缺陷数量的增值(至少是致命缺陷数量)保证在硅前阶段,不应该让其发生在硅后测试阶段。针对缺陷的类型,一般会遵循先易后难的验证方法。我们给出的激励向量应该是先易后难,我们发现出的缺陷也应该是先基本后高级。缺陷率的曲线是否在收敛,或者说斜率是否在变小,这一定程度上可以说明验证的状态是否在收敛和趋于完备。
验证周期
如下图所示:
验证进行工作时,首先需要阅读模块文档进行制定合适的验证计划,然后进行验证环境的搭建,并在搭建过程中回顾是否满足验证计划和功能文档的需求。在调试完成验证环境后,对验证代码进行核查,开始进行验证递归测试,确保验证的完备性,然后进行硅后系统测试,并进行逃逸分析,吸取在验证设计中的经验和教训。
验证方法学基础
对于systemverilog验证方法学采用了如下原则:
- 受约束的随机激励;
- 功能覆盖率;
- 使用事务处理器的分层测试平台;
- 对所有测试通用的测试平台;
- 独立于测试平台之外的个性化测试代码。
这些原则是相关联的。
定向测试与随机测试
验证一个设计的正确性时,传统的做法是进行使用定向测试,这很像平时编写FPGA工程时候的模块验证的tb,针对这种方式,首先需要阅读设计规范,然后写验证计划,根据所写的验证计划进行编写测试需要的激励,然后进行比对测试结果的正确性。这种方法比较容易稳步进行,但是缺点也很明显,对于开发者来说不可能做到面面俱到,将所有的测试点都涵盖到,所以定向测试的弊端也很明显,就是想要测试覆盖达到最佳效果的状态是非常耗时的。
所以这里引入了随机测试的概念,随机激励对测试复杂设计十分关键。定向测试可以找出设计中预期的漏洞;而随机测试则可以找出预料不到的漏洞。虽然随机测试能带来很多好处,但是缺点也是存在的,在第一次进行运行测试时,需要花费大量的时间去准备。如下图:
但在总体而言,随机测试总体需要的时间是小于定向测试的。并且对于随机测试而言,测试的覆盖范围往往比定向测试要大。这时候就要考虑,随机测试是完全随机么?
答案不言而喻。肯定是有一定限制的,所以这里就引入另外一个概念:受约束的随机激励,虽然希望仿真器能产生随机激励,但同时有不希望这些激励数值完全随机。所以要对激励进行约束限制,比如限制数值范围,限制变化形式等等。
随机化对象
在进行随机化时,最容易想到的是对数据字段进行随机,除此之外还需要找到控制逻辑上的漏洞。例如:
- 设备和环境配置
- 输入数据
- 协议异常、错误和违例
- 时延和同步
设备和环境配置
在对RTL设计进行测试时,经常会难以察觉漏洞,这是因为没有对RTL尝试足够多的配置验证,只进行复位测试验证,或者给定一两种已知状态是不科学的,只能保证既定条件下的结果正确,无法挖掘到实际问题。
在实际应用中,你的设备应该包括的有其他设计,对给定模块进行验证测试时,就要尽量满足实际条件的所有情况。你应该对整个环境的配置进行随机化,包括仿真的时长、设备的数量,以及它们的配置方式。当然,你需要创建约束以确保配置的合法性。
输入数据
需要事先估计好所有的分层协议和错误注入,以及计分板的内容和功能覆盖率。
协议异常、错误和违例
为了避免后期实际应用中出现各种异常、错误,应该尽量尝试去仿真在实际的硬件中可能出现的错误,而且应该针对所有可能出现的错误。
时延和同步
一个代码对于来自同一接口的所有可能激励或许会正常工作,但是如果同时面对多个输入,隐藏的漏洞可能就会出现。所以可以尝试协调各个驱动器使他们能够在不同的速率下进行通信。
功能覆盖率
你需要知道哪些部分已经被验证过,这样才能对验证计划中的项目进行核对。所以也就有了功能覆盖率的概念。
功能覆盖率的测量和使用步骤:
- 对于测试平台添加代码用于监控进入设备中的激励,以及设备对激励的反应,并据此确定哪些功能已经被验证过。
- 运行几次仿真,使用不同的种子,将仿真结果合并到一个报告中。
- 结果分析,决定如何进行采用新的激励测试未被测试到的条件和逻辑。
随机测试需要使用反馈。最初的测试会被运行很多次,使用不同的种子,创建很多互异的输入序列。但是到了最后,即时使用新的种子,所产生的激励也很可能无法在设计空间中探测到新区域。随着功能覆盖率逐渐接近极限,你需要改变测试,以期望能找出新的方法去达到那些尚未被覆盖的区域。这被称为“ 覆盖率驱动的验证 ”。
在受约束的随机激励中很少采用动态反馈。相反地,需要手工分析覆盖率报告,然后调整随机约束。
测试平台
测试平台如何编写对于开发效率关系紧密,回想FPGA的Verilog的代码编写,最初是把所有的功能写在一个module里,然后随着设计的越来越复杂,将会逐渐对模块进行分解拆分,进行模块化设计。这也给测试平台的编写带来了一定的启发,分层的测试平台虽然不能包括所有的测试功能,但是能确保测试平台正确的情况下进行测试验证,便于维护和修改。加快开发周期和效率。
一个分层次的测试平台(无测试层)如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x6ONnoDA-1634780209301)(https://gitee.com/Williamwxh/mdimg/raw/master/img/image-20211015193042310.png)]
从上图可以看出,一个分层次的测试平台包括:信号层,命令层,功能层,场景层。
信号层中,主要将待测设计和信号进行相连接。
命令层中,执行总线的读写命令的驱动器驱动了待测设计的输入,待测设计的输出和监视器相连,使用监视器检测信号的变化。断言也穿过命令层和信号层,负责监视独立的信号以寻找穿越整个命令的信号变化。
功能层中,代理(在VMM中称为事务处理器)接收到来自上层的事务,例如DMA读或者写,把它们分解成独立的命令。这些命令也被送往用于预测事务结果的计分板。检验器则负责比较来自监测器和计分板的命令。
场景层中,功能层中的代理被位于场景层中的发生器所驱动。场景就是操作步骤,比如一个手机要同时满足在接打电话的时候可以接收短信,下载游戏,接收应用消息等功能。这每一个功能都可以称为一个场景,每一个场景要实现都需要一定的步骤,比如启动那些设备,读写控制等。场景层就是负责组织协调这些步骤的。
将上述层级都包括,并且位于最高层的是测试层,完整的测试平台如下图:
测试包含了用于创建激励的约束。功能覆盖率可以衡量所有测试在满足验证计划要求方面的进展。随着各项测量标准的完成,功能覆盖率代码在整个项目过程中会经常变化。由于代码经常被修改,所以它不作为测试环境的组成部分。
Reference
- 路科验证西电课程PPT
- 《SystemVerilog验证-测试平台编写指南》
这篇关于SystemVerilog学习-01-系统验证概述的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!