Accessing the UVM RAL model handle inside the testbench module

I want to access the UVM RAL model handle inside the testbench module to get the values of the register fields for writing the system verilog assertions.

I am getting compile error when I am trying to access the RAL model handle using the uvm_test_top hierarchy inside the Testbench top module as classes are not created at elaboration time.

Following is the code I have used to access the RAL handle inside the top testbench module.

initial
begin
_pcrm_reg_mmap_type PCRM_REG;

#10us;

uvm_config_db#(_pcrm_reg_mmap_type)::get(this,“*”,“PCRM_REG”,PCRM_REG);

if(PCRM_REG != null) begin
$display(“PCRMLP_REG is not null”);
end
end

I am getting compilation error that “this” keyword can only be used within a class scope.

In reply to nvjoshi85:

Why do you want to use the RAL model in the toplevel module? There is your DUT instantiated and you can directly Access the Registers through the hierarchical path from this module.

In reply to chr_sue:

The registers are placed at different hierarchies in the design and the number of registers which I need to use for the assertions are more than 100. I do’nt want to snoop the hierarchy for each of the signal . Every time there is a change in the design hierarchy , re-work will be required.

In reply to nvjoshi85:
OK, I understand.
Could you please explain in some more Details where and how do you implement your RL model in the toplevel module.

In reply to chr_sue:

I am creating the RAL model inside the env class build method and I am calling the uvm_config_db::set() method inside the connect() phase as follows.

if(PCRMLP_REG == null) begin
PCRMLP_REG=_pcrm_lp_reg_mmap_type::type_id::create(“PCRMLP_REG”,this);
PCRMLP_REG.build();
PCRMLP_REG._pcrm_lp_reg_rf.set_hdl_path_root(“DUT PATH”);
PCRMLP_REG.lock_model();
PCRMLP_REG.default_map.set_auto_predict(.on(0));
end

if(PCRMHP_REG == null) begin
PCRMHP_REG=_pcrm_hp_reg_mmap_type::type_id::create(“PCRMHP_REG”,this);
PCRMHP_REG.build();
PCRMHP_REG.lock_model();
PCRMHP_REG.helios_pcrm_hp_reg_rf.set_hdl_path_root(“DUT PATH”);
PCRMHP_REG.default_map.set_auto_predict(0);
end

uvm_config_db#(helios_pcrm_lp_reg_mmap_type)::set(this, “", “PCRMLP_REG”, PCRMLP_REG);
uvm_config_db#(helios_pcrm_hp_reg_mmap_type)::set(this, "
”, “PCRMHP_REG”,PCRMHP_REG);

uvm_config_db::get() method is called inside the initial block to get the RAL handle after some random non-zero delay to allow the UVM hierarchy to be built-up as I have mentioned in the first post in this thread.

In reply to nvjoshi85:

A good approach is to put the register model into a configuration object and passing this object to the config_db.
Then you can retrieve it in any place from the config_db. But you have to do the get after the set was executed.
BTW the lock_model should be in the register model. It is one of the last lines like this:

  class mode_reg_block extends uvm_reg_block;
      `uvm_object_utils(mode_reg_block)

      rand MR0_reserved_reg MR0_reserved; // Reserved-1
      rand MR1_DeviceFeature_1_reg MR1_DeviceFeature_1; // Device Feature-1

      uvm_reg_map mode_reg_block_map; 

      // Function: new
      // 
      function new(string name = "mode_reg_block");
         super.new(name, UVM_NO_COVERAGE);
      endfunction


      // Function: build
      // 
      virtual function void build();
         MR0_reserved = MR0_reserved_reg::type_id::create("MR0_reserved");
         MR0_reserved.configure(this);
         MR0_reserved.build();
	 MR0_reserved.add_hdl_path_slice("mode_reg[0]", 0, 8);

         MR1_DeviceFeature_1 = MR1_DeviceFeature_1_reg::type_id::create("MR1_DeviceFeature_1");
         MR1_DeviceFeature_1.configure(this);
         MR1_DeviceFeature_1.build();
	 MR1_DeviceFeature_1.add_hdl_path_slice("mode_reg[1]", 0, 8);

         mode_reg_block_map = create_map("mode_reg_block_map", 'h0, 1, UVM_LITTLE_ENDIAN);
         default_map = mode_reg_block_map;

         mode_reg_block_map.add_reg(MR0_reserved, 'h0, "WO");
         mode_reg_block_map.add_reg(MR1_DeviceFeature_1, 'h1, "WO");

         // Assign dut to the hdl path
         add_hdl_path("xxx_top_tb.dut", "RTL");
         lock_model();
      endfunction
   endclass

In reply to chr_sue:

I also want to use my reg_model in my interface to write immediate and concurrent assertions. Is there any way to do so?

In reply to jasmine_ti:

What kind of immediate assertions on the register content do you mean?
Also using concurrent assertions to check the register content is unclear to me.
Could you please elaborate something more?

In reply to chr_sue:

I want to write concurrent assertions. Since we can’t do that in a class, so I want to access the reg model in my interface or a module. I want to use reg model to know the state of my DUT and then write assertions accordingly. For example, to see if interrupt is enabled by reading Interrupt enable register bit and then writing a check for the interrupt assertion. Something like this.

In reply to jasmine_ti:

OK, I understand.
The UVM RAL is not a UVM component, i.e. it does not have certain position in the UVM hierarchy. It is common practice to put the UVM RAL as a n object into th config_db. Then you can retrive a handle to the RAL in any UVM component, also in an interface. But you have to consider that the class-based components an dobjects are constructed at runtime 0 and after the the staic components (modules, interfaces) have been instantiated.After the connect_phase the complete UVM environment is existing. In the end_elaboration_phase you could triger a uvm_event indivcating you are there and all class-based stuf does exist. Then you can retrieve in a module/interface the RAL handle.
Note it is a good coding practice to hold your concurrent assertions in a seperate module. Then you can bind a special module to your DUT registers using the bind construct. In this way you can also consider DUT register content.