Advantage of calling set() over write()

Hi Forum,
I am new to UVM RAL and was trying to understand the application of calling register.set()

Consider the following 2 ways to configure specific registers during IP initialization

(1) Using set() & update()

 reg_block.rega.set(wdata1);
 reg_block.regb.set(wdata2);
 reg_block.regc.set(wdata3);
 // Configure other registers
 reg_block.update();

(2) Directly calling write()

 reg_block.rega.write(status,wdata1);
 reg_block.regb.write(status,wdata2);
 reg_block.regc.write(status,wdata3);
 // Configure other registers

There is an extra method called in (1) compared to (2) ,
so wouldn’t any user prefer using (2) ?

When should I consider using set() & update() over directly calling write() ?

Simulation performance may be improved with set()/update() when

  • The current mirrored value is the same as the desired given by set(). Then no bus transactions happens.
  • you want to write to multiple fields of a register that are not individually selectable. Writing to multiple fields of register creates multiple read/modify/write transactions. You can use set() to the individual fields and then update then entire register.

Normally you would just apply set() any field/register in the entire register model, and then call a single update() on the entire model.

Hi Dave,
A follow-up question.
Within the task definition of task ‘write’ I observe ::

task uvm_reg::write(output uvm_status_e      status,
                    input  uvm_reg_data_t    value,
                    input  uvm_path_e        path = UVM_DEFAULT_PATH,
                    input  uvm_reg_map       map = null,
                    input  uvm_sequence_base parent = null,
                    input  int               prior = -1,
                    input  uvm_object        extension = null,
                    input  string            fname = "",
                    input  int               lineno = 0);

   // create an abstract transaction for this operation
   uvm_reg_item rw;

   XatomicX(1);

   set(value);  // Updates 'desired' value immediately 
   .................
   do_write(rw);

   status = rw.status;

   XatomicX(0);

endtask

Then within task ‘do_write’ just before it unblocks there is a call to

do_predict(rw, UVM_PREDICT_WRITE); // Updates both 'mirrored' & 'desired' values

Since ‘do_predict’ updates both desired & mirrored values, why is there a need to call set(value) ?