How to code the dist statement with array in the constraint

I have a requirement as below.
the address is randomized and it’s expected to be selected in an array defined.


bit [31:0] my_exc_array[$] = {'h1234, 'h5678, 'hABCD, 'hFFFF};
rand bit [31:0] my_addr;
rand bit [31:0] start_addr;
rand bit [31:0] end_addr;
constraint my_cons {
     end_addr > start_addr;
     my_addr dist { [my_exc_array]  :/1,            <=  how to code this ?
                    [start_addr:end_addr]     :/1 };
}

In reply to zz8318:



// Code your testbench here
// or browse Examples
class tb;
bit [31:0] my_exc_array[$] = {'h1234, 'h5678, 'hABCD, 'hFFFF};
rand bit [31:0] my_addr;
rand bit [31:0] start_addr;
rand bit [31:0] end_addr;
constraint my_cons {
     end_addr > start_addr;
  my_addr dist { my_exc_array  :/1,            
                    [start_addr:end_addr]     :/1 };
}
  
endclass


module hello;
  tb m1;
  
  initial begin
    m1 = new();
    repeat (10) begin
    if (!m1.randomize()) $display ("Error");
    $display ("start_addr = %h, end_addr = %h,my_addr = %h",m1.start_addr,m1.end_addr, m1.my_addr);
    end
  end
  
  
endmodule


In reply to rag123:

I tried but still failed. The error message is below.

an array and arrays are not yet supported as a distribution item.

In reply to zz8318:

When a message reports “not yet supported”, this indicates that it is valid code yet the tool doesn’t support it.

Since this forum isn’t for tool related issues, you should contact the vendor support team for additional assistance.

In reply to zz8318:

A better way of coding this is using a separate mode variable with a distribution on that mode.

bit [31:0] my_exc_array[$] = {'h1234, 'h5678, 'hABCD, 'hFFFF};
rand enum {Range, Array} mode;
rand bit [31:0] my_addr;
rand bit [31:0] start_addr;
rand bit [31:0] end_addr;
constraint my_cons {
     mode dist { Range:=1, Array:=1};
     mode == Array -> my_addr inside {my_exc_array};
     mode == Range -> { my_addr inside {[start_addr:end_addr]};
                        end_addr > start_addr; }
}

In this way the mode can be used to control sets of constraints.

In reply to dave_59:

In reply to zz8318:
A better way of coding this is using a separate mode variable with a distribution on that mode.

bit [31:0] my_exc_array[$] = {'h1234, 'h5678, 'hABCD, 'hFFFF};
rand enum {Range, Array} mode;
rand bit [31:0] my_addr;
rand bit [31:0] start_addr;
rand bit [31:0] end_addr;
constraint my_cons {
mode dist { Range:=1, Array:=1};
mode == Array -> my_addr inside {my_exc_array};
mode == Range -> { my_addr inside [start_addr:end_addr];
end_addr > start_addr; };
}

In this way the mode can be used to control sets of constraints.

Hi Dave,
I have tried running the above code in the simulator every time i ran mode is taking the value 0 and starting addr is 30 , ending addr is 32 and my_addr is 20
what is the significance of my_exc_array i didn’t understand. The question is my_addr is should be in the reange of start-addr & end_addr right ?

In reply to Manikanta Kopparapu:

I had a typo in my code that I corrected (missing{}'s around the range). but once corrected it works for me. You’ll have to ask the original author of this question, but I believe they wanted either my_addr to be inside the start_/end_range or inside my_exc_array.

module top;
  
class A;
  
  bit [31:0] my_exc_array[$] = {'h1234, 'h5678, 'hABCD, 'hFFFF};
  rand enum {Range, Array} mode;
  rand bit [31:0] my_addr;
  rand bit [31:0] start_addr;
  rand bit [31:0] end_addr;
  constraint my_cons {
     mode dist { Range:=1, Array:=1};
     mode == Array -> my_addr inside {my_exc_array};
    mode == Range -> { my_addr inside {[start_addr:end_addr]};
                        end_addr > start_addr; }
   }
endclass
  
  
  A a = new;
  
  initial repeat(20) begin
    assert(a.randomize());
    $displayh(a.mode.name,, a.my_addr);
  end
endmodule

In reply to Manikanta Kopparapu:

the purpose for this is to random the my_addr to be selected either inside the start_addr and end_addr, or one of the elements in my_exc_array.

In reply to dave_59:

A better way to do this is as below. It can help u to control the weights. here is a sample code

rand int test;
  rand int test1;
  int test_range[] = {1,2,3,5,6,9};
   
  constraint c8 {
    test  == get_the_value(100, 200);
  }
  
  constraint c9 {
    test1  == get_the_value(500, 600);
  }
  
  function int get_the_value(int min, int max);
    
    randcase
      1: get_the_value = min;
      1: begin
            int i = $urandom_range(0, test_range.size()-1);
            get_the_value = test_range[i];
          end
      1: get_the_value = max;
    endcase
  endfunction