我原先计划把vcs的ug看完然后每章都整理一些笔记和心得,但是在完成前三章之后我发现这可能要花费我特别多的时间和精力,并且其中很多东西就算记下来了也只是单纯的记下来了,也不知道怎么用,什么时候会用。更糟糕的是我回过头来看一下自己前面写的东西,其实就是在翻译文档,那写博客就真的没有什么意义了。所以我决定改变自己的做法,只选取一些常用到的东西来记录。比如说vcs,这个东西说白了是一个仿真的软件,那我首先要写的是怎么把它用起来,完成一次仿真,其他的技术细节留到后面再探讨,这样也可以避免把写博客变成翻译文档。因此这篇博客就围绕“如何用vcs完成一次仿真”来写。
vcs是编译型的仿真器,支持verilog,VHDL,System C等多种形式的设计输入。现在我也只对verilog有一点了解,所以就不多写另外几种了,主要以verilog为主。所谓编译型仿真器就是要先将设计编译为可执行文件然后进行仿真,所以大体上可以将仿真流程分为两部分:编译+仿真。
1 简介
vcs的工作流程可以分为两种,分别是three-step
和two-step
。首先是three-step
1-1 three-step flow
three-step flow可以应用到所有vcs支持的设计输入方式上。所谓的三步指的是:analysis
,elaboration
,simulation
。
1-1-1 Analysis
这一步的作用是检查设计是否有语法错误,同时将设计以一种中间形式进行保存以供后续的Elaboration使用。针对不同的设计输入方式有vlogan
,和vhdlan
两种工具可以使用。从名字也可以看出它们分别是用在verilog和VHDL的设计上的,本文就只说一下前者吧。为了方便测试,我写了一个简单的格雷码计数器,这里贴一下我的ugly code
module gray_counter(ptr,clk,rst_n,inc,full,empty);
parameter COUNTER_WIDTH = 8;
input clk,rst_n;
input inc,full,empty;
output reg [COUNTER_WIDTH-1:0] ptr;
reg [COUNTER_WIDTH-1:0] bin_counter;
wire [COUNTER_WIDTH-1:0] next_bin_counter;
wire [COUNTER_WIDTH-1:0] next_gray_counter;
always@(posedge clk, negedge rst_n)
if(!rst_n)
bin_counter <= 'd0;
else
bin_counter <= next_bin_counter;
assign next_bin_counter = bin_counter + {{COUNTER_WIDTH-1{1'b0}},inc&~empty&~full};
assign next_gray_counter = {1'b0,next_bin_counter[COUNTER_WIDTH-1:1]} ^ next_bin_counter;
always@(posedge clk, negedge rst_n)
if(!rst_n)
ptr <= 'd0;
else
ptr <= next_gray_counter;
endmodule
然后还有一个testbench,这里就不贴了,文件名是gray_counter_test.v。下面按照three-step flow,先进行analysis
$ vlogan gray_counter.v gray_counter_test.v
这个命令的执行模板如下
$ vlogan [vlogan_options] Verilog_filename_list
这里说明一下我认为比较有用的options
-help
这个参数是干啥的无需多言-nc
屏蔽掉Synopsys的版权信息
如果不加这个参数的话analysis会出现下面的结果
-f filename
这个参数可以把设计包含的文件名放到一个文件里然后通过这个参数传入,如果设计包含的文件比较多的话用这个方法就很方便了,比如我这个设计,就可以建一个design.f
gray_counter.v
gray_counter_test.v
然后analysis的时候这样
$ vlogan -f design.f
-full64
这个参数其实我现在还不知道究竟有什么好处,唯一用到的一次就是之前我用了一个虚拟机,调用vcs总是报错,版本有问题之类的,加上这个参数就可以了。文档里对它的说明是:Analyzes the design for 64-bit simulation-l
filename 将analysis的log打印到文件里-sverilog
支持SystemVerilog-timescale=time_unit/time_precision
为仿真添加时间单位和精度,需要注意的是只对没有`timescale的文件生效+define+macro
定义文本宏+incdir+directory
指定搜索路径,比如有些.v会include其他的.v
这只是一部分的选项(我知道含义的),后续肯定有一些其他的,再查文档吧……
1-1-2 Elaboration
这一步是利用Analysis产生的数据产生用于仿真的二进制文件simv以及其他一些数据。这一步使用的工具是vcs,格式如下
$ vcs [elab_options] [libname.] design_unit
design_unit在verilog里指的是top module的名字,这里我的top就是testbench的名字,比如是top
$ vcs top
同样下面列举一些参数
-h
或者-help
full64
-l filename
定义log文件
这一步执行完就已经产生可执行的二进制文件了,其实到这里仿真就约等于完成了
1-1-3 Simulation
如果只是要做仿真的话,直接这样就可以了
$ ./simv
这样就完成了仿真。比如testbench里添加了一些display什么的,现在就会起作用了。但是这显然不能满足我们的需求,最起码连波形都没有怎么debug。这部分放到后面再讲,下面先说一下two-step flow
1-2 twp-step flow
two-step flow将真个仿真分为了Compilation
和Simulation
两部分。需要注意的是two-step flow仅适用与Verilog和SystemVerilog的设计。
Simulation的作用类似于three-step中的Analysis+Elaboration。编译设计并产生可执行的二进制文件。其实Simulation和Elaboration有很多相似之处,包括后面的Simulation也和three-step的simulation很相似。因为目前我主要使用的语言是Verilog,所以这部分的内容我放到下面一节来写,包括了一些参数,以及如何产生波形,联合Verdi进行调试等等。
2 Debug
这一部分我介绍一下two-step的流程以及一些简单的debug选项。按照two-step的流程,先介绍Elaboration
2-1 Compilation
Elaboration使用vcs命令,执行的模板如下
$ vcs [compile options] Verilog_files
例如我这个设计就是
$ vcs gray_counter.v gray_counter_top.v
下面说一下部分参数
-h
或者-help
+incdir+directory
添加搜索路径-pvalue+parameter_hierarchical_name=value
这个参数的作用是指定设计中的parameter的值。-parameters filename
从文件里指定parameter的值,文件的语法如下
assign value path_to_parameter
并且parameter的路径中要用/代替.
+define+macro=value+
定义文本宏-f filename
-R
编译链接完成之后直接执行仿真
到这一步已经可以编译出可执行的simv,但是这时候还是处于所谓的batch mode,即仿真确实是只执行仿真而不保存仿真过程中的信息,也就没办法debug,这种模式一般是用在设计的后期regression,应为不保存仿真信息所以执行的速度也会快一些。设计的初期一般需要的是debug_mode
2-2 Debug Mode
2-2-1 -debug_access
要启用Debug Mode,在compilation的时候需要通过-debug_access(+<option>)
或者-debug_region=(<option>)(+<option>)
选项来开启。例如
$ vcs -debug_access+all -f design.f
下面说一下-debug_access的可选项
r
对整个设计开启读功能,可以读取仿真过程中变量的值,这个也是最小的debug选项w
对整个设计的register和variable开启写功能wn
对整个设计的net开启写功能。其实这个我没搞懂fn
对整个设计的net开启force功能fwn
对整个设计的net开启force和write功能f
等效于-debug_access+r+w+fndrivers
开启driver debugging功能,这个我也不懂line
开启line debugging,可以单步调试,这个我没试过cbk
开启SystemVerilog的string类型的dump,以及基于PLI的对register,nets和variables的回调cbkd
开启基于PLI的对定义在calss的动态nets,registers和variables的回调和dumping,以及class对象的debuggingthread
开启对SystemVerilog threads的debugclass
等效于-debug_access+r+w+thread+line+cbk+cbkdpp
等效于-debug_access+w+cbk+driversall
等效于-debug+r+w+wn+f+fn+fwn+drivers+line+cbk+cbkd+thread+class+pp-memcbk
注意这里是-号。这里文档的描述是关闭对memory和多维数组的回调,还说-debug_access默认是开启对memories和多维数组的回调的。但是我测试了一下发现不行,经过查下资料我发现应该是这样:默认情况下确实会保存多维数组,但是是通过下面的命令调用的
$fsdbDumpMDA(level,path);
如果想通过$fsdbDumpvars保存的话需要这样写
$fsdbDumpvars(level,path,"+mda");
这样也可以保存。这一部分详细的放到后面再说。
-debug_access的可用选项还有很多,但是现在也看不太明白或者用不到,这里也不往上写了。另外这里添加一个选项的说明:-lca
。这个选项是允许用户使用一些Synopsys在开发中未经测试的功能,如果需要这个参数的话在编译的时候会报错并提示,否则就不用管。
2-2-2 -debug_region
上面提到的-debug_access是用来启动全局的debug模式的,有时候考虑到性能等因素可能要进一步精确控制debug的功能,这就要通过-debug_region来实现。这个指令调用的模板为
$ vcs -debug_access -debug_region(option_name)(option_name)
注意-debug_region必须要和-debug_access一起才可以,这个也很好理解,毕竟只有开启了功能才能做调整。下面简单说明一下-debug_region的参数
+cell
开启对read cell和real cell的端口的debug功能。这里提到的cell module现在也还不知道是什么+cellports
对real cell和lib cell的端口开启debug功能
-debug_region还可以通过下面的语法指定-debug_access到某个instance
-debug_region=level,path
这个功能我没有试验过。
3 Verdi
Synopsys非常nb的调试工具。一开始是novas公司的产品,后来被springsoft收购了,然后springsoft又被Synopsys收购了。其实到现在verdi默认的波形文件名也是叫novas.rc,很有意思。直接百度verdi发现出来的是下面这个人
Verdi以前叫Debussy,下面这个
看来这个老板也是个爱好音乐的人。
3-1 DumpFile
这个工具本身的使用也非常复杂,这里就只简单地介绍一下怎么把它启动起来吧。既然是要看波形,首先就要保存波形。verilog保存的波形可以是ASCII形式的VCD格式,也可以是FSDB的二进制格式,这里就只说一下怎么保存FSDB文件,保存波形文件调用的是下面的系统函数
$fsdbDumpfile(filename);
$fsdbDumpvars(level,path);
注意肯定是先dump文件再dump数据。在testbench中加入这个语句块编译(编译需要又-debug_access)再执行结束之后就可以看到fsdb文件了。除了$fsdbDumpvars
还有一个我前面提到的用于保存MDA的$fsdbDumpMDA
。
3-2 KDB
KDB的全称是Verdi Knowledge Database。不管是two-step还是three-step,要保存kdb的话除了Simulation步骤都需要添加-kdb
。仿真完成之后,verdi可以通过-dbdir
选项指定路径以保证vcs和Verdi使用的是相同的数据,同时也可以通过-ssf
指定打开的fsdb文件。例如这样
$ verdi -ssf test.fsdb -dbdir simv.daidir/
就可以加载仿真的波形以及设计了。
4 Summary
到这里已经可以用vcs和verdi完成简单的仿真了。总结一下流程,假设我们采用verilog做设计输入并且采用two-step flow。首先是Compilation设计
$ vcs -f design.f -debug_access+all -kdb
然后执行仿真(其实可以在上一步添加-R
选项合并Compilation和Simulation)
$ ./simv
然后通过启动verdi进行debug
$ verdi -ssf test.fsdb -dbdir simv.daidir/
5 参数
下面是一些学习过程中了解到的有用的参数,想起来了就记下来吧