Change mirror value of a register field before running uvm_reg_hw_reset_seq

Hi Everyone,

I am running uvm_reg_hw_reset_seq on my regmodel. But before running I am writing onto a register (which is a must for my Env.)
So, I am trying to update the mirror value (through callback) for that register while the uvm_reg_reset_seq is being executed.

Below is the code :

class regmodel_write_cb  extends uvm_reg_cbs;
  ral_sys_REGBLOCK_wrapper regmodel;
  // ... other things
  virtual task post_read(uvm_reg_item rw);
    begin
      bit [31:0] rstcfg;
      this.regmodel.REGBLOCK.RSTCFG.predict(32'h0003);
      rstcfg = this.regmodel.REGBLOCK.RSTCFG.get_mirrored_value();
      $display("after prediction values are rst %h ",rstcfg);
    end
  endtask
  // ... other things
endclass

I have only shown the logic which I am implementing for overwriting the mirror value. Rest other things like callback registration, writing of this registers in the Top Env etc. are being done properly.

My intention here is to test the uvm_reg_hw_reset_seq on this register with it’s updated value ('h3). Not with the reset value ('h0).

Please suggest me how to achieve it. Thanks

In reply to birenkumar:

Did I understand you right: you Need a Special valaue in one of your registers before running the hw_reset_seq?
Does this make sense, writing a certain value which is immediately overwritten bya the reset_seq?

In reply to chr_sue:

My intention is to change the mirrored value (which is 'h0 after reset) to the value which I write (as 'h3 in my Top Env) before running the hw_reset_seq.

So that I can avoid this Error :

reporter [RegModel] Register “regmodel.REGBLOCK.RSTCFG” value read from DUT (0x0000000000000003) does not match mirrored value (0x0000000000000000)

So, basically my Idea is to override the mirrored value just after the read and just before the comparison takes place inside the hw_reset_seq for this register.
Hence, I am calling the predict() method inside the post_read() method.

Hope you got what I am trying to achieve here… :)

There might be one question in your mind that why am I writing to that register from the Top Env. The answer is that my Env needs to have that register written with that value ('h3) due to some setup requirement.

In reply to birenkumar:

I think there is something wrong with your Environment. DUT contains 'h3 this is the value after reset. But the mirror was not reset correctly or your Register model is wrong regarding this reset value. Please double-check.

In reply to chr_sue:

Yes, DUT contains 'h3 after reset. This is because, I do call .predict() method inside pre_write() method in order to make sure that the register will hold 'h3 value through out the simulation.
I want to update the mirror value to 'h3 before the comparison. But I am unable to do it.

In reply to birenkumar:

After running the hw_reset_seq the Registers in the DUT and in the mirror have to have the same value.

In reply to chr_sue:

Yes. That’s why I want to update the mirror value as I have already updated the value in DUT.

In reply to birenkumar:

This happens automatically, when you have set-up your Environment correctly.

In reply to birenkumar:

Below hack can help you,


class customized_uvm_reg_hw_reset_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
 
  // Subset of maps to be considered for running this sequence
  string test_on_maps[$];
  bit [31:0] register_addr;
  reg_test_splitter  m_reg_split_h;
  bit model_should_not_be_reset;
  bit predict_retention;
  int retention_value;
 
  `uvm_object_utils(customized_uvm_reg_hw_reset_seq)
 
  function new(string name="customized_uvm_reg_hw_reset_seq");
    super.new(name);
    m_reg_split_h = reg_test_splitter::type_id::create("m_reg_split_h");
  endfunction
 
  virtual task body();
    uvm_reg   regs[$];
    uvm_reg_map maps[$];
    string    map_name;
 
    if (model == null) 
    begin
      `uvm_error("customized_uvm_reg_hw_reset_seq", "Not block or system specified to run sequence on");
      return;
    end
 
    m_reg_split_h.get_configs();
    uvm_report_info("STARTING_SEQ",{"\n\nStarting ",get_name()," sequence...\n"},UVM_LOW);
 
    if (uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
      "NO_REG_TESTS", 0) != null ||
      uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
      "NO_REG_HW_RESET_TEST", 0) != null )
    return;
 
    // Hack for specific model to be reset/not 
    if(!model_should_not_be_reset)
    begin
      `uvm_info("RESETTING_REG_MODEL",get_name(),UVM_LOW)
      this.reset_blk(model);
      model.reset();
    end 
    else 
      `uvm_info("NOT_RESETTING_REG_MODEL",get_name(),UVM_LOW)
      model.get_maps(maps);
 
    // Iterate over all maps defined for the RegModel block
    foreach (maps[d]) 
    begin
      map_name = maps[d].get_name();
      foreach(test_on_maps[i]) 
      begin
	if (map_name == test_on_maps[i]) 
        begin
          uvm_status_e  status;
 
	  regs.delete();
	  maps[d].get_registers(regs);
          if (regs.size() == 0) 
          begin
            `uvm_fatal("customized_uvm_reg_hw_reset_seq", "Did not find any registers to test")
            return;
          end
          m_reg_split_h.filter(regs);
 
          foreach (regs[i]) 
          begin :foreach_loop
            uvm_reg  my_reg = regs[i];
            uvm_status_e status;
            register_addr = regs[i].get_address();
 
            // Registers with certain attributes are not to be tested
            if (uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},
	    "NO_REG_TESTS", 0) != null ||
	    uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},
	    "NO_REG_HW_RESET_TEST", 0) != null )
            begin
	      continue;
            end 
 
            // Simpl hack to load the mirror value apart from reset value
            if(predict_retention && regs[i].get_name() == "RETENTION_REGISTER")
	       regs[i].predict(retention_value);
 
            // Regular mirror method 
	    regs[i].mirror(status, UVM_CHECK, UVM_FRONTDOOR, maps[d], this);
            if (status != UVM_IS_OK) 
            begin : uvm_okay
              `uvm_error(get_type_name(),
	      $sformatf("Status was %s when reading reset value of register \"%s\" through map \"%s\".",
	      status.name(), regs[i].get_full_name(), maps[d].get_full_name()));
	    end : uvm_okay
          end :foreach_loop
 	end
      end
    end
  endtask: body
 
