ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

makefile脚本常用知识点

makefile脚本常用知识点

1. 如何运行makefile脚本

makefile在当前目录:

b make

makefile不在当前目录:

b make ./script/makefile run64

2. makefile最核心的模版

目标: 依赖1 依赖2 依赖3 命令1 命令2 命令3

注意:命令前面必须是【Tab 制表符】,不能是空格

举个例子:

vcs64: compile_dep file_list @echo "start vcs compile" vcs -full64 +UVM_VERBOSITY=medium ...

执行顺序:先跑 compile_dep、file_list,全部完成,才执行 vcs 编译命令。

3. shell里面常用指令有哪些?

echo: 打印提示信息

echo "===== start VCS compile ====="

ls:列出目录里面的文件

ls $(tc_dir) ls *.v

cp:复制文件

cp rom.txt $(tc_dir)/

rm:删除

rm -rf $(tc_dir)/simv

pwd:打印当前所在路径

find:查找文件

#find 【搜索起点目录】 【匹配条件】 【动作】 find ./run_dir -name "sim.log" # 在 ./run_dir 下面找名字严格等于 sim.log 的文件 find . -name "tc*_log" # 找 tc开头、_log结尾的文件

grep:过滤、查找关键字(抓 ERROR、FATAL、PASS/FAIL)

grep "ERROR" sim.log grep -i fatal sim.log # -i 忽略大小写

date:获取时间、时间戳

date +%Y%m%d # 年月日

4. makefile内置函数$wilcard

ifeq (A, $(wildcard A)) cp A ./ endif

A是完整文件路径;

$(wildcard A):去看 A 这个文件有没有

5. 仿真常用指令

编译指令:vcs

运行仿真:执行 ./simv

-sverilog:开启 SystemVerilog(UVM 必须加)

-full64:64 位模式,现在项目标配

debug_all:全 debug,支持 Verdi 看波形

-f filelist.f:从 f 文件读取源码列表

+incdir+xxx:头文件 include 搜索路径

+define+XXX:宏定义

-cm line+cond+fsm+tgl:打开覆盖率收集

-l run.log:输出 log 文件

-top xxx(显式指定顶层)

# -timescale 全局时间精度,后仿/高速接口经常指定 vcs -timescale=1ns/1ps -f filelist.f # -cm 开启覆盖率(line cond fsm tgl branch)回归用 vcs -cm line+cond+fsm+tgl -cm_dir ./cov.vdb -f filelist.f # 指定随机种子,复现bug超级常用 ./simv +ntb_random_seed=12345 # 直接拉起verdi,仿真一边跑一边dump波形 ./simv -verdi # 把仿真日志单独输出到文件 ./simv -l sim.log # 直接加载文件列表看RTL代码 verdi -f filelist.f

6. 覆盖率收集常用指令

编译加-cm开启覆盖率采集 → 跑 simv 仿真生成.vdb覆盖率数据库

line:行覆盖率,代码行有没有跑到

cond:条件覆盖率,if、&&、|| 判断的所有分支是否都走到

fsm:状态机覆盖率,状态、状态跳转

tgl:toggle 翻转覆盖率,信号 0→1、1→0 是否都翻转

branch:分支覆盖率,case、if else 分支

assert:SVA 断言覆盖率(断言是否触发成功 / 失败)

-cm_hier:后面跟一个文本配置文件,用来告诉 VCS哪些模块统计覆盖率、哪些模块排除。

举个例子:-cm_hier cov.cfg

其中cov.cfg可以是下面内容

# +tree :包含这个层次,统计覆盖率 # -tree :排除这个层次,不统计覆盖率 # 只保留DUT作为覆盖率统计对象 +tree tb_top.u_dut # DUT里面有些第三方IP不想统计,单独排除 -tree tb_top.u_dut.u_external_sram_ip -tree tb_top.u_dut.u_analog_model

-cm_name:给本次仿真产生的覆盖率数据起一个标签名字,属于 VCS 编译参数(写在 vcs 编译命令,不是 simv 后面)

