10. 割り込みシーケンス

Interrupt sequenceです。CPUのバスインターフェースモデルを使っていると、割り込み発生時の検証には必須ですね。

grab, ungrab(sequencerを掴む、離す)を使うということだけわかっていたのですが、UVMのユーザーマニュアルの例はvirtual sequenceのもので、しかもそれほど書いてなくて。

ググるとVerification Academyのサイトが出てきました。そこに書かれてある例を元に、シンプルな割り込みシーケンスの動作確認ができたので、公開したいと思います。

ポイントは、

  • 割り込み処理シーケンスの「中」でgrab, ungrabすること

モチーフは、10日間で身に付けるUVMのコードです。

2つのシーケンスを追加しました。

  1. 既存の連続ライト、連続リードシーケンスをfork join_noneで実施し、一定時間後に他のシーケンスを割り込ませ、終わったら元のシーケンスの続きを実施するシーケンス
  2. 1番で使う割り込みシーケンス。

既存のシーケンスは、アドレスをインクリメントしながらランダムデータを256回書いてから、256回読むというものです。この連続ライトを途中でとめて、0番地に10回ランダムデータを書くシーケンスを割 りこませます。

まずログから。10 番地まで書いたあと、0番地へ連続ライトしたあと、10番地から再開されていることがわかります。波形は確認していませんが、grabメッセージが表示されてから 10 番地へ書き込みが発生し ていますが、モニタはValid-Readyハンドシェイク完了時に表示しているため、ライトトランザクション中にgrab要求を発行したことになっていると考えています。

# UVM_INFO @ 9100: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=0eh wdata=bfh# UVM_INFO @ 9100: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 9700: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=0fh wdata=cdh# UVM_INFO @ 9700: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 10000: uvm_test_top.tb.sample_model.master.sequencer@@intr_test_seq.intr [SEQ] grab sequencer# UVM_INFO @ 10400: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=10h wdata=77h# UVM_INFO @ 10400: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 11100: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=00h wdata=d7h# UVM_INFO @ 11100: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 12000: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=00h wdata=a5h# UVM_INFO @ 12000: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 13000: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=00h wdata=5fh# UVM_INFO @ 13000: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 13300: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=00h wdata=63h# UVM_INFO @ 13300: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 13800: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=00h wdata=6ch# UVM_INFO @ 13800: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 14100: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=00h wdata=31h# UVM_INFO @ 14100: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 14400: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=00h wdata=24h# UVM_INFO @ 14400: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 15000: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=00h wdata=08h# UVM_INFO @ 15000: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 15300: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=00h wdata=d2h# UVM_INFO @ 15300: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 15800: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=00h wdata=cfh# UVM_INFO @ 15800: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 15900: uvm_test_top.tb.sample_model.master.sequencer@@intr_test_seq.intr [SEQ] ungrab sequencer# UVM_INFO @ 16300: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=11h wdata=9bh# UVM_INFO @ 16300: uvm_test_top.tb.sample_scrbd [SCRBD] write expected data# UVM_INFO @ 17200: uvm_test_top.tb.sample_model.master.monitor [MON] write addr=12h wdata=e7h

使用したシーケンス

//------------------------------------------------------------------------class write_read_all_seq extends sample_master_base_seq; write_seq _write; read_seq _read; `uvm_object_utils(write_read_all_seq) function new (string name="write_read_all_seq"); super.new(name); endfunction virtual task body(); int i; for(i=0; i<256; i=i+1)begin `uvm_create(_write) _write.addr = i; _write.data = $urandom_range(255,0); `uvm_send(_write) end for(i=0; i<256; i=i+1)begin `uvm_create(_read) _read.addr = i; `uvm_send(_read) end endtaskendclass//------------------------------------------------------------------------class intr_seq extends sample_master_base_seq; write_seq _write; read_seq _read; `uvm_object_utils(intr_seq) function new (string name="intr_seq"); super.new(name); endfunction virtual task body(); m_sequencer.grab(this); uvm_report_info("SEQ", "grab sequencer"); repeat(10)begin `uvm_create(_write) _write.addr = 0; _write.data = $urandom_range(255,0); `uvm_send(_write) end m_sequencer.ungrab(this); uvm_report_info("SEQ", "ungrab sequencer"); endtaskendclass//------------------------------------------------------------------------class intr_test_seq extends sample_master_base_seq; write_read_all_seq all; intr_seq intr; `uvm_object_utils(intr_test_seq) function new (string name="intr_test_seq"); super.new(name); endfunction virtual task body(); event wait_e; fork begin `uvm_create(all) `uvm_send(all) -> wait_e; end join_none #10000; `uvm_create(intr) `uvm_send(intr) @wait_e; endtaskendclass