IC研发过程中,可能会涉及到多种工具,过程中也可能需要不同格式的波形文件。从网上搜索情况来看,介绍saif的较少,所以这里着重介绍一下saif的dump。
下面粘贴了两个相关背景知识的帖子,如其中介绍,saif主要用在功耗分析中。
1. 下面介绍一下 vcs 如何 dump saif文件
在 vcs的 user_guide中,有一章节专门介绍saif相关的选项
比较推荐使用ucli的方式进行,不用修改环境。
2. 也可以从波形文件直接转换成 saif
比如 fsdb2saif
用ucli方式进行dump,举例如下
(run xxx1 ps/ns/us....) //可以设置先run一段时间,再dump波形
call $fsdbDumpvars(0, xxx, "+mda") //设置dump的层次,以及其他选项
call $fsdbDumpon //开始dump波形
run xxx2 ps/ns/us..... //再run一段时间
power -gate_level on mda //saif dump设置
power xxx_scope //saif dump 层次
power -enable //开始dump saif
run xxx3 ps/ns/us..... //再run xxx3
power -disable //停止dump saif
power -report xxx.saif xxx_scale xxx_scope //生成saif 报告
run xxx4 ps/ns/us..... //再run xxx4
call $fsdbDumpoff //暂停dump波形
fsdbDumpFinish //如果不调用此函数,那么调用call $fsdbDumpon可以接着dump 波形
run xxx5 ps/ns/us..... //再run xxx5
exit //退出仿真
把以上内容保存成xxx.tcl,vcs仿真选项中加入 -ucli -i xxx.tcl,即可控制波形的dump。
上述内容,会dump [(xxx1), (xxx1)+xxx2+xxx3+xxx4] 时间段内的fsdb。
会生成 [(xxx1)+xxx2, (xxx1)+xxx2+xxx3] 时间段内的saif。
在(xxx1)+xxx2+xxx3+xxx4+xxx5 仿真结束
针对不同的波形文件,也可以使用ucli进行dump
【新思验证小课堂】【Verdi】Verdi基础培训第4节---如何产生verdi kdb和import design
【新思验证小课堂】【Verdi】Verdi基础培训第5节---dump波形常用的task
【新思验证小课堂】【Verdi】Verdi基础培训第6节---提取FSDB波形信息的utility
下面介绍一些fsdb dump的技巧
其中,+fsdb+force对于force信号的调试比较有帮助,下面的内容引自
verdi中如何查看force信号信息
在仿真中,我们会有对信号进行force的操作,从而实现某些特定的功能。但是在仿真波形中,不能直接从波形上看出,这些信号的驱动,是因为前级电路的驱动,还是因为force的原因的驱动。从而使debug非常的不友好。
其实在verdi中,是可以直接看到force信号的信息的。这样的话,就会方便我们去debug force的信号。
要想要verdi中,查看force信号,就需要vcs在仿真时候,生成fsdb波形时,加入force信号的波形信息。只需要在仿真参数中,加入 +fsdb+force 参数即可。当fsdb波形生成后,就可以在verdi中,直接查看到信号的force信息。
如以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
其中my_and模块,代码如下:
1 2 3 4 5 6 7 |
|
编译仿真的Makefile如下:
1 2 3 4 5 6 7 8 |
|
在仿真的时候,加上+fsdb+force选项。
打开verdi,查看信号。
从波形上,能够清晰的看到force信号的信息。用紫色虚线标识的波形,就表示这一段时间内,信号是被force驱动的。
-
向下的紫色箭头,表示这个时候,有force语句针对该信号
-
向上的紫色箭头,表示这个时候,有release语句针对该信号
通过特殊的紫色波形标记,就可以很清晰的知道信号的force信息了。
在一个环境中,可能force的信号比较多,通过上面的波形方式,去把每一个信号给拉出来,判断信号是否有force,效率就会比较低了。
此时,我们可以使用fsdbreport命令,从波形里面,把所有的信号force的信息,全部给抓出来,保存在一个文件中,这样,我们通过该文件,就可以知道仿真过程中的所有信号force信息。
命令如下:
1 |
|
其中:
-
xxx.fsdb:是输入的fsdb波形文件
-
-s: 指定查找force信息的层次, /* 表示从最顶层开始
-
-level:表示从指定的层次,向下查找层次的数目。0表示指定的层次和以下所有的层次。1表示指定的层次,2表示指定的层次和下一层次。之后依次类推,一般都是直接使用0
-
-o:指定输出文件
针对刚刚上述产生的force.fsdb波形,来提取force信息。命令如下:
1 |
|
生成的force.txt信息如下:
该文件中,会打印每一个force信号的信息:
-
force信号的层次路径
-
force信号在什么时刻被force,force的值是多少
-
force信号在什么时刻被release
通过查阅该文件,就可以知道波形文件中,所有的force信号的信息,从而可以帮助我们去debug。
以下内容转载自:
interface clocking block使用 及 verdi capture delta cycle_clockingblock_劲仔小鱼的博客-CSDN博客
dump glitch 毛刺分析 及 异步复位同步释放_vcs dump glitch_劲仔小鱼的博客-CSDN博客
clocking block
Input (or inout) signals are sampled at the designated clock event. If an input skew is specified, then the signal is sampled at skew time units before the clock event. Similarly, output (or inout) signals are driven skew simulation time units after the corresponding clock event. Below Figure shows the basic sample and drive timing for a positive edge clock.
clocking block是sv中引入的语法,采样信号发生在时钟沿之前的input skew units,驱动信号发生在时钟沿之后的output skew units。避免TB与RTL接口上的冒险,相当于模拟实际器件的setup time, hold time。若实际器件timing不满足,则会产生亚稳态。实际仿真中就是X态,无法确定高低电平。
示例:
# top.sv
interface master_interface();
logic pclk;
logic prest_n;
logic [31:0] pwdata;
logic [31:0] prdata;
clocking drv_cb @(posedge pclk);
default input #1 output #1;
output pwdata;
input prdata;
endclocking
clocking mon_cb @(posedge pclk);
default input #1 output #1;
input pwdata;
input prdata;
endclocking
endinterface
class master;
logic [31:0] data;
virtual master_interface vif;
task driver();
vif.pwdata = 0;
wait(vif.prest_n == 1);
@(posedge vif.pclk);
vif.pwdata <= 1;
$display("%0t [driver]",$realtime);
#5;
@(posedge vif.pclk);
vif.drv_cb.pwdata <= 2;
$display("%0t [driver]",$realtime);
#5;
@(vif.drv_cb);
vif.pwdata <= 3;
$display("%0t [driver]",$realtime);
#5;
@(vif.drv_cb);
vif.drv_cb.pwdata <= 4;
$display("%0t [driver]",$realtime);
#10;
endtask
task monitor();
wait(vif.prest_n == 1);
//@(posedge vif.pclk); // vif.pwdata = 0 | vif.mon_cb.pwdata = 0
@(vif.mon_cb); // vif.pwdata = 1 | vif.mon_cb.pwdata = 0
$display("%0t [monitor] vif.pwdata:%0h",$realtime,vif.pwdata);
$display("%0t [monitor] vif.mon_cb.pwdata:%0h",$realtime,vif.mon_cb.pwdata);
#5;
//@(posedge vif.pclk); // vif.pwdata = 1 | vif.mon_cb.pwdata = 0
@(vif.mon_cb); // vif.pwdata = 1 | vif.mon_cb.pwdata = 1
$display("%0t [monitor] vif.pwdata:%0h",$realtime,vif.pwdata);
$display("%0t [monitor] vif.mon_cb.pwdata:%0h",$realtime,vif.mon_cb.pwdata);
#5;
//@(posedge vif.pclk); // vif.pwdata = 2 | vif.mon_cb.pwdata = 1
@(vif.mon_cb); // vif.pwdata = 2 | vif.mon_cb.pwdata = 2
$display("%0t [monitor] vif.pwdata:%0h",$realtime,vif.pwdata);
$display("%0t [monitor] vif.mon_cb.pwdata:%0h",$realtime,vif.mon_cb.pwdata);
#5;
//@(posedge vif.pclk); // vif.pwdata = 3 | vif.mon_cb.pwdata = 2
@(vif.mon_cb); // vif.pwdata = 3 | vif.mon_cb.pwdata = 3
$display("%0t [monitor] vif.pwdata:%0h",$realtime,vif.pwdata);
$display("%0t [monitor] vif.mon_cb.pwdata:%0h",$realtime,vif.mon_cb.pwdata);
#10;
endtask
endclass
module top;
logic clk;
logic rst_n;
logic [31:0] rdata,wdata;
logic [31:0] cnt = 0;
master_interface m_if();
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0)
wdata <= 'h0;
else
wdata <= m_if.pwdata;
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0)
m_if.prdata <= 'h0;
else
m_if.prdata <= cnt++;
end
always #5 clk = ~clk;
assign m_if.pclk = clk;
assign m_if.prest_n = rst_n;
initial begin
clk = 'b0;
rst_n = 'b0;
#12;
rst_n = 'b1;
end
initial begin
master m_inst;
m_inst = new();
m_inst.vif = m_if;
fork
m_inst.driver();
m_inst.monitor();
join_any
$finish();
end
initial begin
$fsdbDumpfile("wave.fsdb");
$fsdbDumpvars;
end
endmodule
# Makefile
all: clean comp run
clean:
@rm .[a-zA-Z0-9]* -rf
@ls | grep -v Makefile | grep -v top.sv | xargs rm -rf
@echo clean done
comp:
vcs -full64\
-kdb -lca \
-debug_access+all \
-sverilog \
-timescale=1ns/1ns \
top.sv \
-l compile.lg
run:
./simv \
+fsdb+delta \
-l sim.log
wave:
verdi -ssf wave.fsdb &
如上示例:
- input skew,output skew各1ns。
- task driver() 驱动,task monitor()采样。
- 15ns, 25ns, 35ns, 45ns 四个观察结点。
- vif.pclk,vif.drv_cb,vif.mon_cb,vif.pwdata,vif.drv_cb.pwdata,vif.mon_cb.pwdata混用。
波形:
15ns:
- DUT中的wdata为0,采样到的是前一拍的值。
- Driver中的vif.drv_cb.pwdata为X态,因为task driver中15ns驱动的信号是vif.pwdata,并不会影响vif.drv_cb scope中的pwdata信号,所以是X态。
- Sample中vif.pwdata为1,采样发生在vif.pwdata跳变之后。而vif.mon_cb.pwdtata为0,采样时钟沿前1ns的值。
25ns:
- DUT中的
wdata
为1,采样到的是前一拍的值。- Driver中
vif.pwdata
比vif.drv_cb.pwdata
晚1ns,因为clocking block
drv_cb
的output skew
。
35ns
见 delta cycle分析。45ns
略
结论:
- interface中尽量使用clocking来sync采样和驱动信号,避免冒险。一些TB中不使用也没有出错,只能说明这种情况下没有问题,无法保证和其他RTL连接时这种方式不会出错。
- vif.drv_cb.pwdata,vif.mon_cb.pwdata要分别使用vif.drv_cb和vif.mon推进时间,避免与vif.pclk混用。同理vif.pwdata避免与vif.drv_cb和vif.mon_cb混用。
- 如果采样clocking block中的output信号,会报错。不可以采样驱动信号。可以改用inout类型。inout类型的信号相当于input output。
Verdi capture delta cycle
delta cycle : 时钟采样时数据发生跳变,存在冒险。比如glitch发生,nwave上显示一个实线 |,此时glitch的上升沿和下降沿的$realtime差值为delta = 0。实际仿真器根据IEEE SV协议中的Scheduling semantics章节内容进行Event simulation。
使用:
对于delta cycle的debug,verdi支持三种方式,在 ./simv
时加上
+fsdb+glitch=0
: 查看glitch+fsdb+sequential
: 查看 event sequence+fsdb+region
: 查看event region
使用+fsdb+delta
默认同时采集上述三种。
To enable delta cycle dumping capability in interactive mode, use the +fsdb+delta=1|2 option at runtime.
Following is the syntax:
+fsdb+delta=1|2
1: Enables delta cycle dumping capability
2: Enables delta cycle dumping, but disables cycle dumping at time 0
Use the +fsdb+delta=0 option at runtime to disable the delta cycle dumping capability.
示例:
以上述波形35ns处为例:
event region : nWave中 View
- Expand Delta
第一绿色区域为Active
区,第二个红色区域为NBA
区,非阻塞赋值<=
在NBA生效。
event sequence : nWave中 Tools
- Event Sequence
clk先跳变,vif.mon_cb.pwdata
采样得到2,随后DUT中wdata
被2驱动,然后vif.pwdata
跳变为3。
DUT中的wdata
发生在vif.pwdata
之前,所以被驱动时,vif.pwdata
还是旧值2。