UVM——sequence library

sequence library

本质是一个sequence,包含了一组在其内部注册了的sequence类型,可通过对其进行配置,创建并执行一系列的sequence、sequence_item。

向sequence library永久注册sequence

首先创建sequence library类

class my_sequence_lib extends uvm_sequence_library #(my_transaction);

    `uvm_object_utils(my_sequence_lib)
    // 注册该sequence library
    `uvm_sequence_library_utils(my_sequence_lib)

    function new(string name = "my_sequence_lib");
        super.new(name);
        // 初始化该sequence library
        init_sequence_library();
    endfunction

endclass

接着,创建三个sequence,分别da3_sequence、sa6_sequence、da3_sa6_sequence。

da3_sequence代码如下,其他的方法类似。

class da3_sequence extends my_sequence;

    `uvm_object_utils(da3_sequence)
    `uvm_add_to_seq_lib(da3_sequence, my_sequence_lib)

    int item_num = 10;

    function new(string name = "da3_sequence");
        super.new(name);
    endfunction

    function void pre_randomize();
        uvm_config_db#(int)::get(m_sequencer, "", "item_num", item_num);
    endfunction

    virtual task body();
        my_transaction tr;
        if(starting_phase != null)
            starting_phase.raise_objection(this);

        repeat(item_num) begin
            //`uvm_do(req);
            tr = my_transaction::type_id::create("tr");
            start_item(tr);
            tr.randomize() with { tr.da == 3; };
            finish_item(tr);

            get_response(rsp);
            `uvm_info("SEQ", {"\n", "Sequence get the response:\n", rsp.sprint()}, UVM_MEDIUM)

        end
	   
        #100;
    	if(starting_phase != null)
            starting_phase.drop_objection(this);
    endtask

endclass

启动十次sequence library
在这里插入图片描述

临时添加sequence到sequence library

da3_sequence中注释掉`uvm_add_to_seq_lib

