用Verdi计算AXI带宽的Tcl脚本
摘要:Verdi(Synopsys的nTrace或Verdi工具)是一个强大的波形查看和分析工具,支持Tcl脚本自动化任务,如加载fsdb文件、查询信号、计算切换率和统计数据传输量。这非常适合计算AXI协议的带宽(Bandwidth, BW),因为AXI的BW依赖于数据通道的有效传输(e.g., wvalid && wready高时的wdata字节)。
在Verdi中,Tcl脚本使用npi(nTrace Programming Interface)命令来访问波形数据。计算AXI BW的核心步骤:
- 加载fsdb文件。
- 指定时间窗口(time window)。
- 查询AXI信号(e.g., /top/dut/axi_if/wvalid, wready, wdata, wstrb, wlast)。
- 统计有效周期(valid && ready)。
- 计算总有效字节 = 有效周期 × (数据宽度 / 8) × active strobes (wstrb位计数)。
- BW = 总字节 / 时间 (GB/s = 字节 / 1e9 / 时间秒)。
运行脚本方式:
- 启动Verdi:
verdi -ssf your_fsdb.fsdb -nologo
(加载fsdb)。 - 在Verdi Tcl console(或文件)运行脚本:
source your_script.tcl
。 - 或批处理:
verdi -ssf your_fsdb.fsdb -script your_script.tcl
。 - 注意:脚本假设AXI数据宽度128位(可参数化);调整信号路径为您的设计。需要Verdi许可。
我将提供两个示例脚本:一个基本脚本(计算单个窗口BW),一个高级脚本(多窗口、参数化、输出报告)。每个脚本后附解释。
示例1: 基本AXI带宽计算脚本(单一时间窗口)
这个脚本计算指定时间窗口内的写通道(W channel)BW,假设数据宽度128位。
# basic_axi_bw.tcl - 计算AXI写通道带宽
# 用户参数 (可修改)
set data_width 128 ;# AXI数据宽度 (位)
set time_start 0.0 ;# 开始时间 (ns)
set time_end 1000.0 ;# 结束时间 (ns)
set scope "/top/dut/axi_if" ;# AXI接口scope路径
# 查询信号句柄 (使用npi)
set wvalid_hdl [npi_hdl_by_name -scope $scope -name "wvalid"]
set wready_hdl [npi_hdl_by_name -scope $scope -name "wready"]
set wstrb_hdl [npi_hdl_by_name -scope $scope -name "wstrb"] ;# 字节使能 (e.g., 16位 for 128-bit)
set wlast_hdl [npi_hdl_by_name -scope $scope -name "wlast"] ;# 可选, 检查burst结束
# 检查信号是否存在
if {$wvalid_hdl == "" || $wready_hdl == "" || $wstrb_hdl == ""} {
puts "Error: AXI signals not found in scope $scope"
return
}
# 设置时间窗口
npi_set_time_window $time_start $time_end
# 计算有效周期: wvalid && wready 高时计数 (采样每个周期)
set effective_cycles 0
set total_bytes 0
set current_time $time_start
while {$current_time < $time_end} {
# 获取当前周期值 (假设1ns分辨率, 可调整)
set val_valid [npi_get_value -hdl $wvalid_hdl -time $current_time -format decimal]
set val_ready [npi_get_value -hdl $wready_hdl -time $current_time -format decimal]
set val_strb [npi_get_value -hdl $wstrb_hdl -time $current_time -format hex] ;# hex for bit mask
if {$val_valid == 1 && $val_ready == 1} {
# 计算active strobes (popcount of wstrb bits)
set active_strobes [expr [format "%d" 0x$val_strb]] ;# 简化, 假设strb是mask, 用bit count工具更好
set bytes_per_cycle [expr ($data_width / 8) * ($active_strobes / ($data_width / 8))] ;# 比例
set total_bytes [expr $total_bytes + $bytes_per_cycle]
incr effective_cycles
}
set current_time [expr $current_time + 1.0] ;# 步进1ns (调整为您的时钟周期)
}
# 计算BW (GB/s)
set time_duration [expr ($time_end - $time_start) / 1e9] ;# ns to s
set bandwidth [expr $total_bytes / $time_duration / 1e9] ;# bytes to GB/s
# 输出结果
puts "AXI Write BW in [$time_start, $time_end] ns:"
puts "Effective Cycles: $effective_cycles"
puts "Total Bytes: $total_bytes"
puts "Bandwidth: $bandwidth GB/s"
# 可选: 导出到文件
set fp [open "axi_bw_report.txt" w]
puts $fp "Bandwidth: $bandwidth GB/s"
close $fp
脚本解释
-
参数:自定义data_width、时间窗口、scope。
-
信号查询:用
npi_hdl_by_name
获取句柄(npi是Verdi的API)。 -
循环计算:步进时间(假设1ns分辨率;实际用您的clk周期),检查wvalid && wready,累加字节(考虑wstrb活跃位)。
-
BW公式:总字节 / 时间(s) / 1e9 = GB/s。
-
注意:循环步进慢 for大窗口(优化用npi_iterate_over_time);wstrb计算简化(实际用bit count函数)。适用于写通道;读通道类似替换为rvalid/rready/rdata。
-
运行:在Verdi中
source basic_axi_bw.tcl
,输出到console和文件。
示例2: 高级AXI带宽计算脚本(多窗口、参数化、报告生成)
这个脚本支持多个时间窗口、读/写通道选择、自动计算效率,并生成CSV报告。适用于批量分析。
# advanced_axi_bw.tcl - 多窗口AXI带宽计算 with报告
# 用户参数
set data_width 128 ;# 数据宽度 (位)
set scope "/top/dut/axi_if" ;# 接口scope
set channel "write" ;# "write" or "read"
set time_windows [list {0 1000} {1000 2000} {2000 3000}] ;# 多窗口 (ns)
set output_file "axi_bw_report.csv" ;# 输出CSV
# 根据通道选择信号
if {$channel == "write"} {
set valid_sig "wvalid"
set ready_sig "wready"
set strb_sig "wstrb"
} elseif {$channel == "read"} {
set valid_sig "rvalid"
set ready_sig "rready"
set strb_sig "" ;# Read无strb, 假设全活跃
} else {
puts "Error: Invalid channel"
return
}
# 查询信号
set valid_hdl [npi_hdl_by_name -scope $scope -name $valid_sig]
set ready_hdl [npi_hdl_by_name -scope $scope -name $ready_sig]
if {$strb_sig != ""} {
set strb_hdl [npi_hdl_by_name -scope $scope -name $strb_sig]
}
if {$valid_hdl == "" || $ready_hdl == ""} {
puts "Error: Signals not found"
return
}
# 打开输出文件
set fp [open $output_file w]
puts $fp "Window Start,Window End,Effective Cycles,Total Bytes,Bandwidth (GB/s),Efficiency (%)"
# 循环每个窗口
foreach window $time_windows {
set time_start [lindex $window 0]
set time_end [lindex $window 1]
npi_set_time_window $time_start $time_end
set effective_cycles 0
set total_bytes 0
set total_cycles [expr int(($time_end - $time_start) / 1.0)] ;# 假设1ns/cycle, 调整为clk周期
set current_time $time_start
while {$current_time < $time_end} {
set val_valid [npi_get_value -hdl $valid_hdl -time $current_time -format decimal]
set val_ready [npi_get_value -hdl $ready_hdl -time $current_time -format decimal]
if {$val_valid == 1 && $val_ready == 1} {
set bytes_per_cycle [expr $data_width / 8.0]
if {$strb_sig != ""} {
set val_strb [npi_get_value -hdl $strb_hdl -time $current_time -format hex]
set active_strobes [expr [format "%d" 0x$val_strb]] ;# bit count简化
set bytes_per_cycle [expr $bytes_per_cycle * ($active_strobes / ($data_width / 8.0))]
end
set total_bytes [expr $total_bytes + $bytes_per_cycle]
incr effective_cycles
}
set current_time [expr $current_time + 1.0]
}
set time_duration [expr ($time_end - $time_start) / 1e9] ;# ns to s
set bandwidth [expr {$time_duration > 0 ? $total_bytes / $time_duration / 1e9 : 0}]
set efficiency [expr {$total_cycles > 0 ? ($effective_cycles * 100.0) / $total_cycles : 0}]
puts "Window [$time_start, $time_end]: BW=$bandwidth GB/s, Efficiency=$efficiency %"
puts $fp "$time_start,$time_end,$effective_cycles,$total_bytes,$bandwidth,$efficiency"
}
close $fp
puts "Report generated: $output_file"
脚本解释
-
参数:支持多窗口(list of pairs)、通道选择(write/read,读通道无wstrb假设全活跃)。
-
循环:为每个窗口设置npi时间窗,计算有效周期/字节/效率(efficiency = 有效周期 / 总周期 * 100%)。
-
报告:输出CSV文件,便于Excel绘图(e.g., BW vs. 时间)。
-
注意:循环步进1ns(假设分辨率);大窗口慢,可用npi_iterate_over_transitions迭代转换点优化。读通道类似替换信号(rvalid/rready无strb)。
-
运行:在Verdi中
source advanced_axi_bw.tcl
,生成CSV报告。
一般注意事项
- 精度:步进大小匹配模拟分辨率(e.g., clk=5ns则+5.0);wstrb计算可优化用bit population count函数(自定义Tcl proc)。
- 扩展:添加读/写双通道计算(总BW=写BW+读BW);集成PTPX(source此脚本后调用report_power)。
- 错误调试:如果信号未找到,检查scope路径;用
npi_list_hdl
列出可用信号。 - 性能:大fsdb/长窗口用
-preload off
加速加载;并行脚本需Verdi批模式。