I have a sequence item class, and it’s extension:
class txn extends uvm_sequence_item;
`uvm_object_utils(txn)
rand int A;
//...
endclass
// extension
class txn_ext extends txn;
`uvm_object_utils(txn_ext)
int B;
constraint c_A { A<B; }
//...
endclass
I have the following sequence, which runs a single object of txn.
class seq_A extends uvm_sequence #(txn);
`uvm_object_utils(seq_A)
virtual task body();
txn t;
t = txn::type_id::create("t");
start_item(t);
if(!t.randomize()) `uvm_error("RANDERR","Randomization error")
finish_item(t);
endtask
// ...
endclass
In my test, I want to run the sequence, do a factory override of the transaction, then repeat the sequence.
class test_A extends test_base ;
`uvm_component_utils(test_A)
virtual task run_phase( uvm_phase phase );
phase.raise_objection(this, "Objection raised by test_base");
begin
seq_A seq;
seq = seq_A::type_id::create("seq");
seq.start(sqr); // send unconstrained transaction
txn::type_id::set_type_override(txn_ext::get_type());
// ??? <------- configure B here? How?
seq.start(sqr); // send constrained transaction
end
phase.drop_objection(this, "Objection raised by test_base");
endtask
//...
endclass
Where/How do I configure integer ‘B’ of the extension?
In reply to bmorris:
You can do it like this:
begin
seq_A seq;
seq = seq_A::type_id::create("seq");
seq.start(sqr); // send unconstrained transaction
txn::type_id::set_type_override(txn_ext::get_type());
seq.randomize with {B == any_value or range};
seq.start(sqr); // send constrained transaction
end
In reply to chr_sue:
That will not work as B is not a member of seq_A
You might consider using the config DB for this.
In reply to dave_59:
txn_ext do a dB pull to acquire B? Then I’ve got the performance issue of my transaction extensions all using the dB to configure.
Putting B in the base class would at least allow the sequence to configure it, but that’s not a realistic option because it’s not OO or scalable.
Apparently I’m also supposed to avoid inline constraints for configuring sequences too. So that knocks out the sequence configuring it.
I’m also supposed to avoid m_sequencer/p_sequencer.
Making B static seems like the most straight-forward way to configure it directly from the test.
Is this example not the bread and butter of the language? Why isn’t there a trivial way to implement it?
In reply to bmorris:
The trivial thing to do for your example is making B a parameter.
class txn_ext #(int B) extends txn;
`uvm_object_utils(txn_ext)
constraint c_A { A<B; }
//...
endclass
Then you can set B as part of the factory override
txn::type_id::set_type_override(txn_ext#(.B(10))::get_type());
But more generally, I think your problem is you created an extension requiring external configuration. You could just create more extensions with the configuration self-contained.
class txn_ext10 extends txn_ext;
`uvm_object_utils(txn_ext10)
function new(
super.new()
B = 10;
endfunction
endclass
And still another approach is to construct the transaction before starting the sequence and not constructing inside the sequence. Use clone() to create more copies if you need them rather than create().
In reply to dave_59:
The correct value for B only becomes known well into the simulation. The parameter idea could work. thanks