1 自动化验证平台简介
基于Google的OpenTitan框架搭建自动化UVM验证平台,具备从IP级到子系统级,NOC总线级和SOC系统级的验证垂直复用功能。它包括四个基本组件:dv_lib,env_tool,reg_tool和sim_tool。其中dv_lib是一套基于UVM框架的basic结构和通用函数集合;env_tool是基于python语言的验证平台生成器,可以生成uvm验证框架的大部分内容,同时还可以生成具有统一结构的agent模板;reg_tool是基于python语言的自动化寄存器模型测试平台,可以根据寄存器列表excel文件生成uvm register model验证相关的类和函数;sim_tool是基于pyton语言的仿真调度平台,可以支持多种模式的仿真和日志文件分析,同时支持多线程并发操作。
![](/images/dv-uvm-pioneer1/1.jpg)
自动化平台的主要结构如下:
common_lib:包含通用的库文件,目前集成的有dv_lib, amba_vip, assert_lib。同时,验证项目公用的agent也放在此目录下。
common_script:包含基于python的reg_tool, env_tool和sim_tool。
common_dpi:包含公用的reference model,一般都是基于C或C++语言开发。
ip_env:包含所有的IP验证环境,且各个IP的验证环境具有相同的结构。
sub_sys_env:多个IP环境集成复用成一个子系统验证环境,在IP验证环境中的agent会自动配置成passive模式,只做monitor侦听和scorboard比对。
soc_env:包含NOC总线验证环境和SOC验证环境。其中NOC验证环境会将总线上所有的amba master替换为amba vip,用来全面覆盖总线的功能和评估总线的性能;SOC验证环境会集成sub_sys_env和CPU,在芯片级做寄存器测试和上下电测试。
2 Common_Lib
Common_Lib 是整个环境的公共库,包含common_agent,common_if,dv_lib和dv_util。
2.1 Common_agent
所有项目需要用到的公共agent都放在这个文件夹下,该文件夹下的agent都需要使用env_tool下的脚本生成的模板来完善,这样在使用env_tool下的脚本生成验证环境的时候只需要指定agent的名称数量和模式就可以直接将agent集成到验证环境中
2.2 Common_if
环境中所有的时钟复位信号我们都通过clk_rst_if来产生。函数介绍:
set_freq_khz(int freq_khz):用于设置时钟频率,单位是khz,输入需要是整数。在uvm的环境中,一般是在basetest中调用此函数来配置时钟频率
set_freq_mhz(int freq_khz):用于设置时钟频率,单位是mhz,输入需要是整数。在uvm的环境中,一般是在basetest中调用此函数来配置时钟频率
set_active(), 用于设置驱动时钟和复位信号的选择器,如果不调用这个函数,虽然interface内部会产生时钟信号,但是interface输出的是高阻态
set_period_ps(int period_ps):用于设置时钟周期,单位是ps,输入需要是整数。在uvm的环境中,一般是在basetest中调用此函数来配置时钟频率
set_duty_cycle(int duty):用于设置时钟占空比,输入需要是整数(1-99)。在uvm的环境中,一般是在basetest中调用此函数来配置时钟占空比,默认值是50
apply_reset(), 用于产生reset信号,task默认参数调用用会产生异步复位,同步释放,复位信号持续时钟周期在50-100个cycle,该task在base_test的reset_phase中调用最终的时钟产生逻辑在最后的一个initial块中的forever循环中,通过延时和翻转时钟信号产生。
2.3 DV_Util功能
dv_macros.svh:验证环境中所有公共的宏定义都放在这个文件中,常用宏定义:
- get_clp_value_tmp(name) 用于配合yaml从命令行上解析参数,需要配合寄存器脚本一起使用。一般不手动增加
- get_clp_value(name) 用于给变量name从命令行上取值,类型是int型
- get_clp_string(name) 用于给变量name从命令行上取值,类型是string
- downcast(ext, base, msg) 用于cast,并报fatal消息
- DV_CHECK_RANDOMIZE_WITH_FATAL(var,constraint)
dv_test_status_pkg.svh:case最终状态打印的库,pass和fail
dv_report_server.sv:uvm_default_report_server的子类,增加了命令行控制uvm打印的格式,命令行传递show_file_line,show_file_path等可以控制打印格式
dv_utils_pkg.f:dv_utils的filelist,方便编译时添加
dv_utils_pkg.sv:公共的函数,类型,枚举变量
- if_mode_e: master slave
- clk_freq_mhz_e: ClkFreq24Mhz,…
- set_max_quit_count(int n) 设置多少个error退出仿真
- common_func_pool::gen_golden 从文件中产生golden数据
- common_func_pool::do_compare 做数据对比
str_utils_pkg.sv:字符串处理的函数,包括字符串查找,字符串截取,字符串替换等等
- str_has_sub_str(s,sub) 判断s中是否有sub
- str_find(s,sub) 返回sub在s中的第一个index,找不到返回-1
- str_rfind(s,sub) 返回sub在s中的最后一个index,找不到返回-1
- str_replace(s,sub,new_sub) 替换s中第一个sub为new_sub
- str_split(s,res[$],delim) 把s以分隔符delim分成多个字符串放入res中
- str_join(s[$], delim) 以delim作为分隔符把s中的所有字符串拼接
2.4 DV_Lib结构
dv_base_agent: 所有agent内部组件的例化连接
dv_base_agent_cfg: agent的配置文件 is_active和if_mode来控制agent的模式;
- is_active=0:agent作为monitor,只用于采样数据
- is_active=1,is_mode=master:agent作为master模式,用于发送数据给DUT
- is_active=1,is_mode=slave:agent作为slave模式,用于和DUT有数据交互的接口
dv_base_driver: main_phase中fork了两个进程reset_signals和get_and_drive。子类实现时需要重写这两个函数,用来复位和驱动
dv_base_monitor:子类需要重写collect_trans和watchdog_ok_to_end两个函数,collec_trans的主要作用是从接口上monitor数据,watch_dog_ok_to_end是agent的watchdog,用于监测agent接口上数据,从而判断agent是否在工作。这里给变量ok_to_end赋值为1,表示agent空闲,ok_to_end为0,表示agent在工作。同时需要调整cfg中的ok_to_end_delay_ns,这个变量的含义是,当ok_to_end等于1时,并且持续ok_to_end_delay_ns这么多ns的时间后ok_to_end仍然是1,才会drop_objection
dv_base_sequencer:mon2sqr_port,req_port和rsp_port的例化(后面两个port很少用到)
dv_base_env:所有组件的例化,从basetest中接受env_cfg,从top_tb中接收所有的时钟复位接口,并放入env_cfg的clk_rst_vifs关联数组中。同时根据base_test中的时钟配置配置所有时钟接口的时钟频率
dv_base_env_cfg:
- 各种环境配置和lantency配置
- 寄存器模型的句柄ral
- clk_rst_vif_names[$] 时钟复位接口名字的队列
- clk_rst_vifs[string] 关联数组,保存所有的时钟复位接口
- clk_freqs_mhz[string] 关联数组,保存所有接口的时钟频率(MHz)
- clk_freqs_khz[string] 关联数组,保存所有接口的时钟频率(KHz)
- clk_period_ps[string] 关联数组,保存所有接口的时钟周期(ps)
- 其他的函数基本都是用不到的
dv_base_ref_model:只有一个build_phase中判断cfg不为null的逻辑
dv_base_scoreboard:增加了如果出现uvm_fatal仍然会运行scoreboard的check_phase的逻辑
dv_base_virtual_sequencer:reset_phase中增加了stop_sequence的调用,防止phase跳转后出现错误
dv_base_test:env和cfg的创建,cfg中部分参数从命令行获取,end_of_elaboration_phase中通过命令行设置max_quit_count和超时时间。final_phase中打印case的最终仿真结果
dv_base_pkg:将所有的dv_base类打包到dv_base_pkg中
3 Env_Tool
Env_tool的主要功能有生成agent代码,ip_env环境代码,sub_sys_env环境代码以及soc_env环境代码
3.1 设计思想
- 脚本共用思想:将脚本中一些非公共部分以配置的形式放在sim目录下,使得所有环境都可以使用相同的dvsim.pl脚本来调度。
- Agent自动集成思想:Agent具有统一的命名规则,在环境中统一例化agent的名称、数量和工作模式,同时自动添加fifo,以连接到reference model和scoreboard。
- Filelist自动生成:自动生成各个部分的pkg和filelist,方便组织系统文件。
- Packeget自动导入:在各个xxx.pkg和top_tb.sv中根据需要自动导入其他class的包。
- 环境复用思想:在soc env中可自动化集成ip或者sub_sys的环境,实现底层环境在上层的垂直复用。
3.2 实现方式
Env_tool整体是基于Python3开发,使用第三方Mako库生成环境。Mako库是一个模板文件的渲染库,可以通过特定的语法替换模板中的变量,并且Mako模板特定块中也可以支持python语法。整个UVM环境的所有system verilog文件,packege文件,h头文件均具有一个基于Mako库的template文件。Python主程序根据系统参数来生成和配置template文件所需的变量,经过Mako库解析后,将所有template文件生成为实际的UVM框架文件。
Mako语法参考:link
Env_tool的python整体结构简明,包括gen_agent.py和gen_env.py,分别为产生agent的脚本和产生环境的脚本。
3.3 使用方法
在dv/common_script/env_tool/README中列举了env_tool的五种基本使用方式。
使用方式一:生成agent命令
1 | ./dvgen.py -a [agent_name] |
使用方式二:生成ip_env命令
1 | ./dvgen.py -e [env_name] -p [project_name] -ea [agent_name] [agent_number] [agent_mode] -has_cmodel -has_amba -uvm |
使用方式三:生成soc_env命令(sub_sys_env命令相同)
1 | ./dvgen.py -e [env_name] -p [project_name] |
4 Reg_Tool
Reg_Tool 是基于Python脚本的框架工具,集成了不同用途的子功能函数,可以基于统一描述格式的寄存器列表,产生UVM环境框架所需的寄存器模型测试相关文件和配置相关的依赖文件。Reg_Tool 名字中的前缀 “Reg” 代表本脚本所有功能皆围绕“ 寄存器 ”展开,帮助UVM平台搭建者自动完成的功能有:
寄存器模型生成。
寄存器Constraint生成。
寄存器Coverage生成。
寄存器CModel配置文件生成。
寄存器Yaml配置机制生成。
寄存器九步法检查寄存器读写。
寄存器Debug文件生成。
4.1 设计思想
Reg_Tool使用了面向对象编程OOP(Object Oriented Programming)的思想,把每个子功能视作一个对象,每个对象可以拥有各自的数据和处理方法,同时可以通过句柄索引其他对象实例的内容。
众多分离式子功能脚本共同使用到的寄存器变量和方法(Methods) 被放入到一个公共类中,方便统一调用。
如下图所示(link):通过在公共类建立统一的工作流程(Work Procedures),将所有子功能的步骤均包含在这个流程中,从而公共类每个步骤运行时都会调用所有子功能对象内部相应函数,从而协调所有子功能完成各自的工作。
![](/images/dv-uvm-pioneer1/2.jpg)
4.2 运行方式
- 准备好
${module_name}_boot_config.py
文件,
并放入{reg_tool_path}/code_gen_lib/boot_config
文件夹中 - python3.x环境
- 专用于excel读取的python第三方库:xlrd 1.1.0。已经集成在Reg_Tool中。
- 单独运行,包含3个参数,分别是:寄存器列表名称,模块名,寄存器列表sheet_name
1 | $ cd ${reg_tool_path} |
5 Sim_Tool
Sim_tool的主要功能有:调用reg_tool自动生成验证需要的寄存器模型,编译参考模型(cmodel)生成动态库,编译运行testcase,生成验证结果和覆盖率报告。
5.1 设计思想
Sim_Tool的宗旨是尽可能的依赖脚本实现自动化验证工作,避免需要手动修改进行测试验证。自动化验证应该覆盖寄存器模型的生成,参考模型的生成,编译原型case,验证报告的生成,覆盖率的生成,随机分布报告生成。sim_tool工具遵循以下几点规则:
- 用户可以通过cmd line完成测试的所有功能。
用户命令行交互方式使用的python 的argparse。argparse机制是Python内置的一个用于命令项选项与参数解析的模块,通过在程序中定义好我们需要的参数,然后 argparse将会从sys.argv中解析出那些参数。argparse 模块还会生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。同时,还支持命令行缩写。 - 对于跟用户或者项目相关的个性功能,用户能通过提供给用户的脚本定制。
工具使用的clean 功能,cmodelgen 等功能,都会调用用户目录下对应的脚本。用户可以修改工程下对应的脚本,指定具体的实现方法。比如说-cmodelgen选项,用户可以修改工程目录下的gen_so.sh,指定具体编译cmodel 的方法。 - 框架可扩展性高,后续增加新功能不需要修改基本框架。
5.2 使用方法
目前支持的参数有:
![](/images/dv-uvm-pioneer1/3.jpg)
1 | - help:打印帮助信息 |
5.3 测试与回归
- 指定测试对应的测试case:
comp 和run选项决定是否编译运行,如果不需要编译,只指定run选项即可。comp 和run选项必须选择一个以上选项。
1 | ./dvsim.py -yaml ../yaml/eis_test.yaml -test eis_test_num1_1_num2_1 -comp -run |
- 更新寄存器模型代码编译:
添加-reggen选项 :如果需要生成寄存器模型代码,或者更新寄存器模型代码,需要打开此选项
1 | ./dvsim.py -yaml ../yaml/eis_test.yaml -test eis_test_num1_1_num2_1 -comp -run -reggen |
- 更新cmodel库编译运行:
添加-cmodelgen编译运行:如果更新了cmodel,需要重新生成cmodel 的库文件,-cmodelgen选项会在编译运行之前编译cmodel 库文件。
1 | ./dvsim.py -yaml ../yaml/eis_test.yaml -test eis_test_num1_1_num2_1 -comp -run -reggen -cmodelgen |
- 指定随机种子测试:
添加-seed 选项:如果需要指定随机种子测试验证,使用-seed 选项,testbench 将使用seed 选项传入的随机种子。
1 | ./dvsim.py -yaml ../yaml/eis_test.yaml -test eis_test_num1_1_num2_1 -comp -run -reggen -cmodelgen -seed 123 |
- 回归测试yaml case:
使用-regress 选项:-regress 选项将回归测试yaml 的所有case。
1 | ./dvsim.py -yaml ../yaml/eis_test.yaml -regress -comp -run -reggen -cmodelgen |
- 多轮回归测试yaml case:
回归测试的时候,添加-round 选项,可以指定回归测试的次数,默认所有case的回归测试次数为1次。
1 | ./dvsim.py -yaml ../yaml/eis_test.yaml -regress -comp -run -reggen -cmodelgen -round 5 |
- regress 测试下自动提交jira bugs:
修改 jiraUserInfo.json
文件指定jira server地址,jira用户名,登陆密码等信息。-jira
选项可自动提交bug至jira系统
1 | ./dvsim.py -yaml ../yaml/eis_test.yaml -regress -comp -run -reggen -cmodelgen -jira |