PDA

View Full Version : sequence_item with randc



zinn
12-01-2008, 02:41 AM
Hi folks,

I tried to define a sequence_item with a field instruction. The instruction is of an enumerated type and my idea was to declare it as randc in order to get an even distribution.




typedef enum {ADD, SUB, AND, OR, XOR, INVA, INVB} opCode;
...
class my_sequence_item extends ovm_sequence_item;
...
randc opCode instruction;
...
endclass: my_sequence_item



Now I wanted to define a sequence that simply drives this sequence_item by means of the `ovm_do macro:



class amy_seq extends ovm_sequence;
`ovm_sequence_utils(my_seq, my_sequencer)
my_sequence_item ins;
...
task body;
forever begin
`ovm_do(ins);
end
endtask: body
endclass: my_seq


Unfortunately, I had to realize that the distribution was not even. I looked into the `ovm_do macro and found out that inside the macro a new object is created. Accordingly, each sequence_item object is randomized only once in its life which means that it does not matter at all if i declare a field as rand or randc.

Is this the intended behavior of `ovm_do or is the implementation of the macro buggy?
What do you think how the randc functionality can be used in combination with sequence_item and `ovm_do?


Best regards
Andreas

kurts
12-01-2008, 12:25 PM
Hi Andreas,

There are a couple of things you can do.

First, there are other macros that you can use that do a subset of what the 'ovm_do macro does. `ovm_create performs the new(), and `ovm_rand_send randomizes the item and sends it. If you need even more control, `ovm_send will send it without randomization, leaving you in control over the randomization.

You could do this:


task body;
`ovm_create(ins)
forever begin
`ovm_rand_send(ins)
end
endtask: body

Note that if you take the creation out of the loop, you should probably clone the sequence item before you send it. Otherwise you will be changing the same object memory the next time through the loop, which could cause problems.


my_sequence_item ins, tmp;
task body;
`ovm_create(ins)
forever begin
ins.randomize();
$cast(tmp, ins.clone());
`ovm_send(tmp)
end
endtask: body

Second, you could just avoid the use of macros altogether. This is actually my preferred coding style. The function-based API for sequences is very straightforward and easy to use, and it allows you to have complete control at all times. For example, the minute you need to do anything special with the sequence item, you end up having to use finer-grained macros like those above, and you also end up using callback functions like pre_do, mid_do, and post_do.

After all this, you find that the macros lose what little value they originally offered.

You could use the function API directly like this:



my_sequence_item ins, tmp;
task body;
// Use the factory to create the sequence item
ins = my_sequence_item::type_id::create("ins");
forever begin
wait_for_grant(); // Block until the sequencer chooses this sequence
ins.randomize(); // Do whatever preparation steps are needed on the item
$cast(tmp, ins.clone());
send_item(tmp); // Send the item to the driver
end
endtask: body

Regards,
-Kurt