1.前言
这是知识星球内的球友最近问的一个问题,这个问题涉及到UVM中的寄存器模型中的知识。本文在回答这个问题的基础上,再扩展一些关于UVM寄存器模型中其它内嵌的sequence的功能和用法介绍。
class uvm_reg_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_it em))
使用此sequence也需要指定其model变量。
此sequence使用前门访问的方式向所有寄存器写数据,然后使用后门访问的方式读回并比较结果。最后反过来使用后门访问的方式写入数据,再用前门访问读回。这个sequence要正常工作必须为所有寄存器设置好hdl路径。
function void my_case0::build_phase(uvm_phase phase);
…
//set for reg access sequence
uvm_resource_db#(bit)::set({"REG::",rm.invert.get_full_name(),".*"},"NO_REG_TESTS", 1, this);
uvm_resource_db#(bit)::set({"REG::",rm.invert.get_full_name(),".*"},"NO_REG_ACCESS_TEST", 1, this);
…
endfunction
3.关于uvm_mem_access_seq
这是用于检查存储器读写功能的sequence,它的原型是:
class uvm_mem_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_it em)
启动此sequence同样需要指定其model变量。这个sequence会通过使用前门访问的方式向所有存储器写数据,然后使用后门访问的方式读回并比较结果。最后反过来使用后门访问的方式写入数据,再用前门访问读回。这个sequence要正常工作必须为所有的存储器设置好HDL路径。
function void my_case0::build_phase(uvm_phase phase);
…
//set for mem access sequence
uvm_resource_db#(bit)::set({"REG::",rm.get_full_name(),".*"},"NO_REG_TESTS", 1, this);
uvm_resource_db#(bit)::set({"REG::",rm.get_full_name(),".*"},"NO_MEM_TESTS", 1, this);
uvm_resource_db#(bit)::set({"REG::",rm.invert.get_full_name(),".*"},"NO_MEM_ACCESS_TEST", 1, this);
endfunction
4.uvm_reg_hw_reset_seq
class uvm_reg_hw_reset_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
对于DUT来说在复位完成后其值就是默认值。但对于寄存器模型来说,如果只是将它集成在验证平台上而不做任何处理,那么它所有寄存器的值为0,此时需要调用
reset函数来使其内寄存器的值变为默认值(复位值):
function void base_test::build_phase(uvm_phase phase);
…
rm = reg_model::type_id::create("rm", this);
…
rm.reset();
…
endfunction
这个sequence在其检查前会调用model的reset函数,所以即使在集成到验证平台时没有调用reset函数,这个sequence也能正常工作。除了复位(reset)外,这个sequence所做的事情就是使用前门访问的方式读取所有寄存器的值,并将其与寄存器模型中的值比较。这个sequence在启动时也需要指定其model变量。
function void my_case0::build_phase(uvm_phase phase);
…
uvm_resource_db#(bit)::set({"REG::",rm.invert.get_full_name(),".*"},"NO_REG_TESTS", 1, this);
…
endfunction
或者使用:
function void my_case0::build_phase(uvm_phase phase);
…
uvm_resource_db#(bit)::set({"REG::",rm.invert.get_full_name(),".*"},"NO_REG_HW_RESET_TEST", 1, this);
endfunction
5.uvm_reg_mem_hdl_paths_seq
class uvm_reg_mem_hdl_paths_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item))
class case0_cfg_vseq extends uvm_sequence;
…
virtual task body();
..
uvm_reg_mem_hdl_paths_seq ckseq;
…
ckseq = new("ckseq");
ckseq.model = p_sequencer.p_rm;
ckseq.start(null);
…
endtask
endclass
调用该sequence的start任务时,传入的sequencer参数为null。因为它正常工作不依赖于这个sequencer,而依赖于model变量。这个sequence会试图读取hdl所指向的寄存器,如果无法读取则给出错误提示。由这个sequence的名字也可以看出,它除了检查寄存器外,还检查存储器。如果某个寄存器/存储器在加入寄存器模型时没有指定其hdl路径,那么此sequence在检查时会跳过这个寄存器/存储器。
最后,由于TX修改规则,为了不错过后续内容,欢迎加入QQ群,
另外,由于微信群已经超过200人,添加小编的微信,拉你进入WX学习群。