[DV]一種帶Set、Clear、Mask功能的Register的驗證方案

          一種帶Set、Clear、Mask功能的Register的驗證方案

        前言:在DV工作中,我們經常會遇到如下圖所示的Register定義,例如RW類型的Register:demo,當我們把Register:demo_set設為1的時候,demo會變為1;當我們把demo_clear置為1的時候,demo會被清零;通過mask_demo_set,可以屏蔽掉set這個function;通過mask_clear_demo,可以屏蔽掉Clear功能。

reg                set_mode;
reg                clr_mode;
reg                demo;

always @ (posedge clk or negedge fst_n) begin
  if(!rst_n)
    demo <= 'h0;
  else if(set_demo & ~mask_set_demo)
    demo <= 'h1;
  esle if(clear_demo & ~mask_clr_demo)
    demo <= 'h0;
end

一、基本策略

       Override用predict()的回調函數:post_predict()去Update mirror value和desired value。

二、操作實例

2.1、先定義出Set、Clear、和Mask的Class

  • 必須要繼承自uvm_reg_cbs
  • 必須定義為virtual function
  • 在這個class中實現post_predict()這個function。根據Spec,對mirror value做Update。

2.1.1、set_regs_callback的實現

class set_regs_callback extends uvm_reg_cbs;

  function new(string name = "set_regs_callback");
    super.new(mane);
  endfunction

  virtual function void post_predict(
                                     input uvm_reg_field    fld,
                                     input uvm_reg_data_t   previous,
                                     inout uvm_reg_data_t   value,
                                     input uvm_predict_e    kind,
                                     input uvm_path_e       path,
                                     input uvm_reg_map      map
                                    );
    if(kind == UVM_PREDICT_WRITE) begin
      `uvm_info(get_full_name(), $sformatf("%s Current value: 0x%0h, Previous Mirror Value: 0x%0h", 
                                           fld.get_name(), value, previous), UVM_HIGH)
      value = value | previous;
      `uvm_info(get_full_name(), $sformatf("%s New Mirror value: 0x%0h, fld.get_name(), value), UVM_HIGH)
    end
  endfunction : post_predict

endclass : set_regs_callback

2.1.2、clear_regs_callback的實現

class clr_regs_callback extends uvm_reg_cbs;

  function new(string name = "set_regs_callback");
    super.new(mane);
  endfunction

  virtual function void post_predict(
                                     input uvm_reg_field    fld,
                                     input uvm_reg_data_t   previous,
                                     inout uvm_reg_data_t   value,
                                     input uvm_predict_e    kind,
                                     input uvm_path_e       path,
                                     input uvm_reg_map      map
                                    );
    if(kind == UVM_PREDICT_WRITE) begin
      `uvm_info(get_full_name(), $sformatf("%s Current value: 0x%0h, Previous Mirror Value: 0x%0h", 
                                           fld.get_name(), value, previous), UVM_HIGH)
      value = ~value & previous;
      `uvm_info(get_full_name(), $sformatf("%s New Mirror value: 0x%0h, fld.get_name(), value), UVM_HIGH)
    end
  endfunction : post_predict

endclass : clr_regs_callback

2.13、gcr_prlv_ack_reg_callback的實現

class gcr_prlv_reg_callback extends uvm_reg_cbs;

  function new(string name = "set_regs_callback");
    super.new(mane);
  endfunction

  virtual function void post_predict(
                                     input uvm_reg_field    fld,
                                     input uvm_reg_data_t   previous,
                                     inout uvm_reg_data_t   value,
                                     input uvm_predict_e    kind,
                                     input uvm_path_e       path,
                                     input uvm_reg_map      map
                                    );
    if(kind == UVM_PREDICT_WRITE) begin
      `uvm_info(get_full_name(), $sformatf("%s Current value: 0x%0h, Previous Mirror Value: 0x%0h", 
                                           fld.get_name(), value, previous), UVM_HIGH)
      value = ~previous;
      `uvm_info(get_full_name(), $sformatf("%s New Mirror value: 0x%0h, fld.get_name(), value), UVM_HIGH)
    end
  endfunction : post_predict

endclass : gcr_prlv_reg_callback

2.1.4、apb_ack_mask_callback的實現

class apb_ack_mask_callback extends uvm_reg_cbs;

  function new(string name = "set_regs_callback");
    super.new(mane);
  endfunction

  virtual function void pre_write(uvm_reg_item rw);
    if(rw.path == UVM_BACKDOOR) return;
    `uvm_info(get_full_name(), $sformatf("Start Writing with: 0x%0h", rw.Value[0]), UVM_LOW)
     rw.value = value[0][0:0] = 'h0;
     `uvm_info(get_full_name(), $sformatf("End Writing with: 0x%0h", rw.Value[0]), UVM_LOW)
  endfunction : post_predict

endclass : apb_ack_mask_callback

2.2、在test_base中把需要Update的Register註冊到callback pool中

2.2.1、首先定義一個append_field的function

virtual function void append_field_callback(string reg_name, string sield_name, uvm_reg_cbs cb);
  uvm_reg                    cb_reg;
  uvm_reg_field              cb_field;

  cb_reg   = ral_model.get_reg_by_name(reg_name);
  cb_field = cb_reg.get_field_by_name(field_name);
  uvm_callbacks#(uvm_reg_field, uvm_reg_cbs)::add(cb_field, cb);

endfunction : append_field_callback

2.2.2、將需要使用callback的Register都加入進來

virtual function void update_cirq_reg_callback(string ral_name);
  set_regs_callback                rg_set_cbs;
  clr_regs_callback                rg_clr_cbs;
  apb_ack_mask_callback            apb_ack_mask;

  rg_set_cbs = new({ral_name, "_set_ral_callback"});
  append_field_callback("R_CIRQ_IE_CHECK_MODE_SET", "VPE0_IE_CHECK_MODE_SET", rg_set_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_SET", "VPE1_IE_CHECK_MODE_SET", rg_set_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_SET", "VPE2_IE_CHECK_MODE_SET", rg_set_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_SET", "VPE3_IE_CHECK_MODE_SET", rg_set_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_SET", "VPE4_IE_CHECK_MODE_SET", rg_set_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_SET", "VPE5_IE_CHECK_MODE_SET", rg_set_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_SET", "VPE6_IE_CHECK_MODE_SET", rg_set_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_SET", "VPE7_IE_CHECK_MODE_SET", rg_set_cbs);

  rg_clr_cbs = new({ral_name, "_clr_ral_callback"});
  append_field_callback("R_CIRQ_IE_CHECK_MODE_CLR", "VPE0_IE_CHECK_MODE_CLR", rg_clr_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_CLR", "VPE1_IE_CHECK_MODE_CLR", rg_clr_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_CLR", "VPE3_IE_CHECK_MODE_CLR", rg_clr_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_CLR", "VPE3_IE_CHECK_MODE_CLR", rg_clr_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_CLR", "VPE4_IE_CHECK_MODE_CLR", rg_clr_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_CLR", "VPE5_IE_CHECK_MODE_CLR", rg_clr_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_CLR", "VPE6_IE_CHECK_MODE_CLR", rg_clr_cbs);
  append_field_callback("R_CIRQ_IE_CHECK_MODE_CLR", "VPE7_IE_CHECK_MODE_CLR", rg_clr_cbs);



  apb_ack_mask = new({ral_name, "_apb_ack_mask"});
  append_field_callback("R_CIRQ_APB_ACK_MASK", "CIRG_PAB_ACK_MASK", apb_ack_mask);

endfunction : update_cirq_reg_callback

2.3、在run_phase中調用上述function

virtual task run_phase(uvm_phase phase);
  reg_test_seq                    reg_test_seq_inst;

  phase.raise_objection(this);

  begin
    reg_test_seq_inst = reg_test_seq::type_id::create("reg_test_seq_inst", this);
    uvm_config_db#(uvm_reg_block)::set(null, "*", "__RAL_TEST_MODEL__", ral_model);

    this.update_cirq_call_back("ral_CIRQ_TOP");

    reg_test_seq_inst.start(my_env.apb_mst_inst[0].sequencer);

  end

  phase.drop_objection(this);

endtask : run_phase
发布了208 篇原创文章 · 获赞 150 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/gsjthxy/article/details/105438322
dv