How to confirm the reason of a bug of '$rand.pload'

Hi everyone!
When I try to run a UVM platform,I meet a error after the ‘vsim’ command,the prompt message as follow:
** Error: (vsim-7020) my_case0.sv(14): Illegal attempt to resize random dynamic array ‘$rand.pload’ to 1322392965 elements. (SolveArrayResizeMax=2000)
But I still can get the expect result,I am wondering wheather the error has adverse effect and how to correct it.Thank you!
Here is my 'my_case0’code:


class case0_sequence extends uvm_sequence #(my_transaction);
   my_transaction m_trans;

   function  new(string name= "case0_sequence");
      super.new(name);
   endfunction 
   
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (10) begin
         `uvm_do(m_trans)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask

   `uvm_object_utils(case0_sequence)
endclass


class my_case0 extends base_test;

   function new(string name = "my_case0", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   extern virtual function void build_phase(uvm_phase phase); 
   
   `uvm_component_utils(my_case0)
endclass


function void my_case0::build_phase(uvm_phase phase);
   super.build_phase(phase);

   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "env.i_agt.sqr.main_phase", 
                                           "default_sequence", 
                                           case0_sequence::type_id::get());
endfunction



In reply to xcxfly:

I’d guess you have a dynamic array in my_transaction. Right?
Could you please provide the code for m_transaction.

In reply to xcxfly:

You must have used dynamic array in your my_transaction class.
There can be two possibilities.

  1. Either you have not constrained the size of the dynamic array properly.
  2. Or you are constraining the size of the array with the value which is a way more than the supported size(SolveArrayResizeMax=2000).

Please give the details of your transaction class.

And you can even try below logic in your script.


vsim -c top -do "set SolveArrayResizeMax 0; run -all; exit"

Setting the limit of SolveArrayResizeMax to 0 means the size is unlimited.

In reply to chr_sue:

Thank you very much!Yes,I have used a dynamic array.But I don’t think the constrained the size of the dynamic array is wrong.Here is my 'my_transaction’module.Could you please help me check it?


class my_transaction extends uvm_sequence_item;
  
  rand bit[47:0] dmac;
  rand bit[47:0] smac;
  rand bit[15:0] ether_type;
  rand byte      pload[];
  rand bit[31:0] crc;
  
  constraint pload_cons{
     pload.size>=46;
     pload.size<=1500;
  }
  
  function bit [31:0] calc_crc();
    return 32'h0;
  endfunction
  
  function void post_randomize();
    crc=calc_crc;
  endfunction
  
  `uvm_object_utils_begin(my_transaction)   //fulfill the factory login of my_transaction
    `uvm_field_int(dmac,UVM_ALL_ON)
    `uvm_field_int(smac,UVM_ALL_ON)
    `uvm_field_int(ether_type,UVM_ALL_ON)
    `uvm_field_array_int(pload,UVM_ALL_ON)
    `uvm_field_int(crc,UVM_ALL_ON)
  `uvm_object_utils_end
 
  function new(string name="my_transaction");
    super.new();
endfunction

endclass

In reply to xcxfly:

Hi,

Couple of issues in your sequence item. Following is the fixed version.


class my_transaction extends uvm_sequence_item;
 
  rand bit[47:0] dmac;
  rand bit[47:0] smac;
  rand bit[15:0] ether_type;
  rand byte      pload[];
  rand bit[31:0] crc;
 
  constraint pload_cons{
//     pload.size>=46;
//     pload.size<=1500;
    // Should use size().
    pload.size() inside {[46:1500]};
  }
 
  function bit [31:0] calc_crc();
    return 32'h0;
  endfunction : cald_crc
 
  function void post_randomize();
    crc=calc_crc;
  endfunction : post_randomize
 
  `uvm_object_utils_begin(my_transaction)   //fulfill the factory login of my_transaction
    `uvm_field_int(dmac,UVM_ALL_ON)
    `uvm_field_int(smac,UVM_ALL_ON)
    `uvm_field_int(ether_type,UVM_ALL_ON)
    `uvm_field_array_int(pload,UVM_ALL_ON)
    `uvm_field_int(crc,UVM_ALL_ON)
  `uvm_object_utils_end
 
  function new(string name="my_transaction");
    super.new(name); // you missed to pass the argument
  endfunction : new
 
endclass : my_transaction

-Baser

In reply to xcxfly:

Hi xcxfly,
I see only two errors. This is the missing argument when calling the constructor of the parent/super class and you have to construct the dynamic array in the constructor.
Using the built-in function with/without brackets () should not be an issue. But this might depend on the simulator. Questa is accepting both. Your constraints are also correct. basheer55 is recommending only a one line constraint. It looks smarter.

But having the constraint inside the transaction is not a good coding style. Then you do not really need a dynamic array. rand byte [46:1500] is more or less the same.

Another question: why you are using the uvm_field macros?

In reply to basheer55:

Hi,the first issue have been solved as your method.Thank you!
But I still don’t understand the second issue.How to pass the argument?Could you describe it in detail?

In reply to chr_sue:

Thank you for your reply!
I know little about the argument when calling the constructor of the parent/super class because I just started learning.
Using the uvm_field macros because I need to login ‘my_transaction’ into the factory,in order to use some in-build function.

In reply to xcxfly:

Hi xcxfly,

The second issue is not actually causing the error you were having.
It is actually a guideline and if you don’t propagate the name of the constructor to the super class’s constructor.
Then when you create a my_transaction’s instance with different name, it will not take effect.

With your earlier code (name was not propagated):


my_transaction item;
item = my_transaction::type_id::create("item");
`uvm_info(get_type_name(), item.get_name, UVM_MEDIUM) // displays as uvm_sequence_item in log file.

With my suggested fix:


my_transaction item;
item = my_transaction::type_id::create("item");
`uvm_info(get_type_name(), item.get_name, UVM_MEDIUM) // displays as item in log file

Hope this helps.

-Baser

In reply to xcxfly:

Please see below:

class my_transaction extends uvm_sequence_item;
 
  rand bit[47:0] dmac;
  rand bit[47:0] smac;
  rand bit[15:0] ether_type;
  rand byte      pload[];
  rand bit[31:0] crc;
  rand int       len;

  constraint pload_cons{pload.size() == len;}
  function new(string name="my_transaction");
    super.new(name);
    pload = new[len];
  endfunction : new

  .....
endclass

In your sequence pass the constraint for your transaction to the `uvm_do.

   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (10) begin
         `uvm_do_with(m_trans, {len == inside {[46:1500]};})
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask


In reply to xcxfly:

For registering your object with the factory write simply:
`uvm_object_utils(my_transaction)

In reply to chr_sue:

I got it!
My previous code is coded as a textbook.And now I learn a new method.Thank you!

In reply to basheer55:

OK.I got it.Thank you!

In reply to xcxfly:

It’s a pleasure to me, seeing you got it.


  constraint pload_cons{pload.size() == len;}
  function new(string name="my_transaction");
    super.new(name);
    pload = new[len];
  endfunction : new

Although this is perfectly legal you do not want to be initialising dynamic arrays in the constructor. Everytime you create a sequence_item you will allocate memory space.

The preferred solution is to randomize len according to the constraints, and then allocate space in post_randomise() instead of new(). This allows you much greater flexibiilty when creating and populating the sequencE_item

In reply to Phill_Ferg:

I’m not sure if this is really working. But you can randomize len in pre_randomize() and construct pload with len. Then you’ll get pload also randomized when randomize is called.

In reply to chr_sue:

Agreed you can, but for performance reasosn you don’t want to over subscribe .randomize() with massive amounts of data to randomize. Remember the constraints manager and randomize have a lot of code behind them
In this case, randomising len in randomize() gives you a simple number in one dimension. Then on post_randomize() initialise the array and file it with whatver ever data you need, including the really quick $urandom.


function void post_randomize();

   pload = new[ploadlen];
   foreach (pload[i])dload[i] = $urandom_range($pow(2, 8) - 1, 0); //bytes

   if (checksum_error) checksum = $urandom_range($pow(2,16) - 1, 0);
   else checksum = generate_checksum();

endfunction:post_randomize