一种高效率可重构的CPU验证平台
2021-12-02刘春锐张宏奎黄旭东陈振娇
刘春锐,张宏奎,黄旭东,陈振娇
(中科芯集成电路有限公司,江苏无锡214072)
1 引言
随着大规模集成电路技术的不断发展,数字集成电路的规模不断增大,功能不断增强,这给完备性验证带来了更大的挑战[1]。在CPU芯片的设计中,高效和完备的功能验证已成为CPU可靠性的重要依据[2],为了全面验证CPU的功能,验证工程师通常需要编写成千上万条验证用例[3],并且需要逐一运行测试并分析结果。据统计,验证时间通常占到处理器芯片研发流程的60%以上[4]。如果完全采用人工的方法分析和查错,验证效率极低,正确性难以保证,验证周期长且验证完成时间无法预估。因此,一个快速、完备、系统的功能验证平台对于CPU的设计来说至关重要,可有效缩短芯片设计周期并提高设计质量[5]。除此之外,由于CPU指令多,指令组合场景多,验证用例非常庞大,除了验证平台外,通过编写自动化脚本,批量构建用例和统计验证结果,对提高整个验证效率也是至关重要的[6]。本文提出了一种高效率可重构的CPU验证平台,可通过自动化脚本构建用例和统计结果,通过代码覆盖率标志验证结束。
2 验证平台结构
高效率可重构的CPU验证平台采用了模块化结构,具有更强的可重复使用性和可移植性,有效提高了验证效率,缩短了芯片验证周期[7]。不同指令集架构可以使用验证平台设计思路修改参考模型后即可重复使用。另外,该设计平台提供了自动调试功能,自动比较CPU执行指令的结果值和参考模型执行指令的结果值,为分析、调试和定位错误提供了有效的手段,可以大大提高设计迭代效率。CPU验证平台由验证用例生成模块、汇编器模块、CPU模块、参考模型模块、结果比较模块、参考模型监视模块、CPU监视模块、程序RAM和数据RAM构成,该验证平台可以实现从验证程序开发到验证结果查错的整个流程,其结构如图1所示。
图1 CPU验证平台结构
2.1 CPU模块
CPU模块是验证平台的验证主体,本文的CPU为基于TI指令集架构的某CPU微处理器,该CPU微处理器的特性如下:
1)哈佛结构;
2)8级流水线结构;
3)单发射顺序执行;
4)支持32 bit单精度浮点计算;
5)支持32 bit定点计算;
6)指令长度支持16 bit和32 bit两种。
2.2 验证用例生成模块
一般CPU的流水线结构包括取指、译码、访存、执行和写回等阶段,其中指令便是CPU的输入源。为验证CPU的功能,需要编写指令并将其加载到CPU的程序RAM,然后启动CPU,CPU读取程序RAM中的指令并运行指令,最后根据CPU的指令执行结果验证设计的正确性。
为完备验证CPU的功能,在开发CPU的验证用例前,需要分析CPU的特性,根据CPU的特性进一步将其分解成功能测试点,形成验证规格表,验证人员据此开发验证用例覆盖所有的测试点。由于CPU指令多,CPU相关流水线结构冲突和数据冲突场景多,验证用例数量庞大,所以大部分验证用例通过验证用例生成模块的自动化脚本批量生成,边界验证用例由人工编写生成。为全面覆盖CPU的功能,验证用例采用汇编代码编写,通过验证用例生成模块生成后缀为.asm的汇编验证用例。
验证用例生成模块主要由生成验证用例的Perl(Practical Extraction and Report Language)[8]脚本构成。为保证生成的汇编验证用例的正确性,在Perl脚本中将CPU的每条指令均单独构建子函数,每个子函数使用编号命名,子函数内部将该指令的限制用法单独编程。以UI16TOF32指令为例,其子函数Perl脚本如下:
将待验证的超过400条CPU指令分类并逐条编写Perl子函数,Perl主函数通过调用编号随机的Perl子函数实现各指令间的随机组合,并按照汇编格式生成汇编验证用例。
现有CPU验证平台的验证用例通常使用C语言或者高级语言随机生成,通过编译器编译后加载到CPU中进行验证。使用高级语言编写的验证用例由于编译器的优化,通常不能实现CPU内部资源的高效利用,从而不能覆盖到CPU数据相关冲突和流水线相关冲突的部分场景,造成CPU功能验证不全、功能覆盖率难收敛的情况。本文使用自动化Perl脚本直接构建汇编验证用例,而汇编验证用例会直接指定指令使用的CPU内部资源,从而可以覆盖到CPU数据相关冲突和流水线相关冲突的各种场景。这不仅提高了CPU验证的可靠性,而且由于无需使用编译器编译,提高了仿真效率,缩短了验证周期。
2.3 汇编器模块
汇编验证用例构建完成后,使用TI公司的CCS汇编器编译,通过格式转换器转换成Verilog代码能识别的存储器存储文件,该存储文件是后缀为.hex的程序机器码文件。格式转换器采用Perl语言编写,可生成多种Verilog能够识别的文件。
2.4 程序RAM
程序RAM内部通过Verilog的$readmemh系统函数读取后缀为.hex的存储器文件,存入程序RAM中,CPU模块通过存储器接口读取该程序RAM空间的程序数据。
2.5 数据RAM
数据RAM主要存储CPU流水线访存和回写的数据。
2.6 参考模型模块
参考模型模块是针对CPU模块提出的,参考模型模块和CPU模块是对产品特性的两个独立的实现,也就是说,参考模型模块功能上与CPU模块等价,但参考模型模块与CPU模块的设计不同,两者区别如下。
1)输入:参考模型模块的输入是汇编验证用例,而CPU模块的输入是存储在程序RAM中的经汇编器模块编译后的二进制指令码。
2)指令处理流程:参考模型模块逐行读取汇编验证用例中的指令,每条指令执行完成后才会继续读取下一条汇编指令,而CPU模块是基于流水线的设计,读取当前指令不需要上一条指令执行完成。
3)运算单元:参考模型使用SystemVerilog[9]语言完成指令的乘、加、移位等运算,其具有接口、断言、受约束的随机化激励等特点,能够大幅提高测试效率,且具有较高的功能测试覆盖率[10],而CPU模块的乘、加、移位等运算是基于电路的设计。
根据上述参考模型模块和CPU模块设计的主要区别,可以得出参考模型模块的设计思想:逐行读取汇编文件中的汇编指令,通过SystemVerilog字符串匹配技术完成汇编指令匹配,从而识别出汇编指令功能,然后实现指令功能。参考模型对指令的串行执行方式巧妙地验证了CPU模块的流水线相关冲突和数据相关冲突设计的正确性。同时,由于参考模型模块和CPU模块的运算单元设计不一致,CPU模块运算单元的正确性也可以得到验证。参考模型的设计流程如图2所示。
图2 参考模型模块设计流程
参考模型模块的设计流程描述如下:
1)参考模型模块使用Perl脚本读入验证用例生成模块产生的后缀为.asm的汇编验证用例,将汇编验证用例中的注释去掉,并在汇编验证用例中的每行指令结束位置添加行结束标志;
2)参考模型模块读入Perl脚本处理后的汇编验证用例,通过SystemVerilog的$feof系统任务判断该验证用例是否结束,当验证用例没有被读完时,转步骤3,否则参考模型模块的流程结束;
3)参考模型模块使用$fscanf系统任务按字符读取汇编验证用例,并存入指令字符数组中,然后通过步骤1添加的行结束标志判断该行指令是否结束,如果该行指令未结束,则重复步骤3,否则,跳转至步骤4;
4)参考模型模块读取指令字符数组,通过字符串匹配功能识别汇编指令的操作码和操作数,如MOV32 R0,R1,操作码是MOV32,目的操作数是寄存器R0,源操作数是寄存器R1;
5)参考模型模块根据步骤4识别出的指令功能和操作数执行该指令,如MOV32 R0,R1,将寄存器R1的值送到R0中,然后开始下一条指令的读取,跳转至步骤2。
参考模型模块对比验证CPU模块的方式为:将验证用例生成模块生成的同一验证用例送入参考模型模块和CPU模块,然后比较参考模型模块和CPU模块所有指令的执行结果,如果参考模型模块和CPU模块的行为不一致,或者CPU模块的功能实现出现错误,或者参考模型模块的功能实现出现错误,或者两者实现功能均出现错误,通过定位修改参考模型模块和CPU模块的错误。如果CPU模块和参考模型模块的行为一致,或者两者都对,这是希望的结果;或者两者犯同样的错误,那么需要想办法减小这种情况出现的可能性,比如参考模型模块的设计人员不能为CPU模块设计人员,或者引入第三方,例如VIP、FPGA[11]原型等。本文采用参考模型模块设计人员不为CPU模块设计人员的方法降低参考模型和CPU模块设计同时出错的可能性。
参考模型模块是该验证平台中最重要的组件,参考模型模块是保证功能验证正确性的核心[12],也是该验证平台实现高效率和重构优势的核心组件。现有CPU验证平台参考模型的设计基本分为两类,一类是使用编译器自带的由高级语言编写的软件参考模型,软件参考模型复杂难懂,某些软件参考模型的核心代码甚至是加密的,这增大了验证人员的调试难度。搭建基于软件参考模型的验证平台通常工作量大,人力投入高,且调试周期长。另一类是基于指令码匹配技术设计的参考模型,该类参考模型通常会遵照CPU流水线时序编写,其工作量与CPU设计工作量相当,人力投入和调试周期依然较长。本文通过SystemVerilog的字符串匹配技术串行识别汇编文件,无需严格按照流水线时序设计,参考模型的工作量大大减少,人力投入和周期均减少,不仅提高了CPU的验证效率,而且缩短了验证周期。
2.7 CPU监视模块
CPU监视模块主要完成CPU模块指令执行结果的监测功能,CPU模块通常的指令执行结果是修改CPU模块内部资源和数据RAM,CPU模块内部资源包括通用寄存器和辅助寄存器等,CPU监视模块主要将CPU模块对寄存器和数据RAM的执行结果打印到日志中。
2.8 参考模型监视模块
参考模型监视模块主要完成参考模型模块指令执行结果的监测功能,参考模型模块模拟CPU模块的行为,参考模型模块内部的通用寄存器、辅助寄存器和数据RAM资源也同样参照CPU模块定义,参考模型监视模块主要是将参考模型模块对寄存器和数据RAM的执行结果打印到日志中。
2.9 结果比较模块
结果比较模块通过对比CPU监视模块和参考模型监视模块提供的指令运行的打印结果,给出比较结果,帮助验证人员快速完成CPU验证结果的分析和判断。
3 验证流程
本文采用Synopsys公司的VCS作为仿真工具,为实现批量验证,编写了基于Perl的批处理程序,该程序可一次批量验证多个用例,并统计验证结果,生成验证报告。批量验证流程如图3所示。
图3 批量验证流程
批量验证流程描述如下:
1)通过验证用例生成模块批量生成验证用例,即后缀为.asm的汇编验证用例;
2)将汇编验证用例传入汇编器模块,跳转至第3步,将汇编验证用例传入参考模型模块,跳转至第6步;
3)汇编器模块将汇编验证用例编译成指令码之后,程序RAM将指令码读入RAM中;
4)CPU模块读取存在程序RAM中的指令码指令,并执行指令;
5)CPU的监视模块监测CPU模块的执行结果,并将CPU模块的执行结果输出;
6)参考模型模块读取验证用例生成模块产生的汇编指令,并执行指令;
7)参考模型监视模块监测参考模型模块的执行结果,并将参考模型模块的执行结果输出;
8)结果比较模块比较参考模型的监视模块和CPU监视模块的输出结果,如果结果一致,则输出该验证用例测试通过的信息,否则输出验证用例测试失败的信息;
9)重新开始下一个验证用例的仿真验证,依次循环直到所有的验证用例全部运行结束,批处理程序显示本次批量验证的统计信息,并输出验证用例通过或者失败的信息;
10)所有验证用例仿真均通过后,收集并合并验证用例覆盖率。
4 结果分析
运用该功能验证平台进行了32位CPU的验证。根据该CPU的特性,分别验证了5类共计1044条验证用例,验证结果均通过,验证结果如表1所示。
表1 验证结果
除此之外,为保证验证的充分性,对所有验证用例进行了代码覆盖率收集和合并。通过分析覆盖率,定向构造用例,提高验证的完备性。
本验证平台的代码覆盖率结果如下。
1)行覆盖率:CPU的行覆盖率为100%。
2)翻转覆盖率:CPU的翻转覆盖率为99.81%,覆盖率较低的原因是输入和输出数据信号的翻转覆盖率低,本文主要关注控制信号的翻转覆盖率,对不能达到100%的控制信号均进行了分析,确认是否是CPU不能进入的值,对于CPU可能会翻转的值,定向构造用例,进行覆盖。
3)条件覆盖率:CPU的条件覆盖率为83.17%,未覆盖的条件分支是设计中不会出现的分支。
4)状态机覆盖率:本文的DUT内部无状态机。
5)分支覆盖率:CPU的分支覆盖率为100%。
5 结束语
在CPU的设计中,高效和完备的功能验证已成为CPU是否可靠的重要参考依据,本文设计并实现了一种基于SystemVerilog的CPU验证平台,论述了验证平台的整体设计结构、实现流程和批量验证的实现方式。该验证平台有较好的通用性和可移植性,对于不同的指令集架构,稍加修改参考模型便可使用。该验证平台已成功应用于32位CPU芯片的功能验证,相比该CPU之前的验证方法,验证周期从预估的10个月缩短到3个月,大大提高了验证效率,缩短了CPU交付周期。另外,该设计平台可以通过参考模型模块和监视模块快速定位CPU的设计缺陷,缩短设计人员迭代开发的周期。