In reply to Gunther Clasen:
Unfortunately, uvm_mem does not support multiple physical memories making up a single logical memory of greater depth. The solution is to add a user defined backdoor.
This is an example of a 24 bit wide memory made up of 64 2048x12 memories. In our case HW accesses all these memories in parallel, but for CPU access they are treated as a single logical memory. Code like this can be generalized, but there’s always a variation that breaks the general case, so it’s not too much difficulty to have a few custom backdoors for the few special cases.
class dmem_backdoor extends uvm_reg_backdoor;
string m_sBank[32][2];
uint32 m_nBankSize = 2048;
function new(string name = "dmem_backdoor", string sRootPath);
super.new(name);
for (int i=0; i<32; i++) begin
for (int j=0; j<2; j++) begin
string ss = $sformatf("%s.u_ax_e_core.u_ax_bf.idmem.gen_agl_bram_switch[%0d].iram.ga11d12.iram.uut.mem_core_array", sRootPath, 2*i+j);
m_sBank[i][j] = ss;
end
end
endfunction
virtual task write(uvm_reg_item rw);
bit ok=1;
foreach (rw.value[i]) begin
int nAddr = rw.offset + i;
int nBank = nAddr / m_nBankSize;
int nOffset = nAddr % m_nBankSize;
string sSlice0 = $sformatf("%s[%0d]", m_sBank[nBank][0], nOffset);
string sSlice1 = $sformatf("%s[%0d]", m_sBank[nBank][1], nOffset);
`uvm_info("RegModel", {"backdoor_write to ", sSlice0, " ", sSlice1}, UVM_DEBUG);
ok &= uvm_hdl_deposit(sSlice0, rw.value[i][11:0]);
ok &= uvm_hdl_deposit(sSlice1, rw.value[i][27:16]);
end
rw.status = (ok ? UVM_IS_OK : UVM_NOT_OK);
endtask
virtual task read(uvm_reg_item rw);
bit ok=1;
foreach (rw.value[i]) begin
int nAddr = rw.offset + i;
int nBank = nAddr / m_nBankSize;
int nOffset = nAddr % m_nBankSize;
int nData;
string sSlice0 = $sformatf("%s[%0d]", m_sBank[nBank][0], nOffset);
string sSlice1 = $sformatf("%s[%0d]", m_sBank[nBank][1], nOffset);
`uvm_info("RegModel", {"backdoor_read to ", sSlice0, " ", sSlice1}, UVM_DEBUG);
ok &= uvm_hdl_read(sSlice0, nData);
rw.value[i][15:0] = 16'(signed'(nData[11:0])); // sign extend on read
ok &= uvm_hdl_read(sSlice1, nData);
rw.value[i][31:16] = 16'(signed'(nData[11:0])); // sign extend on read
end
rw.status = (ok ? UVM_IS_OK : UVM_NOT_OK);
endtask
endclass
To use a custom backdoor simply add it to the reg model instance.
your_reg_model.your_mem.set_backdoor(your_back_door_object);
After adding the custom backdoor the uvm_mem instance will use it instead of the built-in backdoor.