reg model使用篇-reg model的集成方法(隐式预测&显式预测)

(1) 《Practical UVM step by step with IEEE》

注1: reg_model内有一个镜像值,需要确保镜像值和DUT内的寄存器值同步;无论是通过前门还是后门的方式对DUT内寄存器进行访问,reg_model内的镜像值都需要被更新,这个过程称为prediction;

注2:为了保持reg_model镜像值与DUT内寄存器值一致,存在三种bus agent集成方法,分别是隐式预测(implicit prediction),显式预测(explicit prediction)和被动预测(passive prediction);

1. 隐式预测

(1) 隐式预测仅仅需要将register model和一个或多个bus sequencers集成在一起;

(2) 隐式预测模式下,每当read/write/peek/poke操作完成后,register model会自动更新镜像值; 

(3) 这种模式简单快捷,但是可能会漏掉一些不是由register model发起的总线操作,这种情况下mirror值不会得到合适的更新;

注1:隐式预测即前文提到的auto_predict(auto_predict针对的是寄存器前门访问操作,而非后门访问操作,可查看源代码);

//示例1
 class environment extends uvm_env;
     virtual function void connect_phase(uvm_phase phase);
     regmodel.default_map.set_auto_predict(1);
     endfunction
 endclass

 

//示例2:该例子中包含uvm内建register seq的使用;
class test_ral extends test_base;
    string                                      seq_name="uvm_reg_bit_bash_seq";
    uvm_reg_sequence                 selftest_seq;
    virtual reset_sequence  rst_seq;

    virtual function void build_phase(uvm_phase phase);
        super.build_phase();
        uvm_config_db #(uvm_object_wrapper)::set(this,"*","default_sequence",null);
    endfunction

    virtual task run_phase(uvm_phase phase);
        rst_seq=virtual_reset_sequence::type_id::create("rst_seq",this);
        phase.raise_objection(this,"starting tests");
        //run reset;
        rst_seq.start(env.rst_seqr);
        clp.get_arg_value("+seq=",seq_name);
        //create test;
        $cast(selftest_seq,factory.create_object_by_name(seq_name));
        //enable auto predict;
        env.regmodel.default_map.set_auto_predict(1);
        selftest_seq.model=env.regmodel;
        //run test;
        selftest_seq.start(env.m_agent.seqr);
        phase.drop_objection(this,"Done with tests");
    endtask
endclass

+UVM_TESTNAME=test_ral +seq=uvm_reg_hw_reset_seq

 

//示例3
class hw_reset extends test_base;
    reset_sequence       reset_seq;
    uvm_reg_hw_reset_seq reset_test;

    ...

    virtual task run_phase(uvm_phase phase);
        phase.raise_objection(this,"starting register tests");
        reset_seq=reset_sequence::type_id::create("reset_seq",this);
        reset_seq.start(env.reset_seqr);

        reset_test=uvm_reg_hw_reset_seq::type_id::create("reset_test",this);
        reset_test.model=env.regmodel;
        reset_test.model.set_auto_predict(1);
        reset_test.start(null);
        phase.drop_objection(this,"Done with register tests");
    endfunction

endclass

//+UVM_TESTNAME=hw_reset

2. 显式预测

(1) 显式预测需要将register model, bus sequencers以及相应的bus monitor集成到一起;

(2) 显式预测模式下, 隐式预测被关闭(set_auto_predict(0)),镜像值由uvm_reg_predictor组件进行更新;

(2.1) predictor接收到bus monitor观察到的总线操作;

(2.2) predictor通过观测到的地址反向查找到正在被访问的register(会用到uvm_reg_map);

(2.3) predictor显式调用register的predict函数来更新镜像值;

(3) 显式预测比较复杂,但是可以看到所有的总线操作(无论是通过register model发起的寄存器访问操作,还是通过第三方bus agent发起的寄存器访问操作),因此镜像值总能得到合适的更新;

