FPGA EDA軟件的位流驗證

? ? ? ? 位流驗證,對于芯片研發是一個非常重要的測試手段,對于純軟件開發人員,最難理解的就是位流驗證。在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::type_id::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::type_id::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::type_id::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)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ::type_id::create("input_analysis_imp", this);
? ? ? ? output_analysis_imp = uvm_analysis_imp #(my_transaction, my_scoreboard)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?::type_id::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 支持工具/功能
SequenceSystemVerilog 編譯器直接支持 UVM sequence 的隨機生成和調試。
Driver通過 VCS 的時鐘精確仿真,支持 UVM driver 精確地驅動 DUT 信號。
MonitorUVM 信號分析器,與 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:生產測試發現問題,關注的是硬件的可靠性。

????????大概就是這樣了,對于仿真的實際運行的細節和實際的硬件相關,有空再說。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/66057.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/66057.shtml
英文地址,請注明出處:http://en.pswp.cn/web/66057.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

px、em 和 rem 的區別:深入理解 CSS 中的單位

文章目錄 前言一、px - 像素 (Pixel)二、em - 相對父元素字體大小 (Ems)三、rem - 相對于根元素字體大小 (Root Ems)四、綜合比較結語 前言 在CSS中,px、em和rem是三種用于定義尺寸(如寬度、高度、邊距、填充等)的長度單位。它們各自有不同的…

【CI/CD構建】關于不小心將springMVC注解寫在service層

背景 之前寫一個接口的時候沒有察覺到將RequestBody這個注解帶到service層了。 今天提交代碼的時候,插件沒有檢測到這個低級錯誤,導致試飛構建連maven編譯都過不了,maven找不到程序包org.springframework.web.bind.annotation這個包 結果…

Oracle Dataguard(主庫為雙節點集群)配置詳解(4):配置備庫

Oracle Dataguard(主庫為雙節點集群)配置詳解(4):配置備庫 目錄 Oracle Dataguard(主庫為雙節點集群)配置詳解(4):配置備庫一、為備庫配置靜態監聽1、配置 li…

《深入理解Mybatis原理》Mybatis中的緩存實現原理

一級緩存實現 什么是一級緩存? 為什么使用一級緩存? 每當我們使用MyBatis開啟一次和數據庫的會話,MyBatis會創建出一個SqlSession對象表示一次數據庫會話。 在對數據庫的一次會話中,我們有可能會反復地執行完全相同的查詢語句&…

win32匯編環境,窗口程序中單選框的一般操作示例

;運行效果 ;win32匯編環境,窗口程序中單選框的一般操作示例 ;比如在窗口程序中生成單選框,默認哪項選中,判斷當前選中哪一項,讓哪項選中,得到選中項的名稱等 ;直接抄進RadAsm可編譯運行。重點部分加備注。 ;以下是ASM文件 ;>&g…

從transformer到informer

Transformer和Informer都是深度學習領域中的模型架構,它們主要用于處理序列數據,如自然語言處理(NLP)和時間序列預測任務。 **Transformer**: Transformer模型最初在2017年由Google的研究者提出,它在NLP領…

hive知識體系

hive知識體系 hive知識體系 鏈接: 1Hive概覽 鏈接: 2Hive表類型 鏈接: 3Hive數據抽樣 鏈接: 4Hive計算引擎 鏈接: 5Hive存儲與壓縮 鏈接: 6Hive Sql 大全 鏈接: 6Hive Sql 大全-Hive 函數 鏈接: 6Hive Sql 大全-窗口函數 鏈接: 7Hive執行計劃 鏈接: 8Hive SQL底層執行原理 鏈接…

優化 Azure Synapse Dedicated SQL Pool中的 SQL 執行性能的經驗方法

在 Azure Synapse Dedicated SQL Pool中優化 SQL 執行涉及了解底層體系結構(例如分布和分區)、查詢優化(例如避免不必要的子查詢和聯接),以及利用具體化視圖和 PolyBase 等工具進行高效數據加載。 1.有效使用分布和分…

個人主頁搭建全流程(Nginx部署+SSL配置+DCDN加速)

