How to set a queue/array in uvm_config_db?


class write_test extends test_base;
  int cmd_arr[$];
  bit [14:0] addr_arr[$];
  bit [7:0]  data_arr[$];
  bit [1:0]  td_arr[$];
  bit [1:0]  addr_inc_arr[$];
  bit [3:0]  num_rd_arr[$];

  `uvm_component_utils(write_test)

  function new(string name, uvm_component parent);
    super.new(name, parent);
    `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
  endfunction

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);

    repeat(3) cmd_arr.push_front(1);
    addr_arr.push_front(15'h7ffc);
    data_arr.push_front(8'hce);
    addr_arr.push_front(15'h7ff2);
    data_arr.push_front(8'h0a);
    addr_arr.push_front(15'h1000);
    data_arr.push_front(8'h11);

    // Specify which sequence to run
    pkt_seq_base::type_id::set_type_override(direct_seq::get_type());
    uvm_config_db#(int)::set(this, "env.e_agent*.seqr", "cmd_arr", cmd_arr);
    uvm_config_db#(bit [14:0])::set(this, "env.e_agent*.seqr", "addr_arr", addr_arr);
    uvm_config_db#(bit [7:0])::set(this, "env.e_agent*.seqr", "data_arr", data_arr);
    
  endfunction
endclass

class direct_seq extends pkt_seq_base;
  int msg_id   = 0;
  int clk_scal = 25;
  int cmd_arr[$];
  bit [14:0] addr_arr[$];
  bit [7:0]  data_arr[$];
  bit [1:0]  td_arr[$];
  bit [1:0]  addr_inc_arr[$];
  bit [3:0]  num_rd_arr[$];

  write_seq wr_seq;
  read_seq  rd_seq;

  `uvm_object_utils_begin(direct_seq)
    `uvm_field_queue_int(cmd_arr, UVM_ALL_ON)
    `uvm_field_queue_int(addr_arr, UVM_ALL_ON)
    `uvm_field_queue_int(data_arr, UVM_ALL_ON)
    `uvm_field_queue_int(td_arr, UVM_ALL_ON)
    `uvm_field_queue_int(addr_inc_arr, UVM_ALL_ON)
    `uvm_field_queue_int(num_rd_arr, UVM_ALL_ON)
  `uvm_object_utils_end

  // Other codes
endclass 

I’m having the error on data type incompatibility as listed below. How can I debug these errors?

uvm_config_db#(int)::set(this, "env.e_agent*.seqr", "cmd_arr", cmd_arr);
                                                                     |

ncelab: *E,TYCMPAT (write_test.sv,31|73): formal and actual do not have assignment compatible data types (expecting datatype compatible with ‘int’ but found ‘queue of int’ instead).

uvm_config_db#(bit [14:0])::set(this, "env.e_agent*.seqr", "addr_arr", addr_arr);
                                                                              |

ncelab: *E,TYCMPAT (write_test.sv,32|82): formal and actual do not have assignment compatible data types (expecting datatype compatible with ‘packed array’ but found ‘queue of packed array [14:0] of bit’ instead).

uvm_config_db#(bit [7:0])::set(this, "env.e_agent*.seqr", "data_arr", data_arr);
                                                                             |

ncelab: *E,TYCMPAT (write_test.sv,33|81): formal and actual do not have assignment compatible data types (expecting datatype compatible with ‘packed array’ but found ‘queue of packed array [7:0] of bit’ instead).

In reply to Reuben:

Hi ,
From the look of the code I guess we can do this way. But im not sure of the outcome as I have not tried it.

foreach(cmd_arr[i])
uvm_config_db#(int)::set(this, “env.e_agent*.seqr”, “cmd_arr”, cmd_arr[i]); //you should manage “cmd_arr” in such a way that each entry into config_db is unique say cmd_arr_0, cmd_arr_1 etc.

foreach(addr_arr[i])
uvm_config_db#(bit [14:0])::set(this, “env.e_agent*.seqr”, “addr_arr”, addr_arr[i]);

foreach(data_arr[i])
uvm_config_db#(bit [7:0])::set(this, “env.e_agent*.seqr”, “data_arr”, data_arr[i]);

Thanks,
Neith

In reply to UVM Beginner:

Hi Neith,

Oh yeah. It works! =)
Wow, I didn’t think of that.

Thanks.

In reply to Reuben:

Yes, it works, but it’s incredibly inefficient. This is just one of the reasons we don’t recommend using the uvm_field macros.
You would be much better off creating a uvm_object that includes the arrays and simply doing a single uvm_config_db call to pass that object.

In reply to tfitz:


foreach(addr_arr[i])
uvm_config_db#(bit [14:0])::set(this, "env.e_agent*.seqr", "addr_arr", addr_arr[i]);

I think this code will override the value again and again.

In reply to Naven8:

Hi Naven8,
I think the below code will not override,


``` verilog

string inst_name;
.
.
.

for(int i=0; i < addr_arr.size(); i++) begin
    $sformat(inst_name, "addr_arr_%0d", i);
    uvm_config_db#(bit [14:0])::set(this, "env.e_agent*.seqr", inst_name, addr_arr[i]);
end




Thanks,
Neith

In reply to UVM Beginner:

Hi,

Yeah. The code override it again and again.
So what I did is this:


foreach(cmd_arr[i])
  uvm_config_db#(int)::set(this, "env.e_agent*.seqr", $sformatf("cmd_arr[%0d]",i), cmd_arr[i]);

foreach(addr_arr[i])
  uvm_config_db#(bit [14:0])::set(this, "env.e_agent*.seqr", $sformatf("addr_arr[%0d]",i), addr_arr[i]);

foreach(data_arr[i])
  uvm_config_db#(bit [7:0])::set(this, "env.e_agent*.seqr", $sformatf("data_arr[%0d]",i), data_arr[i]);

Hi tfitz,

Can you explain further why the code is inefficient? I don’t know exactly how uvm_object works.
Tanks.

Regards,

In reply to Reuben:

If you have N elements in cmd_arr, M elements in addr_arr, and P elements in data_arr, your approach will do N + M + P sets into the config_db, and you’ll have to do N + M + P gets to retrieve the information. If you create an object that holds the three arrays, you’ll only have to do one set and one get.

In reply to tfitz:

Oh I see…
I guess I should take a look at using the uvm_object.
I think there’s a forum here regarding the use of uvm_object for this kind of situation.

Thanks.

hie if we use this to set , then how to get this in different component without knowing the array size ?
foreach(addr_arr[i])
uvm_config_db#(bit [14:0])::set(this, “env.e_agent*.seqr”, “addr_arr”, addr_arr[i]);

In reply to mundhemanasi:

That code does not work. It just overwrites the same config element over and over again. Use a config object extended from uvm_object and have whatever size array you need on that object.

In reply to dave_59:

In reply to mundhemanasi:
That code does not work. It just overwrites the same config element over and over again. Use a config object extended from uvm_object and have whatever size array you need on that object.

Hi Dave,
Could you please point to an example for this? I would like to create a “common” queue and have two independent classes access the same element of the queue at the same time.

In reply to UVM_learner6:

You can use uvm_queue for this purpose