endclass: customized_uvm_reg_hw_reset_seq

In reply to tejastv:

I’m not sure if this hack will help. I’m convinced something is wrong with the environment.
This should be fixed.

In reply to birenkumar:

In reply to chr_sue:
My intention is to change the mirrored value (which is 'h0 after reset) to the value which I write (as 'h3 in my Top Env) before running the hw_reset_seq.
So that I can avoid this Error :
So, basically my Idea is to override the mirrored value just after the read and just before the comparison takes place inside the hw_reset_seq for this register.
Hence, I am calling the predict() method inside the post_read() method.
Hope you got what I am trying to achieve here… :)
There might be one question in your mind that why am I writing to that register from the Top Env. The answer is that my Env needs to have that register written with that value ('h3) due to some setup requirement.

One thing you should note here is,
hw-rst-seq does model.reset() followed by reg.mirror().

From your env if you are writing 'h3 to register and followed by hw-rst-seq, then its expected that the register value to have 'h0. and there will be an UVM_ERROR in hw-rst-seq.

so if you don’t want that register to get affected by model.reset(), then you can skip that register else you can modify the register’s predict value before mirror() method as specified in hack-code and get your job done.

In reply to tejastv:

It is completely confusing what you are saying. Because running a hw_reset seq overwrites any value in the DUT and the mirror. It does not make sense first to write something to a certain Register and immediately afterwards running a hw_reset seq.
If the mirror Returns you 'h0 and #h0 is not the reset value of this Register soemthing is wrong with your Environment. Because the mirror Returns the Default initial value of your Register.
The hw_res seq works perfectly. I’m using it in all my projects.

In reply to chr_sue:

I think, the issue here is, the DUT is right in having the resetvalue of 3, but the reg_model is expecting a value of 0 (which is an issue). So as a workaround he is trying to update the mirror value.

But, I think eventually he will need to fix the reg_model, rather than the working around it.

**Solution:**Now coming to WA, I think rather than predict(), you can use set_reset(val) I think.

Regards,
Ashith

In reply to Ashith:

I believe the DUT register has the value 3. If the mirror is not setup correctly it always returns 0. This is what I have seen in my projects. But another reason could also be the reset value of this register is wrong. This can be checked and corrected manually without big effort.
In this case if you are using the reset method of the register model it will also fail.

In reply to chr_sue:

In my code when I write the register from top env, I call the pre_write() method. In which I update the value to 'h3 by calling the same predict() method.

I have mentioned that I have to write this register for some Env requirement whcih cannot be avoided.

So, I am trying to update the mirror value again while executing the hw_reset_seq.
As I am not able to do it as of now, I would rather skip this register from hw_reset_seq (as suggested by tesjastv).

In reply to birenkumar:

From your environment, you can call like below:

this.regmodel.REGBLOCK.RSTCFG.set_reset(32'h0003);

This would ensure the reset value is updated and when the sequence does reg_model.reset, this would become the mirrored value.

In reply to birenkumar:

Why not Setting the reset value of this register to 'h3. This would avoid any modification prior to running the hw_reset_seq.

In reply to Ashith:

Thanks. This would help. :)