You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UVM环境中队列数据意外被随机化问题求助

问题解决:UVM Scoreboard队列数据被异常修改

问题原因

核心问题是直接将monitor传递的transaction对象引用存入队列,而非对象的独立副本。UVM中monitor通常会复用同一个transaction对象(每次采集数据时覆盖原有内容),队列中存储的只是对象的指针,当monitor更新该对象时,队列里所有指向该对象的元素都会同步变化,表现为队列数据被随机值覆盖。

解决方案

在将transaction存入队列前,必须创建对象的深拷贝副本,确保队列中存储的是独立的对象实例。利用UVM对象的copy()方法配合对象创建,或直接使用clone()方法实现拷贝:

关键修改代码

在write_expdata函数中,替换直接push原对象的逻辑:

function write_expdata(input apb_transaction tr);
  apb_transaction tr_copy;
  if (tr.pwrite == 1 && tr.penable == 1) begin
    // 创建原transaction的深拷贝
    tr_copy = apb_transaction::type_id::create("tr_copy");
    tr_copy.copy(tr);
    // 将副本存入队列
    obj.exp_queue.push_back(tr_copy);
    
    `uvm_info(get_type_name(), "get_write_data", UVM_LOW)
    tr.print();
    `uvm_info(get_type_name(), $psprintf("queue[0]: \n%s", obj.exp_queue[0].sprint()), UVM_LOW)
  end
  
  foreach(obj.exp_queue[i]) `uvm_info(get_type_name(), $psprintf("pwdata[%d]: %8h", i, obj.exp_queue[i].pwdata), UVM_LOW)
endfunction

也可以用更简洁的clone()方式(需确保apb_transaction正确继承uvm_object的clone方法):

function write_expdata(input apb_transaction tr);
  if (tr.pwrite == 1 && tr.penable == 1) begin
    // 直接通过clone获取独立副本
    obj.exp_queue.push_back(apb_transaction'(tr.clone()));
    
    `uvm_info(get_type_name(), "get_write_data", UVM_LOW)
    tr.print();
    `uvm_info(get_type_name(), $psprintf("queue[0]: \n%s", obj.exp_queue[0].sprint()), UVM_LOW)
  end
  
  foreach(obj.exp_queue[i]) `uvm_info(get_type_name(), $psprintf("pwdata[%d]: %8h", i, obj.exp_queue[i].pwdata), UVM_LOW)
endfunction

完整修改后的Scoreboard代码

`uvm_analysis_imp_decl(_expdata)
`uvm_analysis_imp_decl(_actdata)

class exp_obj extends uvm_object;
  `uvm_object_utils(exp_obj)
  apb_transaction exp_queue[$];
  
  function new(string name = "exp_obj");
    super.new(name);
  endfunction
endclass

class apb_scoreboard extends uvm_scoreboard;
  `uvm_component_utils(apb_scoreboard)
  
  uvm_analysis_imp_expdata#(apb_transaction, apb_scoreboard) mon_export;
  uvm_analysis_imp_actdata#(apb_transaction, apb_scoreboard) sb_export;
  exp_obj obj;
  
  
  function new(string name, uvm_component parent);
    super.new(name, parent);
    mon_export = new("mon_export", this);
    sb_export = new("sb_export", this);
    obj = new("obj");
    obj.rand_mode(0);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
  endfunction

  function write_actdata(input apb_transaction tr);
    apb_transaction expdata;
    if (tr.pwrite == 0 && tr.penable == 0) begin
      if(obj.exp_queue.size()) begin
        `uvm_info(get_type_name(), $psprintf("queue[0]: \n%s", obj.exp_queue[0].sprint()), UVM_LOW)
        expdata = obj.exp_queue.pop_front();
        tr.compare(expdata);
        if(tr.prdata == expdata.pwdata)begin
          `uvm_info("",$sformatf("MATCHED, %8h", expdata.pwdata),UVM_LOW)
        end
        else begin
          `uvm_info("",$sformatf("MISMATCHED, tr: %8h, expdata: %8h", tr.prdata, expdata.pwdata),UVM_LOW)
        end
      end
    end
  endfunction
  
  function write_expdata(input apb_transaction tr);
    apb_transaction tr_copy;
    if (tr.pwrite == 1 && tr.penable == 1) begin
      tr_copy = apb_transaction::type_id::create("tr_copy");
      tr_copy.copy(tr);
      obj.exp_queue.push_back(tr_copy);
      
      `uvm_info(get_type_name(), "get_write_data", UVM_LOW)
      tr.print();
      `uvm_info(get_type_name(), $psprintf("queue[0]: \n%s", obj.exp_queue[0].sprint()), UVM_LOW)
    end
    
    foreach(obj.exp_queue[i]) `uvm_info(get_type_name(), $psprintf("pwdata[%d]: %8h", i, obj.exp_queue[i].pwdata), UVM_LOW)
  endfunction
                            
endclass

内容的提问来源于stack exchange,提问作者이정한

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 11:53:18