In the following UVM testbench, I needed to make the sequence item, and hence the rest of the UVM components parametrized because the DUT is parametrized. I define 2 sequences: the base sequence 'MySeq' and a derived sequence 'MyConsecSubFrmSeq'. Also there is the base test class 'MyTest', and derived test class 'MyConsecSubFrmTest', in which I override the sequence class with MyConsecSubFrmSeq class.
Yet when running the testbench, setting UVM_TESTNAME
to MyConsecSubFrmTest
, I see that the sequence class isn't overridden, and the base sequence 'MySeq' is run instead. What is wrong here?
package MyTest;
import uvm_pkg::*;
`include "uvm_macros.svh"
class FrmCfg extends uvm_object;
rand bit [6:0] ResBlks; // Number of resource blocks (NRB)
rand bit [2:0] NumTXAnt; // Number of TX antennas at base station
rand integer FFTSize; // FFT size
function string convert2string();
$sformat(convert2string, "FFT size: %0d", FFTSize);
endfunction
function new(string name="FrmCfg");
super.new(name);
endfunction
`uvm_object_param_utils_begin(FrmCfg)
`uvm_field_int(ResBlks, UVM_DEFAULT)
`uvm_field_int(NumTXAnt, UVM_DEFAULT)
`uvm_field_int(FFTSize, UVM_DEFAULT)
`uvm_object_utils_end
endclass: FrmCfg
class MyTxn #(
parameter IQSIZE=13, // I/Q size
parameter RXANT_NUM=1 // Number of Rx antennas
) extends uvm_sequence_item;
rand FrmCfg cfg;
rand bit [3:0] SubFrmIdx;
function string convert2string;
$sformat(convert2string, "%s", cfg.convert2string());
$sformat(convert2string, "%s idx=%0d", convert2string, SubFrmIdx);
endfunction
function new(string name="MyTxn");
super.new(name);
cfg = FrmCfg::type_id::create("cfg");
endfunction
task display;
`uvm_info("FRM", convert2string, UVM_MEDIUM)
endtask
`uvm_object_param_utils_begin(MyTxn#(IQSIZE, RXANT_NUM))
`uvm_field_object(cfg, UVM_DEFAULT)
`uvm_field_int(SubFrmIdx, UVM_DEFAULT)
`uvm_object_utils_end
endclass: MyTxn
class MySeq #(
parameter IQSIZE=13, // I/Q size
parameter RXANT_NUM=1 // Number of Rx antennas
) extends uvm_sequence #(MyTxn#(IQSIZE, RXANT_NUM));
`uvm_object_param_utils(MySeq#(IQSIZE, RXANT_NUM))
rand bit [3:0] SubFrmIdx;
rand FrmCfg cfg;
constraint cons {
SubFrmIdx < 10;
cfg.FFTSize == 2048;
}
function new(string name="MySeq");
super.new(name);
cfg = FrmCfg::type_id::create("cfg");
endfunction
virtual function string convert2string;
$sformat(convert2string, "idx=%0d", SubFrmIdx);
$sformat(convert2string, "%s %s", convert2string, cfg.convert2string());
endfunction
task body();
`uvm_info("REDMPSEQ", convert2string, UVM_MEDIUM)
req = MyTxn#(IQSIZE, RXANT_NUM)::type_id::create("req");
req.cfg.copy(cfg);
req.cfg.rand_mode(0);
`uvm_rand_send_with(req, {SubFrmIdx == local::SubFrmIdx;})
endtask: body
endclass: MySeq
class MyConsecSubFrmSeq #(
parameter IQSIZE=13, // I/Q size
parameter RXANT_NUM=1 // Number of Rx antennas
) extends MySeq#(IQSIZE, RXANT_NUM);
`uvm_object_param_utils(MyConsecSubFrmSeq#(IQSIZE, RXANT_NUM))
randc integer unsigned SubFrmCnt;
randc bit [3:0] StartSubFrmIdx;
constraint conseq_cons {
StartSubFrmIdx < 10;
}
function new(string name="MySeqConsecSubFrm");
super.new(name);
endfunction
virtual function string convert2string;
$sformat(convert2string, "%s", super.convert2string());
$sformat(convert2string, "%s, start idx=%0d",convert2string, StartSubFrmIdx);
endfunction
task body();
MySeq #(
.IQSIZE(IQSIZE),
.RXANT_NUM(RXANT_NUM)
) seq;
`uvm_info("REDMP_CONSEC_SUBFRM_SEQ", convert2string, UVM_MEDIUM)
seq = MySeq#(IQSIZE, RXANT_NUM)::type_id::create("subfrm_seq");
seq.cfg.copy(cfg);
seq.cfg.rand_mode(0);
SubFrmIdx = StartSubFrmIdx;
repeat(SubFrmCnt) begin
SubFrmIdx++;
SubFrmIdx%=10;
`uvm_rand_send_with(seq, {SubFrmIdx == local::SubFrmIdx; })
end
endtask: body
endclass: MyConsecSubFrmSeq
class MyDrv #(
parameter IQSIZE=13, // I/Q size
parameter RXANT_NUM=1 // Number of Rx antennas
) extends uvm_driver#(MyTxn#(IQSIZE, RXANT_NUM));
`uvm_component_param_utils(MyDrv#(IQSIZE, RXANT_NUM))
function new(string name="MyDrv", uvm_component parent=null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
seq_item_port.get_next_item(req);
req.display;
seq_item_port.item_done();
endtask: run_phase
endclass: MyDrv
class MySqr #(
parameter IQSIZE=13, // I/Q size
parameter RXANT_NUM=1 // Number of Rx antennas
) extends uvm_sequencer #(MyTxn#(IQSIZE, RXANT_NUM));
`uvm_component_param_utils(MySqr#(IQSIZE, RXANT_NUM))
function new(string name="MySqr", uvm_component parent=null);
super.new(name, parent);
endfunction
endclass: MySqr
class MyAgent #(
parameter IQSIZE=13, // I/Q size
parameter RXANT_NUM=1 // Number of Rx antennas
) extends uvm_agent;
`uvm_component_param_utils(MyAgent#(IQSIZE, RXANT_NUM))
MySqr#(IQSIZE, RXANT_NUM) sqr;
MyDrv#(
.IQSIZE(IQSIZE),
.RXANT_NUM(RXANT_NUM)
) drv;
uvm_analysis_port #(MyTxn#(IQSIZE, RXANT_NUM)) dut_in_txn_port;
uvm_analysis_port #(MyTxn#(IQSIZE, RXANT_NUM)) dut_out_txn_port;
function new(string name="MyAgent", uvm_component parent=null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
sqr = MySqr#(IQSIZE, RXANT_NUM)::type_id::create("sqr", this);
drv = MyDrv#(
.IQSIZE(IQSIZE),
.RXANT_NUM(RXANT_NUM)
)::type_id::create("drv", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
if(get_is_active() == UVM_ACTIVE)
drv.seq_item_port.connect(sqr.seq_item_export);
endfunction: connect_phase
endclass: MyAgent
class MyEnv #(
parameter IQSIZE=13, // I/Q size
parameter RXANT_NUM=1 // Number of Rx antennas
) extends uvm_env;
`uvm_component_param_utils(MyEnv#(IQSIZE, RXANT_NUM))
MyAgent#(
.IQSIZE(IQSIZE),
.RXANT_NUM(RXANT_NUM)
) agent;
function new(string name="MyEnv", uvm_component parent=null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
agent = MyAgent#(
.IQSIZE(IQSIZE),
.RXANT_NUM(RXANT_NUM)
)::type_id::create("agent", this);
endfunction: build_phase
endclass: MyEnv
class MyParamTest #(
parameter IQSIZE=13, // I/Q size
parameter RXANT_NUM=1 // Number of Rx antennas
) extends uvm_test;
`uvm_component_param_utils(MyParamTest#(IQSIZE, RXANT_NUM))
MyEnv#(
.IQSIZE(IQSIZE),
.RXANT_NUM(RXANT_NUM)
) env;
function new(string name="MyParamTest", uvm_component parent=null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
env = MyEnv#(
.IQSIZE(IQSIZE),
.RXANT_NUM(RXANT_NUM)
)::type_id::create("env", this);
endfunction: build_phase
task run_phase(uvm_phase phase);
MySeq#(IQSIZE, RXANT_NUM) seq;
phase.raise_objection(this);
seq = MySeq#(IQSIZE, RXANT_NUM)::type_id::create("seq");
seq.randomize();
seq.start(env.agent.sqr);
phase.drop_objection(this);
endtask: run_phase
function void end_of_elaboration_phase(uvm_phase phase);
this.print();
factory.print();
endfunction: end_of_elaboration_phase
endclass: MyParamTest
class MyConsecSubFrmParamTest #(
parameter IQSIZE=13, // I/Q size
parameter RXANT_NUM=1 // Number of Rx antennas
) extends MyParamTest#(IQSIZE, RXANT_NUM);
`uvm_component_param_utils(MyConsecSubFrmParamTest#(IQSIZE, RXANT_NUM))
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_resource_db #(bit) :: set ("", "FullFrame", 1);
endfunction: build_phase
function new(string name="MyConsecSubFrmParamTest", uvm_component parent=null);
super.new(name, parent);
endfunction
virtual function void end_of_elaboration_phase(uvm_phase phase);
set_inst_override_by_type ("seq",
MySeq#(IQSIZE, RXANT_NUM)::get_type(),
MyConsecSubFrmSeq#(IQSIZE, RXANT_NUM)::get_type());
super.end_of_elaboration_phase(phase);
endfunction: end_of_elaboration_phase
endclass: MyConsecSubFrmParamTest
endpackage: MyTest
module t;
import MyTest::*;
import uvm_pkg::*;
`include "uvm_macros.svh"
parameter IQSIZE = 13;
parameter RXANT_NUM=1; // Number of Rx antennas
reg Clk;
/*myDUT #(
.IQSIZE(IQSIZE),
.RXANT_NUM(RXANT_NUM)
) uDUT (
// Clock & reset:
.Clk(Clk),
....
*/
initial begin
Clk <= 0;
forever #(5) Clk = ~Clk;
end
`define UnParamClass(UnParamClassName, ParamClassName, IQSizeVal, RXAntVal) \
class UnParamClassName extends ParamClassName#(IQSizeVal, RXAntVal); \
`uvm_component_utils(UnParamClassName) \
function new(string name="UnParamClassName", uvm_component parent=null); \
super.new(name, parent); \
endfunction \
endclass: UnParamClassName
`UnParamClass(MyTest, MyParamTest, IQSIZE, RXANT_NUM)
`UnParamClass(MyConsecSubFrmTest, MyConsecSubFrmParamTest, IQSIZE, RXANT_NUM)
initial begin
run_test();
end
endmodule: t
# vsim -c "+UVM_TESTNAME=MyConsecSubFrmTest" t
# UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(215) @ 0: reporter [Questa UVM] QUESTA_UVM-1.2.3
# UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(216) @ 0: reporter [Questa UVM] questa_uvm::init(+struct)
# UVM_INFO @ 0: reporter [RNTST] Running test MyConsecSubFrmTest...
# --------------------------------------------------------------
# Name Type Size Value
# --------------------------------------------------------------
# uvm_test_top MyConsecSubFrmTest - @466
# env uvm_env - @473
# agent uvm_agent - @483
# drv uvm_driver #(REQ,RSP) - @599
# rsp_port uvm_analysis_port - @614
# seq_item_port uvm_seq_item_pull_port - @606
# sqr uvm_sequencer - @490
# rsp_export uvm_analysis_export - @497
# seq_item_export uvm_seq_item_pull_imp - @591
# arbitration_queue array 0 -
# lock_queue array 0 -
# num_last_reqs integral 32 'd1
# num_last_rsps integral 32 'd1
# --------------------------------------------------------------
#
#### Factory Configuration (*)
#
# Instance Overrides:
#
# Requested Type Override Path Override Type
# -------------- ---------------- -------------
# <unknown> uvm_test_top.seq <unknown>
#
# No type overrides are registered with this factory
#
# All types registered with the factory: 50 total
# (types without type names will not be printed)
#
# Type Name
# ---------
# MyConsecSubFrmTest
# MyTest
# questa_uvm_recorder
# (*) Types with no associated type name will be printed as <unknown>
#
####
#
# UVM_INFO t.sv(76) @ 0: uvm_test_top.env.agent.sqr@@seq [REDMPSEQ] idx=2 FFT size: 2048
# UVM_INFO t.sv(43) @ 0: uvm_test_top.env.agent.sqr@@seq.req [FRM] FFT size: 2048 idx=2
# UVM_INFO verilog_src/uvm-1.1d/src/base/uvm_objection.svh(1267) @ 0: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
#
# --- UVM Report Summary ---
#
# ** Report counts by severity
# UVM_INFO : 6
# UVM_WARNING : 0
# UVM_ERROR : 0
# UVM_FATAL : 0
# ** Report counts by id
# [FRM] 1
# [Questa UVM] 2
# [REDMPSEQ] 1
# [RNTST] 1
# [TEST_DONE] 1
I tried changing the override to:
set_inst_override_by_type({get_fullname(),".seq"}
MySeq#(IQSIZE, RXANT_NUM)::get_type(),
MyConsecSubFrmSeq#(IQSIZE, RXANT_NUM)::get_type());
which as far as I understand, is functionally equivalent to the original code, yet I got this in the simulation log:
# Instance Overrides:
# Requested Type Override Path Override Type
# -------------- ---------------- -------------
# <unknown> uvm_top_seq.uvm_test_top.seq <unknown>
#