VCS入门
10 Apr 2020 7979字 27分 次 Digital IC Design Tcl打赏作者 CC BY 4.0 (除特别声明或转载文章外)
1 前言
同样只找到Verilog Compiled Simulator 2016,凑合用吧。
- 开发环境:
- Verilog Compiled Simulator 2016
- 操作系统:
- Ubuntu 18.04 LTS
2 综合概述
VCS工作流程如下图:
VCS编译RTL CODE过程如下图:
VCS先将verilog/systemverilog文件转化为C文件,在linux下编译链接生成可执行文件,在linux下运行simv即可得到仿真结果。
VCS的debug有两种方式:
- UCLI debugger:命令行;
- DVE debugger:图形化界面。
仿真时要考虑的因素:
- 仿真速度;
- 信号可见性;
- 信号易处理性;
- 可用性,
Debugging的系统任务有:
- Debug 可视化:
- $display:打印信息,显示当前变量的值;
- $strobe:打印信息,显示用非阻塞赋值的变量值;
- $monitor:打印信息,监控和输出参数列表中的表达式或变量值;
- $time:以64位integer类型返回当前仿真时间;
- 停止仿真:
- $stop:暂停仿真,类似断点;
- $finish:结束仿真;
- 仿真激励和参考:
- $readmemh:从硬盘文件读取十六进制ASCII数据;
- $readmemb:从硬盘文件读取二进制ASCII数据;
VCS的Verilog仿真事件队列:
- 读入源代码;
- 首先执行没有延迟的语句(initial语句);
- 将时间t设为0,即当前时间;
- 进入active区域:执行$display等语句,执行原语,计算非阻塞赋值的右边的表达式;
- 进入inactive区域:执行#0延时的语句;
- 进入nonblocking区域:非阻塞赋值操作;
3 VCS UCLI执行
3.1 编译链接生成二进制可执行文件
编译指令如下:
vcs source_file [compile_time_options]
其中:
- source_file:
- DUT里所有的Verilog/SystemVerilog源文件;
- 按空格分开的多个源文件;
- 顶层文件包含的DUT里的testbench。
- compile_time_options:
- 指示VCS如何编译源文件;
- 对于优化可见性和执行性能至关重要。
compile_time_options编译时可选的选项:
- 基本选项:
- -mupdate:只编译修改过的文件;
- -R:编译后继续执行仿真;
- -gui:打开dve图形界面;
- -l
:设置log文件名,写入编译信息; - -sverilog:支持sv;
- +v2k:支持Verilog2001标准;
- debug_pp:产生vpd文件,用于dve后处理;
- debug:相较debug_pp多了UCLI调试功能;
- debug_all:相较debug多了单步调试功能;
- 工艺库选项:
- -v
:指定工艺库; - -y
:指定工艺库路径; - +libext+
:指定多个库文件; - +incdir+
:代码里如果有include,使用这个命令告诉vcs包含文件的位置。
- -v
- 文件选项:
- -f file:当有很多源代码时,将这些源代码整合到file里;
- 修改可执行文件名字:
- -o foo:使用此命令修改可执行文件simv的文件名;
- define 一个宏:
- +define +
= :macro_name宏名、value初始化值。
- +define +
3.2 仿真
执行指令如下:
simv [compile_time_options]
compile_time_options编译时可选的选项:
- -s:结束仿真时间;
- $plusargs():从键盘或脚本中动态接收参数;
- -E echo:显示使用的选项;
- -l
:把仿真信息写入logfile文件里。
3.3 调用DW库
使用如下指令指定DW库路径:
-y $SYNOPSYS /dw/sim_ver+libext+.v+
使用如下代码直接在代码中例化:
Dwpart #(parameter) u1(
.porta(a),
.portb(b)
);
4 VCS DVE执行
DVE全称为:Discovery Visual Environment。
支持以下三种Debug模式:
- RTL或门级;
- 断言;
- Testbench。
支持的语言:
- Verilog;
- VHDL;
- SystemVerilog;
- SystemC;
- C/C++;
- NTB。
4.1 启动
从编译过程启动:
vcs source.v -R -gui -debug_all
根据现有的可执行文件(simv)启动:
simv -gui
直接启动:
dve&
4.2 打开文件
打开数据库文件:
- vcd:旧版VCS波形文件(占用空间较大);
- vpd:新版VCS波形文件;
- fsdb:Verdi的波形文件;
- wlf:ModelSim的波形文件。
GUI图太多了,以后补图…
5 后处理VCD+
之前的仿真方法在启动DVE后需要点击Run来一步一步显示波形。而VCD+可以直接将波形一次性仿真出来,然后用DVE查看。
仿真流程:
- 将VCD+系统任务嵌入到源代码中;
- 编译并运行仿真来生成VCD+文件;
- 在后处理模式下调用DVE;
- 讲VCD+文件读取到调试器内存;
- 调试。
DVE后处理模式:
- 仿真速度:
- 仿真速度取决于数据转储命令;
- 调试速度最快;
- 信号可见性:
- 用户指定;
- 信号可处理性:
- 通过波形、原理图或源跟踪的信号;
- 可用性:
- 用户友好的图形界面;
- 可在所有复杂级别使用。
VCD+系统任务:
$vcdpluson(level_number,module_instance,...|net_or_reg)
其中:
- level_number:
- 用于记录指定层次结构级别:
- 0:记录指定模块的整个层次结构;
- 1:记录指定模块的顶层结构;
- n:记录指定模块的n级层次结构;
- module_instance:
- 指定要记录的模块;
- net_or_reg:
- 指定要记录的单个网络或寄存器;
- 省略所有参数,记录整个设计的所有网络和寄存器。
通过以下代码停止在模块实例或单独网络或寄存器中的记录:
$vcdplusoff(module_instance,...|net_or_reg);
通过以下代码讲结果写入VCD文件:
$vcdplusautoflushon(); //每当有中断或停止命令时,VCS会自动将内存中的结果写入VCD+文件
$vcdplusautoflushoff(); //关闭中断时数据自动刷新
$vcdplusautoflush(); //指示VCS把内存中的结果写入VCD+文件
通过以下代码控制循环录制:
$vcdplusdeltacycloneon(); //打开增量循环录制,用于后处理
$vcdplusdeltacycloneoff(); //关闭增量循环录制
通过以下代码控制零延迟故障记录:
$vcdplusglitchon(); //打开零延迟故障记录,用于后处理
$vcdplusglithchoff(); //关闭零延迟故障记录
通过以下代码控制寄存器组数据记录:
$vcdplusmemon(); //打开mem记录,用于后处理
$vcdplusmemoff(); //关闭mem记录
VCD+文件的编译:
vcs files vcdplus_switches other_switches
其中:
- files:
- 单元中定义的源文件(包含Verilog,C/C++,PLI);
- vcdplus_switches:
- 指示VCS编译器识别VCD+系统任务;
- 控制VCD+文件生成;
- other_switches:
- 编译器时间选项(如-R,-Mupdate等)。
用于在后处理中调用DVE的示例命令:
dve -vpd vcdplus.vpd
VCD+文件编译可选项:
- -debug:所需编译选项;
- +vpdfile+
:指定写入代替VCD+的文件名而不是默认的“vcdplus.vpd”; - +vpdupdate:允许同时写入和读取VCD+文件;
- +vpdbufsize+MB:指定用于存储VCD+值的临时缓冲区的大小(默认为5MB);
- +vpdfilesize+MB:指定VCD+文件的最大大小(超过限制时,新的覆盖旧的);
6 其它
6.1 辅助选项
使用以下方法报告代码里的竞争冒险状况:
- +race;
- $vcdplusdeltacycloneon;
- vcddiff&vcat;
6.2 产生mismatch的原因
产生mismatch的原因如下:
- 功能仿真mismatch:
- 仿真工具的厂商不同:
- 源代码中的竞争冒险;
- 厂商的实现;
- 同一厂商不同版本的模拟器:
- 源代码中的竞争冒险;
- 仿真工具的厂商不同:
- RTL和门级仿真:
- 相同的模拟器:
- 源代码中的竞争冒险;
- 代码写的不求行。
- 相同的模拟器:
例如:
module race;
reg a;
initial begin
a=0;
#10 a=1;
end
initial begin
#10 if(a)$display("a=1");
end
endmodule
由于第10个单位时间上a跳变,所以不同的仿真工具或者不同版本的相同仿真工具在这个时间点上执行“a=1”和“if(a)”的顺序不同而导致结果不同。
6.3 优化
编译时加入以下命令优化设计:
+rad
它尝试通过以下方法优化设计:
- 提高抽象级别;
- 分析代码,用于快速事件和基于周期的仿真。
6.4 性能分析
编译时通过以下命令做性能分析:
+prof
新版本的VCS中命令该更新为:
-simprofile
使用此命令分析和统计每个模块消耗的时间和内存的百分比等等。
7 覆盖率
7.1 代码覆盖率
代码覆盖率的问题包含:
- 状态或行覆盖率:每一行RTL是否都被仿真;
- 跳变覆盖率:每个信号是否都跳变(上升沿,下降沿都要出现,x->0和x->1的跳变不会统计);
- 状态机覆盖率:状态机所有的状态是否都被用到、状态间跳转是否完全覆盖;
- 条件覆盖率:”if…else”、”case”語句是否都執行到;
- 路径覆盖率:所有initial或always路径是否都被执行。
其中,跳变覆盖在Verilog中只检测以下变量:
- Register;
- Wires;
- Memories(需要加上编译时间选项:“+memcbk”)。
代码覆盖率可以用于:
- 行为级:
- 行覆盖率;
- 条件覆盖率:
- 路径覆盖率;
- 状态机覆盖率;
- RTL级:
- 行覆盖率;
- 条件覆盖率;
- 路径覆盖率;
- 跳变覆盖率;
不推荐
- 状态机覆盖率;
- 门级:
- 跳变覆盖率。
编译时加入以下指令来检测代码覆盖率:
-cm <coverage_type> <other coverage option>
其中:
- coverage_type:
- line:行覆盖率;
- tgl:跳转覆盖率;
- cond:条件覆盖率;
- fsm:状态机覆盖率;
- path:路径覆盖率。
- 如果需要添加多个覆盖率,则需要在多个覆盖率命令间加“+”;
- other coverage option:
- -cm_name
:指定覆盖率统计文件名; - -cm_glitch period:指定在某个周期VCS不检查覆盖率;
- -cm_dir
:指定覆盖率统计文件路径; - -cm_log
:指定覆盖率记录文件名; - -cm_nocasedef:忽略default语句。
- -cm_name
如果不想让源代码中的某些语句被检查覆盖率,可以加入以下代码:
//VCS coverage on
//VCS coverage off
或者可以用synopsys的专用注释,不仅可以忽略覆盖率,还可以忽略综合:
//synopsys translate_on
//synopsys translate_off
如果不想让某些文件被检查覆盖率,可以加入以下开关命令忽略该文件:
-cm_hier <filename>
7.2 功能覆盖率
功能覆盖率的问题包含:
- 是否驗證了所有可能性的組合;
- 所有的邊界條件是否都經過測試設計;
- 處理器在處理高速緩存時出錯,是否能觸發異步中斷。
功能覆盖率一般在验证中使用。
8 后仿真
之前的内容是前仿真,也就是功能仿真。仿真好之后把源代码交给DC综合,得到门级网表和SDF(Standard Delay Format)文件。SDF文件包含了布局布线后的标准延迟参数,结合门级网表和仿真库文件就可以做后仿真了。
8.1 SDF文件
SDF文件中内嵌的时序信息包含:
- 延迟(模块路径、设备、接口、端口);
- 时序检查(建立、保持时间、skew、时钟周期等);
- 时序约束;
- 时序环境(到达时间、波形)。
8.2 VCS中使用SDF
首先通过以下命令在RTL源代码中反标SDF:
$sdf_annotate("sdf_file"[,module_instance][,"sdf_configfile"],[,"sdf_logfile"][,"mtm_spec"][,"scale_factors"][,,"scale_type"]);
然后编译门级网表,同时要指定仿真库:
vcs gate_netlist.v -v sim_lib.v
特别注意,如果使用预编译SDF文件指令,则“+rad”指令将被忽略。
8.3 设置min/typ/max延迟
可以在编译时开启下面的选项来选择任意一个延迟模型:
+mindelays
+typdelays
+maxdelays
也可以三种全部编译:
+allmtm
然后仿真时选择任意一个延迟:
+mindelays
+typdelays
+maxdelays
8.4 延迟过滤(Delay Filtering)
延迟过滤包含以下两种:
- Inertial Delay(惯性延迟):
- 默认VCS延迟处理;
- 输出相较于输入会有延迟,当输入的脉冲小与这个延迟时,输出不再有变化(脉冲被过滤);
- Transport Delay(传输延迟):
- 所有脉冲都可以传输(没有过滤)。
编译时加入以下指令来打开传输延迟过滤开关:
+transport_path_delays ;#为路径延迟打开传输延迟模型
+transport_int_delays ;#为互连延迟打开传输延迟模型
修改延迟过滤标准:
- 对于模块路径延迟:
- +pluse_e/number(error limit in %);
- +pluse_r/number(reject limit in %);
- 举例:
- 当脉冲宽度小于延迟的50%则被忽略;
- 当输出X小于70%大于50%则报错;
- 对于互连延迟:
- +pluse_e/number(error limit in %);
- +pluse_r/number(reject limit in %);
- 举例同上。
告辞