UVM Register layer writing/reading X values

Hi everyone,

I have and UVM Register layer implemented in my UVM environment for BACKDOOR access to my logic signals and memories in RTL.
But I have a problem with writing and reading X values. When I try to do those operations, the value '0 is written/read instead. Is there some way how to achieve this? I have already tried to use uvm_reg_data_logic_t and logic vector for data, but without any change.

In reply to SilentB:
It looks like this is a type problem and you have in between a 2-satet variable.
But without seeing the code it is only guessing.

Thank you for response. Here is snippet of my code for memory model and example of write task.

Creating of memory_model:

// Default memory model.
class memory_model extends uvm_mem;

  `uvm_object_utils(memory_model)

  function new(string name = "memory_model");
    super.new(name,             // Name of the memory model
              ROW_NUM,          // The address range
              WORD_WIDTH,       // The width of the memory in bits
              "RW",             // Access - RW or RO
              UVM_NO_COVERAGE); // Functional coverage
  endfunction

endclass: memory_model

After that in my uvm_block class (extend uvm_reg_block) a have:

rand memory_model m_mem;
..
  virtual function void build;

    // First part of HDL path
    add_hdl_path("top.dut.HDL");

    // Memories
    m_mem = memory_model::type_id::create("m_mem");
    m_mem.configure(this, "");
    m_mem.add_hdl_path_slice(.name("my_mem"), .offset(0), .size(WORD_WIDTH));

And for use in sequence I am using for example this task for write word to memory:

  task automatic write_word_to_memory(
    input logic [WADD_W-1:0] wadd,  // Word address in memory
    input logic [DIN_W-1:0] data,   // Data that will be written
    input memory_model object_id    // ID of object
    );
    uvm_status_e status;
    uvm_reg_data_logic_t outgoing = data;

    object_id.write(status, wadd, outgoing, UVM_BACKDOOR);
    assert( status == UVM_IS_OK ) begin
      `uvm_info("write_word_to_memory", $sformatf("Write to %s address %0d | data %8h", object_id.get_name(), wadd, data), UVM_MEDIUM);
    end else begin
      `uvm_error("write_word_to_memory", "Status of UVM_BACKDOOR approach is not OK!")
    end
  endtask: write_word_to_memory

Call in sequence:

    mem_backdoor.write_word_to_memory(
      read_address,           // Word address in memory
      'X,                     // Data that will be written
      mem_backdoor.m_mem  // ID of object
      );

After more searching I think, that problem is not in my code, but it is the definition of task write and read in uvm_mem file in UVM package.

https://www.vmmcentral.org/uvm_vmm_ik/files3/reg/uvm_mem-svh.html#uvm_mem.write

As you can see, there is uvm_reg_data_t used for value, which is 2-state. And I would need there uvm_reg_data_logic_t type, which is 4-state.

virtual task write(output uvm_status_e status,	  	
	input 	uvm_reg_addr_t 	offset,
	input 	uvm_reg_data_t 	value,	  	
	input 	uvm_path_e path	 = UVM_DEFAULT_PATH,
	input 	uvm_reg_map map = null,
	input 	uvm_sequence_base parent = null,
	input 	int prior = -1,
	input 	uvm_object extension = null,
	input 	string fname = "",
	input 	int lineno = 0

Is there some easy way how to change this without recreating my own tasks for write and read, please?

In reply to SilentB:

    object_id.write(status, wadd, outgoing, UVM_BACKDOOR);

Unfortunately, the register layer uses 2-state datatypes all over the place. In this case, the built-in uvm_mem::write task is defined as:

virtual task write(
   	output 	uvm_status_e 	status,	  	
   	input 	uvm_reg_addr_t 	offset,	  	
   	input 	uvm_reg_data_t 	value,	  	
   	input 	uvm_path_e 	path	 = 	UVM_DEFAULT_PATH,
   	input 	uvm_reg_map 	map	 = 	null,
   	input 	uvm_sequence_base 	parent	 = 	null,
   	input 	int 	prior	 = 	-1,
   	input 	uvm_object 	extension	 = 	null,
   	input 	string 	fname	 = 	"",
   	input 	int 	lineno	 = 	0
)

Where uvm_reg_data_t is 2-state, so you can’t pass an X or Z through this API. I guess the thinking goes that X’s or Z’s are protocol specific, and so should be abstracted. Not sure I agree with that.

Since it appears you are trying to leverage the string based hdl_paths stored in your model here for your backdoor, you might consider directly using get_full_hdl_path() and uvm_hdl_deposit() instead. Those are the methods used internally to implement the backdoor. See uvm_mem::backdoor_write() for the details.

In reply to warnerrs:

As I said, it seems to be an issue with the data types.
What you could try is to overwrite the write task.