Dynamic Arrays with ovm_do_with & ovm_do_on_with

Hi All,

I am facing an issue with passing a dynamic array with
`ovm_do_with

and

ovm_do_on_with.

The following is the snippet of the code.

Can anyone please help me on this ?

class my_trans extends ovm_sequence_item;

    rand  bit [127:0]               data [];

     //---> Configuration
   `ovm_object_utils_begin(my_trans)
   `ovm_field_array_int (            data,             OVM_ALL_ON)
   `ovm_object_utils_end

     function new (string name = "my_trans", ovm_sequencer_base        sequencer = null, ovm_sequence parent_seq = null);
          super.new(name, sequencer, parent_seq);
   endfunction : new
endclass : my_trans
And in the sequence now i am passing dynamic array like this ``` class my_seq extends ovm_sequence #(my_trans);

rand bit [W_DATA-1:0] data_local ;
// OVM automation macros for sequences
`ovm_sequence_utils(my_seq, my_sequencer)

// Constructor
function new (string name = “my_seq”);
super.new(name);
endfunction

virtual task body();
begin
data_local=new[2];
data_local[0] = 128’hDBE7DBE7DBE7DBE77EBD7EBD7EBD7EBD;
data_local[1] = 128’hE7DBE7DBE7DBE7DBBD7EBD7EBD7EBD7E;
`ovm_do_with(req,{req.data == data_local;})
end
endtask

endclass: my_seq

<span style="font-family:'Courier New'">
<font size=2><span style="font-family:'Arial'">
<font color=Blue>But above passing mechanism is NOT working.
<font color=black>
Regards,
Santosh</font>
</font></span> </font></span>

Santosh,

SystemVerilog constraints only work on integral expressions. Arrays need to be unrolled using the foreach construct.

`ovm_do_with(req,{foreach(req.data[i]) req.data[i] == data_local[i];})

Better yet, don’t use the macro and set the fields directly:

virtual task body();
  begin
    assert($cast(req,create_item(my_trans::get_type(),
                                 m_sequencer,"req")); // factory create
    start_item(req);
  //assert(req.randomize(); // optionally randomize other fields
    req.data = '{128'hDBE7DBE7DBE7DBE77EBD7EBD7EBD7EBD,
                 128'hE7DBE7DBE7DBE7DBBD7EBD7EBD7EBD7E};
    finish_item(req);
  end
endtask

Dave

I think that doing direct assignment of the data fields as Dave shows above is often not a good idea. The reason is that it circumvents the constraint solver (ie the constraint solver has no knowledge or control over the values that are assigned). If there are other constraints in the system that rely on these fields then illegal stimulus may be generated.

Even if this problem does not arise in this specific testbench, it may arise when the components are reused later.

A better approach is to use the foreach construct with the equality constraint. Another approach is to use set_mode() to turn off randomization for those fields and then assign them. The advantage of this approach over Dave’s suggestion is that the constraint solver can still properly evaluate other constraints that may apply to these fields.

-Stuart

Stuart,

I tend to agree with you if the fields being manually assigned are usually randomized, but not in the case where the fields will alwaysbe explicitly assigned, or alwaysa derivative of other random values. I don’t know what the original poster’s intent was, and having a field declared with or without therand modifier will show the user’s intent.

Also note that in SystemVerilog, a call to req.randomize(null) will check the validity of the constraints with the current state of all fields without randomizing.

Dave

Hi Dave/Stuart,

I agree with both of your solutions.

However there is a discrepancy w.r.t. to Dave’s solution. The " ’ " construct i.e.
dynamic_array = '{'hEAB7EAB7}; will not work in IUS but works in Questasim.

As a result, to have uniformity across tools, its advisable to use foreach construct within the constraint.

Ashish

Hi Dave/Staurt,

As per suggestions, I tried with “foreach” constraint but the dynamic array DIDNOT get the values what I specified through data_local and req.data value is zero. Did I miss something ?

data_local=new[2];
 data_local[0] = 128'hDBE7DBE7DBE7DBE77EBD7EBD7EBD7EBD;
 data_local[1] = 128'hE7DBE7DBE7DBE7DBBD7EBD7EBD7EBD7E
  `ovm_do_with(req,{foreach(req.data[i]) req.data[i] == data_local[i];})

Regards
Santosh

Oh, we all missed the fact that if you are using constraints, you also need a constraint on the size of the dynamic array to allocate two elements.

Also, with regard to the “'”; that is now optional in this case. The “'” in front of {}'s mean follow the rules for assignment patterns, without it, follow the rules for unpacked array concatenation - to align with C/c++. For single dimensional unpacked arrays of integral values, there’s no difference between the two forms when specifying a list of integral values. Differences start showing up when you have multiple dimensions of dynamically sized arrays.

Dave

Thank you Dave,

It worked by passing array size through inline constraint and I constraint on length in transaction class something like this

`ovm_do_with(req,req.length == this.length;
                         foreach(req.data[i]) req.data[i] == data[i];})
constraint data_len_c          {data.size() == length;  length >= 1; length < 50;}

Thanks
Santosh

Hi,

I am trying to do something like this in a sequence:

`ovm_do_with(bseq, { dest_address == this.dest_address; } )

where bseq is another sequence and dest_address is a bit vector.

What does this pointer evaluate to ? The above contraint is not working. i.e bseq.dest_address is not same as I expect it to be.

If I try this, I get as expected.

`ovm_do_with(bseq, { dest_address == dest_address_l; } )

Can anyone shed some light on this?

Thanks,
Karthik.

Sorry for the double post. I started a new thread here:
http://ovmworld.org/forums/showthread.php?2061-using-this-pointer-in-ovm_do_with-constraint-block&p=7504#post7504