Constraining address and memory locations

During each randomization I would have an address( or even multiple addresses ) . During next call to randomization same addresses shouldn’t be obtained . This is till all possible addresses are observed post-randomization .

Eg : Lets say I have max 4 addresses ( 0 to 3 ) . So 1st randomization gives me address 0 and 2 , during 2nd randomization I can get value 1 and 3 OR only 1 of them in which case during call to 3rd randomization I obtain the last remaining index .

The 1st randomization call can give me only 1 address too . So basically I need minimum of 1 randomization call and max of 4 randomization calls to achieve all addresses .


// Assuming addresses of 0 to 3 are possible 

     bit [1:0] q2[$] ; // Storage element for previous values 
rand bit [1:0] q1 [$] ; 

 constraint SIZE { q1.size() inside { [0 : ( 3 - q2.size() ) ] } ; }

 constraint VAL { unique { q1 , q2  } ; } 

 function void post_randomize() ;

  foreach( q1[i] ) 
  begin
   q2.push_back( q1[i] ) ; 
  end

 endfunction


[Q1] Any alternate solution possible ? Can I achieve the same without helper array q2 ( Using const’() maybe ) ?

[Q2] What if I enhance the question so that ::

 Now I have a memory ( unpacked array )  with possible addresses same as the random address variable 

 So can I constraint the memory such that only those memory address location obtained by q1 are randomized ? 

Eg : If 1st randomization gives us q1 as 0 and 1 , so only memory location 0 and 1 would be randomized

   During 2nd call which gives me q1 as 2 ( memory location 0 and 1 will have previous values ) , memory location 2 will be randomized .

   **The reason I am confused with this is , I know I can't use random variables as indexes so don't know how to proceed .**

    I want to obtain it via constraints not via post_randomize() preferably .       

Thanks ,
TC

In reply to TC_2017:

For every randomize call, if one rand value is good enough, then “randc” can solve the problem without repeating the values until all the values are covered. And it doesn’t required q2 array.

In reply to TC_2017:

I think the answer to [Q1] is no. Unless you only want one value at a time, and that value’s width is small, you can use randc.

For [Q2] you can use a foreach loop. (btw I think you meant to say that q1 holds the index values you want to randomize; q2 holds the index values you previously randomized)

constraint keep_values_outside_q1 {
    foreach (memory[index])
        !(index inside {q1}) -> memory[index] == const'(memory[index]); }

In reply to dave_59:

The original code had a few issues ( after a complete iteration is reached ) which I solved ::


     bit [1:0] q2[$]  ; // Storage element for previous values 
rand bit [1:0] q1 [$] ; 
 
 constraint SIZE {            
	   	    q1.size() inside { [ 1 : ( 4 - q2.size() ) ] } ; 						
	          }
 
 constraint VAL {       
                        unique { q1 , q2  } ;  // q2 is Non-random variable , is it allowed ?
		} 
 
 function void post_randomize() ;
   
    foreach( q1[i] ) 
     begin
      q2.push_back( q1[i] ) ; 
     end
    
    if ( q2.size() == 4 ) 
     begin
      $display("Deleted Queue");
      q2.delete();
     end

 endfunction


[Q1] Will q2 work in unique constraint ? Is non-rand variable allowed ?

LRM 18.5.5 says :: “A group of variables can be constrained using the unique constraint so that no two members of the group have the same value after randomization.”

So this requires just variable which a non-random variable is .

[Q2] const’() doesn’t work with even 2020 version of some simulators .
Any alternate solution ?

In reply to TC_2017:

[A1] The constraint solver doesn’t care anything about non-rand variables, rand variables with rand_mode(0), or const cast expressions. It treats them all the same as if you wrote a literal number with their value at the point of the call to randomize().

[A2] I can’t help you with tool specific issues.