ドライバ、シーケンサ、そしてシーケンスをuvm_envクラスを継承するenvクラスの中で組み立てます。
各インスタンスは、new関数で生成しています。なぜ、build_phase関数で生成しないのでしょうか?
同様に、connect_phase関数でドライバ(drv)とシーケンサ(sqr)を接続しないのでしょうか?
各インスタンスは、new関数で生成しています。なぜ、build_phase関数で生成しないのでしょうか?
同様に、connect_phase関数でドライバ(drv)とシーケンサ(sqr)を接続しないのでしょうか?
一貫性がやっぱりありません
`define NUM_SEQS 10 // uvm_envクラスを継承 class env extends uvm_env; int i; // シーケンサ、シーケンス、ドライバをインスタンス // シーケンスは、10個 uvm_sequencer #(bus_req, bus_rsp) sqr; sequenceA #(bus_req, bus_rsp) sequence_a[`NUM_SEQS]; my_driver #(bus_req, bus_rsp) drv ; function new(string name, uvm_component parent); string str; // <= このstrは使っていませんが、 super.new(name, parent); // シーケンサを生成 sqr = new("sequence_controller", this); // `NUM_SEQS(10)個のシーケンスを生成 for (i = 0; i < `NUM_SEQS; i++) begin // for ( int i = 0; i < `NUM_SEQS; i++) begin // の方がSystemVerilogらしいが // そうすれば、int i; がいらない sequence_a[i] = new("sequence"); end // ドライバを生成 drv = new("slave", this); // ドライバ(drv)とシーケンサ(sqr)を接続 drv.seq_item_port.connect(sqr.seq_item_export); endfunction // uvm_envクラスを継承したら、このタスクを実装する task run_phase(uvm_phase phase); int i; // おまじないのraise_objection/drop_objectionで囲む phase.raise_objection(this); for (i = 0; i < `NUM_SEQS; i++) begin // for ( int i = 0; i < `NUM_SEQS; i++) begin // の方がSystemVerilogらしいが // そうすれば、int i; がいらない // fork/join_noneで`NUM_SEQS(10)こシーケンスを起動する fork sequence_a[i].start(sqr, null); join_none #0; end // 起動したすべてのシーケンスが終了するまで待つ wait fork; // おまじないのraise_objection/drop_objectionで囲む phase.drop_objection(this); endtask endclass endpackage
build_phase関数とconnect_phase関数を使うと、こんな感じでしょうか?
function new(string name, uvm_component parent); super.new(name, parent); endfunction : new task build_phase(uvm_phase phase); sqr = new("sequence_controller", this); for ( int i = 0; i < `NUM_SEQS; i++) sequence_a[i] = new("sequence"); drv = new("slave", this); endtask : build_phase task connect_phase(uvm_phase phase); drv.seq_item_port.connect(sqr.seq_item_export); endfunction
検証、Verification、SystemVerilog、UVM、Unified Verification Methodology