Dusan Krantic
Dusan Krantic

Reputation: 117

Randomize a queue of objects in systemverilog

I have seen techniques used to randomize queues of integral values, but I am having difficulties with queues of objects. An example code:

class int_queue_class;
  rand int x[$];

  function void print;
    $display($sformatf("Size: %0d", x.size()));
    foreach(x[i])
      $display($sformatf("x[%0d] = %0d", i, x[i]));
  endfunction : print

endclass : int_queue_class


class obj;
  rand int value;
endclass : obj

class obj_queue_class;
  rand obj x[$];

  function void print;
    $display($sformatf("Size: %0d", x.size()));
    foreach(x[i])
      $display($sformatf("x[%0d] = %0d", i, x[i].value));
  endfunction : print

endclass : obj_queue_class


program top();
  initial
  begin
    int_queue_class iqc;
    obj_queue_class oqc;
    iqc = new();
    iqc.randomize() with {x.size() == 5; x[2] == 5;};
    iqc.print();
    oqc = new();
    oqc.randomize() with {x.size() == 5; x[2].value == 5;};
    oqc.print();
  end
endprogram : top

It seems that the same approach cannot be used when it comes to objects. Is there a way to randomize such a queue while keeping the ability to simultaneously constrain the queue size and individual element fields? The ideas that I've come up with that use pre/post randomize methods all loose at least one of those two options.

Upvotes: 0

Views: 3511

Answers (1)

Tudor Timi
Tudor Timi

Reputation: 7573

Randomization doesn't create new objects. When you randomize the size of a queue it will create new entries which contain the default values, which for class types is null.

The only thing you can do is to pre-allocate objects inside your queue, to have some to spare. You won't be able to randomize more objects than you initially created, so this limits the value of the queue's size:

class obj_queue_class;
  rand obj x[$];
  local const max_size;

  constraint legal_size {
    x.size() <= max_size;
  }

  function void pre_randomize();
    x = new[max_size];
    foreach (x[i])
      x[i] = new();
  endfunction

  function void print();
    $display($sformatf("Size: %0d", x.size()));
    foreach(x[i])
      $display($sformatf("x[%0d] = %0d", i, x[i].value));
  endfunction

endclass

I've made max_size a local constant value, but it can be something that you can set from outside, a package parameter, etc.

In pre_randomize() you instantiate max_size objects. Since x.size() is always smaller or equal to max_size, whatever value gets randomized will lead to a queue that contains object instances and no null. The rest of the objects will get thrown away when the queue shrinks.

Upvotes: 4

Related Questions