uvm_reg_access_seq无法测试带有RO字段的寄存器

文摘   科技   2024-04-30 22:44   上海  

1.前言

这是知识星球内的球友最近问的一个问题,这个问题涉及到UVM中的寄存器模型中的知识。本文在回答这个问题的基础上,再扩展一些关于UVM寄存器模型中其它内嵌的sequence的功能和用法介绍。

2.关于uvm_reg_access_seq
这个sequence用于检查寄存器的读写,它的原型为:
class uvm_reg_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_it em))

使用此sequence也需要指定其model变量。

此sequence使用前门访问的方式向所有寄存器写数据,然后使用后门访问的方式读回并比较结果。最后反过来使用后门访问的方式写入数据,再用前门访问读回。这个sequence要正常工作必须为所有寄存器设置好hdl路径

如果要跳过某个寄存器的读写检查,可以在启动sequence前使用如下的两种方式之一进行设置:
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

这个sequence用于检查上电复位后寄存器模型与DUT中寄存器的默认值是否相同,它的原型为:
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变量。

如果想跳过某个寄存器的检查,可以在启动此sequence前使用resource_db设置不检查此寄存器。resource_db机制与config_db机制的底层实现是一样的,uvm_config_db类就是从uvm_resource_db类派生而来的。由于在寄存器模型的sequence中get操作是通过resource_db来进行的,所以这里使用resource_db来进行设置:
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

这个sequence用于检查hdl路径的正确性。它的原型为:
class uvm_reg_mem_hdl_paths_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item))
这个sequence的运行依赖于在基类uvm_sequence中定义的一个变量:uvm_reg_block model。启动此sequence时必须给model赋值。在任意sequence中可以启动此sequence:
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);  endtaskendclass

调用该sequence的start任务时,传入的sequencer参数为null。因为它正常工作不依赖于这个sequencer,而依赖于model变量。这个sequence会试图读取hdl所指向的寄存器,如果无法读取则给出错误提示。由这个sequence的名字也可以看出,它除了检查寄存器外,还检查存储器。如果某个寄存器/存储器在加入寄存器模型时没有指定其hdl路径,那么此sequence在检查时会跳过这个寄存器/存储器。

[全文完]

最后,由于TX修改规则,为了不错过后续内容,欢迎加入QQ群,

另外,由于微信群已经超过200人,添加小编的微信,拉你进入WX学习群。

最后,一起好好学习,天天向上!

芯片验证日记
分享芯片验证相关的知识。
 最新文章