In reply to dave_59:
Dave,
Thanks a lot for pointing out the specific topic I should look into. I’ve read up a bit about explicit the last few days, and I have also ensure that I have disabled auto-prediction in my env setup.
m_config.rm.default_map.set_auto_predict(0);
Now, I’ve come to the point that I’m debugging what’s going wrong in my bus2reg operation. I took the code from uvm_reg_predictor, and added in pointers print out for debugging.
In the write function of the my_uvm_reg_predictor (clone from uvm_reg_predictor), I added some print lines and put them in BOLD in code snippet below:
virtual function void write(BUSTYPE tr);
uvm_reg rg;
uvm_reg_bus_op rw;
if (adapter == null)
`uvm_fatal("REG/WRITE/NULL","write: adapter handle is null")
// In case they forget to set byte_en
rw.byte_en = -1;
adapter.bus2reg(tr,rw);
rg = map.get_reg_by_offset(rw.addr, (rw.kind == UVM_READ));
**`uvm_info(get_type_name(),$sformatf("REG::\nkind: %s\naddr: 0x%8h\ndata: 0x%8h", rw.kind, rw.addr, rw.data), UVM_LOW)**
if (rg != null) begin
bit found;
uvm_reg_item reg_item;
uvm_reg_map local_map;
uvm_reg_map_info map_info;
uvm_predict_s predict_info;
uvm_reg_indirect_data ireg;
uvm_reg ir;
if (!m_pending.exists(rg)) begin
uvm_reg_item item = new;
predict_info =new;
item.element_kind = UVM_REG;
item.element = rg;
item.path = UVM_PREDICT;
item.map = map;
item.kind = rw.kind;
predict_info.reg_item = item;
m_pending[rg] = predict_info;
end
predict_info = m_pending[rg];
reg_item = predict_info.reg_item;
if (predict_info.addr.exists(rw.addr)) begin
`uvm_error("REG_PREDICT_COLLISION",{"Collision detected for register '",
rg.get_full_name(),"'"})
// TODO: what to do with subsequent collisions?
m_pending.delete(rg);
end
local_map = rg.get_local_map(map,"predictor::write()");
map_info = local_map.get_reg_map_info(rg);
ir=($cast(ireg, rg))?ireg.get_indirect_reg():rg;
foreach (map_info.addr[i]) begin
if (rw.addr == map_info.addr[i]) begin
found = 1;
reg_item.value[0] |= rw.data << (i * map.get_n_bytes()*8);
predict_info.addr[rw.addr] = 1;
if (predict_info.addr.num() == map_info.addr.size()) begin
// We've captured the entire abstract register transaction.
uvm_predict_e predict_kind =
(reg_item.kind == UVM_WRITE) ? UVM_PREDICT_WRITE : UVM_PREDICT_READ;
if (reg_item.kind == UVM_READ &&
local_map.get_check_on_read() &&
reg_item.status != UVM_NOT_OK) begin
void'(rg.do_check(ir.get_mirrored_value(), reg_item.value[0], local_map));
end
pre_predict(reg_item);
ir.XsampleX(reg_item.value[0], rw.byte_en,
reg_item.kind == UVM_READ, local_map);
begin
uvm_reg_block blk = rg.get_parent();
blk.XsampleX(map_info.offset,
reg_item.kind == UVM_READ,
local_map);
end
rg.do_predict(reg_item, predict_kind, rw.byte_en);
**`uvm_info(get_type_name(), $sformatf("Register %s\n%s", ir.get_full_name(),ir.sprint()), UVM_LOW)**
if(reg_item.kind == UVM_WRITE)
**`uvm_info("REG_PREDICT", {"Observed WRITE transaction to register ",
ir.get_full_name(), ": value='h",
$sformatf("%0h",reg_item.value[0]), " : updated value = 'h",
//$sformatf("%0h",ir.get())},UVM_HIGH)
$sformatf("%0h",ir.get())},UVM_LOW)**
else
`uvm_info("REG_PREDICT", {"Observed READ transaction to register ",
ir.get_full_name(), ": value='h",
$sformatf("%0h",reg_item.value[0])},UVM_HIGH)
reg_ap.write(reg_item);
m_pending.delete(rg);
end
break;
end
end
if (!found)
`uvm_error("REG_PREDICT_INTERNAL",{"Unexpected failed address lookup for register '",
rg.get_full_name(),"'"})
end
else begin
`uvm_info("REG_PREDICT_NOT_FOR_ME",
{"Observed transaction does not target a register: ",
$sformatf("%p",tr)},UVM_FULL)
//$sformatf("%p",tr)},UVM_LOW)
`uvm_info(get_type_name(),"REG_PREDICT_NOT_FOR_ME!", UVM_LOW)
end
endfunction
In my env, I was setting the register access using my own I2C agent instead this time. My sequence transaction is as this:
`uvm_do_on_with(i2c_seq, p_sequencer.i2c_seqr, {reg_rw==CMD_WR; dev_addr==chipid; reg_addr==32’h000200b0; reg_wdata==32’h118081a2; reg_cycle==4;})
model[0].dclp_ctrl0_reg.predict(32’h1180_81A2);
$display(“DEBUG: dclp_ctrl0_reg value=0x%8h”, model[0].dclp_ctrl0_reg.get_mirrored_value());
From the logfile below, it shows that the register-predictor is able to understand I’m programming my register at address 0x12000200B0, with data 0x118081A2. However, when I print out the reg_item after the do_predict line in uvm_reg_predcitor, it shows the value is still not update (I expect the LSB 3-bit, adc_lsb_raw updated to 2), and stays at the default value. It’s only when I manually call the predict function, the above bold line, I can finally see the mirrored value is updated. In line 232 of my_uvm_reg_predictor, it also indicated that it understand I’m trying to update the register content to value 'h118081a2, but it’s updated value is still 'h118081a4. What did I not set right? I have no clues for now, and hope you can help to provide some pointers.
If I switch to use the RAL register access method, then it works.
model[0].dclp_ctrl0_reg.write(status, 32’h1180_81A2, .parent(this));
# UVM_INFO ./tb/my_uvm_reg_predictor.svh(153) @ 9840500000: uvm_test_top.top_e.reg_predictor [my_uvm_reg_predictor #(i2c_transaction)] REG::
# kind: UVM_WRITE
# addr: 0x12000200b0
# data: 0x118081a2
# UVM_INFO ./tb/my_uvm_reg_predictor.svh(230) @ 9840500000: uvm_test_top.top_e.reg_predictor [my_uvm_reg_predictor #(i2c_transaction)] Register rm.rx_reg[0].dclp_ctrl0_reg
# ------------------------------------------------------------------------
# Name Type Size Value
# ------------------------------------------------------------------------
# dclp_ctrl0_reg r_dclp_ctrl0_reg - @12553
# adc_lsb_raw uvm_reg_field ... RW dclp_ctrl0_reg[2:0]=3'h4
# adc_lsb_dp uvm_reg_field ... RW dclp_ctrl0_reg[5:3]=3'h4
# d_dc_msb uvm_reg_field ... RW dclp_ctrl0_reg[8:6]=3'h6
# dc_init uvm_reg_field ... RW dclp_ctrl0_reg[15:9]=7'h40
# dc_dac uvm_reg_field ... RO dclp_ctrl0_reg[23:17]=7'h40
# kdc uvm_reg_field ... RO dclp_ctrl0_reg[26:24]=3'h1
# kdc_d uvm_reg_field ... RO dclp_ctrl0_reg[30:28]=3'h1
# d_dclp_lp_clk uvm_reg_field ... RW dclp_ctrl0_reg[31:31]=1'h0
# ------------------------------------------------------------------------
#
# UVM_INFO ./tb/my_uvm_reg_predictor.svh(232) @ 9840500000: uvm_test_top.top_e.reg_predictor [REG_PREDICT] Observed WRITE transaction to register rm.rx_reg[0].dclp_ctrl0_reg: value='h118081a2 : updated value = 'h118081a4
# DEBUG: dclp_ctrl0_reg value=0x118081a2