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