Constrain the number of occurrences in an array

Hi,

I have a dynamic array of objects. Each object has an enum variable, let’s call it instruction, values can be ADD, SUB, MUL, DIV for example. When trying to randomize the transaction which includes the dynamic array, i want to constraint the number of objects that has instruction set to ADD.

Pseudo code looks something like this:

class c;
rand enum (ADD, SUB, MUL, DIV) e;
endclass

class txn;
rand c c_inst;

constraint add_less_than_5 {(c_inst.find with (item.e == ADD)) <= 5)}
endclass

Any ideas how to achieve this constraint?

Thanks
-Bahaa

In reply to Bahaa Osman:

Hi Bahaa,

I think you want to use the sum() method

constraint add_less_than_5 {(c_inst.sum() with (item.e == ADD)) <= 5)}

This assumes you have either constructed the dynamic array before calling randomize, or constrained the size of c_inst in another constraint.

P.S. And please use a typedef for your enum :)

In reply to dave_59:

Thanks Dave! Trust me, i write better code than the pseudo code snippet above :)

In reply to Bahaa Osman:

FYI, i had to cast to int for this to work correctly


constraint add_less_than_5 {(c_inst.sum() with (int'(item.e == ADD))) <= 5)}

In reply to Bahaa Osman:

Casting works correctly . But i would want to understand why ? Doesnt item.e == ADD → 1

In reply to diptishe:

The result of all the equality/relational/logical operators are all 1-bit 1’b1 or 1’b0. The result of the sum() method has the same type as each element.

In reply to dave_59:
I tried with this:

class c;
  rand enum {ADD, SUB, MUL, DIV} e;
endclass

class txn;
rand c c_inst[];

  function void pre_randomize();
    for(int i=0;i<10;i++)begin
      c_inst[i]= new();
      c_inst[i].randomize();
    end
  endfunction

constraint add_less_than_5 {c_inst.sum() with (int'(item.e == c::ADD)) == 5;}

endclass

module abc;
  txn t1;
  
  initial begin
    t1=new();
    repeat(10) begin
      assert(t1.randomize());
      $display("%p",t1);
    end
  end
endmodule

but getting this

# ** Error: (vsim-7100) Invalid call to class::randomize() via a null class reference.
#    Time: 0 ns  Iteration: 0  Process: /abc/#INITIAL#24 File: testbench.sv Line: 13
# ** Error: (vsim-7100) Invalid call to class::randomize() via a null class reference.
#    Time: 0 ns  Iteration: 0  Process: /abc/#INITIAL#24 File: testbench.sv Line: 13
# ** Error: (vsim-7100) Invalid call to class::randomize() via a null class reference.
#    Time: 0 ns  Iteration: 0  Process: /abc/#INITIAL#24 File: testbench.sv Line: 13
# ** Error: (vsim-7100) Invalid call to class::randomize() via a null class reference.
#    Time: 0 ns  Iteration: 0  Process: /abc/#INITIAL#24 File: testbench.sv Line: 13
# ** Error: (vsim-7100) Invalid call to class::randomize() via a null class reference.
#    Time: 0 ns  Iteration: 0  Process: /abc/#INITIAL#24 File: testbench.sv Line: 13
# ** Error: (vsim-7100) Invalid call to class::randomize() via a null class reference.
#    Time: 0 ns  Iteration: 0  Process: /abc/#INITIAL#24 File: testbench.sv Line: 13
# ** Error: (vsim-7100) Invalid call to class::randomize() via a null class reference.

Can you please tell me reason for this?

In reply to Juhi_Patel:

Reason is your statement


  c_inst[i]= new(); 

There is no element of array c_inst yet .

Change your pre_randomize() to ::


function void pre_randomize();
    c_inst = new[10]; // 10 elements at default value 'null' 
    foreach(c_inst[i])  
    begin
      c_inst[i]= new();
      c_inst[i].randomize();  // Not Needed !!
    end
  endfunction

In reply to ABD_91:

Just FYI, I would prefer creating c_inst inside new function of txn class instead of creating inside pre_randomize phase.

In reply to saurabh.c:

A few points ::

(1) My code was wrt question / code asked
(2) pre_randomize() is method ( function ) not a phase

(3) I would call new() in pre_randomize() OVER a constructor since the Constructor would
be called only once ( when Object of txn is created ) .

 **If the number of objects of c_inst is based on some class property that can be changed via
 run-time , pre_randomize() is the approach to take.**