UVMでシーケンスのコンフィグレーションしたり、RAL(Register Abstraction Level) Modelを取ってきたい場合がある。その場合、シーケンスのコンフィグレーションをConfig DBから取ってくる。取ってくる方法はuvm_config_dbのget()を使うが、一般的にはConfig/ConfiguringSequencesでも紹介されている様にsequenceの中で以下の様にget_full_name()を使って書くと思う。
seq_config m_cfg;
virtual task body();
if(!uvm_config_db #(seq_config)::get( null , get_full_name(), "seq_config", m_cfg ))
`uvm_error("SEQ BODY", "seq_config config_db lookup failed!")
endtask
しかし、これでは問題が生じてコンフィグレーションを取ってこれない場合がある。UVMテストトップでシーケンサーにnullが指定されてstartされたバーチャルシーケンスが使われた場合である。ここで使用されているシーケンスのメンバ関数get_full_name()を見てみると、UVMコンポーネント向けの定義に代えてUVMシーケンス向けにuvm_sequecer_item内で以下の様に定義されている。
function string get_full_name();
if(m_parent_sequence != null)
get_full_name = {m_parent_sequence.get_full_name(), "."};
else if(m_sequencer!=null)
get_full_name = {m_sequencer.get_full_name(), "."};
if(get_name() != "")
get_full_name = {get_full_name, get_name()};
else begin
get_full_name = {get_full_name, "_item"};
end
endfunction
要するに親シーケンスがある場合は親シーケンスから、親シーケンスがないトップのシーケンスの場合は設定されたシーケンサーから階層パス名を取ってきてドットを付けて自分の名前を付け加えている。なのでこれだとシーケンサーの指定がない(nullで指定された)バーチャルシーケンスが大元のトップシーケンスだった場合、get_full_name()の出力結果はシーケンサーの階層パス名から始まらず、いきなりトップのバーチャルシーケンスの名前から始まってしまう。なのでその場合、get_full_name()では正しい階層パス名指定が出来ず、上記のuvm_config_db::get()でのコンフィグレーションの参照はエラーになってしまう。
そこで、get_full_name()を使わずにコンフィグレーションを参照する必要がある。その方法としてResourceAccessForSequencesでは以下の様なそのシーケンスのシーケンサーであるm_sequencerを使用してuvm_config_db::get()にシーケンサーの階層パスを指定する方法も提案されている。
if(!uvm_config_db #(seq_config)::get( m_sequencer, "", "seq_config", m_cfg ))
`uvm_error("SEQ BODY", "seq_config config_db lookup failed!")
子シーケンスは自分より上位のトップのシーケンスにバーチャルシーケンスが使われているのかシーケンサー情報を持ったリアルシーケンスが使われているのかを関知しない。なのでシーケンスではget_full_name()を使用してのコンフィグレーションの参照方法を使うべきではない。
但しこのm_sequencerを使用した方法でもまだ不十分である。これだとシーケンス毎に違うコンフィグレーションを参照したい場合に対応できないのである。この方法ではuvm_config_db::get()に与えているパスがシーケンサーのパスなのでそのシーケンサー上で動くシーケンスは全て同じになってしまい区別ができないのである。そこでシーケンスを個別に区別する為に、少しだけ変えて以下の様な方法を提案する。
if(!uvm_config_db #(seq_config)::get( m_sequencer, get_sequence_path(), "seq_config", m_cfg ))
`uvm_error("SEQ BODY", "seq_config config_db lookup failed!")
m_sequencerと共にget_sequence_path()を与えてでシーケンス毎に違うパス名にしている。get_sequence_path()もuvm_sequence_itemで定義されていて、get_full_name()と違い、必ずトップシーケンスからのシーケンス階層パス名をstringで返す関数である。なのでこれでシーケンス毎に違うコンフィグレーションを参照する事ができる。更にもう少し変えて以下の様にする。
if(!uvm_config_db #(seq_config)::get( get_sequecer(), get_sequence_path(), "seq_config", m_cfg ))
`uvm_error("SEQ BODY", "seq_config config_db lookup failed!")
m_sequencerの代わりにget_sequencer()を使っただけだが、シーケンサーを参照するのにm_sequencerは使わずget_sequencer()の方を使う事が推奨されているのでこちらの方が良いだろう。
結論
シーケンスでのコンフィグレーションでConfig DBのget()にはget_full_name()は使わず全てget_sequencer()とget_sequence_path()を使用した方法にすること。
このシーケンスのコンフィグレーションでのget_full_name()の問題とget_sequence_path()による解決はちょっと検索してみた所では言及されている記事を見つける事が出来なかった。割と良く起こりうるだろう問題なので、この記事を見た人は是非この方法を覚えておくとよいだろう。
参考
Verification Academy/UVM Forum/[Configuration of sequences started from a virtual sequence]
(https://verificationacademy.com/forums/uvm/configuration-sequences-started-virtual-sequence)