静态形式验证工具有很多,主要用于模型检查和等价性检查两个方面。S家 vc formal验证平台主要用于模型检查(只有两个应用嵌入了等价性检查功能),S家formality主要用于等价性检查。本文基于S家 vc formal用户手册整理静态形式验证在DFV中的应用。
Note:受软硬件的限制,目前还是推荐在block level使用formal。soc级的设计规模和复杂度有可能导致验证难以收敛。
应用
AEP
Automatically Extracted Properties 应用会自动从设计中提取properties并且验证这些properties,有点像lint 检查。AEP会做以下的检查:
- 数组边界检查
- 算术溢出
- X态检查
- 同步置位/复位检查
- full_case/parallel_case检查
- 多驱动检查
- 无驱动输入
- 状态机死机
FCA
Formal Coverage Analyzer用于分析unreachable properties以减轻coverage收敛的工作。
从项目周期来看,FCA存在4个阶段:
- 代码设计期(block级别):用于发现dead code,只有rtl输入。
- 仿真回归期(block/chip级别):用于产生exclude文件,输入为rtl+vdb
- 增量回归期(block/chip级别):输入rtl+vdb+el
- 收敛期(block/chip级别):同上,主要是用于更新el(由于rtl的delta change)
set_app_var fml_mode_on true
set_fml_appmode COV
set_fml_var fml_enable_assume_proof true
set_app_var fml_cov_tgl_input_port true
set_fml_var fml_cov_tgl_undriven_as_unr true
set_fml_var fml_cov_gen_trace on
set_fml_var fml_cov_enable_branch_cov true
set_fml_var fml_reset_property_check true
set_fml_var fml_track_loc_reset true
set_app_var enable_cdc true
set_app_var enable_rdc true
read_covdb -cov_input <dbpath> -cov_dut <instance_path_to_topmodule>
#默认情况下vcs 不会收集-v -y文件中module的coverage。
read_file -cov all -top <top_module_name> -vcs "-cm_libs vy <vcs_command_line>"
CC
Connecting Check用于连接性检查,输入支持csv格式和TCL命令。通常用于以下几个方面的连接性检查:
- SOC级输入/输出连接性检查
- Block级的mux/demux
- Macro的连接性和常值检查
- SCAN模式连接性和常值检查
- 复位和全局信号的连接性
- 用于debug的寄存器通路
- 可配置的互联验证
每个CC检查项包含以下9个属性,在csv中通过“,”分隔。
- name:以字母开头的字符串
- src:信号源
- dest:目标信号
- enable_expr:用于使能连接的组合逻辑表达式,1表示使能
- path_delay:延迟值或者一个范围(min,max),默认为0
- enable_hold:信号源需要保持的cycle个数。
- enable_delay:相对于信号源来说,使能的延迟,为负值或者0
- offset_delay:复位释放后,延迟offse_delay开始检查cc
- clock:默认使用create_clock定义的时钟。
每个cc检查项一般放在csv表格文件中,可以通过load_cc来加载该文件。也可直接在tcl中通过add_cc添加检查项。可通过设置 csv_comment_pattern参数来指定comment marker(默认为//)
CC可以统计连接性coverage。compute_cc_cov 用于配置连接性coverage。-par_task parTaskName 用于选择前置任务,一般parTaskName=CC; -endpoint 只会统计source和destination的toggle;-net 会统计 proven property中path上的所有net;-structure会直接将proven property的toggle结果直接映射到coverage database而不进行coverage分析。
# default format is csv
load_cc -format <csv|table> -filename <file_name>
#设置9个属性的顺序,默认值
load_cc_set_param <param-name> "%<value>%"
#简化长path,多次设置同一个alias,后者会覆盖前者
set_cc_alias xx aa.bb.cc
report_cc_alias
delete_cc_alias
#检查两个信号之间是否有连接性
generate_cc -src xx -dest yy
#使能cc coverage统计功能
set_app_var fml_cc_coverage_analyzer true
compute_cc_cov
save_cc_cov_results
FRV
Formal Register Verification可自动为设计中的寄存器创建各种访问模式的assertion。需要用户以IP-XACT,RALF或者CSV格式提供寄存器信息。和uvm_lib提供的寄存器测试目的一致。两者则其一即可。
SEQ
Sequential Equivalence Checking用于比较两个基于systemverilog语言可综合的设计的功能一致性(基于cycle级)。
#设置模式
set_fml_appmode SEQ
analyze -format verilog -library spec <spec_design_file_list>
analyze -format verilog -library impl <impl_design_file_list>
elaborate_seq -spectop <spec_design_top> -impltop<impl_design_top>
FPV
Formal Property Verification用于验证用户自定义的property。这些property主要分为3种:
- 用于检查功能的assertion
- 用于约束激励的assume
- 用于覆盖特殊功能点的coverage property
FTA
Formal Testbench Analyzer用于分析验证bench的质量。原理:通过在设计中注错,来检查bench是否能够检查出错误。有点类似certitude。
AIP
AIP会提高验证效率。具体测试数据。
DPV
Data Path Verification,对于一些通用设计单元:浮点/整数加法器、乘法器、除法器等,DPV将设计和高级抽象模型(通常是c或者c++模型)进行比较。
FSV
&Formal Security Verification用于验证安全数据不可到达非安全区。典型场景:
- data leakage:数据泄漏
- data integrity:数据完整性
#创建安全检查
fsv_generate -src s_in -dest n_neg -exclude {encrypt}//验证src_in不可以直接到达n_neg,必须经过encrypt
fsv_generate -src in1 -src_condition sel1 -dest out1 -dest_condition sel2//验证in1不可以到达out1
FXP
Formal X-propagation用于检查X态。
Function Safety
用于检查安全隐患发生概率以及不同等级的安全隐患是否可控。车载安全认证ISO 26262定义了一套安全认证机制。S家ZOIX工具可以进行错误注错仿真并提供设计的诊断覆盖率(diagnostic coverage)。
命令
vcf 启动
#查找vcf支持的option
vcf -help
#启动图形界面
vcf -verdi
#执行脚本
vcf -f xxx.tcl
查看某个属性设置的默认值,配置属性。
printvar fml_*
report_app_var fml_*
#查看某个特定的属性
report_app_var fml_composite_trace -verbose
#推荐使用的属性设置
set_fml_var fml_enable_initial_blocks true
#当设计中有multiple process assignment(比如双端口memory或者双沿驱动逻辑)
set_fml_var fml_enable_ndmerge true
#改变message等级
set_message_severity -names <message_names> <error|warning|info>
#设置error的行为
set_message_error_action [-stop_at_error_count error_count] <stop|continue>
#设置打印阈值。(info<warning<error<fatal)
set_app_var msg_print_threshold waring
设置应用
#vcf启动时指定
vcf -fmode <FPV|COV|SEQ|CC|AEP|FRV|FTA>
#通过tcl命令设置
set_fml_appmode <FPV|COV|SEQ|CC|AEP|FRV|FTA>
&emspl;设置blackbox
set_blackbox
[-level <N>]
[-exclude <design>]
[-cells <cell>]
[-designs <design>]
#eg
set_blackbox -design {moduleA moduleB}
#报告出empty/blackbox/undefined modules
report_link
读入设计,编译设计。
#systemverilog +sva
##method1
read_file -format sverilog -sva -top <top_module_name> -vcs "a.v b.sv c.sva"
##method2
analyze -format sverilog -vcs "a.v b.sv c.sva"
elaborate <top_module_name> -sva
#混合语言(verilog top)
analyze -format vhdl a.vhd
analyze -format sverilog "c.sva b.sv"
elaborate <top_module_name> -sva -vcs "-lca"
#混合语言(vhdl top)
analyze -format vhdl a.vhd
analyze -format sverilog "c.sva b.sv"
elaborate <top_module_name> -sva -vcs "-lca -sva_bind_enable bind_file"
#使用sva lib,vc formal 支持OVL & VCS sva_cg lib
set SVA_LIB [getenv VC_STATIC_HOME]
read_file -format verilog -sva -vcs "-y $SVA_LIB/vcs-mx/packages/sva_cg +libext+.sv +incdir+$SVA_LIB/vcs-mx/packages/sva_cg +define+ASSERT_ON"
在读入设计之后,推荐使用get_attribute [get_fvtask] raw_signals来报出rtl中blocking语法问题。
设置时钟,工具会使用两个时钟:
- 参考时钟:如果设计只有一个时钟,则工具会将该时钟作为后续工作的参考时钟;如果有多个时钟,工具会挑选最快的时钟作为参考时钟;用户也可以显性设置参考时钟。
- 系统时钟:系统时钟至少是参考时钟的2倍频。
create_clock clk_mux -name "clk0" -period 20 -add
create_clock clk_mux -name "clk1" -period 40 -add
create_generated_clock clk3_from_clk0 -source clk_mux -master_clock "clk0" clk3 -add
create_generated_clock clk3_from_clk1 -source clk_mux -master_clock "clk1" clk3 -add
#设置参考时钟
create_clock clk400 -period 400 -refclk
#报告已经设置的时钟
get_clocks
设置复位,一个create_reset命令等效于sim_force_reset_active_value+set_constant reset_inactive_value
create_reset
[-sync]
[-async]
[-type reset|set|load]
[-name <rst_name>]
[-sense low|high|any]
[-source <master_pin>]
#eg
create_reset rst_n -low -async
foreach_in_collection rst [get_instance -of_module reset_sync] {
set async_rst [get_attribute ${rst} full_name]
set rst_name ${async_rst}.rst_n_sync
create_reset ${rst_name} -low -async
}
foreach_in_collection rst [get_ports "po_reset_n*_i"] {
create_reset $rst -low -async
}
设置初始状态(initial state)
#设置一些信号值为0/1/x/z
sim_set_state
[-unint_script <file_name>] #报告出未初始化的信号
[-apply <logic_value>]
[-regexp]
[-all]
[-uninitialized]
#force release
sim_force
sim_release
#设置常值
set_constant
[-value <constant>]
[-name <constraint_name>]
[-of_objects object_list]
#获取信号的初始值
get_sequentials #获取信号名
sim_get <signal_name>
#时序约束
fvassume -expr {state=2'b0} -depth 3 #复位之后state在前3个参考时钟保持为0。
#设置信号复位状态为1,仿真状态为0
set_constant scan_en -apply 0
sim_force scan_en -apply 1
or
sim_force scan_en -apply 1
sim_run
sim_save_reset
fvassume scan_en0 -expr{scan==0}
#信号为常值
fvassume -stable -expr{a}
#输入信号A=!B
fvassume -expr {A&!(B)}
检查setup,一般来说,如果check_fv_setup运行时间很长,则很大可能是setup有问题。
check_fv_setup
[-block]#首次不推荐使用
[-stop]
[-break <falsification>]
#报告存在的setup问题
report_fv_setup -list
#设置整个property check的最大时间,单位为H/M
set_fml_var fml_max_time 3H
#设置一个property check的最大时间
set_fml_var fml_progress_time_limit 5M
#自动保存session
set_app_var fml_auto_save true
#使能从上次的断点继续执行
set_fml_var fml_enable_resume true
任务分配
vc formal支持LSF/SGE来分配tasks 至各个工作点并行工作以提高效率。
set_grid_usage -type [LSF|SGE|RTDA]=<#_of_worker> -control {submission_cmd/opt}
收敛计策
当设计中有一些复杂的算法或场景时,工具会hang 死,为了避免这样的情况发生,可以通过以下方式降低复杂度,加速收敛。
- set_abstractions :自动将复杂的设计替换成简单的抽象级别更高的模型。默认提供的抽象模型是去除复杂的部分,替换成一个变量。
- 将大设计拆分成小设计,goals数量最好不要超过50K以内。
- 对golden ip设置成blackbox
#将某些结构抽象化
set_abstractions -construct {mult=8 div=8 add=8 sub=8 mod=8 count=8 array=8 vector=8 array_comb=32 vector_comb=32}
#移除抽象模型
set_abstraction -construct {mult=8} -remove
#给counter抽象化
set_abstractions -construct count=3 -using keyvals+{1,3,9,12} //将位宽>=3的counter抽象化成默认值为keyval
#给特定的counter抽象化
set_abstractions -construct count=3 -using keyvals+{2-11}+linearize -filter {name==top.count1.counter1}