前回のおさらい
Virtual SequenceとVirtual Sequencerを作成しました。
今回は、これまで作成したテストベンチをなるべく短いコードで再掲します。
なるべく最小構成
top.sv(最上位階層)
module top;
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "sample_sequence_item.svh"
`include "sample_monitor.svh"
`include "sample_sequencer.svh"
`include "sample_driver.svh"
`include "sample_agent.svh"
`include "sample_env.svh"
`include "sample_seq.svh"
`include "sample_vsequencer.svh"
`include "sample_vseq.svh"
`include "sample_test.svh"
initial begin
run_test("sample_test");
end
sample_if vif();
initial begin
uvm_config_db #(virtual sample_if)::set(null, "*", "vif", vif);
end
dut i_dut(
.din1(vif.din1),
.din2(vif.din2),
.dout(vif.dout)
);
endmodule
dut.sv(検証対象)
module dut(
input [2:0] din1,
input [2:0] din2,
output logic [3:0] dout
);
assign dout = din1 + din2;
endmodule
sample_if.sv(DUTとUVM環境を接続するInterface)
interface sample_if;
logic [2:0] din1;
logic [2:0] din2;
logic [3:0] dout;
endinterface
sample_test.svh(Test階層)
class sample_test extends uvm_test;
`uvm_component_utils(sample_test)
sample_env env;
sample_vsequencer vsequencer;
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, "vsequencer.run_phase",
"default_sequence", sample_vseq::type_id::get());
env = sample_env::type_id::create("env", this);
vsequencer = sample_vsequencer::type_id::create("vsequencer", this);
endfunction
function void connect_phase(uvm_phase phase);
$cast(vsequencer.seqr, env.agent.sequencer);
endfunction
endclass
sample_env.svh(Env階層)
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
endclass
sample_agent.svh(Agent階層)
class sample_agent extends uvm_agent;
`uvm_component_utils(sample_agent)
sample_driver driver;
sample_sequencer sequencer;
sample_monitor monitor;
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);
monitor = sample_monitor::type_id::create("monitor", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
driver.seq_item_port.connect(sequencer.seq_item_export);
endfunction
endclass
sample_driver.svh(Driver階層)
class sample_driver extends uvm_driver #(sample_sequence_item);
`uvm_component_utils(sample_driver)
virtual sample_if vif;
function new(string name, uvm_component parent);
super.new(name, parent);
if (!uvm_config_db #(virtual sample_if)::get(this, "", "vif", vif))
`uvm_fatal(this.get_name(), "vif is invalid")
endfunction
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
vif.din1 = req.din1;
vif.din2 = req.din2;
seq_item_port.item_done(rsp);
end
endtask
endclass
sample_sequencer.svh(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
endclass
sample_monitor.svh(Monitor階層)
class sample_monitor extends uvm_monitor;
`uvm_component_utils(sample_monitor)
virtual sample_if vif;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db #(virtual sample_if)::get(this, "", "vif", vif))
`uvm_fatal(this.get_name(), "vif is invalid")
endfunction
task run_phase(uvm_phase phase);
int exp;
forever begin
#10;
exp = vif.din1 + vif.din2;
`uvm_info(this.get_name(),
$sformatf("exp %d, act %d", exp, vif.dout), UVM_LOW)
end
endtask
endclass
sample_sequence_item.svh(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;
rand bit [2:0] din3;
function new(string name="sample_sequence_item");
super.new(name);
endfunction
endclass
sample_seq.svh(Sequence)
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)
req.din1 <= din1;
req.din2 <= din2;
`uvm_send(req)
#10;
endtask
endclass
sample_vsequencer.svh(Virtual sequencer階層)
class sample_vsequencer extends uvm_sequencer;
`uvm_component_utils(sample_vsequencer)
sample_sequencer seqr;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
sample_vseq.svh(Virtual sequence階層)
class sample_vseq extends uvm_sequence;
`uvm_object_utils(sample_vseq)
`uvm_declare_p_sequencer(sample_vsequencer)
sample_seq seq;
function new(string name="sample_vseq");
super.new(name);
set_automatic_phase_objection(1);
endfunction
virtual task body();
seq = sample_seq::type_id::create("seq");
`uvm_do_on(seq, p_sequencer.seqr)
endtask
endclass
まとめ
これまでのコードをまとめました。
コメント