UVM Tutorial for Candy Lovers – 30. Back of the Back Door

In the earlier posts (Register Access through the Back Door and Backdoor HDL Path), we used configure, add_hdl_path and add_hdl_path_slice, then these functions magically created the HDL paths. That’s fine as a user, but as an expert, would you like to know what happened in the back? This article peeks the back of the backdoor access.

Register Block’s HDL Paths

The register block stores its HDL paths in a queue. To be precise, it can have multiple queues (in a pool keyed by a string). The default key is "RTL". For example, you can specify the key when you call:

  add_hdl_path( string path, string kind = "RTL" );
clear_hdl_path(              string kind = "RTL" );

where the kind argument is used as the key. We can specify the HDL path when we configure the register block:

configure( uvm_reg_block parent = null, string hdl_path = "" );

We can also have more than one HDL path by calling add_hdl_path. If you have multiple HDL paths, you can read/write/peek/poke multiple physical registers at once (with the same value if write or poke). Note that read and peek return only the first read value on the paths even if you had multiple read values. The figure below illustrates how HDL paths are stored in the pool and the queues.

How HDL paths are stored in the register block
How HDL paths are stored in the register block

Register Model’s HDL Path Slices

Similar to the register block, the register model stores its HDL path slices in a queue, but in a slightly more complicated way. Since the slice has offset and size information, the slice is structured as uvm_hdl_path_slice first. Then the slices that belong to the same physical register are grouped into a uvm_hdl_path_concat object. We can have more than one uvm_hdl_path_concat in the queue. If you have multiple uvm_hdl_path_concat, you can read/write/peek/poke multiple physical registers at once (with the same value if write or poke). Note that read and peek return only the first read value on the paths even if you had multiple read values.
Like the register block, the register model can have multiple queues in a pool keyed by a string. The default key is "RTL". For example, you can specify the key when you call:

  add_hdl_path      ( uvm_hdl_path_slice slices[],                      string kind = "RTL" );
  add_hdl_path_slice( string name, int offset, int size, bit first = 0, string kind = "RTL" );
clear_hdl_path      (                                                   string kind = "RTL" );

where the kind argument is used as the key. Note that the add_hdl_path takes a dynamic array of uvm_hdl_path_slice that was mentioned above. The function creates a new uvm_hdl_path_concat to store the specified slices. Similarly, if the first argument of the add_hdl_path_slice is 1, then a new uvm_hdl_path_concat is created to store the specified slice. The figure below illustrates how HDL paths are stored in the pool and the queues.

How HDL paths are stored in the register model
How HDL paths are stored in the register model

HDL Path of Jelly-Bean Register Block

Now we know the data structure behind the scenes, so let’s look at how our HDL paths are stored. We created three register blocks. Each register block has one HDL path.

How HDL paths are stored in the jelly bean register blocks
How HDL paths are stored in the jelly bean register blocks

HDL Path Slices of Jelly-Bean Register

We created four register models and each model has one HDL path concat that has one or more HDL path slices.

How HDL paths are stored in the jelly bean register models
How HDL paths are stored in the jelly bean register models
I hope this article helped you to understand the HDL path in more detail.

Leave a Reply