Constraint a variable so that it's less likely to retain its current value

Hi!
I want to write a constaint for a 1 and 2 bits of logic variables so that each time I randomize, the probability of that logic to be the same value as before will be %5 for example. So its less likely to retain its value, it wants to change. How would I do that? Thanks in advance.

In reply to emin:

You can use this general constraint

class A;
  rand bit [4:0] value;
  // only 5% of the time, bits [1:0] will be the same as the previous bits
  constraint keep { value[1:0] == const'(value[1:0]) dist {1:=5,0:=95}; }
endclass

module top;
  
  A a=new;
  initial repeat(100) begin
    assert(a.randomize());
    $displayb(a.value);
  end
endmodule
1 Like

Thank you Dave. Is below variable distribution valid? Or do I have to change distributions via variables by overriding pre_randomize function?


constraint keep {
  if(!value) 
    value[1:0] == const'(value[1:0]) dist {1:=5,0:=95}; 
  else
    value[1:0] == const'(value[1:0]) dist {1:=95,0:=5};
}

In reply to emin:

It is extremely difficult to use multiple distribution constructs with random constraint interdependencies. You should use a signal distribution controlled by non-random variables. These can be set with pre_randomize or anytime before calling randomize.

In reply to dave_59:
Great! Thank you Dave.

In reply to dave_59:

Can you explain the syntax and meaning of const’(value)?

Does const’() check the value of the variable in the previous cycle?

constraint keep { value[1:0] == const’(value[1:0]) dist {1:=5,0:=95}; }

In reply to hkc:

Yes, it uses the current value as if it were a non-random state variable—same as a constant for randomization. This is defined in section 6.24.1 Cast operator.

1 Like

In reply to dave_59:

In the example below addr picks the values 20 , 71,110 based on the distributions


class packet;
  rand bit [3:0] addr;
 
  constraint addr_range { addr dist { 20 := 5, 71 := 8, 110 := 12 }; }
endclass
 

I am trying to understand the example in this thread as we are comparing
LHS and RHS(old value) and use dist {1:=5,0:=95};

so what does that mean? it seems like a disconnection w.r.t the example i posted as normally we just have a variable and it picks from the values mentioned after dist based on the distribution

LHS == RHS is the expression and the expression being true (1) has a probability of 5% and the expression being false (0) has 95% probability
{ LHS == RHS) dist {1:=5,0:=95}; }

is my understanding correct? I haven’t seen such an example yet as most examples just talk about variables but seems like we could do the same for conditional expressions

In reply to hsam:

Correct. See Issue with following dist Constraint | Verification Academy

I wanted a way to control values to be passed to some variables either using testplusargs or use SV constraints in the absence of it. Meaning a test case could be fired with fixed user values or if none are provided then the default random values could be used. For this to happen, I did not want to define additional variable that first get the plusarg value and then also define a rand variable. I wanted to do all of the above using just one variable. But for this scheme to work testplusargs must work within constraints. Its 2024 and yet I can see that testplusargs are not fully supported to be used within SV constraints($ system calls are not supported ). Atleast Synopsys simulator errors out.

So the next way for to use testplusargs to initialize the variable and then use constraints if testplusargs were absent. So the const keyword in this post would be useful. But again the cadence simulator won’t support it.

//------------------------------------------------------------------------------
//  Class:  example to either use testplus args or use constraints
//------------------------------------------------------------------------------
class testplusargplusconstraints extends uvm_object;

  rand int         m_num_pkts[16];

  `uvm_object_utils_begin(testplusargplusconstraints)
    `uvm_field_sarray_int(m_num_pkts, UVM_DEFAULT | UVM_NOPRINT)
  `uvm_object_utils_end

  //------------------------------------------------------------------------------
  //  Constructor:  new
  //------------------------------------------------------------------------------
  function new(string name = "ethernet_data_gen_config");
    super.new(name);

    // Set the number of packets with +NUM_ETH_PKTS=x
    foreach (m_num_pkts[i]) 
      if($test$plusargs("NUM_ETH_PKTS"))
        if !($value$plusargs("NUM_ETH_PKTS=%d", m_num_pkts[i]) )
          m_num_pkts[i] = -1;
    
  endfunction : new


  //------------------------------------------------------------------------------
  // Constraint
  //------------------------------------------------------------------------------

  // number of packet 
  constraint c_default_num_of_packets {
    foreach (m_num_pkts[i]) {
      if(m_num_pkts[i] == -1) {
        m_num_pkts[i] inside {[10:20]};
      } else {
        m_num_pkts[i] == const'(m_num_pkts[i]);
      }
    }
  }

endclass // testplusargplusconstraints

So basically then I had to use rand_mode(0) to disable the constraint altogether if plusargs were used on the variable. Like below

//------------------------------------------------------------------------------
//  Class:  example to either use testplus args or use constraints
//------------------------------------------------------------------------------
class testplusargplusconstraints extends uvm_object;

  rand int         m_num_pkts[16];

  `uvm_object_utils_begin(testplusargplusconstraints)
    `uvm_field_sarray_int(m_num_pkts, UVM_DEFAULT | UVM_NOPRINT)
  `uvm_object_utils_end


  //------------------------------------------------------------------------------
  //  Constructor:  new
  //------------------------------------------------------------------------------
  function new(string name = "ethernet_data_gen_config");
    super.new(name);

    // Set the number of packets with +NUM_ETH_PKTS=x
    foreach (m_num_pkts[i]) 
      if($test$plusargs("NUM_ETH_PKTS"))
        if !($value$plusargs("NUM_ETH_PKTS=%d", m_num_pkts[i]) )
          m_num_pkts.rand_mode(0);
    
  endfunction : new


  //------------------------------------------------------------------------------
  // Constraint
  //------------------------------------------------------------------------------

  // number of packet 
  constraint c_default_num_of_packets {
    foreach (m_num_pkts[i]) {
        m_num_pkts[i] inside {[10:20]};
    }
  }

endclass // testplusargplusconstraints

So my question is,

  1. am I doing the right thing.
  2. am I the only one whining and screaming for a better solution
  3. are there any other clever ways. I mean using the uvm_cmd_line functions rather than testplusargs.
  4. will the uvm_cmd_line functions work in constraints

Regards,
Nisreen

You need to whine to your vendor about supporting const'() cast in a constraint, as well as supporting $test$plusargs. $value$plusargs is illegal in a constraint because it is a function call that modifies one of its arguments.

There’s no need for$test$plusargs in your final example; $value$plusargs is all you need.
In the your example, the foreach loop in the constructor is unnecessary.

class testplusargplusconstraints extends uvm_object;
  `uvm_object_utils(testplusargplusconstraints)

  rand int         m_num_pkts[16];

  function new(string name = "ethernet_data_gen_config");
    int num;
    super.new(name);

    // Set the number of packets with +NUM_ETH_PKTS=x
    if ($value$plusargs("NUM_ETH_PKTS=%d", num) ) begin
      m_num_pkts.rand_mode(0);
      m_num_pkts = '{default: num};
    end
  endfunction : new
  // number of packet 
  constraint c_default_num_of_packets {
    foreach (m_num_pkts[i]) {
        m_num_pkts[i] inside {[10:20]};
    }
  }
endclass : testplusargplusconstraints
1 Like