位流驗證,對于芯片研發是一個非常重要的測試手段,對于純軟件開發人員,最難理解的就是位流驗證。在FPGA芯片研發中,位流驗證是在做什么,在哪些階段需要做位流驗證,如何做?都是問題。
我們先整體的說一下:
首先:在硬件設計階段,位流驗證是設計驗證部的重要工作,它是為了驗證硬件設計的數字電路部分的合理性,對于FPGA芯片,主要就是對標準的架構組件進行驗證。如果相應的EDA軟件未成形之前,相應的位流需要通過手工單獨生成。
然后:在FPGA配套的EDA軟件開發階段,位流驗證也非常重要。因為EDA軟件的最大目標就是生成正確的位流,位流輸出是否符合預期,關系到軟件各個環節的正確性。所以,一般會將位流驗證做為重要的回歸測試手段,一方面,可以持續驗證最新輸出軟件的正確性,另外,如果芯片的底層架構發生變化,模型變更,仿真庫變更,也可以通過位流驗證,保證架構更改的正確性(架構主要是按照硬件設計對應的軟件模型,而硬件設計的這些模型,都會有對應的仿真庫和參考模型,用于驗證)。
最后:在生產測試階段,位流驗證同樣是非常好的測試手段,它可以測試位流寫入芯片后上板上芯片的效果,確認芯片實際的運行情況。在軟件中只是保證了邏輯上的正確,實際結合電氣特性和各種不同環境是否能正常可靠運行,可能通過位流加載后的效果進行驗證。加載到實際板上的效果,也可以通過驅動程序取出,與預期參老模型的結果做對比,驗證其準確性。
當然,位流驗證可能并不僅限于上面的三種情況(限于我了解的內容有限),但通過上面的描述,你可以發現,位流驗證本身是就是會跨多個部門的比較特殊的手段,在不同部門做驗證時,一定會存在配合,和一些有相似的工作。但是,因為各自的目的不同,發現錯誤后,定位和糾錯的方向也很不一樣。反以,反過來說,選擇的相應示例也會有些不同。
今天,我們只講在EDA軟件如何利用位流驗證,完成對EDA軟件的重要回歸測試。
大概的講法是:
:我們會講解位流驗證依賴的框架UVM
:會講一下UVM的實現平臺。
:會講一下針對EDA軟件的驗證,會對哪些部分進行驗證,會使用什么樣的示例 。
:發現問題后,會如何通過輸出去定位錯誤。
:因為用于自動化回歸,也講一下相應的自動化平臺應該如何拱建。
首先,我們還是得再來理解一下位流驗證需要用到的UVM框架。
一:UVM框架
1.1:理論
Universal Verifacation Methodology:是一套基于SystemVerilog的標準驗證方法學。它提供了一套完整的框架,用于構建復雜的驗證環境,應用于芯片設計領域的功能驗證。旨在提高驗證的可重復性、可重用性和自動化程度。應該說,對于硬件設計的驗證,UVM是最基礎,最常用的平臺,離不開它。
2.1.1:DUT
待測設計——Design Under Test,就是你要驗證的設計單元。
如果你是要驗證/測試一顆 FPGA 芯片,DUT 一般會分為三種,一種是單Tile的設計,一種是多Tile的設計,還有就是整個芯片的設計。
注意這里我加了個bitstream,這并不是UVM必須的,加上bitstream是和我們今天要講的位流驗證扣題,也就是我們在驗證時,使用FPGA的位流文件,來形成DUT的功能。
env:Testbenc Environment ,除了DUT,其它就是UVM的驗證環境了,它包含了一大堆東西,后面一個一個介紹。
Sequencer:測試數據序列,因為測試時需要很多的輸入數據,我們按序列提供。
Driver:如何數據輸入DUT的過程,可以理解為激勵的過程。
Monitor:監控DUT的輸入/輸出信號
Reference Model:參考模型,對應DUT的設計,提供相同行為的給果。
這里參考模型的運行,一般我們會使用仿真工具的內置實現來完成。
Compare:比較DUT的輸出和參考模型的輸出,判斷是否匹配。
2.1.2:Sequencer
Sitmulus:生成測試數據序列。我們需要基于測試的需求,產生數據,交給Driver來驅動到DUT。比如:你要測試DSP的乘法,那就是提供相應的輸入數值對。
class my_sequence extends uvm_sequence #(my_transaction);
`uvm_object_utils(my_sequence)
task body();
my_transaction tr;
foreach (tr.data[i]) begin
tr.data[i] = $urandom_range(0, 255); // 隨機生成 8 位數據
start_item(tr); // 發送數據
finish_item(tr);
end
endtask
endclass
2.1.3:Driver
接收Sequencer的測試數據并將其轉換為DUT的輸入信號。
class my_driver extends uvm_driver #(my_transaction);
`uvm_component_utils(my_driver)
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req); // 接收 sequencer 的數據
@(posedge clk); // 時鐘同步
dut_input = req.data; // 將數據驅動到 DUT
seq_item_port.item_done();
end
endtask
endclass
2.1.4:Monitor
實時監控DUT的輸入和輸出信號,將監控到的數據送出到比較系統Compare,進行輸出分析。
class my_monitor extends uvm_monitor #(my_transaction);
`uvm_component_utils(my_monitor)
task run_phase(uvm_phase phase);
forever begin
@(posedge clk);
tr.data = dut_output; // 采集 DUT 的輸出數據
analysis_port.write(tr); // 將數據發送給 Scoreboard
end
endtask
endclass
2.1.5:Reference Model
參考模型,用于生成和DUT相同邏輯功能的輸出(Golden Model)。
基于相同的輸入激勵信號,獲得理想的輸出。
function bit [7:0] ref_model(input bit [7:0] data);
return data + 1; // 示例:參考模型輸出為輸入加 1
endfunction
2.1.6:Compare
這里的Compare,可能是簡單的比較結果的輸出,也可能是比較復雜的Scoreboard(一個記錄數據表)。根據比較結果,輸出不匹配的情況,并輸出報告。
class my_scoreboard extends uvm_scoreboard;
`uvm_component_utils(my_scoreboard)
task run_phase(uvm_phase phase);
my_transaction ref_tr, dut_tr;
forever begin
ref_tr = ref_fifo.get(); // 從參考模型接收預期數據
dut_tr = dut_fifo.get(); // 從 DUT 獲取實際輸出
if (ref_tr.data !== dut_tr.data)
`uvm_error("Mismatch", $sformatf("Expected: %0h, Got: %0h", ref_tr.data, dut_tr.data));
end
endtask
endclass
2.1.7:示例
我們再來一個完整的示例,說明一下各部分做的事情。
DUT設計—— 一個簡單的8位加法器。
DUT代碼:(對于位流驗證,輸入不是這個,后面會舉例說明)
module adder(
input logic [7:0] a,
input logic [7:0] b,
output logic [7:0] sum
);
assign sum = a + b;
endmodule
UVM環境:
這里需要定義一個Transaction,因為每次激勵的執行都是不同的事務,事務標明輸入和輸出。
Transaction 定義:
class my_transaction extends uvm_sequence_item;
rand bit [7:0] a, b; // 輸入信號
bit [7:0] expected_sum; // 參考模型生成的期望輸出
`uvm_object_utils(my_transaction)
// 構造函數
function new(string name = "my_transaction");
super.new(name);
endfunction
endclass
Sequencer:
class my_sequence extends uvm_sequence #(my_transaction);
`uvm_object_utils(my_sequence)
task body();
my_transaction tr;
repeat (10) begin
tr = my_transaction::create("tr");
tr.a = $urandom_range(0, 255); // 隨機生成輸入 a
tr.b = $urandom_range(0, 255); // 隨機生成輸入 b
start_item(tr); // 開始傳輸數據
finish_item(tr); // 結束傳輸數據
end
endtask
endclass
Driver:
class my_driver extends uvm_driver #(my_transaction);
`uvm_component_utils(my_driver)
// DUT 的接口
virtual adder_if dut_if;
// 構造函數
function new(string name = "my_driver", uvm_component parent);
super.new(name, parent);
endfunction
// 運行階段
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req); // 從 Sequencer 獲取數據
@(posedge dut_if.clk); // 等待時鐘上升沿
dut_if.a = req.a; // 驅動 DUT 輸入 a
dut_if.b = req.b; // 驅動 DUT 輸入 b
seq_item_port.item_done(); // 標記數據已完成
end
endtask
endclass
Monitor:
輸入監控
class input_monitor extends uvm_monitor;
`uvm_component_utils(input_monitor)
// DUT 接口
virtual adder_if dut_if;
uvm_analysis_port #(my_transaction) analysis_port; // 分析端口
function new(string name = "input_monitor", uvm_component parent);
super.new(name, parent);
endfunction
// 運行階段
task run_phase(uvm_phase phase);
forever begin
@(posedge dut_if.clk); // 等待時鐘上升沿
my_transaction tr = my_transaction::create("tr");
tr.a = dut_if.a; // 采集 DUT 輸入 a
tr.b = dut_if.b; // 采集 DUT 輸入 b
analysis_port.write(tr); // 將交易數據發送給分析端口
end
endtask
endclass
輸出監控:
class output_monitor extends uvm_monitor;
`uvm_component_utils(output_monitor)
// DUT 接口
virtual adder_if dut_if;
uvm_analysis_port #(my_transaction) analysis_port; // 分析端口
function new(string name = "output_monitor", uvm_component parent);
super.new(name, parent);
endfunction
// 運行階段
task run_phase(uvm_phase phase);
forever begin
@(posedge dut_if.clk); // 等待時鐘上升沿
my_transaction tr = my_transaction::create("tr");
tr.expected_sum = dut_if.sum; // 獲取 DUT 輸出 sum
analysis_port.write(tr); // 發送到分析端口
end
endtask
endclass
Compare:
class my_scoreboard extends uvm_scoreboard;
`uvm_component_utils(my_scoreboard)
uvm_analysis_imp #(my_transaction, my_scoreboard) input_analysis_imp;
uvm_analysis_imp #(my_transaction, my_scoreboard) output_analysis_imp;
my_transaction expected_tr, actual_tr;
function new(string name = "my_scoreboard", uvm_component parent);
super.new(name, parent);
input_analysis_imp = uvm_analysis_imp #(my_transaction, my_scoreboard)
::create("input_analysis_imp", this);
output_analysis_imp = uvm_analysis_imp #(my_transaction, my_scoreboard)
::create("output_analysis_imp", this);
endfunction
// 輸入數據分析
function void write(input my_transaction tr);
expected_tr = tr;
expected_tr.expected_sum = expected_tr.a + expected_tr.b; // 參考模型
endfunction
// 輸出數據分析
function void write(output my_transaction tr);
actual_tr = tr;
// 比較 DUT 輸出和參考模型的期望值
if (actual_tr.expected_sum !== expected_tr.expected_sum) begin
`uvm_error("Mismatch", $sformatf("Expected: %0d, Got: %0d",
expected_tr.expected_sum, actual_tr.expected_sum));
end
endfunction
endclass
2.1.8:位流驗證
那對于位流驗證,UVM是如何使用的呢?
1:首先,必須準備好你的FPGA的EDA軟件(準備好運行時需要的 Flow 的tcl命令)。給出你的芯片仿真時需要的Primitve仿真庫。
2:針對你要測試的全芯片或者部分tile,選擇你要測試的設計用例(需要有一定的代表性噢,可以是N多,需要有一定覆蓋度),用 flow 生成仿真用的門級網表文件,并輸出用例的route結果,輸出最終的bitstream。
3:開始對要測試的用例,編寫參考模型(也是另外一種實現方案)。
4:編寫激勵(測試)程序,提供相應的激勵數據序列。
5:在TestBench上,針對 DUT 的 RefModel模型進行仿真,驗證兩者輸出是否一致,如果一致,說明位流測試正常。比較的方法,要看測試用例的功能。
6:如果測試不正常,可以利用中間輸出,日志輸出,波形輸出等信息進行定位,查看出錯原因。
好了,那UVM框架是如何實現的呢?有什么支撐平臺和工具嗎?
1.2:支撐
那UVM這種框架是如何通平臺來支撐它的呢?我們以Synopsys的VCS為例,來說明它是如何支持的(當然,也可以使用Mentor提供的QuestaSim)。
1.2.1:工具
VCS(Verlog Compiler Simulator)是業界領先的仿真工具,原生支持UVM,它提供了一系列的工具和功能,全而覆蓋了UVM測試平臺中的各項工作。
UVM 組件 | VCS 支持工具/功能 |
---|---|
Sequence | SystemVerilog 編譯器直接支持 UVM sequence 的隨機生成和調試。 |
Driver | 通過 VCS 的時鐘精確仿真,支持 UVM driver 精確地驅動 DUT 信號。 |
Monitor | UVM 信號分析器,與 DVE 圖形工具集成,監控信號流。 |
Compare Scoreboard |
與覆蓋率分析工具集成,支持寄存器覆蓋率和功能覆蓋率的檢查。 |
Debug | 提供圖形化的 UVM Phase 調試工具,支持動態調試和波形交互分析。 |
Verification | 集成 DVE 和 Verdi 工具,查看波形和調試測試平臺的運行時行為。 |
基于VCS的功能,要實現UVM平臺,還需要封裝一些標準的命令,達成常見的功能。
1.2.2:平臺
為了實現UVM的基礎功能,我們需要提供一些封裝功能,我們稱之為平臺。因為VCS并不是直接針對UVM的,所以,我們需要針對它做一些封裝,然后我們基于封裝來使用,這樣,看起來就更像是一個針對UVM實現的平臺了。
基本功能如下:(封裝方法可以使用Python或其它腳本語言來實現)
平臺初始化:
確認 測試平臺的主目錄,測試工程目錄,測試用例目錄,工具目錄,輸出目錄……
設置重要參數:
測試的代碼列表庫
測試用例的分組
運行次數
是否調試模式:提供更多log輸出
提供隨機種子數:用于控制輸入參數的隨機種子,控制測試數據的生成。
……
編譯/構建:
我們的testbench的代碼還是相對比較復雜的,另外,它也依賴于背后的仿真平臺提供的大量的庫文件,所以,我們一般需要對testbench的代碼進行構建,輸出各種我們需要的環境。
首先要對DUT代碼進行編譯,一般是SystemVerilog代碼。
一般會使用 Makefile,需要編寫相應的makefile,主要是需要將用到的UVM的動態庫和引用資源進行構建。VCS有一些針對UVM的支撐庫。
仿真:
直接調用VCS的仿真,有低功耗的仿真模式可選
波形分析:
輸出波形,用于Verdi波形調試
代碼覆蓋率統計:
統計測試的代碼覆蓋率
……
1.2.3:運行
在運行期,為了保證示例可以并行執行,一般會使用HPC集群環境。我們可以使用LSF集群管理,通過 bsub 來將相應的任務,提交到HPC中運行。
比如:
‘一般會把任務分為多條,按順序將任務放入同一個隊列,保證先后次序
bsub -n 1 -M 20480 -q dv_test -Is "上面封裝的命令,完成編譯或仿真或波形分析的功能"
以上是運算支撐最基本的要求。詳細的實現,我們后面會展開給個實例來講。
二:位流驗證
對于位流驗證,我們今天要講的主要是 FPGA的EDA工具測試,在EDA工具的Flow已基本成形的情況下,就可以開始搭建位流驗證平臺了,用于回歸/驗證EDA工具的功能。
2.1:流程圖
我們先來解釋一下上面的典型流程:
測試用例RTL文件
使用FPGA的器件的用例。測試用例文件,一般是DeviceModel提供的一些適合于驗證功能的標準用例。作為待測用例。(這些用例,一般是由簡到繁)
EDA Flow
FPGA的軟件工具的運行flow,在自動化運行時,一般是采用無界面的tcl命令來執行。
這里需要保留多個輸出:
綜合/映射后的網表:這是針對所有Primitve的電路實現,可以理解為羅列出,我們的設計最終實際用到了哪些邏輯的實例。就是可以看到設計最終使用的Instance,有明確的標識名稱。
Route后輸出的路由文件:這個用來定位所有實例Instance在芯片中實際的物理位置。也就是Impl后,實際上物理芯片上使用的邏輯塊和相應的布線。結合上一步的輸出,可以明確查到實例具體的位置,以及走線的路徑。
Bitstream 位流:這個是生成的bitstream,這個作為Dut的輸入,直接加載到測試平臺(如:VCS),加上提前準備好的芯片的原生的仿真庫,仿真平臺可以實際的模擬芯片的運行,并且得到相應的運行中結果和中間輸出。
用例的TestBench
根據實際情況,生成的tb文件。包含激勵,定位,比較的邏輯。
測試用例表:原始的測試用例
Primitive行為模型:明確這個Primitive的行為是什么,在尋找參考模型時,需要找到對應的參考實現。
解析輸入/輸出管腳:找出輸入IO 和 輸出IO,這個可以在Route 中找到。
編寫用例參考模型:根據Primitive的行為和你的設計用例,寫等價的功能。注意,這里的等價模型,一般是仿真平臺直接執行出結果(并不是基于FPGA的邏輯電路來執行)。
設計輸入的激勵信號:設計測試的輸入數據和相應的序列。
編寫比較函數:看如何比較兩者的輸出。對于返回值 ,可以簡單比較輸出。對于時序,可能需要檢查波形,一般是選擇幾個關鍵的點,不可能全部檢查。
位流測試平臺
結合位流文件,仿真庫,testbech ,使用UVM平臺進行實際的運行。完成代碼的編譯,構建,仿真,結果比較的功能。
測試結果
實際比較結果,將結果輸出到指定位置,并形成報告。
對于失敗的報告,還可以通過查看其它輸出(日志,波形等),具體進行問題定位。
對于覆蓋度的統計,可以查看目前回歸用例的覆蓋度,進而逐漸提升。
2.2:驗證的問題
如果2.1驗證出問題,那可能有哪些問題呢?我們可以看看。
文件的問題
可能是測試用例的問題,route輸出的問題(net丟失之類),postmap輸出的問題……
IOPackage的問題
可能是IO Pad的錯誤,這可能是IO Package的問題。可能是輸入Pad,也可能是輸出Pad不對。IO配置不對,配置信號不對,綁定約束的處理問題。
路由的問題
提供的switch box 的連接不對。
邏輯單元不對
模塊的配置有問題,配置問題導致功能出錯,模塊到Switch box的連線問題
其它
DeviceModel建模的問題,也有可能是Primitive實現的問題(硬件方面的)
具體的定位,可以通過源代碼,PostMap文件,route文件來查到具體的實例,然后在VCS的仿真器上,查看具體時點的輸出,這里可能是需要使用工具查看波形。
route文件,postmap文件(這個一般是打平的flattern文件)的具體格式就不方便給出樣例了,這個每家FPGA的格式會有所不同。
三:FPGA芯片驗證方法
我們設計出來的FPGA芯片,是否能滿足預期。我們要保證我們提供給用戶的FPGA上每一個器件的功能是符合預期的,也就是單個tile的功能,以及Tile之間的連接,整體芯片的邏輯是完全正常的。
所以,我們需要針對單Tile,多Tile,fullchip做位流驗證。方法就是使用上面的位流驗證平臺。針對這三種方法,我們分別來說明,說明應該如何設計樣例 ,來達成相應的結果。
3.1:單Tile位流驗證
對于每一種Tile做單獨的測試(所有的Primitive),比如:CLB(LUT,CLA,DFF,SFTR……),CMT,IO,DSP,BRAM,EMRAM,FIFO,OBUF,IBUF,IOBUF,……
并且也包括Tile內部的連接信號路由的驗證。
我們以CLB為例:
對于CLB,里面主要涉及不同的LUT,DFF,CLA,SFTR,需要設計一系列的用例,去覆蓋相關的器件使用。
我們以最簡單的 Lut2為例,來看看如何構建測試用例,參考用例,激勵數據,結果比較。
3.1.1:CLB —— LUT2
首先,我們要了解Lut2的原理,它是由2輸入1輸出組成,可以完成 2個單bit輸入1個輸出的任何邏輯。比如:a & b,a | b , a xor b。
一般來說,廠商會提供 LUT2的Primitive IP,我們假如提供的IP就叫做 YY_LUT2。
那么,對于Dut,那就很簡單了。注意 a & b 的真值 表是 1000b 也就是 h8
Dut的設計代碼:
moudule And2(
input a,
input b,
output result
);
YY_LUT2 #(.INIT(4'h8)) lut2(.Io(a), .I1(b), .O(result));
end module
將該代碼使用 eda flow 執行,生成 bitstream。
我們來看一下參考用例的寫法:
module RefModel(input A,
input B,
output Y);
assign Y = A & B ; // 參考模型的布爾函數
endmodule
以上的代碼,仿真工具在運行時,會在每個仿真周期,根據輸入數據的變化來重新輸出結果。對應的邏輯表達式的運算是在仿真器中執行(實際上就是語法解析,然后交給CPU來執行了)。
當然,你的示例還可以是 A | B,A xor B,若干的樣例。
另外:
INIT=0 IS_C_INVERTED = 0 IS_CLR_INVERTED=1 可以驗證 DFFCE 的功能
1bit加,1bit 減 可以驗證CLA功能
wclk極性不反轉 驗證 SFTR32
將INIT、IC_C_INVERTED、IS_PRE(CLR/R/S/)_INVERTED的值進行隨機,inst約束到FFA0 驗證 LPQCE
3.1.2:DSP
我們再以DSP為例,選擇合適的用例(針對DSPX18 的 2個輸入乘法)
直接調用 YY_DSP48_CPLX18 ,具體就不寫了。
具體如何設置用例,需要根據DSP48_CPLX18的輸入參數來設置,盡量保證相關的參數可覆蓋。
3.2:多Tile位流驗證
需要驗證 Tile間路由的正確性,在多個tile分配資源,全局信號,時鐘可以正常共享,跨tile的優化結果符合預期。主要是對一組tile,某個功能區域進行驗證。驗證多個tile的功能及其之間的交互。可以用來驗證協同工作,比如:DSP 與 BRAM的協同工作情況,驗證范圍有限,無法覆蓋全芯片的全局資源,比如:時鐘網絡,全局布線等。
需要構造如下用例:
長路徑信號傳輸:
Tile間級聯:多個tile之間的邏輯級聯(比如:多級加法器)
Tile內外通信:在不同Tile實現的模塊之間進行通信(如:FIFO,AXI總線)
3.3:全芯片位流驗證
對于全局資源(如:時鐘,全局線)的使用進行驗證。關注邊界行為(I/O引腳,DDR,PCIe)。
需要構建的用例 :
設計一條覆蓋盡可能多Tile的信號路徑,從一個邊界Tile傳播到對角線另一側。
在設計中啟動全局時鐘。
包含外部接口(I/O,DDR,PCIe)在設計中。
選用的用例,一般會是一些經典的電路設計,比如:FPGA一般會和閃存配合使用,那我們就選用一些標閃的閃存器件來搭建用例(因為閃存用例是有公開的行為模型和仿真庫的)
因為是針對整個芯片的測試,所以,激勵數據,應該采用jtag方式輸入,涉及到PRAM的操作。相對比較復雜,這里不再展開細說。
3.4:代碼的測試覆蓋率
測試是否有效,主要看覆蓋率,所以,在仿真運行中輸出測試覆蓋率,是非常重要的指標。
覆蓋率報告通常包括以下信息:
總體覆蓋率:
顯示整個設計的總體覆蓋率(如行覆蓋率、分支覆蓋率等)。
模塊級覆蓋率:
顯示每個模塊的覆蓋率詳情。
代碼行覆蓋率:
顯示每一行代碼是否被執行。
分支覆蓋率:
顯示每個分支是否被覆蓋。
條件覆蓋率:
顯示每個布爾表達式的條件組合是否被覆蓋。
狀態機覆蓋率:
顯示狀態機的所有狀態和狀態轉換是否被覆蓋。
翻轉覆蓋率:
顯示信號是否發生了 0 到 1 或 1 到 0 的翻轉。
代碼覆蓋度能夠查看測試的完整度。是非常重要的參考指標。
最后我們來看看,要搭建一個自動化的驗證平臺,需要做一些什么樣的工作:
這部分是一個封裝動作,和驗證本身的關系并不是很大,但如果對驗證的細節不清楚,也不能搭建一個好的,可擴展的平臺,因為平臺的功能也不是一成不變的,需要有一個演進的過程。如果有好的設計,自然最佳。
四:位流驗證的自動化平臺
4.1:平臺架構
這軟件EDA的位流驗證的架構。如果驗證是上板驗證(生產測試中心)。那位流的運行就不是在仿真環境,而是在板上的物理芯片運行,然后想辦法把物理芯片的運行結果,按時序取回,然后進行對比。
4.2:資源管理
需要管理的資源:
平臺的代碼
主要是流程控制的代碼,Python,Shell腳本,主要是存放到Git中,應該需要管理版本,
一般會是解釋性腳本語言,不會有編譯/構建的過程。
測試工程
每一次回歸測試,我們定義為一個工程。而工程會描述所有運行的輸入,輸出。
工程的定義:針對某個芯片,某種驗證方式,某個器件的測試,我們認為是一個驗證工程。
待驗證芯片——芯片的系列(架構),具體輸出的芯片版本號(鎖定的版本)
待驗證的內容—— FullChip,或者 TILE_CLB_LUT2,或者 BRAM & DSP 的聯合工程。
對應的仿真庫——不同驗證點,需要提供不同的仿真庫,比如 fullchip和單tile需要的仿真庫是不同的。但相對固定,基本上是提前準備好的。但是如果芯片的架構發生變化,需要做相應的更換。也可以理解芯片系列的版本發生變化。
對應的待測式DUT——待測試的DUT的測試用例。
DUT 對應的RefModel—— 對應的參考模型。
相關的配置信息——可能存在一些配置,可能待測內容不同,配置會有所不同。略
輸出目錄——包括位流輸出目錄(包括一些中間文件輸出),最終輸出目錄。
DUT Testbench
每個待測工程,都需要有一個TestBench 代碼,TestBench 用來定義整個測試的過程。包括如何使用生成的位流進行仿真運行,如何調用RefModel(Golden case)獲得結果,兩者如何進行比較,如何輸出。
注意,不同測試工程,可能代碼會有所不同。
測試用例
測試用例是針對芯片待測單元的調用。可能需要覆蓋待測單元的大多數輸入組合。這些用例需要進行統一管理,在需要時,在測試工程中配置。
比如:針對 LUT1的測試用例 (只需要初始化一下真值表即可)
YY_LUT1 # ( INIT (2'h3) inst_lut1() // o = a
參考模型代碼
針對測試用例,與之對應的另外一種實現(不依賴于FPGA),直接在VCS中運行。如果需要考慮時序,該模型代碼需要打拍。
比如:assign o = a 就是針對上面的LUT1用例的Golden case。
其它配置
配置EDA工具的運行環境,這個是可以按需配置,因為對于EDA,研發每天都會有新的版本。
4.3:調度平臺
因為需要自動化,必須要有調度,這樣可以定時自動執行。
可以通過腳本控制執行的入口和過程,控制超時時間,控制運行的隊列(串行還是并行),可以將大任務發到計算集群。
調度很簡單,一般使用 Jekins的 Pipeline即可,Jekins支持Shell,可以進行任務的編排。
4.4:位流生成
位流生成,就是使用j最新EDA和相應的flow tcl ,用來生成位流。
位流生成需要注意幾個點:
可能會添加固定的物理約束,簡化輸出,明確實際的 IOPAD。
4.5:仿真運行
對于test bencch 運行,會有多個步驟。
激勵數據的處理
這里要看一下,是否需要形成有針對性的激勵數據。可能和位置轉換有關(實際位置可以通過位流輸出的 instance和 route信息,獲取實際的位置信息)。
test bench 代碼編譯
針對 test bench代碼,建議采用makefile進行編譯/構建,這樣比較容易針對VCS進行動態鏈接和引用,也定義輸出的動作。
test bech 仿真運行
使用仿真平臺,輸入激勵,進行仿真,輸出波形,輸出代碼覆蓋度。
對Golden Case 進行運行,輸入激勵,執行輸出。
兩者進行比較,在仿真log中輸出
4.6:結果輸出
收集結果,確認是否成功,輸出最終報告。
可能還會輸出一些必要的數據,波形,代碼覆蓋度之類。
五:其它
5.1:硬件設計驗證
對于硬件部的位流驗證,實際上基本上是一致的。不同之處主要有:
1:在EDA的位流生成功能不成熟前,需要有其它方式生成位流。
2:硬件驗證不通過的情況,會關注硬件本身的設計,而不是位流的生成。關注點會有所不同。
5.2:生產測試中心位流驗證
對于生產測試中心,需要實際上板測試。所以。
1:位流需要download到實際芯片上運行,激勵需要實際輸入到芯片。
2:參考模型與軟件一樣,但注意,大多數時候要考慮時序,而不是簡單的組合邏輯。
3:對于實際芯片的運行輸入/輸出,一般需要做特殊處理,比如:設計專用電路,完成激勵輸入,設計驅動程序將輸出數據寫入本地磁盤,然后通過磁盤文件獲取結果,進行比較。
輸出的文件需要表達時序信息。
4:生產測試發現問題,關注的是硬件的可靠性。
原文鏈接:https://community.sslcode.com.cn/6789d33a59bcf8384aa65e71.html
-
FPGA
+關注
關注
1643文章
21985瀏覽量
615097 -
芯片
+關注
關注
459文章
52282瀏覽量
437509 -
eda
+關注
關注
71文章
2902瀏覽量
176740 -
數字電路
+關注
關注
193文章
1637瀏覽量
81660
原文標題:FPGA EDA軟件的位流驗證
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
驗證中的FPGA原型驗證 FPGA原型設計面臨的挑戰是什么?
FPGA設計新需求走熱 EDA戰況升溫
設計與驗證Verilog HDL FPGA設計與驗證的好書
FPGA設計的仿真驗證概述
基于EDA技術的FPGA該怎么設計?
基于EDA技術的FPGA該怎么設計?
EDA軟件的安裝與配置(僅針對開發Altera FPGA)
EDA Tools in FPGA
基于多種EDA工具的FPGA設計

芯片設計EDA軟件的使用
什么是板級EDA軟件 eda器件分幾類 數字EDA和模擬EDA的區別
使用加密和身份驗證來保護UltraScale/UltraScale+ FPGA比特流

評論