• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

SOC/IP验证工程师

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

UVM中寄存器模型内置测试sequence的用法

不少有经验的UVM用户可能会忽略UVM针对寄存器模型内建的一些sequence,实际上如果可以将这些自建的序列作为验证项目一开始的健康检查必选项的化,这对于整个项目的平稳运行会有不小的贡献。
这是因为在项目一开始的阶段,设计内部的逻辑还不稳定,对于verifier而言,如果想要跟上设计的进度,可以展开验证的部分无外乎是系统控制信号(时钟、复位、电源)和寄存器的验证。
在项目早期,寄存器模型的验证可以为后期各个功能点验证打下良好的基础。比如,通过内建的寄存器或者存储序列可以实现完善的寄存器复位值检查,又比如检查读写寄存器的读写功能是否正常等。
不过有一些寄存器即便可以测试,也建议将其作为例外而过滤出去,例如一些重要的系统控制信号(时钟、复位、电源),当写入某些值以后,会使得系统全部或者局部复位、时钟也可能被关闭,这就可能阻碍寄存器的下一步检查。
所以UVM提供了一些特殊域,用来禁止sequence检查这些寄存器或者存储。

内建序列示例
下面的例码演示如何利用内建序列完成MCDF寄存器测试一开始的健康检查。分别添加了uvm_reg_hw_reset_seq、uvm_reg_bit_bash_seq和uvm_reg_access_seq来测试寄存器模型。
从代码的整洁性来看,用户并不需要额外再添加什么,这种使用方法非常方便,且又能完成寄存器的大规模集成测试。

class mcdf_example_seq extends uvm_reg_sequence;
	mcdf_rgm rgm;
	`uvm_object_utils(mcdf_example_seq)
	`uvm_declare_p_sequencer(mcdf_bus_sequencer)
	...
	task body();
		uvm_status_e status;
		uvm_reg_data_t data;
		uvm_reg_hw_reset_seq reg_rst_seq=new();  //
		uvm_reg_bit_bash_seq reg_bit_bash_seq=new();
		uvm_reg_access_seq reg_acc_seq=new();
		if(!uvm_config_db#(mcdf_rgm)::get(null,get_full_name(),"rgm",rgm))begin//
			`uvm_error("GETRGM",“no top-down RGM handle is assigned”)//
		end                                                              //
		//wait reset asserted and release
		@(negedge p_sequencer.vif.rstn);//
		@(posedge p_sequencer.vif.rstn);//
		`uvm_info("BLTINSEQ","register reset sequence started",UVM_LOW)
		reg_rst_seq.model=rgm;//
		reg_rst_seq.start(sequencer);//
		`uvm_info("BLTINSEQ","register reset sequence finished",UVM_LOW)
		`uvm_info("BLTINSEQ","register bit bash sequence started",UVM_LOW)
		//reset hardware register and register model
		reg_acc_seq.model=rgm;//
		reg_acc_seq.start(m_sequencer);//
		`uvm_info("BLTINSEQ","register access sequence finished",UVM_LOW)
	endtask
endclass

寄存器健康检查
对于一些寄存器,如果想将其排除在某些内建序列测试范围之外,用户可以额外添加上面列表中提到的"禁止域名"。由于uvm_reg_block和uvm_reg均是uvm_object类而不是uvm_component类,所以可以使用uvm_resource_db来配置"禁止域名"。
下面的代码摘自mcdf_rgm::build()方法,这相当于寄存器模型在自己的建立阶段设定了一些属性。当然,uvm_resource_db的配置也可以在更高层指定,只不过考虑到uvm_resource_db不具备层次化的覆盖属性,我们建议只在一个地方进行"禁止域名"的配置。

class mcdf_rgm extends uvm_reg_block;
	...
	virtual function build();
	...
	//disable build-in seq attributes
	uvm_resource_db#(bit)::set({"REG::",this.chnl0_stat_reg.get_full_name()},
										"NO_REG_ACCESS_TEST",1);
	uvm_resource_db#(bit)::set({"REG::",this.chnl1_stat_reg.get_full_name()},
										"NO_REG_ACCESS_TEST",1);
	uvm_resource_db#(bit)::set({"REG::",this.chnl2_stat_reg.get_full_name()},
										"NO_REG_ACCESS_TEST",1);
	endfunction
endclass										

其他写法:

 class mcdf_reg_builtin_virtual_sequence extends mcdf_base_virtual_sequence;
    `uvm_object_utils(mcdf_reg_builtin_virtual_sequence)
    function new (string name = "mcdf_reg_builtin_virtual_sequence");
      super.new(name);
    endfunction

    task do_reg();
      uvm_reg_hw_reset_seq reg_rst_seq = new(); //
      uvm_reg_bit_bash_seq reg_bit_bash_seq = new();
      uvm_reg_access_seq reg_acc_seq = new();

      // wait reset asserted and release
      @(negedge p_sequencer.mcdf_vif.rstn);//
      @(posedge p_sequencer.mcdf_vif.rstn);//

      `uvm_info("BLTINSEQ", "register reset sequence started", UVM_LOW)
      rgm.reset();//
      reg_rst_seq.model = rgm;//
      reg_rst_seq.start(p_sequencer.reg_sqr);//
      `uvm_info("BLTINSEQ", "register reset sequence finished", UVM_LOW)

      `uvm_info("BLTINSEQ", "register bit bash sequence started", UVM_LOW)
      // reset hardware register and register model
      p_sequencer.mcdf_vif.rstn <= 'b0;//
      repeat(5) @(posedge p_sequencer.mcdf_vif.clk);
      p_sequencer.mcdf_vif.rstn <= 'b1;//
      rgm.reset();
      reg_bit_bash_seq.model = rgm;//
      reg_bit_bash_seq.start(p_sequencer.reg_sqr);//
      `uvm_info("BLTINSEQ", "register bit bash sequence finished", UVM_LOW)

      `uvm_info("BLTINSEQ", "register access sequence started", UVM_LOW)
      // reset hardware register and register model
      p_sequencer.mcdf_vif.rstn <= 'b0;
      repeat(5) @(posedge p_sequencer.mcdf_vif.clk);
      p_sequencer.mcdf_vif.rstn <= 'b1;
      rgm.reset();
      reg_acc_seq.model = rgm;
      reg_acc_seq.start(p_sequencer.reg_sqr);
      `uvm_info("BLTINSEQ", "register access sequence finished", UVM_LOW)
    endtask
  endclass: mcdf_reg_builtin_virtual_sequence

其他写法:

class case0_cfg_vseq extends uvm_sequence;
   `uvm_object_utils(case0_cfg_vseq)
   `uvm_declare_p_sequencer(my_vsqr)
   function  new(string name= "case0_cfg_vseq");
      super.new(name);
   endfunction 
   virtual task body();
      uvm_reg_access_seq ckseq;
      uvm_mem_access_seq ckseq2;
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      ckseq = new("ckseq");
      ckseq.model = p_sequencer.p_rm;
      ckseq.start(null);
      ckseq2 = new("ckseq2");
      ckseq2.model = p_sequencer.p_rm;
      ckseq2.start(null);
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
endclass

posted on 2022-11-24 22:50  SOC验证工程师  阅读(5781)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3