Verification Engineerの戯言
ovm_doマクロは、Sequence Actionマクロと呼ばれるもので、クラス・リファレンスのPage.266に説明があります。
Sequence Actionマクロには、ovm_doマクロの他にovm_do_withマクロがあります。
これらマクロは、itemあるいsequenceに対して、次の7つのステップを実行します。
itemはovm_sequence_itemクラスを継承したもの。sequenceは、ovm_sequenceクラスを継承したもの。
Sequence Actionマクロには、ovm_doマクロの他にovm_do_withマクロがあります。
これらマクロは、itemあるいsequenceに対して、次の7つのステップを実行します。
itemはovm_sequence_itemクラスを継承したもの。sequenceは、ovm_sequenceクラスを継承したもの。
1)、Create 2)、Synchronize with sequencer 3)、pre_do 4)、Randomize 5)、mid_do 6)、Post synchronization/body execution 7)、post_do
それでは、ovm_doマクロのコードを見ていきましょう!
ovm_doマクロのコードは、src/macros/ovm_sequence_defines.svhにあります。
start_itemタスクでは、引数(type_var)がovm_sequence_itemクラスの子クラスあるいはovm_sequenceクラスの子クラスなのかで処理が多少違います。
引数がovm_sequence_itemクラスの子クラスのときは、同期化(this.m_sync(type_var)し、pre_doタスクを引数(1)で実行します。
一方、ovm_sequenceクラスの子クラスのときは、pre_doタスクを引数(0)で実行するだけです。
引数がovm_sequence_itemクラスの子クラスのときは、同期化(this.m_post_sync(type_var)します。
一方、ovm_sequenceクラスの子クラスのときは、Sequncerのbodyタスク(m_seq.body())を実行します。
そして、post_doタスクを実行します。
ovm_doマクロのコードは、src/macros/ovm_sequence_defines.svhにあります。
`define ovm_do(OVM_SEQUENCE_ITEM) \ begin \ ovm_virtual_sequencer ovs; \ ovm_sequence os; \ OVM_SEQUENCE_ITEM = new(`"OVM_SEQUENCE_ITEM`");\ if ($cast(ovs, m_sequencer)) \ if(!$cast(os, OVM_SEQUENCE_ITEM)) \ ovm_report_fatal("ITMVSQ", "Cannot do items in a virtual sequence."); \ $cast(OVM_SEQUENCE_ITEM , create_item(OVM_SEQUENCE_ITEM, m_sequencer)); \ start_item(OVM_SEQUENCE_ITEM); \ assert(OVM_SEQUENCE_ITEM.randomize()) else begin \ ovm_report_warning("RNDFLD", "Randomization failed in ovm_do action"); \ end finish_item(OVM_SEQUENCE_ITEM);\ endovm_doマクロでは、
$cast(OVM_SEQUENCE_ITEM, create_item(OVM_SEQUENCE_ITEM, m_sequencer)でOVM_SEQUENCE_ITEMを生成(1)、 start_item(OVM_SEQUENCE_ITEM)を実行(2, 3) OVM_SEQUENCE_ITEM.randomize()でランダム生成(4)、 finish_item(OVM_SEQUENCE_ITEM)を実行(5, 6, 7)を実行しています。
start_itemタスクでは、引数(type_var)がovm_sequence_itemクラスの子クラスあるいはovm_sequenceクラスの子クラスなのかで処理が多少違います。
引数がovm_sequence_itemクラスの子クラスのときは、同期化(this.m_sync(type_var)し、pre_doタスクを引数(1)で実行します。
一方、ovm_sequenceクラスの子クラスのときは、pre_doタスクを引数(0)で実行するだけです。
task ovm_sequence::start_item(ovm_sequence_item type_var); if (type_var.is_item()) begin this.m_sync(type_var); this.pre_do(1); end else begin this.pre_do(0); end endtaskfinish_itemタスクでもstart_itemタスクと同様に、引数(type_var)がovm_sequence_itemクラスの子クラスあるいはovm_sequenceクラスの子クラスなのかで処理が多少違います。
引数がovm_sequence_itemクラスの子クラスのときは、同期化(this.m_post_sync(type_var)します。
一方、ovm_sequenceクラスの子クラスのときは、Sequncerのbodyタスク(m_seq.body())を実行します。
そして、post_doタスクを実行します。
task ovm_sequence::finish_item( ovm_sequence_item type_var ); ovm_sequence m_seq; this.mid_do(type_var); if(type_var.is_item()) begin this.m_post_sync( type_var ); end else begin //is sequence $cast(m_seq, type_var); #0 -> m_seq.started; m_seq.body(); -> m_seq.ended; end this.post_do(type_var); m_sequencer.end_tr(type_var); endtaskこのように、ovm_sequence_itemクラスとovm_sequenceクラスでは、多少処理が違います。
ovm_sequenceクラスの最後の方で説明したbodyタスクはここ(m_seq.body())で実行されます。
検証、Verification、SystemVerilog、OVM、Open Verification Methodology