目次
I. 概要
SVの検証環境構築では、従来のハードウェア設計モデルはシミュレーション開始前にインスタンス化・接続されていましたが、SVのソフトウェア部分のオブジェクトインスタンス化はシミュレーション開始後に実行する必要がありました。オブジェクトのインスタンス化は構築関数new()を呼び出すことで実現されますが、検証環境が階層化されている場合のインスタンス化の順序やインスタンス化後の各コンポーネントの接続順序の問題はnew()関数だけでは解決できません。
最上位から最下位レベルへの構成など、高度な機能を実装する必要がある場合、SV は最下位コンポーネントがインスタンス化される前に最下位構成ロジックを完了できません。そのため、UVM では検証環境の構築時にフェーズ機構を導入しており、この機構によりUVM シミュレーションのステージを階層化することができ、各フェーズの実行順序だけでなく、同じフェーズ内の階層コンポーネント間のフェーズ関係も含めることができます。
2. 9フェーズの実行メカニズム
9 つのフェーズは 9 つのメソッドに対応しており、この 9 つのフェーズを持つのはコンポーネントのみです。つまり、型がコンポーネント型の場合、その型にはフェーズ メカニズムが必要です。
UVM コンポーネントの場合、主な関心事は各フェーズが実行される順序です。各フェーズの仮想メソッドを定義した後、UVM 環境はこれらのメソッドをフェーズの順序で呼び出します。
これら 9 つのフェーズは、テスト環境のライフサイクルに対して実行順序が固定されており、同時に、同じフェーズ内のコンポーネントについても、階層の順序またはトップダウンまたはトップに従って実行されます。アップ。
build_phaseの場合、実行シーケンスはトップダウンであり、高レベルのコンポーネントがインスタンス化された場合にのみ、低レベルのコンポーネントを収容するためのスペースが作成されるため、検証構造構築のロジックに沿っています。
uvm_component と uvm_componentから継承されたそのサブクラスのみが、フェーズ メカニズムに従って上記の 9 つのフェーズを連続して実行します。これらのフェーズは、 uvm_component の_phaseのサフィックスによって仮想メソッドの定義を完了します。たとえば、 build_phase() はいくつかのコンポーネントのインスタンス化と構成を定義できます。タスク。
class subcomp extends uvm_component; //1:继承c0mp0nent
`uvm_component_utils(subcomp) //:2:宏注册
function new(string name, uvm_component parent); //:3:new
super.new(name, parent);
endfunction
//下面是九个阶段phase
function void build_phase(uvm_phase phase); //默认形式,把参数传进来
`uvm_info("build_phase", "", UVM_LOW)
endfunction
function void connect_phase(uvm_phase phase);
`uvm_info("connect_phase", "", UVM_LOW)
endfunction
function void end_of_elaboration_phase(uvm_phase phase);
`uvm_info("end_of_elaboration_phase", "", UVM_LOW)
endfunction
function void start_of_simulation_phase(uvm_phase phase);
`uvm_info("start_of_simulation_phase", "", UVM_LOW)
endfunction
task run_phase(uvm_phase phase);
`uvm_info("run_phase", "", UVM_LOW)
endtask
function void extract_phase(uvm_phase phase);
`uvm_info("extract_phase", "", UVM_LOW)
endfunction
function void check_phase(uvm_phase phase);
`uvm_info("check_phase", "", UVM_LOW)
endfunction
function void report_phase(uvm_phase phase);
`uvm_info("report_phase", "", UVM_LOW)
endfunction
function void final_phase(uvm_phase phase);
`uvm_info("final_phase", "", UVM_LOW)
endfunction
endclass
class topcomp extends subcomp; //继承了subcomp上面九个phase
subcomp c1, c2;
...
function void build_phase(uvm_phase phase);
`uvm_info("build_phase", "", UVM_LOW)
c1 = subcomp::type_id::create("c1", this); //利用工厂创建对象 c1:实例名称 c2即parent:实例句柄
c2 = subcomp::type_id::create("c2", this);
endfunction
endclass
class test1 extends uvm_test;
topcomp t1;
...
function void build_phase(uvm_phase phase);
t1 = topcomp::type_id::create("t1", this);
endfunction
endclass
上記のコード階層:
シミュレーション結果:
要約:
これら 9 つのフェーズは、テスト環境のライフサイクルに対して実行順序が固定されており、同時に、同じフェーズ内のコンポーネントについても、階層の順序またはトップダウンまたはトップに従って実行されます。アップ。
出力結果から、buildはトップダウンの実行順序で、まず最上位の t1 を作成し、次に t1 に c1 と c2 を作成し、次にconnectはボトムアップの実行順序で、最初に c1 と c2 を作成し、次に t1 を作成します。残りはフェーズで指定された同じ実行順序で作成されます。
すべてのフェーズの中で、時間のかかるタスクはrun_phaseメソッドだけです。つまり、このメソッドは待機、刺激、サンプリングのいくつかのタスクを完了できます。他のフェーズのメソッドはすべて関数であり、すぐに返さなければなりません (時間がかかりません)。run_phase でテストを完了したい場合は、通常、電源投入、リセット、設定の登録、メイン テスト コンテンツの送信、DUT がテストを完了するのを待つというスティミュラス シーケンスを整理する必要があります。
3、12 分岐フェーズ (run_phase の細分フェーズ)
インセンティブを送信する簡単な方法は、上記のすべてのインセンティブを run_phase で完了することです。別の方法は、上記の典型的なシーケンスを異なる間隔に分割することです。対応するインセンティブが間隔の順序で送信される場合、テストはより正確になります。層です。したがって、run_phase は次の 12 フェーズに分割できます。
- pre_reset_phase
- リセットフェーズ
- ポストリセットフェーズ
- pre_configure_phase
- 構成フェーズ
- post_configure_phase
- pre_main_phase
- メインフェーズ
- ポストメインフェーズ
- pre_shutdown_phase
- シャットダウンフェーズ
- シャットダウン後のフェーズ
実際、run_phase タスクは、上記で細分化された 12 のフェーズと並行しています。つまり、start_of_simulation_phase タスクが実行された後、run_phase とreset_phase の実行が開始され、shutdown_phase が実行された後、run_phase が完了するまで待つ必要があります。 extract_phase に入る前に実行されます。
注: Lu Sang は、12 の細分割フェーズは作業に使用されない可能性があり、9 つのフェーズで十分であると示唆しました。
4、UVM コンパイルと実行シーケンス
時間 0 より前:ハードウェア モデルをロードしてエミュレータを呼び出す前に、コンパイルとモデリングの段階を完了する必要があります。
Run0 または 0 moment:次に、シミュレーションを開始する前に、ハードウェアの always/initial ステートメントがそれぞれ実行され、UVM 呼び出しテスト メソッド run_test といくつかのフェーズがそれぞれ build、connect、end_of_elaboration、および start_of_simulation になります。
シミュレーションの開始:シミュレーションの開始後、run_phase または対応する 12 個のサブディビジョン フェーズが実行されます。
シミュレーションの終了:シミュレーションが終了すると、残りのフェーズ (抽出、確認、レポート、最終) が実行されます。
UVMシミュレーションが開始されます
シミュレーションの開始時に検証環境をセットアップするには、次のことを選択できます。
- どの uvm_test を実行するかは、グローバル関数 (uvm_pkg によって提供される) run_test() によって選択的に指定できます。ここでのテスト クラスはすべて uvm_test から継承されます。この場合、指定されたテスト クラスがインスタンス化され、最上位コンポーネントとして指定されます。一般に、run_test() 関数は、適切なモジュール/プログラムの最初のプロセス ブロックで呼び出すことができます。
- run_test() にパラメータが渡されない場合、シミュレーション中にパラメータ +UVM_TESTNAME=<test_name> を渡すことで、シミュレーション中に呼び出される uvm_test を指定できます。run_test() 関数が呼び出されたときにすでにテスト名が渡されている場合でも、指定されたテストはシミュレーション中に最上位から上書きできます。このメソッドはコンパイルする必要がなく、テストを柔軟に選択できます。
上記の方法に関係なく、グローバル関数はトップレベルで呼び出す必要がありrun_test()
、run_test()
グローバル関数の重要性はまさにuvm_root
UVM ワールドの作成から始まります。
task run_test(string test_name="");
uvm_root top;
uvm_coreservice_t cs;
cs = uvm_coreservice_t::get();
top = cs.get_root();
top.run_test(test_name);
endtask
UVM 最上位クラス uvm_root も uvm_component から継承しており、UVM 環境構造体のメンバーであり、最上位クラスの構造体クラスとして使用できます。UVM の世界で中心的な役割を果たす run_test() などのいくつかのメソッドを提供します。uvm_pkg には、最上位クラス uvm_root によってインスタンス化されたオブジェクトが 1 つだけあります。つまり、uvm_top です。
uvm_topのコア機能には次のものが含まれます。
- 非表示の UVM 検証構造の最上位層として、他のコンポーネント インスタンスはその下にあり、コンポーネントの作成時に親が指定されて階層を形成します。親が null に設定されている場合、それは uvm_top の子コンポーネントになります。
- すべてのコンポーネントの位相順序を制御します。
- インデックス機能。コンポーネント インスタンスを階層名でインデックス付けします。
- レポート構成。uvm_top を通じてレポートの複雑さをグローバルに構成します。
- デバイスをグローバルにレポートします。uvm_top インスタンスはグローバルにアクセスできるため、UVM レポート デバイスはコンポーネントの内部とコンポーネントの外部 (モジュールやシーケンスなど) の両方からアクセスできます。
run_test(test_name) メソッドは uvm_top によって呼び出され、 uvm_top は次のように初期化されます。
- 正しい test_name を取得します。
- オブジェクトメカニズムを初期化します (制御シミュレーション終了)。
- uvm_test_top インスタンスを作成します。
- フェーズ制御メソッドを呼び出して、すべてのコンポーネントのフェーズ メソッドの実行順序を調整します。
- すべてのフェーズの実行が終了するのを待って、フェーズ制御プロセスを閉じます。
- レポートはシミュレーションを要約して終了します。
UVMシミュレーションの終了
UVM がシミュレーションを終了するためのメカニズムは 1 つだけあり、それは、オブジェクション一時停止メカニズムを使用してシミュレーションの終了を制御することです。uvm_objection クラスは、すべてのコンポーネントとシーケンスで共有されるカウンターを提供します。オブジェクトをハングするコンポーネントがある場合は、そのオブジェクトも忘れずにドロップする必要があります。オブジェクトメカニズムに参加している参加コンポーネントは、run_phase の終了を防ぐために独立してオブジェクトを一時停止できますが、これらのコンポーネントがオブジェクトを削除した後にのみ、uvm_objection によって共有されるカウンターが 0 になり、これは run_phase 終了の条件が満たされたことを意味します。 run_phase を終了することができます。
uvm_objection クラスの場合、アンチストップに使用される制御メソッドは次のとおりです。
//挂起objection
raise_objection(uvm_object obj=null, string description="", int count=1)
//落下objection
drop_objection(uvm_object obj=null, string description="", int count=1)
//设置退出时间
set_drain_time(uvm_object obj=null, time drain)
これらのメソッドでは、component() の場合、run_phase() でphase.raise_objection() またはphase.drop_objection() を使用して、run_phase exit を制御できます。パラメータ説明文字列の説明を提供することが最善であり、これは後のデバッグに有益です。デフォルトのカウント値を使用する必要があります。uvm_top または uvm_test_top の場合、set_drain_time() の使用はできる限り少なくする必要があります。
反対意見によりシミュレーションを終了できません
class test1 extends uvm_test;
...
task run_phase(uvm_phase phase);
phase.raise_objection(this); //this:当前的组件 当前的组件在当前的phase挂起了objection
`uvm_info("run_phase", "entered...", UVM_LOW)
#1us; //1us后
`uvm_info("run_phase", "exited...", UVM_LOW)
phase.drop_objection(this); //当前的组件在当前的phase了落下
endtask
endclasshou