vcs -cm line+cond -cm_dir ./cov_case1 -cm_name $(TC_NAME) -top tb_top -f filelist.f

跑完之后,在./cov_case1/这个 vdb 库里面,这一组覆盖率数据的名字就叫$(TEST_NAME)

覆盖率合并:

方案1:每个 case 单独一个 vdb

-cm_name ${TEST_NAME}_${SEED} -cm_dir ${SESSION_DIR}/coverage 每个 test/seed 都会生成独立目录,类似: run_seed1/coverage/simv.vdb run_seed2/coverage/simv.vdb run_seed3/coverage/simv.vdb # 新版urg(推荐,输出merge.vdb) urg -full64 -dir run_seed1/coverage -dir run_seed2/coverage -dir run_seed3/coverage \ -merge \ -out ./cov_merge.vdb \ 打开覆盖率的方法 verdi -cov -covdir ./cov_merge.vdb &

方案2:编译一次 simv,多次跑仿真追加到同一个 vdb

vcs -cm line+cond -cm_dir ./cov_total

7.一个常用makfile脚本

makefile脚本

TC= TB= MOD= MY_DF= IS_COV= TIME_SCALE=1ns/1ps SEED= `data +%N` CMD=busb -IP -P xxx -q queue_name ifeq($(IS_COV),1) cov_opt= -cm cond+fsm+tgl+branch+line -cm_heir $(VCS_COV) -cm_name $(TEST_NAME)_$(SEED) -cm_dir $(SESSION_DIR)/coverage endif SIM_LIST =+define+AXIM_AGENT_EN+RTLSIM_TRCB \ +define+$(MY_DF) \ +incdir+$(FILE_PATH)/$(TC_BRANCH)/$(MOD)/testcase/$(TC)/tc_vlg \ +incdir+$(FILE_PATH)/$(TC_BRANCH)/$(MOD)/tc_public_v \ +incdir+$(FILE_PATH)/tb/tb_$(TB) \ $(FILE_PATH)/tb/eda/tb_top.v \ -f $(FILE_PATH)/tb/eda/tb_$(TB)/tb_$(TB).f ifeq "$(SIM_BRANCH)" "rtl" FILE_LIST= $(SIM_LIST) \ -f $(FILE_PATH)/tb/tb_$(TB)/rtl.f else endif ifeq "$(MY_DF)" "" tc_dir=$(TC)_$(MY_DF) else tc_dir=$(TC) endif cmp_opt= -full64 -debug_acc+pp+dmptf -debug_region=cell+encrypt +vcs+wait -sverilog -l vcs_cmp.log -top $(TOP_NAME) \ +notimingcheck -kdb \ $(cov_opt) \ +assert svaext \ -timescale=$(TIME_SCALE) sim_opt = +ntb_random_sees=$(SEED) -l vcs_run.log $(cov_opt)\ +fsdb+sva_success\ +fsdb+power mk_dir: @if [ -d $(tc_dir) ]; then \ echo $(tc_dir); \ else \ mkdir $(tc_dir); \ fi sim64: mk_dir cd $(tc_dir) && rm -rd simv* csrc *.txt ifeq (/path/$(MOD)/irom.txt, $wilcard(/path/$(MOD)/irom.txt) ) cp $(tc_dir) && cp /path/$(MOD)/irom.txt ./iram.txt endif cd $(tc_dir) && $(CMD) vcs $(cmp_opt) $(FILE_LIST) cd $(tc_dir) && $(CMD) ./simv $(sim_opt)

如何调用这个makefile脚本?

set tc_num = 000 # 默认case号:000 if ( $#argv > 1 ) then # 判断:传入参数个数>1 echo "WRONG FILE! Please Input Again!" exit # 参数太多,报错退出 endif if ( $#argv == 1 ) then # 如果传了1个参数 unset tc_num set tc_num = $1; # 把传入的参数赋值给tc_num(就是testcase编号) endif b make -f ../script/makefile TB=... MOD=... TC=$tc_num vcs64 IS_COV=1
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进