How to control randomization of each item in an array acc. to parameter

I have a sequence_item as follows :

class base_sequence extends uvm_sequence_item;
   ...
   rand [31:0] IP_Table1[0:63];
   rand [31:0] IP_Table2[0:63];

   rand [31:0] Tx_IP_addresses[0:200];
   ...
endclass

I want to write a constraint for each item in Tx_IP_addresses, so that acc. to a parameter, it’s value will be taken from either IP_table1/2 or not.
i.e. something like this(pseudo code) :

foreach Tx_IP_addresses[i] {
  80% probability -> Tx_IP_addresses[i] inside {IP_Table1,IP_Table2}; 
  20% probability -> Tx_IP_addresses[i] NOT inside {IP_Table1,IP_Table2};
}

I tried to use a combination of dist + inside but could not find one that will pass compilation.
I also tried to define another random array of integers (value between 0 and 100), and use it, but this causes the simulator to stuck in randomization :

rand int random_array_of_int [0:200];
...
random array_of_int[i] inside {[0:100]};
...
solve array_of_int before Tx_IP_addresses;
foreach Tx_IP_addresses[i] {
   array_of_int[i] > 20 -> Tx_IP_addresses[i] inside {IP_Table1,IP_Table2}; 
}

Thanks,
Shay

In reply to shaygueta:

Try following code. I guess it should work for you.


class C #(int unsigned WIDTH=16);
  rand bit[31:0] IP_Table1[63:0];
  rand bit[31:0] IP_Table2[63:0];
  rand bit[31:0] Tx_IP_addresses[WIDTH-1:0];
  rand protected bit _dummy_array[WIDTH-1:0];


  constraint c_0 {_dummy_array.sum(item) with (int'(item == 1)) == WIDTH*8/10;}  //WIDTH*0.8 = 80%


  constraint c_1 {
    foreach(_dummy_array[i]) {
      (_dummy_array[i] == 1) -> Tx_IP_addresses[i] inside {IP_Table1, IP_Table2};
  }}
 

  constraint c_2 {  
    solve IP_Table1 before Tx_IP_addresses;   
    solve IP_Table2 before Tx_IP_addresses;      

    solve _dummy_array before IP_Table1;
    solve _dummy_array before IP_Table2;
    solve _dummy_array before Tx_IP_addresses;         
  }  
   
 
  virtual function void print();
    $display("_dummy_array.sum()=%2d", _dummy_array.sum(item) with (int'(item == 1))); 
    $display("===============================================================");     
    foreach(_dummy_array[i]) begin  
      string aux = "";
      foreach(IP_Table1[j]) begin
        if(IP_Table1[j] == Tx_IP_addresses[i]) begin
          aux = "IP_Table1"; break;
        end
      end 
      foreach(IP_Table2[j]) begin
        if(IP_Table2[j] == Tx_IP_addresses[i]) begin
          aux = "IP_Table2"; break;
        end
      end          
      $display("_dummy_array =%2d  |  %9s  |  Tx_IP_addresses =%11d", _dummy_array[i], aux, Tx_IP_addresses[i]);  
    end    
  endfunction : print
endclass

    
    
module top();
  
  C#(.WIDTH(200)) c;
  initial begin
      c = new;
      rnd:assert(c.randomize());
      c.print();
    end
endmodule : top

In reply to shaygueta:

You can use the dist construct to select often a constraint expression is true:

 class base_sequence;
    typedef bit [31:0] dataWidth;
    rand dataWidth IP_Table1[64];
    rand dataWidth IP_Table2[64];
    rand dataWidth Tx_IP_addresses[200];
    
  constraint eightytwenty {
    foreach (Tx_IP_addresses[i])
    Tx_IP_addresses[i] inside {IP_Table1,IP_Table2} dist { 1:=80, 0:=20 };
  }
  endclass