Question

I've UVM verification environment.

In my test sequence I read (mirror) from REGA through FRONTDOOR (serial transaction) upon receiving interrupt.

In my scoreboard I've used .predict methods to updated expected values of REGA.

However I've following error:

Register "regmodel.REGA" value read from DUT (0x00000000000000AA) does not match mirrored value (0x0000000000000000)

Value read from DUT is correct (AA), and if I print value used in predict method then that is correct as well (AA)

However In simulation I've following warning sometime before error:

Trying to predict value of register 'regmodel.REGA' while it is being accessed

My first thought was its because of race (predict and FRONTDOOR access), so I added delay before reading from register but it still happens to be same behavior.

I would like to know what exactly that warning means, and if I should change something

Was it helpful?

Solution

This really does mean that you're predicting your register during a read. If you call predict(value) and you're reading/writing the register at the same time, the read/write will error on the register model before your prediction completes (with front door access, anyway).

Personally, I'd make sure that your register read completes fully (by showing regmodel.REGA.is busy() == 0) before you start a predict operation.

If you want a little more info on UVM's register model, this link is excellent: http://cluelogic.com/2013/02/uvm-tutorial-for-candy-lovers-register-access-methods/

OTHER TIPS

When you call Predict function, it calls do_predict(). Do predict checks if the register is busy. If the register is found to be busy, do_predict() will not perform the predict operation.

So, user has to check the return value of the predict() function to check if the operation was done successfully

Predict returns 1 for SUCCESS and 0 for UN_SUCCESSFUL operation

You may write something like the following, to make sure the predict operation is done

  while (! (REGISTER.predict(<value>))); 


           OR
 Declare a standard task something like the following, and call it whenever you need



task dac_reg_base_seq::predict_register(uvm_reg REGISTER, bit [31:0] predict_value ); 
      uvm_reg register_temp;
      predict_register = 0; //Unsuccessful
      if (!$cast(register_temp, REGISTER))
      begin
        `uvm_fatal("NOT_UVM_REG_TYPE","Provided REGISTER is not of the correct type")
      end

     `uvm_info("PREDICT_REGISTER", $psprintf(" Starting the predict function setting register %s with value %h", register_temp.get_name(),predict_value), UVM_HIGH);
    while(1) begin
          if(register_temp.is_busy == 1) begin
           `uvm_info("PREDICT_REGISTER", $psprintf(" register %s  is busy ", register_temp.get_name()), UVM_HIGH);
         // Adding Delay to avoid simulater gets locked up here
         #1;
         continue;
          end
      else begin
            register_temp.predict(register_temp.get()| predict_value); 
            break;
          end
        end
     `uvm_info("PREDICT_REGISTER", $psprintf(" Done with updating the predict value to the register %s", register_temp.get_name()), UVM_HIGH);
endtask : predict_register 

Here another example on how to wait until the front door is ready to accept predictions using is_busy function.

function void do_reset_key_registers(hmac_sha256_regblock parent_reg_block, uvm_reg      reg);
//$cast(parent_reg_block, this.get_parent());//this has been done outside
            fork 
                automatic uvm_reg reg=reg;//this is to copy the correct handle for each thread
                begin
                    if (reg.get_name=="inst_STATUS") begin
                        if  (reg.is_busy()) begin    wait(!reg.is_busy()); end//wait until this register is not busy 
                    end
                    assert( parent_reg_block.inst_STATUS.KEY_ERROR.predict(1));//key protect 0                                                    
                end
                begin
                    if (reg.get_name=="inst_KEY_0") begin
                        if  (reg.is_busy()) begin    wait(!reg.is_busy()); end//wait until this register is not busy 
                    end                    
                    assert( parent_reg_block.inst_KEY_0.KEY_0.predict(0));//reset KEYS 0
                end
            join_none
        endfunction: do_reset_key_registers
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top