前回のおさらい
テストベンチにAgent階層を追加しました。
sample_agent.svh
class sample_agent extends uvm_agent;
`uvm_component_utils(sample_agent)
function new(string name, uvm_component parent=null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
`uvm_info(this.get_name(), "Agent", UVM_NONE)
endtask
endclass
sample_env.svh
class sample_env extends uvm_env;
`uvm_component_utils(sample_env)
sample_agent agent; // 追加
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase); // 追加
super.build_phase(phase);
agent = sample_agent::type_id::create("agent", this);
endfunction
task run_phase(uvm_phase phase);
`uvm_info(this.get_name(), "Env", UVM_NONE);
endtask
endclass
Sequence_item/Sequencer/Driver/Sequenceを追加する
uvm_sequence_itemtを継承したsample_sequence_item、
uvm_sequenceを継承したsample_seq、
uvm_sequencerを継承したsample_sequencer、
uvm_driverを継承したsample_driver
を作成します。
sample_sequence_item.svh
Sequencer/Driverでやり取りするデータをuvm_sequence_itemを継承して作成します。
class sample_sequence_item extends uvm_sequence_item;
`uvm_object_utils(sample_sequence_item)
rand bit [2:0] din1;
rand bit [2:0] din2;
function new(string name="sample_sequence_item");
super.new(name);
endfunction
endclass
sample_seq.svh
SequenceはSequencerを通してDriverを動作させます。
先ほど作成したsample_sequence_itemをパラメータにセットしたuvm_sequenceを継承してsample_seqを作成します。
class sample_seq extends uvm_sequence #(sample_sequence_item);
`uvm_object_utils(sample_seq)
rand bit [2:0] din1;
rand bit [2:0] din2;
function new(string name="sample_seq");
super.new(name);
set_automatic_phase_objection(1); // おまじない
endfunction
virtual task body();
`uvm_create(req) // Sequencerを通してDriverを動作させる。
req.din1 <= din1;
req.din2 <= din2;
`uvm_send(req)
#10;
endtask
endclass
sample_sequencer.svh
Sequencer階層はSequenceからの命令をDriverに伝えます。
先ほど作成したsample_sequence_itemをパラメータにセットしたuvm_sequencerを継承してsample_sequencerを作成します。
class sample_sequencer extends uvm_sequencer #(sample_sequence_item);
`uvm_component_utils(sample_sequencer)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
`uvm_info(this.get_name(), "Sequencer", UVM_NONE)
endtask
endclass
sample_driver.svh
Driver階層はSequenceからの命令に従ってDUTを動作させます。
先ほど作成したsample_sequence_itemをパラメータにセットしたuvm_driverを継承してsample_driverを作成します。
class sample_driver extends uvm_driver #(sample_sequence_item);
`uvm_component_utils(sample_driver)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
`uvm_info(this.get_name(), "Driver", UVM_INFO)
forever begin
seq_item_port.get_next_item(req);
`uvm_info(this.get_name(), $sformatf("din1 %d", req.din1), UVM_NONE)
`uvm_info(this.get_name(), $sformatf("din2 %d", req.din2), UVM_NONE)
seq_item_port.item_done(rsp);
end
endtask
endclass
Driver,Sequencer階層をAgent階層にインスタンスします。
sample_agent.svh(Sequencer/Driverをインスタンスする)
connect_phaseでsequencerとDriverを接続します。
class sample_agent extends uvm_agent;
`uvm_component_utils(sample_agent)
sample_driver driver; // 追加。
sample_sequencer sequencer; // 追加。
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
driver = sample_driver::type_id::create("driver", this); // 追加。
sequencer = sample_sequencer::type_id::create("sequencer", this); // 追加。
endfunction
function void connect_phase(uvm_phase phase); // build_phaseの次に実行される。
super.connect_phase(phase);
driver.seq_item_port.connect(sequencer.seq_item_export); // sequencerとdriverを接続する。
endfunction
task run_phase(uvm_phase phase);
`uvm_info(this.get_name(), "Agent", UVM_NONE)
endtask
endclass
Env階層に変更はありません。
sample_env.svh(変更なし)
class sample_env extends uvm_env;
`uvm_component_utils(sample_env)
sample_agent agent;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent = sample_agent::type_id::create("agent", this);
endfunction
task run_phase(uvm_phase phase);
`uvm_info(this.get_name(), "Env", UVM_NONE);
endtask
endclass
Test階層にシーケンスを追加します。
sample_test.svh(Sequenceを追加する)
class sample_test extends uvm_test;
`uvm_component_utils(sample_test)
sample_env env;
function new(string name="sample_test", uvm_component parent=null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db #(uvm_object_wrapper)::set( // シーケンスをセットする。
this, "env.agent.sequencer.run_phase",
"default_sequence", sample_seq::type_id::get());
env = sample_env::type_id::create("env", this);
endfunction
task run_phase(uvm_phase phase);
`uvm_info(this.get_name(), "Hello World", UVM_NONE)
endtask
endclass
top.sv(sample_sequence_item.svh, sample_sequencer.svh, sample_driver.svh, sample_seq.svhを追加する)
module top;
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "sample_sequence_item.svh" // 追加。
`include "sample_sequencer.svh" // 追加。
`include "sample_driver.svh" // 追加。
`include "sample_agent.svh"
`include "sample_env.svh"
`include "sample_seq.svh" // 追加。
`include "sample_test.svh"
initial begin
run_test("sample_test");
end
endmodule
実行結果
シミュレーションを実行すると以下が出力されます。
[UVM_INFO][uvm_test_top] Hello World
[UVM_INFO][env] Env
[UVM_INFO][agent] Agent
[UVM_INFO][sequencer] Sequencer
[UVM_INFO][driver] Driver
[UVM_INFO][driver] din1 4
[UVM_INFO][driver] din2 3
解説
sequence_itemは、sequenceからsequencerを通してdriverを動作させるときの変数を定義します。
Driverにある以下の記述をすると、sequence_itemの変数がreqの要素として使用できます。
seq_item_port.get_next_item(req);
以下の記述で、作成したsequencer, driverをagentで接続します。
function void connect_phase(uvm_phase phase); // build_phaseの次に実行される。
super.connect_phase(phase);
driver.seq_item_port.connect(sequencer.seq_item_export); // sequencerとdriverを接続する。
endfunction
以下の記述で、SequenceをTest階層に接続します。
uvm_config_db #(uvm_object_wrapper)::set( // シーケンスをセットする。
this, "env.agent.sequencer.run_phase", "default_sequence", sample_seq::type_id::get());
まとめ
Sequence_item, Sequence, Sequencer, Driverを追加しました。
コメント