Virtual sequencer
Virtual sequencer 有三个属性:
Virtual sequencer 中装有其他的sequencer的句柄
Virtual sequencer并不和任何driver相连
Virtual sequencer本身并不处理item
m_sequencer 与 p_sequencer
m_sequencer是uvm_sequencer类型的句柄,是每个sequence中自带的属性
一旦sequence被挂载到某个sequencer,那么m_sequencer就会指向这个sequencer
p_sequencer可以理解为将m_sequencer做了类型转换,使m_sequencer适应多种子类sequencer
示例
//--------------------------------------module---------------------------------
module hardware1;
import pack1::*;
import uvm_pkg::*; //+UVM
initial begin
run_test("test1");
end
endmodule
//-------------------------------------package--------------------------------
package pack1; //pack1头
import uvm_pkg::*; //+UVM
`include "uvm_macros.svh"//+工厂
//-----------------------------------A----------------------------------------//
//A-item
class item_a extends uvm_sequence_item;
rand bit [7:0] data_a;
`uvm_object_utils_begin(item_a)
`uvm_field_int(data_a,UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "item_a");
super.new(name);
endfunction
endclass
//A-sequence
class seq_a extends uvm_sequence;
rand int database = 0;
`uvm_object_utils(seq_a)
function new(string name = "seq_a");
super.new(name);
endfunction
task body();
item_a req;
repeat(3) begin
#20ns;
`uvm_do_with(
req,
{data_a inside {[database:database+9]};}
)
end
#20ns;
endtask
endclass
//A-sequencer
class seqr_a extends uvm_sequencer;
`uvm_component_utils(seqr_a)
function new(string name = "seqr_a", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass
//A-driver
class dri_a extends uvm_driver;
`uvm_component_utils(dri_a)
function new(string name = "dri_a", uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
uvm_sequence_item temp;
item_a req;
forever begin
seq_item_port.get_next_item(temp);
void'($cast(req,temp));
$display("\n=================================================");
`uvm_info("dri_a","driver already recive item", UVM_LOW)
`uvm_info("dri_a",$sformatf("item in sequence:%s",req.get_parent_sequence().get_name()), UVM_LOW)
`uvm_info("data",$sformatf("%d",req.data_a), UVM_LOW)
$display("=================================================\n");
seq_item_port.item_done();
end
endtask
endclass
//A-agent
class agent_a extends uvm_agent;
dri_a driver;
seqr_a sequencer;
`uvm_component_utils(agent_a)
function new(string name = "agent_a", uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
driver = dri_a::type_id::create("driver", this);
sequencer = seqr_a::type_id::create("sequencer", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
driver.seq_item_port.connect(sequencer.seq_item_export);
endfunction
endclass
//-----------------------------------B----------------------------------------//
//B-item
class item_b extends uvm_sequence_item;
rand bit [7:0] data_b;
`uvm_object_utils_begin(item_b)
`uvm_field_int(data_b,UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "item_b");
super.new(name);
endfunction
endclass
//B-sequence
class seq_b extends uvm_sequence;
rand int database = 0;
`uvm_object_utils(seq_b)
function new(string name = "seq_b");
super.new(name);
endfunction
task body();
item_b req;
`uvm_do_with(
req,
{data_b inside {[database:database+9]};}
)
endtask
endclass
//B-sequencer
class seqr_b extends uvm_sequencer;
`uvm_component_utils(seqr_b)
function new(string name = "seqr_b", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass
//B-driver
class dri_b extends uvm_driver;
`uvm_component_utils(dri_b)
function new(string name = "dri_b", uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
uvm_sequence_item temp;
item_b req;
forever begin
seq_item_port.get_next_item(temp);
void'($cast(req,temp));
$display("\n=================================================");
`uvm_info("dri_b","driver already recive item", UVM_LOW)
`uvm_info("dri_b",$sformatf("item in sequence:%s",req.get_parent_sequence().get_name()), UVM_LOW)
`uvm_info("data",$sformatf("%d",req.data_b), UVM_LOW)
$display("=================================================\n");
seq_item_port.item_done();
end
endtask
endclass
//B-agent
class agent_b extends uvm_agent;
dri_b driver;
seqr_b sequencer;
`uvm_component_utils(agent_b)
function new(string name = "agent_b", uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
driver = dri_b::type_id::create("driver", this);
sequencer = seqr_b::type_id::create("sequencer", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
driver.seq_item_port.connect(sequencer.seq_item_export);
endfunction
endclass
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//-----------------------------------------------------------------------------
//=============================================================================
//*****************************************************************************
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//-------------------------------vseqr,vseq,env,test---------------------------
class v_seqr extends uvm_sequencer;
seqr_a sequencer_a;
seqr_b sequencer_b;
`uvm_component_utils(v_seqr)
function new(string name="v_seqr" ,uvm_component parent = null);
super.new(name,parent);
endfunction
endclass
class v_seq extends uvm_sequence;
`uvm_object_utils(v_seq)
`uvm_declare_p_sequencer(v_seqr)
//这个宏的作用:声明p_sequencer指针
//并完成m_sequencer到p_sequencer的类型转化
//(记住p_sequencer是指向virtual_sequencer的就行)
function new(string name="v_seq");
super.new(name);
endfunction
task body();
seq_a sequence_a;
seq_b sequence_b;
fork
`uvm_do_on_with(sequence_a,p_sequencer.sequencer_a,{database == 10;} )
`uvm_do_on_with(sequence_b,p_sequencer.sequencer_b,{database == 100;})
//由于virtual_sequence里面要发送多个挂载到不同
//sequencer的sequence,所以使用`uvm_do_on宏可以直接指
//明待发送sequence要挂载的sequencer
join
endtask
endclass
class env extends uvm_env;
agent_a ag_a;
agent_b ag_b;
v_seqr vir_seqr;
`uvm_component_utils(env)
function new(string name="env" ,uvm_component parent = null);
super.new(name,parent);
endfunction
function void build_phase(uvm_phase phase);
ag_a = agent_a::type_id::create("ag_a",this);
ag_b = agent_b::type_id::create("ag_b",this);
vir_seqr = v_seqr::type_id::create("vir_seqr",this);
//例化所有的agent,和一个virtual_sequencer
endfunction
function void connect_phase(uvm_phase phase);
//将virtual_sequencer中悬空的句柄,连接到具体对象
vir_seqr.sequencer_a = ag_a.sequencer;
vir_seqr.sequencer_b = ag_b.sequencer;
endfunction
endclass
class test1 extends uvm_test;
env env0;
`uvm_component_utils(test1)
function new(string name = "test1", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env0 = env::type_id::create("env0",this);
`uvm_info("test1",$sformatf("build"), UVM_LOW)
endfunction
task run_phase(uvm_phase phase);
v_seq seq0;
phase.raise_objection(this);
`uvm_info("test1",$sformatf("run"), UVM_LOW)
this.print();
$display("======================================================");
seq0 = new();
seq0.start(env0.vir_seqr);
phase.drop_objection(this);//退出run_phase需要先落手
endtask
endclass
endpackage
输出结果: