Constraint

Hi, I run this code in QuestaSim but it has an error. Can anyone help me why this randomization failed?

class Packet;
    rand bit p[2048];
    int sum=0;
    function int total(bit p[2048]);
        for (int i=0;i<2048;i++)
            sum = sum + p[i];
    endfunction
    constraint c_stim{
        total(p)==256;
    }
endclass:Packet

In reply to Moein75:

There are several problems with this code.

Calling user defined functions in a constraint break the solution space in that the random variables as inputs to the function must choose their values first. Then the return value of the function becomes a non-random state variable. The constraint solver is not required to keep trying different inputs to make sure its return value satisfies the remaining constraint (==256).

Also functions used in constraint must be “pure” they cannot reference or modify variables outside their scope. Imagine the behavior if there were multiple calls to your function total.

And finally, the LRM does not allow references to random variables that are aggregate arrays without using an iterative construct like foreach or sum reduction method that can be unrolled into a set of boolean equations.

In reply to Moein75:

Hi, Observed your code from top to bottom. There are loads of things to say and there are few speculations of mine.
1)You have called a user-defined method which will be acting after the randomization method and will return a value. That’s why you might get the right result but most of the time, you will get the wrong one.
2)It’s the dynamic array you are using. So in order to get the proper answer you have to use system defined method (array_manipulation). You gotta use p.sum().
3)Now return type of the sum will be depending upon the variable type you are dealing with. Here variable type is a bit. So you will get either 1 or 0.
4)Now finally, to get rid of all of these hindrances, you have to use the int variable. I tried to do so in the following code.


class Packet;
  rand int p[20];
 constraint values{
    foreach(p[i])
      p[i] inside {[0:1]};
  }
    constraint c_stim{
      p.sum()==13;
    }
endclass:Packet

module test;
  
  Packet P=new;
  initial begin
    assert(P.randomize)
    $display("%p",P.p);
  end
  
endmodule


// Another way
class Packet;
  rand bit[3:0][7:0] p[20];
  rand bit[31:0]p1[20];
 //rand int unsigned p1[20]; // by-defualt signed
 constraint values{
    foreach(p[i])
      p[i] inside {[0:1024]};
  }
    constraint c_stim{
      p.sum()>1352;
    }
  constraint eq{p[5] == p1[5];p[5]<=105 && p[5] >=99;} //extra ; some observation ;
  
endclass:Packet
 
module test;
 
  Packet P=new;
  initial begin
    assert(P.randomize)
    $display("%p",P.p);
    $display("%0p",P.p1);
  end
 
endmodule

Now go through it gingerly.
I have one tiny little problem here. During declaring the array, instead of using rand int along with constraint values, when I was using rand unsigned int along with no such values constraint, I was getting garbage value. WHY?

Good clarification, thank you

In reply to Shubhabrata:

If you remove the constraint values, the constraint solver is giving you back values that satisfy the other active constraints. You need to plug in the “garbage values” into the constraint equation and see that it does in fact satisfy those constraints.

In reply to dave_59:

Hello sir, I have clarity of that. But that will happen in case of signed int (rand int p[20]) . In case of unsigned int declaration (rand int unsigned p[20]) , it’s giving garbage values which is not satisfying the constraint (2nd one) .
I should have got series of 0s and 1s.

In reply to Shubhabrata:
Show me exactly the code you ran and the “garbage” values you got.

In reply to dave_59:


class Packet;
  rand int unsigned p[20];
  constraint c_stim{
      p.sum()==13;
    }
endclass:Packet
 
module test;
 
  Packet P=new;
  initial begin
    assert(P.randomize)
    $display("%p",P.p);
  end
 
endmodule

The result , I am getting -

vsim -voptargs=+acc=npr

run -all

'{257152500, 3154634279, 1845763276, 3696871621, 631626809, 2108533005, 2922957038, 2580893384, 1715310603, 828324944, 3022238876, 3785499950, 2835521728, 3653584145, 2354463875, 2745584841, 1287618582, 201913747, 2622534294, 698645476}

exit

As I am using unsigned , I was supposed to have 1s and 0s . Instead , I am these values.

In reply to Shubhabrata:

module top;
  
  int unsigned p[20] =

'{257152500, 3154634279, 1845763276, 3696871621, 631626809, 2108533005, 2922957038, 2580893384, 1715310603, 828324944, 3022238876, 3785499950, 2835521728, 3653584145, 2354463875, 2745584841, 1287618582, 201913747, 2622534294, 698645476};
  
  initial begin
    $display("p.sum =                    %16d",p.sum);
    $display("p.sum =                  0x%16h",p.sum);
    $display("p.sum with (64'(item)) = 0x%16h",p.sum() with (64'(item)));
  end
endmodule

In reply to dave_59:

Ok, Got it. Numbers are made of 32 bits, but the summation consists of more than 32 bits. As we are taking int variable that’s why we’ll be getting the sum result up to the 32nd bit. And the answer is 13. Hope I got it correct.

Hi Dave,

Here I am getting unexpected result
p.sum with (64’(item)) = 0x0000000b0000000d
may I know why?

Thanks !!!

In reply to UVM_geek:

Ok, Got it. Numbers are made of 32 bits, but the summation consists of more than 32 bits. As we are taking int variable that’s why we’ll be getting the sum result up to the 32nd bit. And the answer is 13. Hope I got it correct.

That is your answer.