Jump to content
Sign in to follow this  

Hierarchical UVM Register Model and maps

Recommended Posts



I have a bus system with one master and upto 64 slaves. Each of the slaves has a register block, which is accessible by the bus master and a local SPI interface like this:

                           +-----------+                +-----------+
                           | SPI Master|                | SPI Master|
                           |   Agent   |                |   Agent   |
                           +-----+-----+                +-----+-----+
                                 |                            |
                       +---------+--------+         +---------+--------+
                       |                  |         |                  |
                       |    SBUS Slave    |         |    SBUS Slave    |
                       |                  |         |                  |    ...
                       +---------+--------+         +---------+--------+
+-------------------+            |                            |
|                   |            |                            |
|    SBUS Master    +------------+----------------------------+---------------+
|                   |

In my testbench for this system (env) I wanted to reflect the register situation with a hierarchical UVM register model. I created a hierarchy of uvm_reg_blocks with one uvm_reg_block for every master and slave. These reg_blocks are sub-blocks of the top-level uvm_reg_block. Moreover I created two maps for every reg_block, one for SBUS access and one for SPI bus access. In the top-level map I created two maps and added all the SBUS  slave maps to the top-level SBUS map and SPI slave maps to the SPI map.


Now I have two issues with this approach:


1. Although the uvm_reg::write() method has got a map parameter, the sequencer and adapter are not taken from this map, but from system_map, which in my case is the top-level map. How can I tell e.g., that I want to use the SPI sequencer of slave nr 45 for an access? For illustration, see this code snippet:

task uvm_reg_map::do_write(uvm_reg_item rw);
  uvm_sequence_base tmp_parent_seq;
  uvm_reg_map system_map = get_root_map();
  uvm_reg_adapter adapter = system_map.get_adapter();
  uvm_sequencer_base sequencer = system_map.get_sequencer();
  if (adapter == null) begin
  else begin
    do_bus_write(rw, sequencer, adapter);

2. The uvm_reg_block::mirror() method does not allow to specify a map, i.e. it is not possible at all to tell which interface to use for this operation. I guess, the default map is always used, right?

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this