验证开始的第一步,创建整个验证平台的目录
前言
如果要使用uvm的话首先需要导入uvm标准库,可以直接去官网下载最新版本的库
一、创建脚本
首先需要编写一个生成目录的bash脚本。通常的验证平台有以下几个目录(指的是单纯的文件目录,不是testbench框架):
1、bin,存放dump波形的tcl仿真脚本
2、cfg,存放顶层top文件,以及整个验证平台的文件目录.f文件
3、rtl,存放所有rtl代码
4、sim,仿真目录,存放makefile,波形文件,log文件,各种运行脚本等
5、tc,存放testcase,一些跑仿真的cfg等(我个人习惯把sequence也放在这里)
6、ver,存放验证平台代码
dir_gen.sh代码如下:
#!/bin/csh -f
mkdir $1
cd $1
mkdir sim
mkdir cfg
mkdir rtl
mkdir ver
mkdir bin
mkdir tc
mkdir tc/cfg
touch ./ver/ver.f
touch ./rtl/dut.f
touch ./cfg/tb.f
touch ./tc/tc.f
touch ./tc/cfg/default.cfg
echo "-f ../rtl/dut.f" >> ./cfg/tb.f
echo "-f ../ver/ver.f" >> ./cfg/tb.f
echo "../cfg/top.sv" >> ./cfg/tb.f
cp /home/IC/uvm/Makefile sim/
cp /home/IC/uvm/regress.py sim/
cp /home/IC/uvm/get_cfg_name.sh sim/
cp /home/IC/uvm/dump_fsdb.tcl bin/
echo "Hello,how are you? Have a good day!"
解释:
(1)前两行的$1代表获取第一个参数,也就是运行脚本时所输入的名称
(2)接下来mkdir创建各个目录
(3)touch命令创建各个.f文件,以及一个默认的cfg文件
(4)cfg目录下的tb.f是整个验证平台的filelist,在其中写入其他几个filelist的路径,以及写入顶层文件top.sv
(5)接下来把makefile和两个脚本拷贝到sim目录下,两个脚本一个是回归测试脚本一个是获取cfg文件名称的脚本(也是回归测试中使用);把tcl仿真脚本拷贝到bin目录下
(6)最后可以写一些话送给自己,一定记得要好好吃饭😂
至此整个目录就创建好了
二、tcl脚本
dump_fsdb.tcl脚本内容基本都差不多,我同时还启用了断言
global env
fsdbDumpfile "$env(TC_FSDB_NAME).fsdb"
fsdbDumpvars 0 "top"
fsdbDumpSVA 0 "top"
fsdbDumpMDA
run
三、Makefile
makefile非常重要,所有仿真命令的执行都离不开它。
#seed := $shell date +%Y%m%d%H%M%S)
seed := $(shell date +%d%H%M%S)
#tc
cfg := default
TC_CFG_DIR := ../tc/tc_cfg/
tc := tc_sanity
LOG_DIR := log_dir
mode := normal
ifeq ($(mode),regress)
LOG_DIR := rgr_log_dir
endif
首先产生种子,使用时间格式。然后是testcase相关内容,常规测试和回归测试使用不同的log保存路径。这里 ":=" 表示的是直接赋值,即赋予当前位置的值。
RUN_NAME := $(tc)_$(cfg)_$(seed)
$(shell if [ ! -e $(LOG_DIR) ];then mkdir -p $(LOG_DIR); fi)
规定跑仿真的名称,如果没有LOG_DIR就新建一个,fi是shell中和if搭配的结尾。
#assert
assert := on
ASSERT_CMP_OPT :=
ASSERT_RUN_OPT :=
ifeq ($(assert),on)
ASSERT_CMP_OPT := +define+SVA+ASSERT_ON
ASSERT_RUN_OPT := +fsdb+sva_success
endif
断言的启动,前期不用的时候需要设置成off
#cov
cov := on
COV_CMP_OPT :=
COV_RUN_OPT :=
ifeq ($(cov),on)
COV_CMP_OPT := -cm tgl+branch+line+cond+fsm -cm_dir top_cov -cm_name $(RUN_NAME)
COV_RUN_OPT := -cm tgl+branch+line+cond+fsm -cm_dir top_cov -cm_name $(RUN_NAME)
endif
覆盖率的启动,前期要关掉,等整个testbench调试好了之后再采集覆盖率
#wave
wave := on
WAVE_RUN_OPT :=
FSDB_DIR := wave_dir
export TC_FSDB_NAME:=
$(shell if [ ! -e $(FSDB_DIR) ];then mkdir -p $(FSDB_DIR); fi)
ifeq ($(wave),on)
export TC_FSDB_NAME := $(FSDB_DIR)/$(RUN_NAME)
WAVE_RUN_OPT := -ucli -i ../bin/dump_fsdb.tcl +fsdb +autoflush
endif
波形的dump
FILE_LIST := -f ../cfg/tb.f
all:run result
#elab
cmp:
vcs -sverilog -full64 -debug_pp -fsdb -l ./$(LOG_DIR)/compile.log $(FILE_LIST)\
-timescale=1ns/1ns\
-ntb_opts uvm-1.1\
-kdb -lca $(ASSERT_CMP_OPT) $(COV_CMP_OPT)
run:ru result
ru:cmp
./simv -l ./$(LOG_DIR)/$(RUN_NAME).log\
-f $(TC_CFG_DIR)$(cfg).cfg \
+ntb_random_seed=$(seed)\
$(WAVE_RUN_OPT) $(ASSERT_RUN_OPT) $(COV_RUN_OPT)\
+UVM_TESTNAME=$(tc)\
+UVM_OBJECTION_TRACE
nrun:nru result
nru:
./simv -l ./$(LOG_DIR)/$(RUN_NAME).log\
-f $(TC_CFG_DIR)$(cfg).cfg \
+ntb_random_seed=$(seed)\
$(WAVE_RUN_OPT) $(ASSERT_RUN_OPT) $(COV_RUN_OPT)\
+UVM_TESTNAME=$(tc)
rung:cmp
./simv -gui -l run_log.log \
+ntb_random_seed=$(seed)
verdi:
verdi -sv $(FILE_LIST)
cov:
dve -full64 -cov -dir top_cov.vdb
urg:
urg -dir top_cov.vdb -report cov_report -format both
clean:
rm -rf AN.DB DVEfiles csrc simv.* *simv inter.vpd ucli.key novas* *.fsdb simv* verdiLog *.log ./$(LOG_DIR)/* ./$(FSDB_DIR)/* stack.info*
result:
$(call print_result)
define print_result
@echo "+-------------------------------------------------------+"
@echo "+ Compile log : ./$(LOG_DIR)/compile.log "
@echo "+ Simulation log : ./$(LOG_DIR)/$(RUN_NAME).log "
@echo "+-------------------------------------------------------+"
@echo ""
endef
各种编译执行命令,指定总的filelist是cfg目录下的tb.f。其中有几点:
(1)cmp中需要加入uvm-1.1命令
(2)规定timescale
(3)我使用urg这个命令打印出覆盖率报告
(4)定义了一个打印结果函数,可以直接显示log名称方便打开
总结
至此,基本的验证平台目录就完成了,下一步就是搭建整个testbench的框架。