このページは機械翻訳を使用して翻訳されました。元の英語を参照するには、ここをクリックします。
SystemVerilog DPI を UVM フレームワーク ワークフローに統合する
この例では、HDL Verifier™ ソフトウェアを使用して、Simulink® モデルから SystemVerilog DPI コンポーネントとして再利用可能な検証コンポーネントを生成する方法を示します。MATLAB-to-UVMF (mtlb2uvmf) ワークフローを使用して、Universal Verification Methodology (UVM) テストベンチを迅速に作成します。mtlb2uvmf ワークフローの詳細については、Siemens Verification Academy の MathWorks Integration を参照してください。
RTL 設計は、その規模と複雑さが飛躍的に増大しています。堅牢で再利用可能なテストベンチを生成することは、複雑な設計を検証し、バグを早期に発見するために不可欠です。UVM ベースの検証テストベンチと検証 IP を手動で作成するには、膨大な労力が必要です。設計検証エンジニアは、検証コンポーネントとテストベンチの生成を自動化することで、時間と労力を節約します。この例では、完全に機能する UVMF テストベンチを生成するためのステップバイステップのプロセスと、チップレベルの検証テストベンチを生成する際にブロックレベルの検証環境を再利用するためのプロセスを示します。
mtlb2uvmf ワークフローの紹介
UVM フレームワーク (UVMF) は、Siemens® がリリースしたオープン ソース パッケージです。このパッケージは、UVM ベースの検証テストベンチのインフラストラクチャを生成するコード ジェネレーターを提供します。詳細については、UVMF インストールに同梱されているドキュメントを参照してください。UVMF 2023.1 リリースは、Linux® マシンの Siemens Verification Academy からダウンロードできます。
この図は、mtlb2uvmf ワークフローを示しています。
mtlb2uvmf ワークフローを使用して UVMF コードを生成するには、次の手順に従います。
MATLAB® または Simulink 設計および刺激コンポーネント用の SystemVerilog DPI コンポーネントを生成します。
設計には独自の RTL コードを使用します。または、MATLAB または Simulink HDL コード生成を使用して設計コンポーネントの HDL コードを生成します。これには HDL Coder™ ライセンスが必要です。
生成されたフォルダーを引数として
mtlb2uvmf
CSH スクリプトに渡し、UVMF コードを生成します。これらのフォルダーには、SystemVerilog DPI コンポーネントが含まれています。生成された DPI コードを正しくコンパイルし、UVMF テストベンチを RTL デザインにリンクするには、生成されたセットアップ スクリプトを必要なすべての環境変数で更新します。
mtlb2uvmf ワークフローは次の機能をサポートしています。
生成された DPI コードから必要なすべての情報を取得して YAML スクリプトを生成し、スクリプトを手動で作成する必要がなくなります。
生成された UVMF コードのシーケンスと予測子コンポーネントに DPI コードを統合して、それらのファイルを手動で編集する必要がないようにする。
モデルの概要
この図は、この例で使用する Simulink モデルを示しています。
サンプル作業フォルダを exampleWorkingFolder
変数に保存し、Simulink モデルを開きます。
exampleWorkingFolder = pwd;
open_system("PulseGen_Chip")
チップの名前はPulseGen_Chip
です。チップには 4 つのサブモジュールが含まれています。IO インターフェイスには次の入力があります。
バイパス — 入力信号を
data_out
出力信号にバイパスするオプション。bypass
が1
の場合、チップはdata1
入力信号をdata_out
出力信号にバイパスします。bypass
が2
の場合、チップはdata2
入力信号をdata_out
出力信号にバイパスします。bypass
が0
の場合、チップはdata1
とdata2
入力に基づいてパルス信号を返します。data1 — チップへの入力データ。
data2 — チップへの入力データ。
valid — 入力データ信号に対応する有効な信号。
インターフェースには次の出力があります。
data_out — チップからデータを出力します。
bypass
が0
の場合、この式の出力値は になります。valid_out — 出力データ信号に対応する有効な信号。
モデルのシミュレーションを実行します。
open_system("PulseGen_Chip/scope_chip") sim("PulseGen_Chip");
この図は、チップのシミュレーション出力を示しています。
bypass
が 2
の場合、data_out
信号は data2
信号と同じになります。bypass
が 0
の場合、data_out
信号は data1
および data2
入力に対応するパルス信号のようになります。
この図は、mtlb2uvmf
ワークフローを使用してブロックレベルおよびチップレベルの検証テストベンチを生成する方法を示しています。
ブロックレベルの検証
この図は、ブロックレベルの UVMF 検証環境のアーキテクチャを示しています。
AbsVal_Blk および PulseOut_Blk ブロックはテスト対象の RTL デザインであり、PulseGen_Chip
Simulink モデル内のサブシステムに対応します。単一の入力インターフェイスがすべての入力信号をバンドルし、単一の出力インターフェイスがすべての出力信号をバンドルすると仮定します。対応するブロックレベルの検証環境には、次のコンポーネントがあります。
Block_input_agent — テスト ベクトルを設計の入力インターフェイスに送り込むアクティブ エージェント。YAML スクリプトを通じてエージェントの内部を構成できます。たとえば、YAML スクリプトで
has_coverage
フラグを true に設定すると、UVMF コード ジェネレーターはエージェント内のカバレッジ コレクター コンポーネントをインスタンス化します。このエージェントは、刺激サブシステムの DPI コードをシーケンスとして使用します。Block_predictor — 設計サブシステムから生成された DPI コードを使用して出力を予測する Component。このコンポーネントは、予測された出力をスコアボード コンポーネントに送信します。
Block_output_agent — デザインの出力インターフェイスを監視し、信号情報を Scoreboard コンポーネントに転送する Passive エージェント。
スコアボード — 出力エージェントと予測子からそれぞれ受信した実際の設計出力と予想される設計出力を比較する コンポーネント。このコンポーネントは、比較の不一致を検出すると uvm_error を生成します。
ブロックレベルの検証環境の生成
ブロックレベルの検証のために、チップ内の各ブロックに対応する刺激サブシステムを生成します。この図は、PulseGen_Chip
の AbsVal_Blk
ブロックの刺激サブシステムを示しています。
open_system("PulseGen_Chip/AbsVal_Stim")
チップ内のすべてのサブシステムのブロックレベルの検証環境を生成するには、次の手順に従います。
必要な DPI 構成設定で Simulink モデルを構成する
Simulink モデル設定を構成して、mtlb2uvmf ワークフローで期待される必要な DPI コードを生成します。helperConfigureModelForUVMF
関数を使用して、必要なすべてのモデル設定を構成します。
helperConfigureModelForUVMF("PulseGen_Chip")
または、モデル設定で設定を手動で構成することもできます。
まず、コード生成 ペインで、次の手順を実行します。
システム ターゲット ファイル の ターゲットの選択 で、参照 をクリックします。リストから
systemverilog_dpi_grt.tlc
を選択します。ツールチェーンを
Automatically locate an installed toolchain
に設定します。
次に、左側のペインで コード生成 > SystemVerilog DPI を選択します。
テストベンチの生成 を選択してテストベンチを生成します。
SystemVerilog ポート セクションで、ポート データ型 を
Bit Vector
に設定します。同じセクションで、接続 を
Port list
に設定します。
刺激および設計サブシステム用の DPI コンポーネントを生成する
刺激サブシステムと設計サブシステムの DPI コンポーネントを同じフォルダーに生成するには、手順 5.SystemVerilog DPIコンポーネントを生成する の手順 5 を参照してください。この図は、両方のサブシステムの DPI コンポーネントを生成した後に生成されたフォルダーを示しています。
PulseGen_Chip,
内のすべてのブロックの DPI コンポーネントを生成するには、helperGenerateDPIForSubsystems
関数を使用します。
helperGenerateDPIForSubsystems("PulseGen_Chip/AbsVal_Blk","PulseGen_Chip/AbsVal_Stim");
残りのブロックの DPI コンポーネントを生成します。
helperGenerateDPIForSubsystems("PulseGen_Chip/SignalCompare_Blk","PulseGen_Chip/SignalCompare_Stim"); helperGenerateDPIForSubsystems("PulseGen_Chip/ValidOut_Blk","PulseGen_Chip/ValidOut_Stim"); helperGenerateDPIForSubsystems("PulseGen_Chip/PulseOut_Blk","PulseGen_Chip/PulseOut_Stim");
設計サブシステムの HDL コードを生成する
AbsVal_Blk
、PulseOut_Blk
、SignalCompare_Blk
、および ValidOut_Blk
V ファイルは、各設計サブシステムの HDL コードに対応します。あるいは、HDL Coder ライセンスをお持ちの場合は、次の手順を使用して設計サブシステムから HDL コードを生成できます。
モデル設定のHDL コード生成ペインで、言語を
VHDL
またはVerilog
に設定します。左側のペインで HDL コード生成 > グローバル設定 を選択します。クロック設定セクションで、リセットアサートレベルを
Active-low
に設定し、リセット入力ポートをrst
に設定します。追加設定セクションのポートで、クロック イネーブルを最小化するを選択します。この設定により、ソフトウェアは生成された HDL コードのポート リストにクロック イネーブル ポートを追加しなくなります。
デザイン サブシステムを右クリックし、[HDL コード] > [サブシステムの HDL を生成] をクリックします。この図は、HDL コードを生成した後に生成されたフォルダーを示しています。
UVMF コードの生成
次の環境変数を設定します。
UVMF_HOME
– この環境変数を UVMF 2023.1 インストール パスに設定します。MTI_VCO_MODE
– UVMF テストベンチシミュレーションに 64 ビット QuestaSim 実行可能ファイルを使用するには、この環境変数を64
に設定します。他のシミュレーターも互換性がある必要がありますが、この例ではワークフローは示されていません。
setenv("UVMF_HOME","/home/Documents/UVMF_2023.1") setenv("MTI_VCO_MODE","64")
helperGenerateUVMFTestBench
関数を使用して、すべてのブロックの UVMF テスト ベンチを生成します。DPI コンポーネントを含むフォルダーの名前をこの関数への入力として渡します。mtlb2uvmf
CSH
スクリプトでは、フォルダー名が <name>_build
形式 (<name>
は mtlb2uvmf
CSH
スクリプトへの入力として渡す値) であると想定されるため、_build
サフィックスなしでフォルダー名を渡す必要があります。
helperGenerateUVMFTestBench("AbsVal_Blk","AbsVal_Stim")
他のブロックの UVMF テストベンチ コードを生成します。
helperGenerateUVMFTestBench("PulseOut_Blk","PulseOut_Stim") helperGenerateUVMFTestBench("SignalCompare_Blk","SignalCompare_Stim") helperGenerateUVMFTestBench("ValidOut_Blk","ValidOut_Stim")
または、次の手順に従って、ブロックレベルの UVMF テストベンチを手動で生成します。
刺激および設計サブシステムの DPI 成果物が含まれるフォルダーに移動します。
2 つの引数を指定して
mtlb2uvmf
CSH
スクリプトを実行します。これらの引数は、DPI コンポーネントを含むフォルダーの名前に対応します。ホスト マシンのコマンド ウィンドウでこのコマンドを実行します:
$UVMF_HOME/scripts/mtlb2uvmf.csh AbsVal_Blk AbsVal_Stim
。
この図は、ブロックレベルの UVMF テストベンチを生成した後に生成されたフォルダーと YAML スクリプトを示しています。
生成されたセットアップ スクリプトで環境変数を設定する
uvmf_template_output/project_benches/AbsVal_Blk/sim
フォルダーで、.source 拡張子を持つ setup_AbsVal_Blk_environment_variables
スクリプトを見つけます。この図は、生成されたセットアップ ファイルの内容を示しています。
スクリプトには次の環境変数が含まれています。
AbsVal_Blk_VERILOG_DUT_SRC — 設計 RTL ファイルへのパス、
AbsVal_Blk
。AbsVal_Blk_ENV_DPI_SRC — デザイン用に生成された DPI ファイルが含まれるフォルダーへのパス。
AbsVal_Blk_ENV_GCC_COMP_ARGUMENTS — デザインの DPI ファイルをコンパイルするために必要なコンパイル フラグ。
AbsVal_Blk_input_agent_IF_DPI_SRC — 刺激用に生成された DPI ファイルが含まれるフォルダーへのパス。
AbsVal_Blk_input_agent_IF_GCC_COMP_ARGUMENTS — 刺激の DPI ファイルをコンパイルするために必要なコンパイル フラグ。
helperUpdateEnvironmentVariables
関数を使用して環境変数を更新します。この関数は、MATLAB からの環境変数も設定します。
helperUpdateEnvironmentVariables("AbsVal_Blk_Env");
他のブロックの UVMF テストベンチのセットアップ スクリプトを更新します。
helperUpdateEnvironmentVariables("PulseOut_Blk_Env"); helperUpdateEnvironmentVariables("SignalCompare_Blk_Env"); helperUpdateEnvironmentVariables("ValidOut_Blk_Env");
または、次の手順に従って、必要なコンパイル フラグを手動で取得します。次の手順に従って、刺激 DPI のコンパイル フラグを取得することもできます。
デザイン用に生成された DPI ファイルがあるフォルダーに移動します。そのフォルダーには、
AbsVal_Blk
という名前の makefile が含まれています。make -f BlockA_DUT.mk info
コマンドを使用して、makefile 内のinfo
ターゲットをビルドします。ソフトウェアは、コンパイル フラグをホスト マシンのコマンド ウィンドウに出力します。CPPFLAGS
変数のすべてのフラグをコピーし、セットアップ スクリプトに貼り付けて、対応する環境変数を設定します。これらのフラグを引用符で囲んで貼り付けます (例:setenv ENV_VARIABLE_NAME "
<flags_copied_from_terminal>
"
)。この図は、コピーする必要があるフラグを強調表示した出力例を示しています。source setup_AbsVal_Blk_environment_variables.source
コマンドを使用して、ホスト マシンのコマンド ウィンドウでセットアップ スクリプトを実行します。
ブロックレベルのシミュレーションを使用してブロック機能を検証する
次の手順に従って、Questa®Sim ソフトウェアでブロックレベルのシミュレーションを実行します。
uvmf_template_output/project_benches/AbsVal_Blk/sim
フォルダに移動します。
cd(fullfile("AbsVal_Blk_Env","uvmf_template_output","project_benches","AbsVal_Blk","sim"))
QuestaSim で UVMF テスト ベンチ シミュレーションを実行するには、MATLAB でこのコマンドを実行します。
!make debug TEST_NAME=DPI_stimgen_test
QuestaSim ウィンドウのトランスクリプト ウィンドウに「run -all
」と入力します。この図はQuestaSimでのシミュレーション結果を示しています。
サンプルの作業フォルダーに戻ります。
cd(exampleWorkingFolder);
チップレベルの検証
この図はチップレベルの検証環境を示しています。
チップレベルの環境には、すべてのブロックレベルの検証環境のインスタンス化が含まれます。チップ内のブロックの入力および出力インターフェースは、対応するブロックレベル環境の入力および出力エージェントに接続されます。ブロックレベル環境内のすべてのエージェントは、対応するブロック インターフェイスに信号を送信してはならないため、パッシブになるように構成する必要があります。chipEnv, でチップレベルの入力エージェントをインスタンス化し、テスト ベクトルをチップ入力インターフェイスに送ります。このエージェントは、チップレベルの刺激サブシステムに生成された DPI コードを使用します。
このアーキテクチャは、チップレベルの刺激に対して追加の DPI コード生成を要求することで、すべてのブロックレベルの環境を再利用してチップレベルの検証シミュレーションを実行します。対応するブロックレベル環境におけるスコアボードの不一致は、設計上の欠陥を示しています。ブロックレベルの検証環境を再利用すると、チップレベルのシミュレーション障害における問題の範囲を絞り込むのに役立ちます。
チップレベル検証環境の生成
PulseGen_Chip
モデルの PulseGen_Stim
サブシステムをチップの刺激として使用します。
open_system("PulseGen_Chip/PulseGen_Stim")
刺激サブシステムの DPI コンポーネントを生成する
チップレベルの刺激サブシステムの DPI コンポーネントを生成します。この場合、チップ レベルの環境でブロック レベルの DPI コンポーネントが再利用されるため、チップ サブシステムの DPI コンポーネントを生成する必要はありません。helperGenerateDPIForSubsystems
関数を使用して PulseGen_Chip
の DPI コンポーネントを生成します。
helperGenerateDPIForSubsystems("PulseGen_Chip/PulseGen_Stim");
トップレベル Verilog モジュールの生成
PulseGen_Chip
ファイルを最上位の Verilog モジュールとして使用します。あるいは、すべてのサブモジュールをインスタンス化し、それらの間の適切な接続を設定するトップレベルの Verilog ファイルを手動で作成することもできます。この図は、ブロックレベル モジュールのインスタンス化を含むチップレベル HDL コードの一部を示しています。
また、このトップレベル モジュールには、すべてのブロック レベルの HDL ファイルを含める必要があります。この図は、ブロックレベルの HDL ファイルを組み込む方法を示しています。
チップレベルの環境を記述する YAML スクリプトを作成する
YAML スクリプトは、UVMF テストベンチ アーキテクチャに関する情報を UVMF コード ジェネレーターに伝える唯一の方法です。前のセクションで説明したアーキテクチャに従って、チップレベルの検証用の UVMF コードを生成するには、YAML スクリプトを作成する必要があります。YAML スクリプトには次の情報が含まれている必要があります。
チップレベル環境におけるブロックレベル環境のインスタンス化。
ブロックレベル環境内のすべてのエージェントは、
PASSIVE
として構成する必要があります。チップレベル環境でのチップレベル入力エージェントのインスタンス化と、このエージェントの DPI インターフェイスの定義。詳細については、UVMF インストールに同梱されている UVMF_Code_Generator_YAML_Reference ドキュメントの「インターフェイス YAML 構造」の章を参照してください。
独自のスクリプトを作成する代わりに、この例では Chip
YAML スクリプトを使用できます。
open("Chip.yaml")
UVMF コードの生成
すべてのブロックレベルの YAML ファイルと、チップレベルの環境を記述する YAML スクリプトを UVMF コード ジェネレーターに提供するには、次の手順に従います。
1. すべての YAML ファイルを 1 つのフォルダーにコピーします。
copyfile("AbsVal_Blk_Env/output_mtlb.yaml","PulseGen_Chip_Env/AbsVal_Blk.yaml",'f'); copyfile("SignalCompare_Blk_Env/output_mtlb.yaml","PulseGen_Chip_Env/SignalCompare_Blk.yaml",'f'); copyfile("ValidOut_Blk_Env/output_mtlb.yaml","PulseGen_Chip_Env/ValidOut_Blk.yaml",'f'); copyfile("PulseOut_Blk_Env/output_mtlb.yaml","PulseGen_Chip_Env/PulseOut_Blk.yaml",'f'); copyfile("Chip.yaml","PulseGen_Chip_Env/Chip.yaml",'f');
2. PulseGen_Chip_Env フォルダに移動します。
cd("PulseGen_Chip_Env")
3. YAML ファイル名を yaml2uvmf
スクリプトの引数として指定して、yaml2uvmf
コマンドを実行します。
!$UVMF_HOME/scripts/yaml2uvmf.py AbsVal_Blk.yaml SignalCompare_Blk.yaml ValidOut_Blk.yaml PulseOut_Blk.yaml Chip.yaml
この図は、生成されたフォルダーと YAML スクリプトを示しています。
サンプルの作業フォルダーに戻ります。
cd(exampleWorkingFolder);
生成されたセットアップ スクリプトで環境変数を設定する
チップ サブシステムには個別の DPI コンポーネントがないため、次の環境変数のみを設定する必要があります。
PulseGen_Chip_VERILOG_DUT_SRC
PulseGen_Chip_input_agent_IF_DPI_SRC
PulseGen_Chip_input_agent_IF_GCC_COMP_ARGUMENTS
helperUpdateEnvironmentVariables
関数を使用して、チップレベル環境のセットアップ ファイルを更新します。
helperUpdateEnvironmentVariables("PulseGen_Chip_Env")
生成された hdl_top SystemVerilog ファイルを更新する
すべての mtlb2uvmf
フロー ファイルが正しいフォルダーにあることを確認するには、名前が <NAME>_mtlb_prep
の形式になっている .sh
拡張子を持つスクリプトを実行します。ブロックレベル環境では、mtlb2uvmf
スクリプトがこれらのファイルを実行します。ただし、チップレベルの環境では、mtlb2uvmf
スクリプトを使用しないため、これらのファイルを手動で実行する必要があります。このプロセスを自動化するには、helperExecuteMtlbScripts
関数を使用します。uvmf_template_out
フォルダーへのパスを helperExecuteMtlbScripts
関数への入力として渡します。
helperExecuteMtlbScripts(fullfile("PulseGen_Chip_Env","uvmf_template_output"))
hdl_top
SV ファイルは、合成可能なすべてのコンテンツをインスタンス化する最上位モジュールです。このファイルはuvmf_template_output/project_benches/PulseGen_Chip/tb/testbench
フォルダにあります。デフォルトでは、このファイルはすべてのインターフェースが最上位の DUT にあると想定しています。その結果、ファイルはブロックのすべての IO 信号を DUT.<BLOCK_INTERFACE_NAME>.<IO_SIGNAL_NAME>
として参照します。ただし、ブロック レベルのインターフェイスはチップ内のブロックのインスタンス化内にあるため、IO 信号を次の形式で参照する必要があります。
DUT.<BLOCK_INSTANCE_NAME>.<BLOCK_INTERFACE_NAME>.<IO_SIGNAL_NAME>
これらの変更を反映するように hdl_top
SV ファイルを変更します。この図は、生成された hdl_top
SV ファイルと変更されたファイルの違いの 1 つを示しています。
添付の hdl_top
SV ファイルと生成された hdl_top
SV ファイルを比較すると、すべての違いを理解できます。hdl_top
SV ファイルを開きます。
open("hdl_top.sv")
生成された hdl_top
SV ファイルを、この更新された hdl_top
SV ファイルに置き換えます。
copyfile("hdl_top.sv",fullfile("PulseGen_Chip_Env","uvmf_template_output","project_benches","PulseGen_Chip","tb","testbench","hdl_top.sv"),'f')
チップレベルのシミュレーションを使用してチップの機能を検証する
ブロックレベルの検証環境を生成する手順 6 で説明したプロセスに従って、チップレベルのシミュレーションを実行します。
cd(fullfile("PulseGen_Chip_Env","uvmf_template_output","project_benches","PulseGen_Chip","sim"))
QuestaSimでUVMFテストベンチシミュレーションを実行する
!make debug TEST_NAME=DPI_stimgen_test
シミュレーションを開始する前に、QuestaSim の波形ウィンドウに data_out
信号やその他の関心のある信号を追加できます。信号を追加したら、QuestaSim のトランスクリプト ウィンドウに「run -all
」と入力してシミュレーションを開始します。この図は、QuestaSim ソフトウェアでのチップレベルのシミュレーション結果を示しています。
サンプルの作業フォルダーに戻ります。
cd(exampleWorkingFolder);
まとめ
この例では、Simulink から SystemVerilog DPI コンポーネントを生成し、mtlb2uvmf
ワークフローを使用して UVMF に統合する方法を示します。この例では、ブロックレベルの UVMF 環境を再利用してチップレベルの検証環境を生成するプロセスを段階的に示します。このアプローチに従って、設計用の UVMF 環境を生成できます。