Hi! I have a register model containing multiple registers, as well as a CTRL register with multiple fields. This CTRL register contains a go_bsy
field, which when is set, writes to every register/field, including itself should be ignored (you can’t write go_bsy
back to 0, it is automatically deasserted by the DUT after a transaction or after reset).
I made a callback for this purpose that looks like this:
class spi_master_lock_reg_callback extends uvm_reg_cbs;
uvm_reg_field protected_field;
function new(string name, uvm_reg_field protected_field);
super.new(name);
this.protected_field = protected_field;
endfunction
virtual function void post_predict(
input uvm_reg_field fld,
input uvm_reg_data_t previous,
inout uvm_reg_data_t value,
input uvm_predict_e kind,
input uvm_path_e path,
input uvm_reg_map map
);
if(kind == UVM_PREDICT_WRITE)
return;
if (value) begin
void'(protected_field.set_access("RO"));
`uvm_info("LOCKER", $sformatf("Locked field %s", protected_field.get_name()), UVM_LOW)
end
endfunction
endclass
It is instanced for each field and attached to the go_bsy
field:
foreach(ctrl_fields[i]) begin
ctrl_locks[i] = new($sformatf("lock_%s", ctrl_fields[i].get_name()), ctrl_fields[i]);
`uvm_reg_field_cb::add(ctrl_reg.go_bsy, ctrl_locks[i]);
end
// the same for other registers
The access is set to RO
when I write go_bsy
to 1, and it is set back to RW
in my predictor after a transaction.
It works almost fine: I write go_bsy
to 1 and any subsequent writes are ignored.
The issue is that if I have an operation where I write 1 to go_bsy
and change any of the control fields at the same time, the other control fields do not update.
Note: it is interesting that fields that have their position before
go_bsy
(for examplechar_len
’s position is reg[0:6] andgo_bsy
is at reg[8]), seem to update just fine. I already tried changing the order of the callbacks, sogo_bsy
’s is called last, but it didn’t work.