automatically generating fifo empty checker tcl

When the vast majority of block-level verification, by the end of normal cases, all of the fifo should be empty. If the fifo is not empty, it is likely there is a potential problem. Therefore, the platform should be before the end of the use case, whether done all at once dut in fifo empty check. However, for verification, the need to dut have got all the fifo is not a simple matter. And the script to achieve this function.

verdi NPI tool provides a set of interfaces, allowing users to get hierarchy design. So that we can pass fifo string matching, extract all the fifo, and generates a function, for platform invoke.

The following script fifo_empty_checker.tcl

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
debImport "-elab" "$env(DMPDIR)/simv.daidir/kdb" 
set tbdir "$env(CURDIR)"

set debug 0

set ::m_fp [ open "$tbdir/test_end_checker.sv" "w" ]
set ::log [open "$env(DMPDIR)/checker.log" "w"]


set ::cfg_list {}

set cfgfile [ open "$tbdir/checker.cfg" "r" ]
set line 1
while { [gets $cfgfile data] >= 0 } {
set data [string trim $data]
if {$debug} {
puts $log "cfg=$data"
}
if { [string match {#*} $data ] == 0 } {
set fields [split $data ","]
if {[llength $fields] == 3} {
lappend ::cfg_list $fields
} else {
error "config syntax error. please use "module, signal, value". line [$line]: $data"
}
}
incr line
}
close $cfgfile

foreach cfg $::cfg_list {
set cfg_mod [lindex $cfg 0]
set cfg_sig [lindex $cfg 1]
set cfg_val [lindex $cfg 2]
if {$debug} {
puts $::log "cfg_list: $cfg_mod $cfg_sig $cfg_val"
}
}

proc trv_mod {hdl debug} {
if {$hdl != "" } {
set def_name [npi_get_str -property npiDefName -object $hdl]
set type [npi_get_str -property npiType -object $hdl]
set module_fullname [npi_get_str -property npiFullName -object $hdl]
if {$type == "npiModule"} {
if {$debug} {
puts $::log "full= 大专栏  tcl自动生成fifo empty checker$module_fullname def=$def_name type=$type "
}
foreach cfg $::cfg_list {
set cfg_mod [lindex $cfg 0]
set cfg_sig [lindex $cfg 1]
set cfg_val [lindex $cfg 2]
if {[string match $cfg_mod $def_name] == "1"} {
if {$debug} {
puts $::log "match module $cfg_mod $def_name"
}
set itr [ npi_iterate -type npiPort -refHandle $hdl ]
if { $itr != "" } {
set sub_hdl [ npi_scan -iterator $itr]
while { $sub_hdl != "" } {
set module_port [npi_get_str -property npiName -object $sub_hdl]
if {[string match $cfg_sig $module_port] == "1"} {
puts $::m_fp "tif($module_fullname.$module_port != $cfg_val)begin"
puts $::m_fp "tterr = 1;"
puts $::m_fp "tt$error("$module_fullname.$module_port != $cfg_val");"
puts $::m_fp "tend"
}
set sub_hdl [ npi_scan -iterator $itr]
}
}
}
}
}
}

set itr [npi_iterate -type npiInternalScope -refHandle $hdl]
if {$itr == "" } {
return
}
set sub_scp [npi_scan -iterator $itr ]
while {$sub_scp != "" } {
set scp_type [npi_get_str -property npiType -object $sub_scp]
if {$scp_type == "npiModule" || $scp_type == "npiGenScope"} {
trv_mod $sub_scp $debug
}
set sub_scp [npi_scan -iterator $itr]
}
}

puts $::m_fp "t$display("test end checking start...");"
set itr [npi_iterate -type npiModule -refHandle "" ]
if {$itr != "" } {
set top_mod [npi_scan -iterator $itr]
while {$top_mod != "" } {
trv_mod $top_mod $debug
npi_release_handle -object $top_mod
set top_mod [npi_scan -iterator $itr ]
}
}
puts $::m_fp "t$display("test end checking end");"
close $::m_fp
close $::log

exit

The script needs to be generated to call the following command before compiling platform.

1
verdi -batch -play fifo_empty_checker.tcl

The script is by eating vcs generated kdb, of course, you can eat filelist, or fsdb.

Test_end_checker.sv generated by the script format is as follows:

1
2
3
4
5
6
$display("test end checking start...");
if(top_tb.dut.xx.fifo.empty != 1)begin
err = 1;
$display(top_tb.dut.xx.fifo.empty != 1);
end
$display("test end checking end");

可以将它封装到一个task中

1
2
3
4
5
function int checker();
int err = 0;
`include "test_end_checker.sv"
return err;
endfunction

在平台结束之前,就可以调用该function来检查fifo是否都空了。

再增加一个配置文件checker.cfg。第一列是module名称,第二列是信号,第三列是要检查的值。

1
*fifo*,o_empty,1

提示:如果使用filelist的方式加载,若design有error,有可能取到的hierarchy不全,需要增加环境变量setenv NPI_IGNORE_ERROR_VIEW 1。当然,更好的方式是通过打开kdb的方式加载。

扩展:verdi其实提供了apps来实现类似功能。

verdi –> tools –> VC Apps Toolbox –> Design Expioration

里面有比如 Get Module Hierarchy,Get Module IO, Find Instance with Module Def Name等app。

这个apps都可以使用GUI的方式,也可以使用batch的方式。例如:

1
$VERDI_HOME/share/VIA/Apps/DesignComprehension/FindInstDefWild/findInstDefWild_batch.pl -f flist -top top_tb -pattern "*fifo*" -outlog fifo.log

参考资料:

verdi/doc/NPI_tutorial.pdf

verdi/doc/VC_APPS_NPI.pdf

Guess you like

Origin www.cnblogs.com/lijianming180/p/12432969.html
TCL