1 引 言
1. 1 背景
TURBO51的工程背景是TURBO51嵌入式微处理器结构设计上采取经时间考验过的32位机主流系统结构, 在严格保证对8051 指令集兼容的前提下, 通过重新定义其处理器核的系统结构来挖掘处理器结构上的并行性实现。在传统8051软件开发环境下实现本要由更高位宽的32位处理器来完成的工作并完全重 用所有现有软件资源。在 8051指令级多种寻址方式混合且指令不定长的现实下实现了高性能的体系结构, 乱序发射, 分支预测, 精确例外处理, 基于猜测的先行预取, 片上一级指令高速缓存。处理器系统结构的复杂给验证提出了很高的要求。而且, 由于TURBO51 是作为SoC 的嵌入式处理器核, 是整个大规模SOC 的控制核心和用户接口, 如果嵌入式处理器设计中验证不完善或性能达不到设计要求, 都会导致整个SoC 项目的开发致命失败, 因此对嵌入式处理器的验证在SoC 设计中是最重要的部分之一。
一切对高性能体系结构的追求都必须首先建立在以设计的正确性为前题才是有意义的。TURBO51的验证面临三个主要挑战:
( 1)正确性, 所采用的高性能体系结构也是复杂和高风险的, 只有设计正确才会带给SoC 性能上的提升。
( 2)兼容性: 相对于传统8051, 在程序的执行过程中, 中断和异常常会打断程序的执行, 动态流水线的处理器由于指令的动态乱序执行, 但又必须对外部程序来说是和完全顺序执行只存在速度的差别而非结果的差别, 所以它必须能精确地与顺序执行条件下的例外结果保持一致。
( 3)指令和操作数空间巨大, 寻址方式复杂:
8051指令集共有111条指令, 有多种寻址方式和不定的指令长度。另外, 8051指令集还将输入输出设备寄存器与体系结构寄存器作为同种寄存器访问。
这些都成为了结构设计和验证中的难点问题。
( 4)验证充分性的衡量: 在验证过程中根据发现错误的性质、原因和数量分布, 评估正确性程度和调整下面的验证计划, 使验证更深入, 实现设计错误的快速收敛。
1. 2 微处理器验证现状
目前世界各处理器公司用于功能验证的方式主要是模拟验证, 形式验证, 硬件仿真加速。但总的看来, 由于指令集庞大, 比如, 它的完全无错的测试向量的数量是指令条数阶乘及每个操作数, 地址数阶乘。在有限的时间很难实现。除非指令和操作数的所有两两组合都已测试过, 否则, 即便经过了这些验证, 也只能证明在测试已覆盖地方正确而不能证明设计在任何情况下都正确。
形式验证是指通过数学方法证明设计的完备性, 即这种方法下的样本空间是测试对象所有可能的状态。A rithSMV, * PHDD。由于状态样本空间巨大, 它只用设计属性检查工具, 目前仅用于局部逻缉验证。
模拟验证: 包括RTL仿真和门级仿真。这一阶段验证的效果很大程度上由测试激励和判定模拟结果的方法决定。在微处理器验证中, 采用汇编语言编写测试激励, 运行操作系统, 应用程序和随机生成测试向量。
硬件加速仿真: 为克服模拟仿真验证速度慢的缺点, 采用FPGA 的物理原型验证可以在流片前运行操作系统和应用程序, 进一步在系统级验证正确性。
2 TURBO51的验证方法
TURBO51在设计中用到了形式验证、模拟仿真和硬件加速仿真。采用自底向上的子模块级验证再自顶向下的宏模块及系统级验证的方法。在整个设计过 程中, 验证与设计是一个整体, TURBO51在进行文档时序设计时就同时开始针对正在进行的设计编写验证计划, 设计和验证的工作在设计文档和验证计划中进行精确到每个时钟周期的行为描述和变量定义开始, 是整个设计和验证最重要的部分。由于TURBO51的设计要保证对传统8051指令集的后向兼容, TURBO51采用两台可进行单步调试的8051硬件仿真器, 两片传统8051, 两片采用了简单流水结构的改进版8051 作为正确标尺。测试激励在此先逐一运行, 并将其运行结果作为界定执行正确和兼容正确的标准。每个模块在每个时钟周期的每个寄存器读写和各个设计阶段的验证方法, 验证结果,问题分布, 验证策略在此规定, 并手工编写测试程序进行仿真。在验证文档中记录如何判定设计正确的与严重设计漏洞及原因, 并在设计文档中记录哪些临界态已考虑过了, 为以后怀疑某种情况下有没有可能是此出错提供重要依据。在TURBO51的设计中覆盖率指标在文档阶段已经引入, 每个设计了的逻辑一定要用测试来证明有必要这样设计和功能正确。功能设计中每个条件判断总能在测试文档中找到测这个条件的方法及判对标准。很多时候在写测 试方法时发现了很多设计中没有考虑过的情况。功能设计文档和以覆盖率为指导的验证文档相互作用, 使TURBO51在开始RTL之前就己经完成了时序设计, 寄存器定义及全部块级测试的完全覆盖, 比如在寄存器重命名中多种寻地方式下对同一物理地址写入的重命名, 乱序发射, 精确例外。一般说来,越是文档级描述的错误越容易修改, 越是硬件级的错误越难于发现, 修改量很大且容易引入其他错误。
这个阶段可以较容易用排列组合等进行形式验证进行完全的情况覆盖, 排除了绝大部分严重错误, 而且用于仿真的手工编写的测试程序也用于此后的验证中。RTL不过是文档的一个V erilog 描述的翻译过程, 因此RTL并不是TURBO51设计最重要的地方,只是要按功能设计文档和代码检查的要求可很快完成, 但期间要用综合结果指导对流水线负载平衡并在细节上进一步调整, 但每一处与原功能设计文档描述不同的RTL修改首先是修改功能及验证文档,再次审核通过后才能改动RTL 代码。仿真和RTL编写是一体的, 在Turbo51 验证中分为模块、宏模块、系统级3个阶段。只有在一个阶段的设计和验证及文档完全达到计划要求, 即代码检查和代码覆盖率后才能再开始下一阶段工作, 这样使得错误得以快速收敛。这期间把错误分为高风险区错误和低风险区错误。出现不正常时首先从影响程序运行走向的高风险区开始排查, 排除高风险区的错误后再去找低风险区错误。模块级RTL 模拟仿真完成后就是宏模块级, 指令流水线, LOAD /STORE, Cache等, 再下来是系统级RTL 仿真。在Turbo51 的设计验证中, 只有在TURBO51 整个的RTL代码规范检验代码覆盖率达到RTL模拟仿真对覆盖率的要求并通过设计描述文档与验证文档相结合的审议通过后才可以再进行FPGA 验证。所以TURBO51设计验证的底线是在FPGA 硬件原形验证前至少排除全部会引起死机或兼容性的这类严重错误。TURBO51的设计验证不是依赖下一阶段测试发现本应在上个阶段发现并解决的错误, 而是只用下阶段确认上阶段目标的完成。FPGA 验证的目的是用于测试长时间在真实环境下运行应用程序, 因为毕竟很多对外部信号的响应不易在RTL 仿真中模拟, 而不是用来发现调试应在仿真中排除的问题。
3 形式验证
形式验证的好处是它能遍历全部状态空间, 可以实现验证的完备。它在设计行为描述规格书中就开始使用, 用于高风险区的存贮访问, 高速缓存, 分支预测, 动态执行, 例外处理中最高风险组合的完备性证明。比如在TURBO51 的片内一级指令高速缓存的替换策略设计时, 必须要处理每个可能的状态,吞则可能会出现状态机死锁。在这里首先就是对是否有且仅有的几种状态进行数学证明, 然后再开始编写功能行为描述和验证计划。这种方式可以使出错影响大但状态空间不大的逻辑达到完全正确, 而且后来的事实也证明, 通过形式的设计在此后的所有测试激励下没有出现异常。
形式验证在TURBO51 验证中的另一个地方是在进行RTL代码风格检查的时候用形式验证工具对修改前后的RTL进行功能比较, 另外类似的做法也用于物理网表与前端网表的等价性比较。
4 RTL模拟仿真和覆盖率及代码风格检查
4. 1 RTL仿真
在功能时序文档和制定RTL 模拟仿真计划时,RTL编写和模拟仿真在每个子模块, 宏模块, 系统级设计功能行为描述和验证计划完成后才开始, 每个子模块RTL编码完成后放入用行为级描述的模型进行仿真, 再用EDA 工具提供的代码检查工具作RTL代码检查, 再仿真直到达到代码覆盖率, 然后层层向上做宏模块和系统级的RTL 代码检查和基于代码覆盖率的仿真。验证的主要排错和测试在这个阶段进行, 包括检查是否与8051标准完全兼容的验证, 高风险区的验证和运行操作系统及应用程序。
这里面使用了两个标准, 即由EDA工具给出的测试激励对已设计逻辑的代码覆盖率和自己定义的临界功能覆盖率。
在模拟仿真中, 对临界指令组合采用手工汇编语言编写激励。在兼容性测试中, 包括指令集测试,位寻址空间遍历, 上电测值测试, 寄存器文件读写遍历, LS变量RAM 遍历, 代码空间分页切换, 中断控制, 8051标准外设, 定计, IO, 扩展外设验证, SOC 总线读写, PWM 脉宽调制, 在线程序烧入, 基础应用:
软件I2C读写, 从外部读取64KB 数据和系统测试,基于操作系统的遥控按键解码和对片上其它器件的参数读取。在此期间使用闪存的仿真模型, 对于指令集测试, 在现有商用软件开发环境下创建测试激励, 对全部111条指令, 按 标准8051手册上对每条指令的执行结果值, 按分支目标, 分支方向, 对标识位的影响这几个方面进行测试。先在基准平台上进行单步运行, 记下每条指令的每种状态值, 再将这些值作为正确依据, 执行完一项比较一项结果, 如相同就继续向前, 同时一条IO 输出一个方波, 如不同则进入本条指令结果, 标记, 分支的死循环, 通过查这个死循环地址便可快速定位是错在哪条指令的什么地方, 同时另一IO输出另一种方波。此程序先在基准平台运行通过, 不进死循环, 再把它转成数据文件导入仿真模型。寄存器文件读写也是依据8051手册, 区分不同寻址方式对应的寄存器文件。在测试结果中, 最重要的一个观测点是指令提交地址寄存器, 它记录了真正的处理器运行走向, 只要它未出现异常, 这个测试项就认为无严重错误。RTL模拟在TURBO51中分为测试激励生成, 结果检测和覆盖率分析三个部分。TURBO51采用了手工编写临界条件和基础测试程序, 通过后再运行实际应用程序和操作系统。此阶段完成的标准是对代码和功能覆盖率的检查。在模块级RTL的编写过程中一边对代码风格和仿真测试覆盖率进行检 查, 同时进行综合以测试关键路径对设计时序的满足。作为辅助验证, 自动指令生成指令库, 指令生成控制器生成的测试激励同时也在一个行为级8051指令集模拟器仿真模型中一起运行, 逐条进行结果比较, 当发现结果不一致时对指令进行记录, 当发现分支不一致时仿真停止或仿真量到达一定规模时也停止仿真, 供查看代码覆盖率用。
4. 2 覆盖率和代码风格检查
基于模拟仿真的验证的困难是无论采用的测试激励是来自真实应用还是指令自动生成, 都无法证明整个处理器不出错。因此TURBO51仿真验证的完成标准是在错误收敛了的情况下增加更多的测试向量, 使EDA 工具提供的设计逻辑覆盖率达到块级100%和表达式级93% , 功能覆盖率达到100% 。
功能覆盖率的测试是设计规格书中定义的全部行为和验证计划的全部临界点。在进行覆盖率检查的过程中, 可以得出目前的总覆盖率和对一个模块中某个状态未被测试向量覆盖的逻缉和输入值, 它指明了漏洞存在, 指导手工编写直接针对未覆盖逻缉的测试。另外代码覆盖在TURBO51的设计中也被用于排除冗余或重复的逻辑, 节省不必要的关键路径开销和逻辑资源。代码检查: 代码检查使用EDA 工具所提供的功能。使代码在综合中不会产生异常, 使模拟仿真的结果与FPGA 不一致。在这里用形式验证工具对修改后和修改前的代码进行等价性比较。表1是各大模块的RTL 仿真代码覆盖率, 表2是主要模块在不同测试激励下的代码块覆盖率和表达式覆盖率。均由Cadence Incisive 给出。
表1 主要模块代码测式覆概率。
表2 主要模块在不同的测试激励下的覆盖率
5 物理原型验证
物理原型验证是AS IC 设计中通常采用的另一种重要的验证手段。它是将RTL 描述通过针对FPGA目标器件的综合及优化, 布局布线及优化并同时进行了静态时序分析后形成ASIC 设计的另一种物理实现形式。它能比RTL 模拟仿真更接近真实的AS IC, 能在系统板上在功能上完全取代ASIC 进行工作, 但最高速度一般比ASIC 慢一半以上。在这些都完成并通过了设计描述文档和验证文档的审核后进行FPGA 硬件加速仿真, 完全在系统应用环境下检验兼容性及正确性并做出初步性能*测。相对于仿真而言, 它能在提高系统运行速度上提高几个数量级。
TURBO51的FPGA 验证的前提是设计已经过了关键点的形式验证, 完成了块覆盖率为100% 的RTL仿真及代码检查且错误已收敛完毕, 故对FPGA验证的首要目的是通过运行和真实应用环境完全相同的完整目标应用系统验证两步的错误估计是否正确并配合其他SOC 模块作SOC 协同验证。因为对有的仿真做起来不方便的系统验证在FPGA 平台上很方便验证。在TURBO51的FPGA 验证中, 充分利用了FPGA 上的剩余资源, 用于实时定位与监测TURBO51的FPGA 实现版每个时钟的状态及其运行状态, 这其实已使原本认为FPGA 上难于定位错误的缺陷大为改观, 在真实环境下运行系统提供了非常接近RTL仿真的调试能力的观测窗口。这里依然首先选用了指令提交地址和指令取指地址,累加器, B 寄存器, 程序状态字PSW, 重定序缓冲状态, 例外处理标识, 写回总线, 提交总线位为主要观察点, 显示每个时钟的状态, 将它们协同SOC 其它模块的输出, 示波器观测输出波形结果一起形成FPGA 验证结果。TURBO51在FPGA 验证时工作在60MH z, 除运行全部手工编写的用于模拟仿真的测试程序外, 还成功连续两百小时运行全部现有量产的基于RTOS商用系统及其极限条件, 没有发现严重错误。通过对寄存器值的实时监测发现十处以内的外设非致命错, 比如GPIO 与外设输入输出复用。
当然, 每改一次RTL或监视寄存器都需要重新进行FPGA 烧写文件的生成, TURBO51耗时近两小时, 故它仍然不可能取代仿真。完成FPGA 验证后做准备流片的工厂提供的工艺标准单元库综合及静态时序分析, 交出网表做后端布局布线, 完成后再用带门延时的后端门级网表进行门级仿真, 最后编写样片基台测试程序。
6 验证结果分析
由于最初在制定实现的方法和制定验证计划时是同步进行的, 致使整个设计阶段的错误累积。在TURBO51的设计和验证中, 首先用形式验证将最高风险的存贮访问, 高速缓存, 分支预测, 动态执行, 例外处理中的最高风险组合进行完备证明, 使错误得以排除。在此后的验证中, 凡经形式验证正确的部分再未出现过异常, 如图1所示。
图1 错误时间累计统计。
这样使得全部的高风险错误在RTL仿真的中期已经全部排除并且大多数都由手工编写的测试激励完成。由于8051指令集指令死角空间相对较小,手工编写可行。其中大部分RTL 仿真发现的错是IO设备错误与处理器指令执行部分无关。如图2所示, 错误99. 7% 百分比在FPGA 验证前已收敛,故可认定前面工作扎实有效。假如一个设计如果在FPGA 验证阶段错误还未能收敛完, 还能发现大量新增错误尤其是严重错误的话, 这说明仿真及行为模型描述与验证计划都存在严重问题, 应退回去重走一遍, 否则流片风险较大。
图2 不同验证阶段发现的错误分布统计。
7 总结和未来工作
TURBO51嵌入式微处理器使用了上述多种验证方法使得越严重的错误得到了越早的收敛, 加上高的RTL代码覆盖率及长时间在FPGA 上成功运行了全部目标应用程序及所有仿真测试程序, 表明设计正确且兼容性完备, 使TURBO51嵌入式微处理器顺利采用富士通微电子(日本) 90nmCMOS 工艺一次流片成功。但另一方面, 可配置约束的自动随机指令序列已在更复杂的处理器验证中越来越广泛地采用, TURBO51的验证中在这一方面目前还处于初级阶段, 这将是以后的主要改进方向。