//示例1
class environment extend uvm_env;
    typedef uvm_reg_predictor #(master_data) mreg_predictor;
    mreg_predictor mreg_predict;

    virtual function void build_phase(uvm_phase phase);
        mreg_predictor=mreg_predictor::type_id::create("mreg_predict",this);
    endfunction

    virtual function void connect_phase(uvm_phase phase);
        mreg_predict.map=regmodel.get_default_map();
        mreg_predict.adapter=adapter;
        regmodel.default_map.set_auto_predict(0);
        m_agent.analysis_port.connect(mreg_predict.bus_in);
    endfunction
endclass

 

//示例2:该例子中包含uvm内建register seq的使用;
class test_ral extends test_base;
    string                                      seq_name="uvm_reg_bit_bash_seq";
    uvm_reg_sequence                 selftest_seq;
    virtual reset_sequence  rst_seq;

    virtual function void build_phase(uvm_phase phase);
        super.build_phase();
        uvm_config_db #(uvm_object_wrapper)::set(this,"*","default_sequence",null);
    endfunction

    virtual task run_phase(uvm_phase phase);
        rst_seq=virtual_reset_sequence::type_id::create("rst_seq",this);
        phase.raise_objection(this,"starting tests");
        //run reset;
        rst_seq.start(env.rst_seqr);
        clp.get_arg_value("+seq=",seq_name);
        //create test;
        $cast(selftest_seq,factory.create_object_by_name(seq_name));
        //enable auto predict;
        env.regmodel.default_map.set_auto_predict(0);
        selftest_seq.model=env.regmodel;
        //run test;
        selftest_seq.start(env.m_agent.seqr);
        phase.drop_objection(this,"Done with tests");
    endtask
endclass

+UVM_TESTNAME=test_ral +seq=uvm_reg_hw_reset_seq

3. 集成所需组件bus sequencer

(1) 所有集成方法(隐式预测和显式预测)都需要为register model配置一个或多个bus sequencers;

(2) uvm_reg_sequence可能直接在一个bus sequencer上发送,也可能作为virtual sequence,还可能在一个通用的sequencer上运行,该通用sequencer位于dowstream bus sequencer之上;

3.1 register sequence running on the bus sequencer

(1) register sequence通过reg model, 使用预先配置好的bus adapter产生bus sequence激励;

(2) 这种情况下, register sequence会和其他在该bus sequencer上运行的sequence竞争;

(3) 这种方式对于只有一个bus interface的情况而言,是很合适的;

(4) 使用这种方法,需要为register model内的address map设置bus adapter与bus sequencer;

//示例1
class block_env extends uvm_env;
    block_reg_model regmodel;
    subblk_env      subblk;

    virtual function void connect_phase(uvm_phase phase);
        ...
        if(regmodel.get_parent()==null) begin
            reg2apb_adapter reg2apb=reg2apb_adapter::type_id::create("reg2apb",get_full_name());
            regmodel.APB.set_sequencer(apb.sequencer, reg2apb);
            regmodel.set_auto_predict(0);
            ...
        end
    endfunction
    ...

endclass

class my_reg_sequence extends uvm_reg_sequence;
    `uvm_object_utils(my_reg_sequence)
    block_reg_model model;

    virtual task body();
        uvm_status_e   status;
        uvm_reg_data_t data;

        model.A.write(status,'h33,.parent(this));
        if(status==UVM_NOT_OK) `uvm_error(...)
        model.A.read(status,data,.parent(this));
        if(data!='h33) `uvm_error(...)

    endtask

endclass

class my_test extends uvm_test;
    block_env env;
    virtual function void run_phase(uvm_phase phase);
            my_reg_sequence seq=my_reg_sequence::type_id::create("seq",this);
            seq.start(env.apb.master);
    endfunction

endclass

3.2 register sequence running as a virtual sequence

(1) 当DUT中的register可以通过多组物理总线接口访问, register sequence将会作为virtual sequence启动, 因为每次read/write调用时都不再指明sequencer;

(2) register model会为寄存器操作分配合适的sequencer;

(3) register sequence running as a virtual sequence与register sequence running on the bus sequencer的区别:前者有多个sequencer/adapter在register model中寄存, 此外,在调用register sequence的start method时,不指定sequencer;

 

posted @ 2023-01-28 20:41  luckylan  阅读(693)  评论(0)    收藏  举报