Hi forks:
I have the following 2 transactions. When a_transaction is instantiated and randomized, messages inside the function post_randomize of b_transaction are
printed twice. I don’t know why. It seems that b_transaction was instantiated twice.
class b_transaction extends uvm_sequence_item;
...
function void post_randomize();
`uvm_info("TRACE", $sformatf("%m"), UVM_LOW)
endfunction
endclass
class a_transaction extends uvm_sequence_item;
rand b_transaction b_xact_queue[$];
...
constraint c_xact_queue_size {
b_xact_queue.size == 0;
}
...
function void post_randomize();
b_transaction b_xact;
`uvm_info("TRACE", $sformatf("%m"), UVM_LOW)
b_xact = b_transaction ::type_id::create("b_xact", m_sequencer);
b_xact.randomize();
b_xact_queue.push_back(b_xact);
endfunction
endclass
class a_sequence extends uvm_sequence #(a_xaction);
...
task body();
repeat(1) begin
`uvm_do_with(req, {
id == local::id
});
id++;
end
endtask
endclass
Note that in following testcases, a_transaction and b_transaction will be overrided by their derived classes.
When you randomize a_transaction, b_transaction is randomized since it is declared ‘rand’, hence the first message. Then, in the post_randomize() function of a_transaction, b_transaction is randomized again, hence the second message.
Based on you answer, I delete the ~rand~ keyword before b_transaction declared in a_transaction. The simulation result shows that the ~post_randmize~ function of b_transaction is only printed once, which is exactly the same as what you said!
Still I am little confused. If ~b_transaction~ is decared as rand in ~a_transaction~ and the size of ~b_xact_queue~ is contrained to 0, do it mean that during the randomization process ~b_transaction~ will be created and randomized but not pushed into b_xact_queue? Is that the truth ?
This is likely a tool-specific behavior on how it creates the randomization state space. The following self-contained example will have different behavior depending on which simulator is used on EDA Playground. As long as the end result is valid, I don’t think that the intermediate results will have any detrimental effects.
import uvm_pkg::*;
`include "uvm_macros.svh"
class b_transaction extends uvm_sequence_item;
`uvm_object_utils(b_transaction)
rand int a;
function void post_randomize();
`uvm_info("TRACE", $sformatf("%m"), UVM_LOW)
endfunction
endclass
class a_transaction extends uvm_sequence_item;
`uvm_object_utils(a_transaction)
rand b_transaction b_xact_queue[$];
constraint c_xact_queue_size {
b_xact_queue.size == 0;
}
function void post_randomize();
b_transaction b_xact;
`uvm_info("TRACE", $sformatf("%m"), UVM_LOW)
b_xact = b_transaction ::type_id::create("b_xact", m_sequencer);
if (!b_xact.randomize()) begin
`uvm_fatal("ERR", "Unable to randomize b_transaction");
end
else begin
b_xact_queue.push_back(b_xact);
end
endfunction
endclass
module top();
a_transaction a;
initial begin
a = a_transaction::type_id::create("a");
if (!a.randomize()) `uvm_fatal("ERR", "Unable to randomize");
end
endmodule