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;

浙公网安备 33010602011771号