Main Content

このページは機械翻訳を使用して翻訳されました。元の英語を参照するには、ここをクリックします。

SystemVerilog DPI を UVM フレームワーク ワークフローに統合する

この例では、HDL Verifier™ ソフトウェアを使用して、Simulink® モデルから SystemVerilog DPI コンポーネントとして再利用可能な検証コンポーネントを生成する方法を示します。MATLAB-to-UVMF (mtlb2uvmf) ワークフローを使用して、Universal Verification Methodology (UVM) テストベンチを迅速に作成します。mtlb2uvmf ワークフローの詳細については、Siemens Verification AcademyMathWorks Integration を参照してください。

RTL 設計は、その規模と複雑さが飛躍的に増大しています。堅牢で再利用可能なテストベンチを生成することは、複雑な設計を検証し、バグを早期に発見するために不可欠です。UVM ベースの検証テストベンチと検証 IP を手動で作成するには、膨大な労力が必要です。設計検証エンジニアは、検証コンポーネントとテストベンチの生成を自動化することで、時間と労力を節約します。この例では、完全に機能する UVMF テストベンチを生成するためのステップバイステップのプロセスと、チップレベルの検証テストベンチを生成する際にブロックレベルの検証環境を再利用するためのプロセスを示します。

mtlb2uvmf ワークフローの紹介

UVM フレームワーク (UVMF) は、Siemens® がリリースしたオープン ソース パッケージです。このパッケージは、UVM ベースの検証テストベンチのインフラストラクチャを生成するコード ジェネレーターを提供します。詳細については、UVMF インストールに同梱されているドキュメントを参照してください。UVMF 2023.1 リリースは、Linux® マシンの Siemens Verification Academy からダウンロードできます。

この図は、mtlb2uvmf ワークフローを示しています。

mtlb2uvmf_workflow_illustration.png

mtlb2uvmf ワークフローを使用して UVMF コードを生成するには、次の手順に従います。

  1. MATLAB® または Simulink 設計および刺激コンポーネント用の SystemVerilog DPI コンポーネントを生成します。

  2. 設計には独自の RTL コードを使用します。または、MATLAB または Simulink HDL コード生成を使用して設計コンポーネントの HDL コードを生成します。これには HDL Coder™ ライセンスが必要です。

  3. 生成されたフォルダーを引数として mtlb2uvmf CSH スクリプトに渡し、UVMF コードを生成します。これらのフォルダーには、SystemVerilog DPI コンポーネントが含まれています。

  4. 生成された DPI コードを正しくコンパイルし、UVMF テストベンチを RTL デザインにリンクするには、生成されたセットアップ スクリプトを必要なすべての環境変数で更新します。

mtlb2uvmf ワークフローは次の機能をサポートしています。

  • 生成された DPI コードから必要なすべての情報を取得して YAML スクリプトを生成し、スクリプトを手動で作成する必要がなくなります。

  • 生成された UVMF コードのシーケンスと予測子コンポーネントに DPI コードを統合して、それらのファイルを手動で編集する必要がないようにする。

モデルの概要

この図は、この例で使用する Simulink モデルを示しています。

PulseGen_Chip_with_Blocks.png

サンプル作業フォルダを 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 の場合、チップは data1data2 入力に基づいてパルス信号を返します。

  • data1 — チップへの入力データ。

  • data2 — チップへの入力データ。

  • valid — 入力データ信号に対応する有効な信号。

インターフェースには次の出力があります。

  • data_out — チップからデータを出力します。bypass 0 の場合、この式の出力値は data_out={[+1if data1>data2-1if data1<data2 0if data1=data2]} になります。

  • valid_out — 出力データ信号に対応する有効な信号。

モデルのシミュレーションを実行します。

open_system("PulseGen_Chip/scope_chip")
sim("PulseGen_Chip");

この図は、チップのシミュレーション出力を示しています。

Chip_Simulations_Simulink.png

bypass 2 の場合、data_out 信号は data2 信号と同じになります。bypass0 の場合、data_out 信号は data1 および data2 入力に対応するパルス信号のようになります。

この図は、mtlb2uvmf ワークフローを使用してブロックレベルおよびチップレベルの検証テストベンチを生成する方法を示しています。

mtlb2uvmf_FlowChart.png

ブロックレベルの検証

この図は、ブロックレベルの UVMF 検証環境のアーキテクチャを示しています。

Block_Verification_Env.png

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_ChipAbsVal_Blk ブロックの刺激サブシステムを示しています。

AbsVal_Blk_Block_with_Stimulus.png

open_system("PulseGen_Chip/AbsVal_Stim")

チップ内のすべてのサブシステムのブロックレベルの検証環境を生成するには、次の手順に従います。

必要な DPI 構成設定で Simulink モデルを構成する

Simulink モデル設定を構成して、mtlb2uvmf ワークフローで期待される必要な DPI コードを生成します。helperConfigureModelForUVMF 関数を使用して、必要なすべてのモデル設定を構成します。

helperConfigureModelForUVMF("PulseGen_Chip")

または、モデル設定で設定を手動で構成することもできます。

まず、コード生成 ペインで、次の手順を実行します。

  1. システム ターゲット ファイルターゲットの選択 で、参照 をクリックします。リストからsystemverilog_dpi_grt.tlcを選択します。

  2. ツールチェーンAutomatically locate an installed toolchainに設定します。

次に、左側のペインで コード生成 > SystemVerilog DPI を選択します。

  1. テストベンチの生成 を選択してテストベンチを生成します。

  2. SystemVerilog ポート セクションで、ポート データ型Bit Vector に設定します。

  3. 同じセクションで、接続Port list に設定します。

