Shortening a dist style constraint in SystemVerilog

Viewed 104

I have a constraint of the form:

s dist {0:= 20, 1:= 25, 2:= 30, <many more, possibly hundreds>};

Instead of writing down the constraint this way, I found in my application the RHS (i.e. the weights - 20, 25, 30, etc,) could come from an array my_array whose i-th element contains the weight for the i-th element.

Is there any way to shorten it to something like below? This is just to show the concept and is syntactically incorrect:

s dist {foreach rhsArray[j] {j: rhsArray}};
1 Answers

One brute-force approach is populating an array with each value appearing the number of times the weight of each element.

module top;
  typedef int unsigned uint;
  class A;
    uint my_array[$];
    uint rhsArray[] = {20, 25, 30, 25};
    rand uint s,index;
    function new;
      foreach(rhsArray[j]) repeat (rhsArray[j]) my_array.push_back(j);
    endfunction
    constraint curve { 
      s == my_array[index];
      index < my_array.size;
    }
  endclass
  
  A a = new;
  uint my_dist[uint] = '{default:0};
  initial begin
    repeat(10000) begin
      assert(a.randomize);
      my_dist[a.s]++;
    end
    $display("%p",my_dist);
  end
endmodule

There is another variation of this where you construct an array of structures with ranges based on the weights (i.e. range[0]: 0-19, range[1]: 20-44, range[2]: 45-74, range[3]: 75-99). Then pick a random number between 0-99 and the number that is inside the range[j] becomes j==s.

A more convoluted approach is creating a another class for each element, where each element has a distribution for being picked or not.

 class element;
    uint weight, sum;
    rand bit picked;
    constraint d { picked dist {0:=sum, 1:= weight}; }
  endclass
    
  class A;
    uint rhsArray[] = {20, 25, 30, 25};
    rand element e[];
    rand uint s,index;
    function new;
      uint sum = rhsArray.sum();
      e = new[rhsArray.size];
      foreach(rhsArray[j]) begin
        e[j] = new;
        e[j].weight = rhsArray[j];
        e[j].sum = sum;
      end
    endfunction
    constraint curve { 
      e.sum() with (uint'(item.picked)) == 1;
      foreach(e[j]) e[j].picked -> j == s;
    }
  endclass
Related