PDA

View Full Version : How to extend created sequences for sequence lib



david@intelliprop.com
02-14-2008, 08:45 AM
Can someone help me with creating a sequence lib? I have a class that extends the ovm_sequence. This runs fine. When I try to extend that class to override a field and call the parent task it says that p_sequencer is a bad pointer access. If I duplicate the first sequence to the second and change the method it is fine.

class my_sequence extends ovm_sequence;
integer a;
virtual task my_task;
@(posedge p_sequencer.monitor.transaction_collected);
a += p_sequencer.monitor.a;
`ovm_do_with(sub_seq, {a == this.a});
endtask
virtual task body();
my_task();
endtask
endclass

class my_sequence2 extends my_sequence;
integer b;

virtual task body();
a = b;
my_task();
endtask
endclass


Thanks

kurts
02-14-2008, 10:47 PM
Hi David,

The problem is that the class property p_sequencer is declared in *both* the parent class and the child class due to the `ovm_sequence_utils() macro, and the child's copy is overriding (blocking) the parent one.

When you have the sequencer start the derived sequence, it's p_sequencer handle is set to point to the sequencer, but the one in the parent class is not set.

Then, when you call the inherited my_task, it is running in the "context" of the parent class, so it uses the only p_sequencer that it knows about - the parent one, which is null!

You can get around this by adding the statement
super.p_sequencer = p_sequencer

Put this statement in either the pre_body() function of the child or at the beginning of the body() of the child, and it should work.

Note - this illustrates why it is a *BAD* idea to override data members of a class. (of course, because of the macros, you don't have much of a choice here)

-Kurt

jfowler
02-20-2008, 05:41 PM
You omitted the `ovm_sequence_utils macros from your code snippet, but I assume from your questions that you are using them since the p_sequencer reference in my_sequence is working and you do not show a manual assignment.

The other alternative, and probably better solution, is to only use the part of the macro that you need in this case. The macro is just shorthand for templated code.

The ovm_sequence_utils_begin(TYPE_NAME, SEQUENCER) macro expands into:

static bit is_registered_with_sequencer =
SEQUENCER``::add(`"TYPE_NAME`"); \
SEQUENCER p_sequencer;\
virtual function void m_set_p_sequencer(); \
$cast(p_sequencer, get_sequencer());\
endfunction
`ovm_object_utils_begin(TYPE_NAME) \

In this case, you only need to register the sequence with the sequencer and then provide the `ovm_object_utils() macro (along with any `ovm_field_* macros). Declaring p_sequencer again is not necessary and produces a bad side effect as Kurt points out. Likewise, there is no need to redeclare the m_set_p_sequencer() function.

The code to do this would look like:

static bit is_registered_with_sequencer =
your_sequencer_type::add("my_sequence2");
`ovm_object_utils_begin(my_sequence2)
`ovm_field_...

des00
11-09-2008, 08:58 AM
In this case, you only need to register the sequence with the sequencer and then provide the `ovm_object_utils() macro (along with any `ovm_field_* macros). Declaring p_sequencer again is not necessary and produces a bad side effect as Kurt points out. Likewise, there is no need to redeclare the m_set_p_sequencer() function.

The code to do this would look like:


I have confronted with the same problem.

I want to make virtual sequence base class, in which all calls to non-virtual sequence are wrapped up in task what permanently to not write a lot off
"ovm_do_on()/ovm_do_on_with()" macros.

I have brought to the file ovm_sequence_defines.svh of OVM2.0 in the following editing



`define ovm_extend_sequence_utils_begin(TYPE_NAME, SEQUENCER) \
`ovm_register_sequence(TYPE_NAME, SEQUENCER) \
`ovm_object_utils_begin(TYPE_NAME)


I believe it would be not bad to add this macros in the following library release.

Thank for your advice!!!

jfowler
11-09-2008, 11:04 AM
In OVM 2.0, the ovm_sequence_utils() macro is written in terms of three sub-macros. Each of these sub-macros performs functionality that can be used on its own to do exactly what you are showing.

The ovm_sequence_utils() macro is...
`ovm_register_sequence(TYPE_NAME, SEQUENCER) - which does the registration
`ovm_declare_p_sequencer(SEQUENCER) - which declares and initializes the p_sequencer variable
`ovm_object_utils(TYPE_NAME) - which does the normal utils functions

So for your case, you need the first and third sub-macros. This separation was done such that you do not need to create more macros to provide the functionality.

JF

JPK
11-14-2008, 09:55 AM
David, etal. ;
Looks like several people encounter this feature:

Although Kurt and John have the essence of the issue,
there is IMO a cleaner and more OOP loyal solution.
This is to use the accessor call instead of any direct assignment
or macro split up.

This has the advantages of protecting your code base from
any changes to OVM and accommodates type overrides seamlessly.
You still Do have to place a hookup call in your extended class however.
So your example would look something like this;




class my_sequence extends ovm_sequence;
integer a;

virtual function void hookup_sequencer();
$cast(p_sequencer, get_sequencer());
endfunction : hookup_sequencer

virtual task my_task;
@(posedge p_sequencer.monitor.transaction_collected);
a += p_sequencer.monitor.a;
`ovm_do_with(sub_seq, {a == this.a});
endtask
virtual task body();
my_task();
endtask
endclass

class my_sequence2 extends my_sequence;
integer b;

virtual task body();
hookup_sequencer();
a = b;
my_task();
endtask
endclass


I choose to put this in body() vs. pre_body() to guard
against this sequence being in a chain and therefore
possibly not having its pre_body() called.

JPK