[CU]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 //示例1 2 class environment extends uvm_env; 3 virtual function void connect_phase(uvm_phase phase); 4 regmodel.default_map.set_auto_predict(1); 5 endfunction 6 endclass
1 //示例2:该例子中包含uvm内建register seq的使用; 2 class test_ral extends test_base; 3 string seq_name="uvm_reg_bit_bash_seq"; 4 uvm_reg_sequence selftest_seq; 5 virtual reset_sequence rst_seq; 6 7 virtual function void build_phase(uvm_phase phase); 8 super.build_phase(); 9 uvm_config_db #(uvm_object_wrapper)::set(this,"*","default_sequence",null); 10 endfunction 11 12 virtual task run_phase(uvm_phase phase); 13 rst_seq=virtual_reset_sequence::type_id::create("rst_seq",this); 14 phase.raise_objection(this,"starting tests"); 15 //run reset; 16 rst_seq.start(env.rst_seqr); 17 clp.get_arg_value("+seq=",seq_name); 18 //create test; 19 $cast(selftest_seq,factory.create_object_by_name(seq_name)); 20 //enable auto predict; 21 env.regmodel.default_map.set_auto_predict(1); 22 selftest_seq.model=env.regmodel; 23 //run test; 24 selftest_seq.start(env.m_agent.seqr); 25 phase.drop_objection(this,"Done with tests"); 26 endtask 27 endclass 28 29 +UVM_TESTNAME=test_ral +seq=uvm_reg_hw_reset_seq
1 //示例3 2 class hw_reset extends test_base; 3 reset_sequence reset_seq; 4 uvm_reg_hw_reset_seq reset_test; 5 6 ... 7 8 virtual task run_phase(uvm_phase phase); 9 phase.raise_objection(this,"starting register tests"); 10 reset_seq=reset_sequence::type_id::create("reset_seq",this); 11 reset_seq.start(env.reset_seqr); 12 13 reset_test=uvm_reg_hw_reset_seq::type_id::create("reset_test",this); 14 reset_test.model=env.regmodel; 15 reset_test.model.set_auto_predict(1); 16 reset_test.start(null); 17 phase.drop_objection(this,"Done with register tests"); 18 endfunction 19 20 endclass 21 22 //+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 //示例1 2 class environment extend uvm_env; 3 typedef uvm_reg_predictor #(master_data) mreg_predictor; 4 mreg_predictor mreg_predict; 5 6 virtual function void build_phase(uvm_phase phase); 7 mreg_predictor=mreg_predictor::type_id::create("mreg_predict",this); 8 endfunction 9 10 virtual function void connect_phase(uvm_phase phase); 11 mreg_predict.map=regmodel.get_default_map(); 12 mreg_predict.adapter=adapter; 13 regmodel.default_map.set_auto_predict(0); 14 m_agent.analysis_port.connect(mreg_predict.bus_in); 15 endfunction 16 endclass
1 //示例2:该例子中包含uvm内建register seq的使用; 2 class test_ral extends test_base; 3 string seq_name="uvm_reg_bit_bash_seq"; 4 uvm_reg_sequence selftest_seq; 5 virtual reset_sequence rst_seq; 6 7 virtual function void build_phase(uvm_phase phase); 8 super.build_phase(); 9 uvm_config_db #(uvm_object_wrapper)::set(this,"*","default_sequence",null); 10 endfunction 11 12 virtual task run_phase(uvm_phase phase); 13 rst_seq=virtual_reset_sequence::type_id::create("rst_seq",this); 14 phase.raise_objection(this,"starting tests"); 15 //run reset; 16 rst_seq.start(env.rst_seqr); 17 clp.get_arg_value("+seq=",seq_name); 18 //create test; 19 $cast(selftest_seq,factory.create_object_by_name(seq_name)); 20 //enable auto predict; 21 env.regmodel.default_map.set_auto_predict(0); 22 selftest_seq.model=env.regmodel; 23 //run test; 24 selftest_seq.start(env.m_agent.seqr); 25 phase.drop_objection(this,"Done with tests"); 26 endtask 27 endclass 28 29 +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 //示例1 2 class block_env extends uvm_env; 3 block_reg_model regmodel; 4 subblk_env subblk; 5 6 virtual function void connect_phase(uvm_phase phase); 7 ... 8 if(regmodel.get_parent()==null) begin 9 reg2apb_adapter reg2apb=reg2apb_adapter::type_id::create("reg2apb",get_full_name()); 10 regmodel.APB.set_sequencer(apb.sequencer, reg2apb); 11 regmodel.set_auto_predict(0); 12 ... 13 end 14 endfunction 15 ... 16 17 endclass 18 19 class my_reg_sequence extends uvm_reg_sequence; 20 `uvm_object_utils(my_reg_sequence) 21 block_reg_model model; 22 23 virtual task body(); 24 uvm_status_e status; 25 uvm_reg_data_t data; 26 27 model.A.write(status,'h33,.parent(this)); 28 if(status==UVM_NOT_OK) `uvm_error(...) 29 model.A.read(status,data,.parent(this)); 30 if(data!='h33) `uvm_error(...) 31 32 endtask 33 34 endclass 35 36 class my_test extends uvm_test; 37 block_env env; 38 virtual function void run_phase(uvm_phase phase); 39 my_reg_sequence seq=my_reg_sequence::type_id::create("seq",this); 40 seq.start(env.apb.master); 41 endfunction 42 43 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;