Regarding get_reg_by_ofset function in uvm_register_model

Hi,

There was a function in the register model called get_reg_by_offset,which is a reg_map function,which returns the register handle of the given offset in the function.It is working fine when i use it with the top block and not working when i am trying to access from the sub block.

for example, i have a reg model which has two sub blocks s1,s2 which contains registers at off set 0 and 4,and the sub blocks were added to the top block’s default map at off set 0000 ,and 1000.

when i am trying to access like

reg_model.default_map.get_reg_by_offset(0000);
reg_model.default_map.get_reg_by_offset(0004);
reg_model.default_map.get_reg_by_offset(1000);
reg_model.default_map.get_reg_by_offset(1004);

These are working fine and giving the proper register handle.

But when i am accessing like

reg_model.s1.default_map.get_reg_by_offset(4);
reg_model.s1.default_map.get_reg_by_offset(0);
reg_model.s2.default_map.get_reg_by_offset(4);
reg_model.s2.default_map.get_reg_by_offset(0);
The above statements are giving null.May i know the reason ,why this is working like this?
Is this function works fine only for top blocks register map?Please help me in this regard.

Thanks in advance…

Sai Subhash

Here’s what the reference guide says about get_reg_by_offset():

get_reg_by_offset

virtual function uvm_reg get_reg_by_offset( uvm_reg_addr_t offset, 	   	
bit read = 1 )

Get register mapped at offset:
Identify the register located at the specified offset within this address map for the specified type of access. Returns null if no such register is found.
The model must be locked using uvm_reg_block::lock_model() to enable this functionality.

Is it possible you didn’t call lock_model() on reg_model.s1 or s2?

In reply to tfitz:

Actually i called lock_model for each block when ever they are created…

In reply to subhash@ineda:

Hi,

Recently I run into exactly same issue as you.

It turns out that you must take the base address of mid-layer map into offset calculation, besides, you can’t use other default_map except the top_map.

I don’t know what base address you used for s1~s4, let me assume you are using 'h100, 'h200, 'h300 and 'h400.

reg_model.s1.default_map.get_reg_by_offset(4);
reg_model.s1.default_map.get_reg_by_offset(0);
reg_model.s2.default_map.get_reg_by_offset(4);
reg_model.s2.default_map.get_reg_by_offset(0);

Above codes should be changed as following to make sure get_reg_by_offset can return the register you want to get.

reg_model.default_map.get_reg_by_offset('h100 + 4);
reg_model.default_map.get_reg_by_offset('h200 + 0);
reg_model.default_map.get_reg_by_offset('h300 + 4);
reg_model.default_map.get_reg_by_offset('h400 + 0);

Hope it helps.
WangYang

Hi,

It’s possible to use get_reg_by_offset from any map except the bottom most map.
The array that is used to return the register handle when this method is called, is actually populated when a submap is added to the map provided the reg_model is locked.

Ex:
Lets assume we have three reg_blocks; a3 that is added to a2 and a2 to a1;
Following is the sequence of commands to follow in the reg_block a1(after creating and configuring a2);

default_map=create_map(“default”,arguments);
lock_model();
default_map.add_submap(a2.default_map,base_addr_of_a2);

The same procedure should be followed for a2 when adding a3 to it.
Then, the below command returns the required register handle.
a1.a2.default_map.get_reg_by_offset(base_addr_of_a3+reg_offset_in_a3);

So, we cannot use this method only for the bottom most map (i.e a3) since it doesn’t have any submaps added to it.

Thanks.

Hi,

For the get_reg_by_offset() to work, lock the reg block before configuring it, i.e before the the parent to the block is set.
The lock_model ensures that the dynamic array which returns the register handles based on offset is populated at that level, when parent block is not set.

Let s1,s2 be the sub blocks of the reg_model. Use following way in the build() of reg model.

s1 = new();
s1.build();
s1.lock_model();
s1.configure(this,“”);

Now,
reg_model.s1.default_map.get_reg_by_offset(4);
reg_model.s1.default_map.get_reg_by_offset(0);
These statements will return the correct register handle.

This should work even if s1.default_map has any submaps added to it also.

P.S: Don’t know whether it is correct to call lock_model() or build() before setting parent block through configure(), just tried these based on the source code and it worked.

Thanks,
Sreekar

This is very usefully for me. Thank you
free online store builder

In reply to sreekar kokkonda:

Hi, I have a leaf-level block at a non-zero offset. The design has a very odd indirect-addressing method, so the normal RAL indirect_data_reg isn’t usable. So I created an instance of the indirect-addressable registers as a block at a super-high address, and am treating them like they are directly-accessible.

When a read/write comes in for the indirect-address register, the data field (which is the address for the indirect-address) is captured, and I use get_reg_by_offset() to get a pointer to the indirect-access register, using the indirect_map.

get_reg_by_offset() always returns null.

But when I get all registers from the indirect_map and print them out, however, I see that they exist and have correct offsets.

subblock.build() does the following:

  • creates registers
  • creates map
  • does map.add_reg(…) for each register
  • lock_model()

topblock.build() does the following:
U_subblock = subblock_type::type_id::create(“U_subblock”);
U_subblock.configure(this);
U_subblock.build();
lock_model();

Then at the environment:
reg_model = topblock_type::type_id::create(“reg_model”);
reg_model.build();
reg_model.reset();
reg_model.lock_model();

Any suggestions would be most appreciated.

In reply to erik.k.jessen@raytheon.com:

An alternative question: would these indirect-register banks be better modeled using separate, top-level uvm_reg_maps, instead of at high addresses in single map?