class da3_sequence extends my_sequence;

    `uvm_object_utils(da3_sequence)
    // `uvm_add_to_seq_lib(da3_sequence, my_sequence_lib)

    int item_num = 10;

    function new(string name = "da3_sequence");
        super.new(name);
    endfunction

    function void pre_randomize();
        uvm_config_db#(int)::get(m_sequencer, "", "item_num", item_num);
    endfunction

    virtual task body();
        my_transaction tr;
        if(starting_phase != null)
            starting_phase.raise_objection(this);

        repeat(item_num) begin
            //`uvm_do(req);
            tr = my_transaction::type_id::create("tr");
            start_item(tr);
            tr.randomize() with { tr.da == 3; };
            finish_item(tr);

            get_response(rsp);
            `uvm_info("SEQ", {"\n", "Sequence get the response:\n", rsp.sprint()}, UVM_MEDIUM)

        end
	   
        #100;
    	if(starting_phase != null)
            starting_phase.drop_objection(this);
    endtask

endclass

在my_test(test_case)中注册要添加到sequence library中的sequence。

class my_test extends uvm_test;

    `uvm_component_utils(my_test)

    my_env m_env;
    env_config m_env_cfg;

    function new(string name = "", uvm_component parent);
        super.new(name, parent);
        m_env_cfg = new("m_env_cfg");
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        m_env = my_env::type_id::create("m_env", this);

        my_sequence_lib::add_typewide_sequence(da3_sequence::get_type());
        my_sequence_lib::add_typewide_sequence(sa6_sequence::get_type());
    
        uvm_config_db#(uvm_object_wrapper)::set(this, "*.m_seqr.run_phase","default_sequence", my_sequence_lib::get_type());

        uvm_config_db#(int)::set(this, "*.m_seqr", "item_num", 20);

        m_env_cfg.is_coverage = 1;
        m_env_cfg.is_check    = 1;
        m_env_cfg.m_agent_cfg.is_active  = UVM_ACTIVE;
        m_env_cfg.m_agent_cfg.pad_cycles = 5;

        if(!uvm_config_db#(virtual dut_interface)::get(this, "", "top_if", m_env_cfg.m_agent_cfg.m_vif)) begin
            `uvm_fatal("CONFIG_ERROR", "test can not get the interface !!!")
        end

        uvm_config_db#(env_config)::set(this, "m_env", "env_cfg", m_env_cfg);

    endfunction

    virtual function void start_of_simulation_phase(uvm_phase phase);
        super.start_of_simulation_phase(phase);
        uvm_top.print_topology(uvm_default_tree_printer);
    endfunction
endclass

如下两行代码向my_sequence_lib中注册sequence。

my_sequence_lib::add_typewide_sequence(da3_sequence::get_type());
        my_sequence_lib::add_typewide_sequence(sa6_sequence::get_type());

使用sequence library对象来添加sequence

在某一个单独的sequence library实例中添加sequence

class my_test extends uvm_test;

    `uvm_component_utils(my_test)

    my_env m_env;
    env_config m_env_cfg;

    my_sequence_lib m_seqlib;

    function new(string name = "", uvm_component parent);
        super.new(name, parent);
        m_env_cfg = new("m_env_cfg");
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        m_env = my_env::type_id::create("m_env", this);

        m_seqlib = my_sequence_lib::type_id::create("m_seqlib", this);

        m_seqlib.add_sequence(da3_sequence::get_type());
        m_seqlib.add_sequence(sa6_sequence::get_type());
    
        uvm_config_db#(uvm_sequence_base)::set(this, "*.m_seqr.run_phase","default_sequence",m_seqlib); 

        uvm_config_db#(int)::set(this, "*.m_seqr", "item_num", 20);

        m_env_cfg.is_coverage = 1;
        m_env_cfg.is_check    = 1;
        m_env_cfg.m_agent_cfg.is_active  = UVM_ACTIVE;
        m_env_cfg.m_agent_cfg.pad_cycles = 5;

        if(!uvm_config_db#(virtual dut_interface)::get(this, "", "top_if", m_env_cfg.m_agent_cfg.m_vif)) begin
            `uvm_fatal("CONFIG_ERROR", "test can not get the interface !!!")
        end

        uvm_config_db#(env_config)::set(this, "m_env", "env_cfg", m_env_cfg);

    endfunction

    virtual function void start_of_simulation_phase(uvm_phase phase);
        super.start_of_simulation_phase(phase);
        uvm_top.print_topology(uvm_default_tree_printer);
    endfunction
    
endclass

实例化my_sequence_lib之后,通过下面的代码注册。

m_seqlib.add_sequence(da3_sequence::get_type());
        m_seqlib.add_sequence(sa6_sequence::get_type());

// 配置sequencer中的default_sequence    
        uvm_config_db#(uvm_sequence_base)::set(this, "*.m_seqr.run_phase","default_sequence",m_seqlib);

UVM——sequence library_第1张图片

sequence library相关变量

UVM——sequence library_第2张图片

****
UVM_SEQ_LIB_RAND: 自定义的seq完全随机
UVM_SEQ_LIB_RANDC: 自定义的seq会先随机排序,然后按照次顺序执行,保证每个seq都执行
UVM_SEQ_LIB_ITEM: sequence library不执行自定义的sequence, 而是自己产生transaction
UVM_SEQ_LIB_USER: 用户自定义算法

selction_mode,min_random_count,max_random_count这三个参数均可通过config机制进行配置。
代码示例

class my_test extends uvm_test;

    `uvm_component_utils(my_test)

    my_env m_env;
    env_config m_env_cfg;

    function new(string name = "", uvm_component parent);
        super.new(name, parent);
        m_env_cfg = new("m_env_cfg");
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        m_env = my_env::type_id::create("m_env", this);

        uvm_config_db#(uvm_object_wrapper)::set(this, "*.m_seqr.run_phase","default_sequence", my_sequence_lib::get_type());
        uvm_config_db#(uvm_sequence_lib_mode)::set(this, "*.m_seqr.run_phase", "default_sequence.selection_mode", UVM_SEQ_LIB_ITEM);
        uvm_config_db#(int unsigned)::set(this, "*.m_seqr.run_phase", "default_sequence.min_random_count", 20);
        uvm_config_db#(int unsigned)::set(this, "*.m_seqr.run_phase", "default_sequence.max_random_count", 40);
	  // 此处经过实验,配置不了
	  // uvm_config_db#(int unsigned)::set(this, "*.m_seqr.run_phase", "default_sequence.sequence_count", 38);

        uvm_config_db#(int)::set(this, "*.m_seqr", "item_num", 20);

        m_env_cfg.is_coverage = 1;
        m_env_cfg.is_check    = 1;
        m_env_cfg.m_agent_cfg.is_active  = UVM_ACTIVE;
        m_env_cfg.m_agent_cfg.pad_cycles = 5;

        if(!uvm_config_db#(virtual dut_interface)::get(this, "", "top_if", m_env_cfg.m_agent_cfg.m_vif)) begin
            `uvm_fatal("CONFIG_ERROR", "test can not get the interface !!!")
        end

        uvm_config_db#(env_config)::set(this, "m_env", "env_cfg", m_env_cfg);

    endfunction

    virtual function void start_of_simulation_phase(uvm_phase phase);
        super.start_of_simulation_phase(phase);
        uvm_top.print_topology(uvm_default_tree_printer);
    endfunction
    
endclass

sequence library配置类

上一节配置变量部分代码修改如下:

my_seqlib_cfg = new(
                            "seqlib_cfg",
                            UVM_SEQ_LIB_ITEM,
                            20,
                            40);

        uvm_config_db#(uvm_sequence_library_cfg)::set(
                this, "*.m_seqr.run_phase",
                "default_sequence.config",
                my_seqlib_cfg);

你可能感兴趣的:(IC验证,systemverilog)