BlkStep2_SystemVerilog_DPI_Settings.png

刺激および設計サブシステム用の DPI コンポーネントを生成する

刺激サブシステムと設計サブシステムの DPI コンポーネントを同じフォルダーに生成するには、手順 5.SystemVerilog DPIコンポーネントを生成する の手順 5 を参照してください。この図は、両方のサブシステムの DPI コンポーネントを生成した後に生成されたフォルダーを示しています。

BlkStep1_DPI_Generation.png

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_BlkPulseOut_BlkSignalCompare_Blk、および ValidOut_Blk V ファイルは、各設計サブシステムの HDL コードに対応します。あるいは、HDL Coder ライセンスをお持ちの場合は、次の手順を使用して設計サブシステムから HDL コードを生成できます。

  1. モデル設定HDL コード生成ペインで、言語VHDLまたはVerilogに設定します。

  2. 左側のペインで HDL コード生成 > グローバル設定 を選択します。クロック設定セクションで、リセットアサートレベルActive-low に設定し、リセット入力ポートrstに設定します。

  3. 追加設定セクションのポートで、クロック イネーブルを最小化するを選択します。この設定により、ソフトウェアは生成された HDL コードのポート リストにクロック イネーブル ポートを追加しなくなります。

BlkStep2_HDL_Codegen_Settings.png

デザイン サブシステムを右クリックし、[HDL コード] > [サブシステムの HDL を生成] をクリックします。この図は、HDL コードを生成した後に生成されたフォルダーを示しています。

BlkStep3_HDL_Generation.png

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 テストベンチを手動で生成します。

  1. 刺激および設計サブシステムの DPI 成果物が含まれるフォルダーに移動します。

  2. 2 つの引数を指定して mtlb2uvmf CSH スクリプトを実行します。これらの引数は、DPI コンポーネントを含むフォルダーの名前に対応します。

  3. ホスト マシンのコマンド ウィンドウでこのコマンドを実行します: $UVMF_HOME/scripts/mtlb2uvmf.csh AbsVal_Blk AbsVal_Stim

この図は、ブロックレベルの UVMF テストベンチを生成した後に生成されたフォルダーと YAML スクリプトを示しています。

BlkStep4_Folder_Contents_UVMF.png

生成されたセットアップ スクリプトで環境変数を設定する

uvmf_template_output/project_benches/AbsVal_Blk/sim フォルダーで、.source 拡張子を持つ setup_AbsVal_Blk_environment_variables スクリプトを見つけます。この図は、生成されたセットアップ ファイルの内容を示しています。

BlkStep5_Setup_Script_Update.png

スクリプトには次の環境変数が含まれています。

  • 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 のコンパイル フラグを取得することもできます。

  1. デザイン用に生成された DPI ファイルがあるフォルダーに移動します。そのフォルダーには、AbsVal_Blk という名前の makefile が含まれています。

  2. make -f BlockA_DUT.mk info コマンドを使用して、makefile 内の info ターゲットをビルドします。ソフトウェアは、コンパイル フラグをホスト マシンのコマンド ウィンドウに出力します。

  3. CPPFLAGS 変数のすべてのフラグをコピーし、セットアップ スクリプトに貼り付けて、対応する環境変数を設定します。これらのフラグを引用符で囲んで貼り付けます (例: setenv ENV_VARIABLE_NAME "<flags_copied_from_terminal>")。この図は、コピーする必要があるフラグを強調表示した出力例を示しています。

  4. source setup_AbsVal_Blk_environment_variables.source コマンドを使用して、ホスト マシンのコマンド ウィンドウでセットアップ スクリプトを実行します。

BlkStep5_Makefile_Compilation_Flags.png

ブロックレベルのシミュレーションを使用してブロック機能を検証する

次の手順に従って、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でのシミュレーション結果を示しています。

BlkStep6_AbsVal_Blk_Block_Level_Simulations.png

サンプルの作業フォルダーに戻ります。

cd(exampleWorkingFolder);

チップレベルの検証

この図はチップレベルの検証環境を示しています。

Chip_Verification_Env.png

チップレベルの環境には、すべてのブロックレベルの検証環境のインスタンス化が含まれます。チップ内のブロックの入力および出力インターフェースは、対応するブロックレベル環境の入力および出力エージェントに接続されます。ブロックレベル環境内のすべてのエージェントは、対応するブロック インターフェイスに信号を送信してはならないため、パッシブになるように構成する必要があります。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 コードの一部を示しています。

ChipStep2_Top_Module.png

また、このトップレベル モジュールには、すべてのブロック レベルの HDL ファイルを含める必要があります。この図は、ブロックレベルの HDL ファイルを組み込む方法を示しています。

ChipStep2_Include_block_HDLs.png

チップレベルの環境を記述する 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 スクリプトを示しています。

ChipStep4_Generated_Folder_Contents.png

サンプルの作業フォルダーに戻ります。

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 つを示しています。

ChipStep6_hdl_top_differences.png

添付の 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 ソフトウェアでのチップレベルのシミュレーション結果を示しています。

ChipStep7_Chip_Simulations_Questa.png

サンプルの作業フォルダーに戻ります。

cd(exampleWorkingFolder);

まとめ

この例では、Simulink から SystemVerilog DPI コンポーネントを生成し、mtlb2uvmf ワークフローを使用して UVMF に統合する方法を示します。この例では、ブロックレベルの UVMF 環境を再利用してチップレベルの検証環境を生成するプロセスを段階的に示します。このアプローチに従って、設計用の UVMF 環境を生成できます。

関連するトピック

外部の Web サイト