继续最近的交付总结系列更新,本篇遇到和处理的问题和带宽统计以及性能有关。简单说就是在推进过程中,需要一些方法来实时/分阶段/整体的统计一下有效带宽,以确定一些环境的异常报错是环境引起的还是RTL内部的问题。
最开始想到了多年前的一个统计带宽的脚本,这个脚本是tcl做的工具,能够嵌入verdi里,然后对着你的波形一顿扫描。只要你的波形里做了en和size两个信号,脚本就能够统计出从黄线到白线之间的总数据量,然后根据时间计算出来平均带宽。
对了,统计的时候这个黄线还在实时动态的往白线那移动,所以很长时间我都觉得这个脚本太神奇了。后来试了好几次想复现但是因为tcl的基础太弱对verdi的dpi也不熟悉,所以一直搞不出来,如果谁会咱们好好聊一聊。所以没有办法,就另辟蹊径吧。
目前需求比较明确:
1.能够进行感兴趣时间段的流量带宽统计;
2.不影响已有的RTL结构和验证环境,独立于RTL交付和验证环境之外;
3.可以同时监控多个模块、多个接口的流量;
基于这三个需求,我觉得用一个RTL的组件来做可以了,没有太难。于是快进到组件的开发,在此也没研究有没有现成的组件哈,总觉得简单的这个功夫自己就写完了(?_?)。先看进行带宽统计,这个其实不难办,核心就是跟刚刚提到的脚本一样做一个模块对关心的接口进行采样。所以把这个模块的顶层搞出来:
module flow_cnt #( //parameter parameter realtime START_TIME = 0ns, parameter realtime END_TIME = -1ns, parameter BIT_W = 10, //max 1023bit per cycle parameter MAX_W = 64 //bit cnt max)( /*AUTOARG*/ // Inputs clk, rst_n, power, bit_cnt );
// ----------------------------------------------------------------// Interface declare// ----------------------------------------------------------------input clk;input rst_n;input power;input [BIT_W -1:0]bit_cnt;
endmodule四个parameter,START_TIME~END_TIME就是我们关心的时间段,BIT_W是送进来的size(模块里我叫bit_cnt)的位宽,MAX_W是内部数据量计数器的位宽。
接口就更简单了,时钟复位使能和使能时的数据有效量。顶层搞定了,那里面怎么办呢,也很简单在关心的时间段里power有效就把bit_cnt往上累加呗(要是累加加翻了就把MAX_W设置的大一些嗷):
logic [MAX_W -1:0]whole_bit_cnt;
always @(posedge clk or negedge rst_n) begin if(!rst_n) begin whole_bit_cnt end else if($realtime>=START_TIME && ($realtime if(power) whole_bit_cnt end end然后,等到时间一超过END_TIME,就根据累加值和时间间隔,把带宽给算出来:initial begin: BANDWIDTH_REPORT real flow_bandwidth; realtime time_duration; while(1)begin @(posedge clk); if($realtimebegin continue; end else begin time_duration = $realtime - START_TIME; flow_bandwidth = whole_bit_cnt/time_duration; $display("=============================================================================="); $display("%m bandwidth report at %t:", $realtime); $display(" whole_bit_cnt = %0dbit = %0dByte", whole_bit_cnt, whole_bit_cnt/8); $display(" time_duration = %t", time_duration); $display(" flow_bandwidth = %fGbps", flow_bandwidth); $display("=============================================================================="); break; end endend好了,代码看起来就搞定了。开始思考第二个需求,如何合入已有的RTL结构和验证环境中,还能尽量不影响原本的代码呢?例化在RTL内是肯定不可能的,例化在验证环境中还要去动别人的代码,这也不行那也不行,就只能借助bind来搞定了。在绝大部分场景中,bind都是用来搞并发断言的,但其实bind的使用场景很多,各种我们自己写的不需要交付的辅助小组件小模块都可以用bind的方式与需要监控的模块或结构进行绑定。那么再看下第三个需求,可以监控多模块多接口。那其实这件事也就简单了,在flow_cnt上封装一个顶层,在顶层里对确切的某个inst进行bind就可以了呀!
我们借助sync_fifo那个验证环境,在该环境中sync_fifo例化在testbench中:
//-------------------------------------{{{rtl instsync_fifo #( .WIDTH(WIDTH), .DEPTH(DEPTH)) u_sync_fifo( .clk(clk), .rst_n(rst_n), .afull_th(afull_th), .aempty_th(aempty_th), .winc(winc), .wdata(wdata), .wfull(wfull), .almost_wfull(almost_wfull), .rinc(rinc), .rdata(rdata), .rempty(rempty), .rvld(rvld), .almost_rempty(almost_rempty));我们监控其一段时间内的输出带宽,那么power即rvld信号,bit_cnt其实就是WIDTH每笔数据固定的数据量为WIDTH。因此在flow_cnt.sv同一层级做bind_fifo_flow_cnt.sv文件,文件内容如下:bind testbench.u_sync_fifo flow_cnt #( .START_TIME(800ns), .END_TIME(80000ns)) u_fifo_flow_cnt( .clk(clk), .rst_n(rst_n), .power(rvld), .bit_cnt(WIDTH));将testbench.u_sync_fifo的信号和parameter作为flow_cnt的输入,将flow_cnt bind在testbench.u_sync_fifo模块上进行接口采样,采样时间为800ns~80000ns。然后只需要把这两个文件放到filelist中,而不需要对验证环境进行任何的改动:
+libext+.v+.sv+incdir+/home/ICer/gitee_path/verilog_fifo_code/src/ut_ver/../rtl-y /home/ICer/gitee_path/verilog_fifo_code/src/ut_ver/../rtl
/home/ICer/gitee_path/verilog_fifo_code/src/bind/flow_cnt.sv/home/ICer/gitee_path/verilog_fifo_code/src/bind/bind_fifo_flow_cnt.sv
../ver/sync_fifo_pkg.sv/home/ICer/gitee_path/verilog_fifo_code/src/ut_ver/../rtl/sync_fifo.v../top/testbench.sv咱们先来理论上算一下,目前环境的配置是时钟周期10ns,fifo位宽WIDTH=16,如果满通路输出那么计算的平均带宽应该是:16bit/10ns = 1.6 * 10^9 bps = 1.6Gbps在sim目录下执行仿真,得到仿真结果:
对应时间段的波形确实是满带宽输出:
看起来好像算的还是挺准的。那么因为有个bind_fifo_flow_cnt.sv这个顶层存在,只需要在bind时给定具体inst路径,就可以在该文件里对感兴趣的多个模块和内部总线进行监控了。
基本的工作就完成啦!后面只需要按自己的需求,在flow_cnt.sv的基础上分装一个axi_flow_cnt.sv来对AXI总监挂接监控带宽就可以,这里就不多聊了。
系列文章入口——
【芯片设计】SoC 101(一):绪论 | 【芯片设计】FIFO漫谈(零)从无处不在的FIFO开始说起 | 【芯片设计】计算机体系结构(一)虚拟内存 | 【芯片设计】深入理解AMBA总线(零)绪论
| 【芯片设计】握手协议的介绍与时序说明 | 【芯片设计】复位那些小事 —— 复位消抖 | 【芯片设计】快速入门数字芯片设计(一)Introduction | 【芯片验证】UVM源码计划(零)下定决心读源码前的自测环节
| 【芯片设计】异步电路碎碎念(一) 到底什么是异步电路
| 【芯片设计】从RTL到GDS(一):Introduction
| 其他文章链接——
【芯片验证】sva_assertion: 15道助力飞升的断言练习 | 【芯片验证】可能是RTL定向验证的巅峰之作 | 【芯片验证】RTL仿真中X态行为的传播 —— 从xprop说起 | 【芯片验证】年轻人的第一个systemVerilog验证环境全工程与解析 |
【芯片设计】verilog中有符号数和无符号数的本质探究
| 【芯片设计】论RTL中always语法的消失术 | 【芯片设计】代码即注释,注释即代码 | 【芯片设计】700行代码的risc处理器你确实不能要求太多了 |
入职芯片开发部门后,每天摸鱼之外的时间我们要做些什么呢 | 如何计算系统的outstanding 和 burst length? | 芯片搬砖日常·逼死强迫症的关键词不对齐事件 | 熟人社会里,一群没有社会价值的局外人 |
|