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,提问作者이정한
相关产品推荐
相关产品推荐

