[PV]用Verdi计算AXI带宽的Tcl脚本

用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的核心步骤:

  1. 加载fsdb文件。
  2. 指定时间窗口(time window)。
  3. 查询AXI信号(e.g., /top/dut/axi_if/wvalid, wready, wdata, wstrb, wlast)。
  4. 统计有效周期(valid && ready)。
  5. 计算总有效字节 = 有效周期 × (数据宽度 / 8) × active strobes (wstrb位计数)。
  6. 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批模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

元直数字电路验证

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值