UVM学习记录4

本文档详细介绍了如何在UVM环境中使用寄存器模型进行读写操作,以及如何通过reg2mcdf_adapter类实现总线操作与寄存器模型之间的转换。在mcdf_env组件中,配置了registerblock、adapter和predictor,并完成了句柄连接。在虚拟序列中,将原本的总线级寄存器操作替换为寄存器模型操作,实现了更高效和精确的测试流程。最后,利用内置序列uvm_reg_hw_reset_seq、uvm_reg_bit_bash_seq和uvm_reg_access_seq对寄存器模块进行全面测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

寄存器模型的完善和嵌入

  • 实现reg2mcdf_adapter类的方法reg2bus以及bus2reg。
class reg2mcdf_adapter extends uvm_reg_adapter;
  `uvm_object_utils(reg2mcdf_adapter)
  function new(string name = "reg2mcdf_adapter");
    super.new(name);
    provides_responses = 1;  // 需返回response
  endfunction
  function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);  //返回值类型由子类句柄隐性转换为父类句柄
    reg_trans t = reg_trans::type_id::create("t");
    t.cmd = (rw.kind == UVM_WRITE) ? `WRITE : `READ;
    t.addr = rw.addr;
    t.data = rw.data;
    return t;
  endfunction
  function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
    reg_trans t;
    if (!$cast(t, bus_item)) begin  //父类句柄转换为到子类句柄
      `uvm_fatal("CASTFAIL","Provided bus_item is not of the correct type")
      return;
    end
    rw.kind = (t.cmd == `WRITE) ? UVM_WRITE : UVM_READ;
    rw.addr = t.addr;
    rw.data = t.data;
    rw.status = UVM_IS_OK;
  endfunction
endclass
  • 在mcdf_env中分别声明register block,adapter和predictor,并完成例化,同时在connect阶段中完成句柄的连接。
// MCDF top environment
class mcdf_env extends uvm_env;
  ...
  //declare the mcdf_rgm handle, reg2mcdf_adapter handle and the
  //predictory handle
  mcdf_rgm rgm;
  reg2mcdf_adapter adapter;
  uvm_reg_predictor #(reg_trans) predictor;

  `uvm_component_utils(mcdf_env)
  ...

	function void build_phase(uvm_phase phase);
    ...
    //instantiate those objects
    //  -mcdf_rgm object
    //  -reg2mcdf_adapter object
    //  -predictory object
    //and finish necessary configuration
    rgm = mcdf_rgm::type_id::create("rgm", this);
    rgm.build();
    //rgm.lock_model();
    adapter = reg2mcdf_adapter::type_id::create("adapter", this);
    predictor = uvm_reg_predictor#(reg_trans)::type_id::create("predictor", this);
  endfunction

  function void connect_phase(uvm_phase phase);
    ...
    // Link the register model with the adapter and the predictor
    rgm.map.set_sequencer(reg_agt.sequencer, adapter);
    reg_agt.monitor.mon_ana_port.connect(predictor.bus_in);
    predictor.map = rgm.map;
    predictor.adapter = adapter;
    // connect the virtual sequencer's rgm handle with rgm object
    virt_sqr.rgm = rgm;
  endfunction

寄存器模型的使用

  • 完成register block句柄的传递。
virtual task body();
  `uvm_info(get_type_name(),
  // connect rgm handle
  rgm = p_sequencer.rgm;  //v_seq执行body()时,通过p_sequencer拿到v_sqr里的rgm句柄
  this.do_reg();
  this.do_formatter();
  this.do_data();
endtask
  • 将mcdf_data_consistence_basic_virtual_sequence原有的由总线sequence实现的寄存器读写,改为由寄存器模型操作的寄存器读写方式。
task do_reg();
  bit[31:0] wr_val, rd_val;
  uvm_status_e status;
  // slv0 with len=8,  prio=0, en=1
  wr_val = (1<<3)+(0<<1)+1;
  rgm.chnl0_ctrl_reg.write(status, wr_val);
  rgm.chnl0_ctrl_reg.read(status, rd_val);
  void'(this.diff_value(wr_val, rd_val, "SLV0_WR_REG"));

  // slv1 with len=16, prio=1, en=1
  wr_val = (2<<3)+(1<<1)+1;
  rgm.chnl1_ctrl_reg.write(status, wr_val);
  rgm.chnl1_ctrl_reg.read(status, rd_val);
  void'(this.diff_value(wr_val, rd_val, "SLV1_WR_REG"));

  // slv2 with len=32, prio=2, en=1
  wr_val = (3<<3)+(2<<1)+1;
  rgm.chnl2_ctrl_reg.write(status, wr_val);
  rgm.chnl2_ctrl_reg.read(status, rd_val);
  void'(this.diff_value(wr_val, rd_val, "SLV2_WR_REG"));

  // send IDLE command
  `uvm_do_on(idle_reg_seq, p_sequencer.reg_sqr)
endtask
  • 将mcdf_full_random_virtual_sequence原有的由总线sequence实现的寄存器读写,改为由寄存器模型预先设置寄存器值,再统一做总线寄存器更新的方式,并且由后门读取的方式取得寄存器值。
task do_reg();
  bit[31:0] ch0_wr_val;
  bit[31:0] ch1_wr_val;
  bit[31:0] ch2_wr_val;
  uvm_status_e status;

  //reset the register block
  rgm.reset();

  //slv0 with len={4,8,16,32},  prio={[0:3]}, en={[0:1]}
  ch0_wr_val = ($urandom_range(0,3)<<3)+($urandom_range(0,3)<<1)+$urandom_range(0,1);
  ch1_wr_val = ($urandom_range(0,3)<<3)+($urandom_range(0,3)<<1)+$urandom_range(0,1);
  ch2_wr_val = ($urandom_range(0,3)<<3)+($urandom_range(0,3)<<1)+$urandom_range(0,1);

  //set all value of WR registers via uvm_reg::set()
  rgm.chnl0_ctrl_reg.set(ch0_wr_val);
  rgm.chnl1_ctrl_reg.set(ch1_wr_val);
  rgm.chnl2_ctrl_reg.set(ch2_wr_val);

  //update them via uvm_reg_block::update()
  rgm.update(status);

  //wait until the registers in DUT have been updated
  #100ns;

  //compare all of write value and read value
  rgm.chnl0_ctrl_reg.mirror(status, UVM_CHECK, UVM_BACKDOOR);
  rgm.chnl1_ctrl_reg.mirror(status, UVM_CHECK, UVM_BACKDOOR);
  rgm.chnl2_ctrl_reg.mirror(status, UVM_CHECK, UVM_BACKDOOR);
  // rgm.mirror(status, UVM_CHECK, UVM_FRONTDOOR);

  // send IDLE command
  `uvm_do_on(idle_reg_seq, p_sequencer.reg_sqr)
endtask

寄存器内建序列的应用

  • 在mcdf_reg_builtin_virtual_sequence类中,使用uvm_reg_hw_reset_seq,uvm_reg_bit_bash_seq和uvm_reg_access_seq对MCDF寄存器模块展开全面测试。
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.intf.rstn);
  @(posedge p_sequencer.intf.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.intf.rstn <= 'b0;
  repeat(5) @(posedge p_sequencer.intf.clk);
  p_sequencer.intf.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.intf.rstn <= 'b0;
  repeat(5) @(posedge p_sequencer.intf.clk);
  p_sequencer.intf.rstn <= 'b1;
  rgm.reset();
  reg_acc_seq.model = rgm;
  reg_acc_seq.start(p_sequencer.reg_sqr);
  `uvm_info("BLTINSEQ", "register accesssequence finished", UVM_LOW)
endtask
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小破同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值