在项目搭建和调试后仿环境时做了很多工作,因此希望总结一下使用VCS做芯片后仿的步骤和遇到的一些主要问题。芯片后仿真又可分为PR前仿真(综合后)和PR后仿真(布局布线后),本文记录Pre-PR仿真的部分。
PR前门仿采用的是RTL插入DFT后的综合网表,因此首先需要修改filelist,将原有top及各子模块RTL替换为综合后的网表文件,然后需要处理一些编译问题,主要有以下问题:
在仿真综合后网表时需要添加以下一些编译选项:
+nospecify 仿真时忽略specify路径延时
+notimingcheck 仿真时关闭时序检查
-add_seq_delay 0.01ns 设置或覆盖时序UDP(user-defined primitive)的延时,参数如无时间单位则采用timescale的时间单位
还有一些其他选项及其含义,这里不需要用到,仅作参考:
+delay_mode_zero 所有门和路径延时替换为0
+delay_mode_unit 忽略所有模块路径延时,并更改为`timescale的最小时间精度
+no_notifier 关掉时序检查产生不定态,时序检查任务不会改变notifier的值,避免标准单元输出不定态
+optconfigfile+ 自定义文件配置设计的一些时序控制属性,例如:
module {mod1}{noSpecify};
instance {mod1.mod2_inst.mod3_inst}{noIopath};
tree {mod1,mod2}{noTiming};
支持的属性包括:
noIopath Disables module path delays in the pecified module instances.
Iopath Enables module path delays in the specified module instances.
noSpecify Disables the specify blocks in the specified module instances.
Specify Enables specify blocks in the specified module instances.
noTiming Disables timing checks in the specified module instances.
Timing Enables timing checks in the specified module instances.
仿真时出现问题可以通过ctrl+C
进入UCLI命令交互模式进行调试,建议在编译时添加-debug_access+all
启用。这里整理了调试过程中比较有用的一些UCLI命令:
run 运行仿真直到遇到$stop或者设置的断点
run <time> 运行指定时间后停止
step 单步调试
scope 显示当前顶层
show 显示当前模块信息
restart 重新启动工具并停在0时刻
senv activeScope 显示synopsys环境项下的当前作用域
force <signal> 0 将信号值force为0
force -deposit <signal> 0 给信号值设置为0
release <signal> 释放对信号的force
<cmd> -h 查询cmd命令的帮助
由于UCLI命令本身是基于Tcl的,因此UCLI也可以执行一些Tcl脚本,例如初始化一些寄存器值,或者做一些loop调试,后面会介绍到。
综合后由于RTL替换为逻辑门,会有一些X态传递问题需要发现。部分X态问题可在RTL仿真时加入VCS编译选项 -xprop开启X-propagation功能调试,目前支持以下三种模式:
-xprop=vmerge,不定义-xprop的默认模式,典型的verilog行为,比较乐观;
-xprop=tmerge,仅定义-xprop的默认模式,更接近真实门级行为,在输出有多个可能的情况下为X态;
-xprop=xmerge,比门级仿真更悲观的一种行为,X态会无条件传播。
另外可以直接调用系统函数如 $set_x_prop("vmerge")
在case中选择指定的xprop模式;还可以用-xprop=
指定一个xprop配置文件,单独控制某些模块的xprop开关。
下面整理了一些可能出现X态问题的场景和仿真环境中的解决方法:
后仿相比前仿消耗的时间要多很多,编译和仿真时间都有明显增加,因此缩短后仿时间很有必要。
验证的时间成本有三个维度,仿真时间、CPU运行时间和真实世界的时间。在前仿中已经采用了一些手段以缩短仿真时间:改写一些参数化设计的模块参数(综合后参数会固化);force一些信号或计数器的值来跳过一些时间;软件配置一些时序控制寄存器等。CPU运行时间的优化一般依赖于验证环境,比如尽量控制线程开辟、优化循环、修改仿真选项、关闭波形dump、减少打印log、增量或单次编译等。真实时间可能要依靠一些手段以优化效率,如多服务器并行计算、作业管理优化、上硬件加速器等。
在后仿时可以根据需要选用以下方法以加快一些仿真速度:
除X态问题外,调试门仿时主要卡在了以下一些问题上,这里做一些记录。
loop_detect 1000
就是step 1000次并dump到loop.txt。根据保存的结果发现在lib中一些cell进入了loop,因此修改并添加了一些延时。#!usr/bin/tcsh
proc loop_detect {args} {
set help "-help"
if { [string equal $args $help ] != 1 } {
config followactivescope on
set i 0
while {$i < $args} {
run_step
incr i
}
} else {
puts "Usage: loop_detect "
}
}
proc run_step {} {
redirect -f loop.txt -a {set x [step]};
redirect -f loop.txt -a {set y [scope]};
puts $x;
puts $y;
}
ICG时序问题
一些IP在DC综合后自动生成了一些ICG (Integrated Clock Gating cell)。由于修改cell delay时给ICG也加了delay,导致delay后的上升沿没有采到D端。尝试修改了多次延时时间,仅在延时设为0时仿真波形才正确,否则就是有glitch或者采不到。这里0延时仅用于功能仿真,还是要参考PR网表引入门延时和布线延时后的实际情况。
DDR时序问题
在读DDR时读出了X态,定位到RAM口时序有问题,最后发现在DDR的模拟模型中通过specify块定义了路径延时,而在后仿中定义了-nospecify
(lib中给每个cell都定义了0延时的specify块,无nospecify会导致进0延时loop)。这里尝试了几种方法:修改DDRC时序寄存器配置,未成功;不定义-nospecify
,尝试用+optconfigfile+
指定cell为noSpecify
,未成功;定义-nospecify
,并将dlygen模型中的specify延时改为rtl内定延时表述,可以解决。在DDR中也发现了其他X态问题,并在前仿中通过xporp仿真复现。因此建议在后仿前先用xprop清理一下X态问题。