前言 最近開始準備秋招,打算做一個個人主頁,以便在秋招市場上更有競爭力。 目前,現有的一些搭建主頁的博文教程存在以下一些問題: 使用Github Page進行部署,這在國內訪問容易受阻使用寶塔面板等框架,功能…

Spring MVC簡單數據綁定

【圖書介紹】《SpringSpring MVCMyBatis從零開始學(視頻教學版)(第3版)》_springspringmvcmybatis從零開始 代碼、課件、教學視頻與相關軟件包下載-CSDN博客 《SpringSpring MVCMyBatis從零開始學(視頻教學版)(第3版&…

嵌入式系統Linux實時化(四)Xenomai應用開發測試

1、Xenomai 原生API 任務管理 Xenomai 本身提供的一系列多任務調度機制,主要有以下一些函數: int rt_task_create (RT_TASK task, const char name, int stksize, int prio, intmode) ; 任務的創建;int rt_task_start(RT_TASK task, void(entry)(void cookie), void cookie…

如何在Ubuntu上安裝和配置Git

版本控制系統(VCS)是軟件開發過程中不可或缺的工具之一,它幫助開發者跟蹤代碼變更、協作開發以及管理不同版本的項目。Git作為當前最流行的分布式版本控制系統,因其高效性和靈活性而廣受青睞。本文將指導你如何在Ubuntu操作系統上…

[python] bisect_right

等價于C中的upper_bound bisect_right 函數介紹 在Python的 bisect 模塊中, bisect_right (別名 bisect )用于在有序序列中查找插入點。插入點是在序列中插入元素后,序列仍保持有序的位置。 bisect_right 函數返回的插入點是在已…

Mac上安裝Label Studio

在Mac上安裝Anaconda并隨后安裝Label Studio,可以按照以下步驟進行: 1. 在Mac上安裝Anaconda 首先,你需要從Anaconda的官方網站下載適用于Mac的安裝程序。訪問Anaconda官網,點擊“Download Anaconda”按鈕,選擇適合M…

vscode開啟調試模式,結合Delve調試器調試golang項目詳細步驟

1.前期準備 (1).在vs code中的擴展程序中搜索并安裝Go擴展程序 (2).安裝 Delve 調試器 go install github.com/go-delve/delve/cmd/dlvlatest (3).打開vs code的命令面板,輸入Go: Install/Update Tools,并單擊該命令執行,安裝或更新Go語…

SQL面試題1:連續登陸問題

引言 場景介紹: 許多互聯網平臺為了提高用戶的參與度和忠誠度,會推出各種連續登錄獎勵機制。例如,游戲平臺會給連續登錄的玩家發放游戲道具、金幣等獎勵;學習類 APP 會為連續登錄學習的用戶提供積分,積分可兌換課程或…

爬山算法與模擬退火算法的全方面比較

一、基本概念與原理 1. 爬山算法 爬山算法是一種基于啟發式的局部搜索算法,通過不斷地向當前解的鄰域中搜索更優解來逼近全局最優解。它的核心思想是,從當前解出發,在鄰域內找到一個使目標函數值更大(或更小)的解作為新的當前解,直到找不到更優的解為止。 2.模擬退火算…

PostgreSQL 超級管理員詳解

1. 什么是 PostgreSQL 超級管理員 PostgreSQL 超級管理員(superuser)是擁有數據庫系統最高權限的用戶。他們可以執行任何數據庫操作,包括但不限于創建和刪除數據庫、用戶、表空間、模式等。超級管理員權限是 PostgreSQL 中權限的最高級別。 …

安裝本地測試安裝apache-doris

一、安裝前規劃 我的服務器是三臺麒麟服務器,2臺跑不起來,這是我本地的,內存分配的也不多。 fe192.168.1.13 主數據庫端口9030訪問 8Gbe192.168.1.13內存4G 硬盤50be192.168.1.14內存4G 硬盤50be192.168.1.12內存4G 硬盤5013同時安裝的fe和be 。 原理:192.168.1.13 服…

GPT(General Purpose Timer)定時器

基本概念: 在嵌入式系統中,General Purpose Timer(GPT)是一種非常重要的硬件組件,用于提供定時功能。 定義:通用定時器是一種能夠提供精確時間測量和控制功能的電子設備或電路模塊。它可以產生周期性的時…