UVM INDIRECT registers

Hi
Question 1:
I want to implement registers which need 2 accesses , first being index written to some register and second with actual data . I was trying to implement them with uvm_reg_indirect_data and index but didn’t get any consolidated example. Can anyone tell me how exactly this will be implemented.
Scenario :
5 registers say reg[i] {0<=i<5}. To access them first we have to write offset register ( say address 'h12 } with value “i” .Then write data register ( say address 'h16) with actual data .

Question 2:
Also one more thing ,is it advisable to override uvm_reg with write/read methods modified to achieve some conditional writes (say data needs to be modified in some scenario before writing) , or better to write a task over RAL and calls uvm_reg read/write conditionally with updated values ?
example : for 1 register write if ABC define is there I need to make lower 8 bit 0 .
first case :
modify uvm_reg write and include this condition
if(define) data[7:0] =0 ;
do_write();

second_case:
Instead of reg.write calls from TB , will call write_wrapper() which will have following code
if(define) data[7:0] =0;
reg.write();

Which one is recommended and why ?

Thanks in advance

In reply to nikhilverif:

Could you please explain your scenarios in some more detail.

For scenario 1.
You have 5 registers reg1, …, reg5. There address depends on an offset, defined in another register (offset_reg). Is this correct?

In reply to chr_sue:

No we have 5 registers reg1…reg5 . Then we have 2 more registers say index_register and data_register . To access reg1 , I need to write index_register with value 1 and data_register with actual data .
But this split , I don’t want to expose to test coder . Test coder should say write(reg1) , automatically I need to put this splitting into 2 in RAL somehow . I read about indirect_reg which does something like this , but not sure how to implement .

In reply to nikhilverif:

I did still not get your point.

You have 7 registers: reg1, …, reg5, ind_reg, data_reg. Correct?
Which addresses do they have? Are there fixed addresses?
If you say you have to split the command write(reg1) into ot writes to 2 registers, the ind_reg and the data_reg, what does it menan for writing reg2?

In reply to chr_sue:

Ok let me try again .
There are 5 functional registers reg1…5 (say at addr 'h100…'h500) which needs to be programmed . Now these registers can be programmed in 2 ways .

  • First way is direct access from interface A which means we need to launch transaction at adderess 'h100 …'h500 for reg1…reg5 resp . This is normal case , so I skipped this from the question
  • Second way is to access indirect from interface B , By indirect I mean these addresses ('h100…'h500) are not accessible directly . To access these registers , we have 2 more registers in this space say index_register ('h12) and data_register ('h16) . If we need to access reg1 , we need to launch 1st transaction for index_register('h12) and write 1 into it and then second transaction to data_register ('h16) with actual data . For writing reg2…reg5 , we need to write 2…5 in index_register . In DUT ,when data_register is accessed , it will see the value of index_register , depending on its value 1…5 it will write the data written to data_register to reg1…reg5 resp .

Few solutions I can think of, help me with any more solution which seems better :

  • Now simple solution is to write a task which takes reg_name and interface(map) , and if interface is B , i will launch 2 write transactions (on index_reg and data_reg which will eventually write to desired reg) in that task .
  • Other solution is modify the write function of uvm_reg and do this splitting there on the basis of which map is accessed .
  • Third possible solution can be indirect_reg , which I am not able to do .

My question is which one is best among 3 and why ? Also if solution 3 can solve the issue , can I have some small code .

In reply to nikhilverif:

I could imagine a frontdoor sequence is a solution for your problem.