繼續(xù)最近的交付總結(jié)系列更新,本篇遇到和處理的問題和帶寬統(tǒng)計以及性能有關(guān)。簡單說就是在推進過程中,需要一些方法來實時/分階段/整體的統(tǒng)計一下有效帶寬,以確定一些環(huán)境的異常報錯是環(huán)境引起的還是RTL內(nèi)部的問題。
最開始想到了多年前的一個統(tǒng)計帶寬的腳本,這個腳本是tcl做的工具,能夠嵌入verdi里,然后對著你的波形一頓掃描。只要你的波形里做了en和size兩個信號,腳本就能夠統(tǒng)計出從黃線到白線之間的總數(shù)據(jù)量,然后根據(jù)時間計算出來平均帶寬。
對了,統(tǒng)計的時候這個黃線還在實時動態(tài)的往白線那移動,所以很長時間我都覺得這個腳本太神奇了。后來試了好幾次想復(fù)現(xiàn)但是因為tcl的基礎(chǔ)太弱對verdi的dpi也不熟悉,所以一直搞不出來,如果誰會咱們好好聊一聊。所以沒有辦法,就另辟蹊徑吧。
目前需求比較明確:
1.能夠進行感興趣時間段的流量帶寬統(tǒng)計;
2.不影響已有的RTL結(jié)構(gòu)和驗證環(huán)境,獨立于RTL交付和驗證環(huán)境之外;
3.可以同時監(jiān)控多個模塊、多個接口的流量;
基于這三個需求,我覺得用一個RTL的組件來做可以了,沒有太難。于是快進到組件的開發(fā),在此也沒研究有沒有現(xiàn)成的組件哈,總覺得簡單的這個功夫自己就寫完了(?_?)。先看進行帶寬統(tǒng)計,這個其實不難辦,核心就是跟剛剛提到的腳本一樣做一個模塊對關(guān)心的接口進行采樣。所以把這個模塊的頂層搞出來:
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就是我們關(guān)心的時間段,BIT_W是送進來的size(模塊里我叫bit_cnt)的位寬,MAX_W是內(nèi)部數(shù)據(jù)量計數(shù)器的位寬。
接口就更簡單了,時鐘復(fù)位使能和使能時的數(shù)據(jù)有效量。頂層搞定了,那里面怎么辦呢,也很簡單在關(guān)心的時間段里power有效就把bit_cnt往上累加唄(要是累加加翻了就把MAX_W設(shè)置的大一些嗷):
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,就根據(jù)累加值和時間間隔,把帶寬給算出來: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結(jié)構(gòu)和驗證環(huán)境中,還能盡量不影響原本的代碼呢?例化在RTL內(nèi)是肯定不可能的,例化在驗證環(huán)境中還要去動別人的代碼,這也不行那也不行,就只能借助bind來搞定了。在絕大部分場景中,bind都是用來搞并發(fā)斷言的,但其實bind的使用場景很多,各種我們自己寫的不需要交付的輔助小組件小模塊都可以用bind的方式與需要監(jiān)控的模塊或結(jié)構(gòu)進行綁定。那么再看下第三個需求,可以監(jiān)控多模塊多接口。那其實這件事也就簡單了,在flow_cnt上封裝一個頂層,在頂層里對確切的某個inst進行bind就可以了呀!
我們借助sync_fifo那個驗證環(huán)境,在該環(huán)境中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));我們監(jiān)控其一段時間內(nèi)的輸出帶寬,那么power即rvld信號,bit_cnt其實就是WIDTH每筆數(shù)據(jù)固定的數(shù)據(jù)量為WIDTH。因此在flow_cnt.sv同一層級做bind_fifo_flow_cnt.sv文件,文件內(nèi)容如下: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中,而不需要對驗證環(huán)境進行任何的改動:
+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咱們先來理論上算一下,目前環(huán)境的配置是時鐘周期10ns,fifo位寬WIDTH=16,如果滿通路輸出那么計算的平均帶寬應(yīng)該是:16bit/10ns = 1.6 * 10^9 bps = 1.6Gbps在sim目錄下執(zhí)行仿真,得到仿真結(jié)果:
對應(yīng)時間段的波形確實是滿帶寬輸出:
看起來好像算的還是挺準(zhǔn)的。那么因為有個bind_fifo_flow_cnt.sv這個頂層存在,只需要在bind時給定具體inst路徑,就可以在該文件里對感興趣的多個模塊和內(nèi)部總線進行監(jiān)控了。
基本的工作就完成啦!后面只需要按自己的需求,在flow_cnt.sv的基礎(chǔ)上分裝一個axi_flow_cnt.sv來對AXI總監(jiān)掛接監(jiān)控帶寬就可以,這里就不多聊了。
系列文章入口——
【芯片設(shè)計】SoC 101(一):緒論 | 【芯片設(shè)計】FIFO漫談(零)從無處不在的FIFO開始說起 | 【芯片設(shè)計】計算機體系結(jié)構(gòu)(一)虛擬內(nèi)存 | 【芯片設(shè)計】深入理解AMBA總線(零)緒論
| 【芯片設(shè)計】握手協(xié)議的介紹與時序說明 | 【芯片設(shè)計】復(fù)位那些小事 —— 復(fù)位消抖 | 【芯片設(shè)計】快速入門數(shù)字芯片設(shè)計(一)Introduction | 【芯片驗證】UVM源碼計劃(零)下定決心讀源碼前的自測環(huán)節(jié)
| 【芯片設(shè)計】異步電路碎碎念(一) 到底什么是異步電路
| 【芯片設(shè)計】從RTL到GDS(一):Introduction
| 其他文章鏈接——
【芯片驗證】sva_assertion: 15道助力飛升的斷言練習(xí) | 【芯片驗證】可能是RTL定向驗證的巔峰之作 | 【芯片驗證】RTL仿真中X態(tài)行為的傳播 —— 從xprop說起 | 【芯片驗證】年輕人的第一個systemVerilog驗證環(huán)境全工程與解析 |
【芯片設(shè)計】verilog中有符號數(shù)和無符號數(shù)的本質(zhì)探究
| 【芯片設(shè)計】論RTL中always語法的消失術(shù) | 【芯片設(shè)計】代碼即注釋,注釋即代碼 | 【芯片設(shè)計】700行代碼的risc處理器你確實不能要求太多了 |
入職芯片開發(fā)部門后,每天摸魚之外的時間我們要做些什么呢 | 如何計算系統(tǒng)的outstanding 和 burst length? | 芯片搬磚日!け扑缽娖劝Y的關(guān)鍵詞不對齊事件 | 熟人社會里,一群沒有社會價值的局外人 |
|