【SystemVerilog】UVMで検証環境を作成する~なるべく最小構成~【#8】

Systemverilog

前回のおさらい

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

まとめ

これまでのコードをまとめました。

コメント

タイトルとURLをコピーしました