In my base_sequence which is virutal sequence class, i have instance of a sequence as seq1. x & y are the seq items for seq1. When i am trying to give inline constraints, the code is compile free. However, the constraints with uvm_do_on_with are not working. Can someone please help me figuring out why this is happening and how to make these constraints work.
Is ‘req’ part of seq1? You don’t show the fields of seq1, but perhaps you meant for your constraint to be {seq1.x inside [0,1,3,4]; seq1.y inside [2,6]}?
The issue is that your sub-sequence (mem_sequence) is also using the uvm_do() macro to create the mem_seq_item. The uvm_do() macro will create and randomize the item every time, which will ignore any constraints passed in.
This is a perfect example of why using the `uvm_do_* macros is bad. I recommend you review the UVM Cookbook chapter on sequences and use the sequence/sequence_item methods directly.
So, what i conclude from you answer is that inline constraints cannot be used with `uvm_do macros.
However, one more thing i want to ask that if “inside” works in inline constraints.As of now, i have never seen any example where inside is used in inline constriants. I have doubt on its functionality as well.
I’d suggest doing it slightly differently so that you can constrain all fields of ‘req’, not just the ones you export to the sequence:
class mem_sequence extends uvm_sequence #(mem_seq_item)
rand mem_seq_item req;
function void pre_randomize();
req = mem_seq_item::type_id::create("req");
endfunction
task body();
start_item(req);
finish_item(req);
endtask: body
`uvm_object_utils(mem_sequence)
endclass
This way, ‘req’ gets randomized together with the sequence, so any inline constraints you apply when randomizing the sequence won’t get discarded by a second call to ‘req.randomize()’. Now, the code you showed us in the beginning should work:
I like your solution better. I would make one change to mem_sequence to prevent a possible null object. This doesn’t follow the just-in-time randomization recommendation, but since it is being generated without constraints, it shouldn’t matter.
class mem_sequence extends uvm_sequence #(mem_seq_item)
rand mem_seq_item req;
function void pre_randomize();
req = mem_seq_item::type_id::create("req");
endfunction
task body();
if (req == null) begin
req = mem_seq_item::type_id::create("reg");
if (!req.randomize())
`uvm_error("randerr", "Unable to randomize mem_seq_item");
end
start_item(req);
finish_item(req);
endtask: body
`uvm_object_utils(mem_sequence)
endclass
Thanks Mr. Tudor Timi and Mr. Cgales for the soltution. This is working fine. However, i want to drive 10 packets here. Please have a look at below code.
class mem_sequence extends uvm_sequence #(mem_seq_item)
rand mem_seq_item req;
rand int loop;
function void pre_randomize();
req = mem_seq_item::type_id::create("req");
endfunction
task body();
if (req == null) begin
req = mem_seq_item::type_id::create("reg");
if (!req.randomize())
`uvm_error("randerr", "Unable to randomize mem_seq_item");
end
for(int i=0;i<loop;i++) begin
start_item(req);
finish_item(req);
end
endtask: body
`uvm_object_utils(mem_sequence)
endclass
When i am trying like this, all 10 generated packets have the same data, which of course is expected as packet is randomized only once in base sequence.
I tried like taking loop variable in base sequence instead of mem_sequence, like below: