Randomization of two arrays with dependencies between them

Hi,

I’m trying to randomize two arrays with following dependencies between them:

  1. First array contains grater or equal respective elements than second one
  2. Differences between respective arrays’ elements fall in between min_c and max_c constants
  3. Minimal difference of respective arrays’ members subtracted from maximal one is lower than relative_c constant

I’m not sure how to put the third constraint. Could anybody help?


  class C;
    const bit [11:0] max_c = 'd3774;
    const bit [11:0] min_c = 'd2980; 
    const bit [11:0] relative_c = 'd161;
    
    rand bit [11:0] pos[16];
    rand bit [11:0] neg[16]; 
     
    constraint c1 { foreach(pos[i]) (pos[i] >= neg[i]);}    
    constraint c2 { foreach(pos[i]) (pos[i] - neg[i]) inside {[min_c:max_c]};}
    // pseudo:   max(pos[i] - neg[i])  -  min(pos[j] - neg[j])  <=  relative_c;   
 
  endclass
 

In reply to nedicm:

I do not understand your pseudocode. What are the min/max functions? Are i and j simply a nesting of foreach loops? It might help to write a function that the condition you want, and then we can show you have to turn it into a constraint.

In reply to dave_59:

Hi Dave,

Thanks for your response.
Exactly, i and j are just a nesting of foreach.
Assume there is an auxiliary array storing the difference between respective elements of pos and neg arrays. Something like:


 foreach(aux[i]) aux[i] = pos[i] - neg[i];

Then, the third constraint could be expressed in pseudocode as:


 aux[i].max() - aux[i].min() <= relative_c;

In reply to nedicm:

I still don’t know what you mean by aux[i].max. do you just mean

aux.max() - aux.min() <= relative_c;

In reply to dave_59:

Exactly as you wrote:

aux.max() - aux.min() <= relative_c;

My mistake. Thanks.

In reply to nedicm:

Then you don’t need nested foreach loops. You can use the min/max array reduction methods ‘with’ clause as an iterator.

constraint c3 { pos.max() with (pos[item.index] - neg[item.index]) 
              - pos.min() with (pos[item.index] - neg[item.index])
              <= relative_c; }

Also, you need to be careful with overflow/underflow. You might have to cast your subtraction to 13 bits.

In reply to dave_59:

Thanks Dave.

The ‘with’ trick seems to be fine. To meet my requirements I guess it should be modified a bit:


constraint c3 { 
  (pos.max() with (pos[item.index] - neg[item.index]) - neg.max() with (pos[item.index] - neg[item.index])) 
- (pos.min() with (pos[item.index] - neg[item.index]) - neg.min() with (pos[item.index] - neg[item.index])) 
  <= relative_c; } 

However, even modified the solution is getting a compile error. I think the issue is that min/max functions return a queue as a result, so it cant be used further in constraint. I have a min example on Eda Playground.

In reply to nedicm:

Sorry, I always forget that min/max return a queue in the case that the input array is empty. I’ll have to think some more about it, but at least I now know exactly what you are looking to do.

 class C;
    const bit [11:0] max_c = 'd3774;
    const bit [11:0] min_c = 'd2980; 
    const bit [11:0] relative_c = 'd161;
 
    rand bit [11:0] pos[16];
    rand bit [11:0] neg[16];
    
    rand bit [11:0] dummy[16];
 
    constraint c1 { foreach(pos[i]) (pos[i] >= neg[i]);}    
    constraint c2 { foreach(pos[i]) (pos[i] - neg[i]) inside {[min_c:max_c]};}
    constraint c3 { foreach(dummy[i]) dummy[i]==(pos[i] - neg[i]);
                    foreach(dummy[i])
                      foreach(dummy[j])
                        (dummy[i]-dummy[j]) <= relative_c;
                  } 
  endclass

  module tb;
    C c;
    initial begin
      c = new();
      c.randomize();
      $display("###############");
      $display ("# POS is");
      foreach(c.pos[i])
        $display("%0d",c.pos[i]);
      $display("###############"); 
      $display ("# NEG is");
      foreach(c.neg[i])
        $display("%0d",c.neg[i]);
      $display("###############");      
    end
  endmodule

OR

  class C;
    const int max_c = 'd3774;
    const int min_c = 'd2980; 
    const int relative_c = 'd161;
 
    rand int unsigned pos[16];
    rand int unsigned neg[16];
    
    rand int dummy[16];
 
    constraint c1 { foreach(pos[i]) {(pos[i] >= neg[i]); pos[i]<=4096; neg[i]<=4096;}};    
    constraint c2 { foreach(pos[i]) (pos[i] - neg[i]) inside {[min_c:max_c]};};
    constraint c3 { foreach(dummy[i]) dummy[i]==(pos[i] - neg[i]);
                    foreach(dummy[i])
                      foreach(dummy[j])
                        (dummy[i]-dummy[j]) <= relative_c;
                  };
  endclass

  module tb;
    C c;
    initial begin
      repeat(10) begin
      c = new();
      c.randomize();
      $display("###############");
      $display ("# POS is");
      foreach(c.pos[i])
        $display("%0d",c.pos[i]);
      $display("###############"); 
      $display ("# NEG is");
      foreach(c.neg[i])
        $display("%0d",c.neg[i]);
      $display("###############");    
      $display ("# DUMMY is");
      foreach(c.dummy[i])
        $display("%0d",c.dummy[i]);
      $display("###############"); 
      end
    end
  endmodule

ENJOY!