- .do文件
- 全编译
- 增量编译
.do文件说白了就是TCL指令集。modelsim中需要执行的执行的指令写到.do文件中,然后输入命令 do (.do文件的名字).do,modelsim会逐行执行.do文件的指令,省去大量时间,可以说是一劳永逸。接下来说一下仿真的步骤:
1、创建库文件
2、编译文件
3、运行仿真
4、调试
.do文件的任务就是把前三个过程执行完,第四个步骤就是自己进行代码调试。下面直接上代码讲解全编译和增量编译。
#===================================================================================
#作者: stone
#时间: 2021.10.3
#功能描述:modelsim自动化脚本,全编译,如果没有wave.do文件就把tb的波形添加到wave中
#===================================================================================
#======================================================
# 可修改参数
#======================================================
#需要编译的.v路径
set file_name ./../rtl/*.v
set file_wave ./wave.do
#wave.do文件存在标志
set wave_exist [file exists $file_wave]
#======================================================
#退出仿真,清空命令行
quit -sim
.main clear
#在根目录下建立库文件
vlib ./lib/
vlib ./lib/work
#库文件地址映射
vmap work ./lib/work
#编译Verilog文件
vlog $file_name
#vlog $file_name -cover bcesxf 看覆盖率
#启动仿真器
vsim -voptargs=+acc work.TESTBENCH
#加信号
if {$wave_exist} {
do wave.do
} else {
add wave -divider {TESTBENCH}
add wave TESTBENCH/*
}
log -r /*
#运行
run 100us
vlib:创建指定的文件目录
vmap:用于将逻辑工作库work映射到当前实际工作库
vlog:编译指定的文件,这里我指定的路径是rtl/*.v,其中 *是通配符,表示所有后缀为.v的文件,后面加上-cover bcesxf参数,表示覆盖分支条件表达式语句,用于查看覆盖率
vsim:链接到默认的work库,启动仿真顶层测试逻辑库work里面的TESTENCH模块,注意这里面的TESTENCH是模块名,而不是文件名,-voptargs=+acc表示优化部分参数,-novopt表示不进行优化,
add wave -divider {TESTBENCH}:添加分解线名字是TESTBENCH,如下图所示添加了TESTBENCH和TESTBENCH111),add wave必须在vsim之后!
add wave TESTBENCH/*:添加TESTBENCH文件的所有信号,如果想添加子模块里面的信号,顶层模块名/子模块名/信号名
log -r /*:记录所有的信号,即使仿真前没有将信号加入到wave窗口,意思是没有add wave命令,在开始仿真后直接加入wave窗口就可以查看波形。对于比较大的工程,该命令会加大仿真时间,占用内存也比较大
有时候为了方便查看,自己会对波形信号分组。如果重新编译,就要重新进行分组,这时候可以ctrl+s保存波形,然后编译完后输入do wave.doTCL命令,自己编辑的波形就会重新出现。注意:wave.do是你保存的波形文件名字,也可以重新命名。
增量编译#==========================================================================
#作者: stone
#时间: 2021.10.3
#功能描述:modelsim增量编译自动化脚本,第一次全编译,后面只编译修改的文件
#==========================================================================
#======================================================
# 可修改参数
#======================================================
#rtl.f存放的是.v路径
set file_name ../filelist/rtl.f
#生成时间戳的文件名字
set file_txt ./file_time.txt
#======================================================
#建立库文件夹
vlib work
#映射工作库
vmap work ./work
# file_txt 是否存在标志,存在则表示已经编译过一次,不存在说明第一次编译,则全编译
set file_exist [file exists $file_txt]
set file_stone [open $file_name r]
#存储修改过文件的路径
set var_name {}
#======================================================
# 判断文件是否需要编译
#======================================================
if {$file_exist} {
set file_time_r [open $file_txt r]
while {[gets $file_time_r name_time] >= 0 & [gets $file_stone name_list] >= 0} {
if {$name_time == [file mtime $name_list]} {
puts "[file tail $name_list] no compile"
} else {
lappend var_name $name_list
puts "[file tail $name_list] yes compile"
}
}
close $file_stone
close $file_time_r
}
#======================================================
#======================================================
# 写时间戳
#======================================================
set file_time_w [open $file_txt w]
set file_stone_1 [open $file_name r]
while {[gets $file_stone_1 name_list] >= 0} {
puts $file_time_w [file mtime $name_list]
}
close $file_time_w
close $file_stone_1
#======================================================
#======================================================
# 编译
#======================================================
if {$file_exist} {
foreach i $var_name {
vlog $i -cover bcesxf
}
} else {
vlog -f $file_name -cover bcesxf
}
#======================================================
#启动仿真器
vsim -voptargs=+acc -coverage work.testbench
log -r /*
run -all
exit
增量编译和全编译一样,需要
1、建立库文件
2、映射工作库
3、编译
4、启动仿真
增量编译第一次就进行全编译,后面只编译修改的文件。
怎么判断哪个文件被修改,哪个文件没有被修改?
根据文件的时间戳来判断。文件被修改,那么时间戳就会被更新,对比编译前和编译后的时间戳,可以知道哪个文件被修改,哪个没有被修改。所以需要建立文件保存上一次的时间戳,用来和现在时间戳做对比。
怎么判断是第一次编译?
根据是否有保存时间戳的txt文件判断。如果是第一次判断,那肯定没有这个文件,因为只有编译一次后,时间戳文件才会生成。所以如果没有这个文件,就全编译vlog -f $file_name -cover bcesxf,如果有就只编译修改过的文件。
rtl.f文件是用python生成的需要编译的.v列表,-f命令就是编译指定文件的内容,如何用python生成list文件可以看Python创建list文件这篇文章。
为了方便阅读,下面说一下简单的TCL指令
set:定义变量,取变量内容时要用$+变量名
[]:表示里面是命令,不加[],这只是普通的字符串
fill exists:判断文件是否存在,存在返回1,否则返回0
open r:以只读模式打开文件
set var_name {}:创建一个空列表,用来存储修改的文件地址
gets:从第一行开始读,gets $file_time_r name_time把file_time_r文件的每一行给name_time变量,如果读完了,返回-1。
file mtime:获取文件最后一次被修改的时间戳
puts ""打印字符串
lappend:把变量加到列表后面
puts 文件名 变量:把变量内容写到指定的文件中
foreach i $var_name:循环,i依次取var_name列表的元素
对于小工程而言,可以用全编译,对于大工程而言用增量编译可以加快调试速度。如果用.bat批处理运行modelsim,那么关闭modelsim后如果重新打开modelsim,需要删掉时间戳文件,因为不建立工程,编译内容无法被记录,所以用增量编译建议建立工程使用。为了方便阅读,上面给出了一些简单的TCL语言,本人学习TCL没几天,有错误之处请指正~



