package pack1; //pack1头
import uvm_pkg::*; //+UVM
`include "uvm_macros.svh"//+工厂
class item extends uvm_sequence_item;
rand int data_auto;
rand int data_noauto;
//声明两个data,一个加入自动化域,一个
//不加入
`uvm_object_utils_begin(item)
`uvm_field_int(data_auto,UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "item");
super.new(name);
endfunction
endclass
class seq extends uvm_sequence;
`uvm_object_utils(seq)
function new(string name = "seq");
super.new(name);
endfunction
task body();
uvm_sequence_item temp;
item req,rsp;
temp = create_item(item::get_type(),m_sequencer,"req");
//create_item:能够实例化一个继承于uvm_sequence_item类的类
//返回值:uvm_sequence_item句柄
//参数1:指明要例化的继承于uvm_sequence_item类的类
//参数2:指明这个对象即将挂载到哪个sequencer上
// (m_sequencer是uvm_sequence类的一个属
// 性,当m_sequencer被挂载到某个
// sequencer上时,m_sequencer会自动指向
// 这个sequencer)
//参数3:这个对象的名字
void'($cast(req,temp));
//在上一句话中由于使用create_item方法,导致
//父类句柄指向子类对象
//(uvm_sequence_item句柄) --> (item对象)
//做个转化使子类对象重新被子类句柄指向
start_item(req);
void'(req.randomize with{data_auto == 50;
data_noauto == 50;});
`uvm_info("sequence","sequence request to send item", UVM_LOW)
`uvm_info("data_auto",$sformatf("%d",req.data_auto), UVM_LOW)
`uvm_info("data_noauto",$sformatf("%d",req.data_noauto), UVM_LOW)
req.print();
finish_item(req);
//
//seq发起start告知seqr,我要向driver发送item
//(start会立即返回,然后执行下面的语句)
//seqr判断此时的driver是否已经get_next_item,
//若否,则继续等待。若是,那么driver收到完item
//后会执行item_done,收到item_done后,
//finish_item的阻塞结束
//
get_response(temp); //get_response返回的uvm_sequence_item是句柄,
//需要做个中间转化
void'($cast(rsp,temp));
`uvm_info("sequence","sequence already recive item", UVM_LOW)
`uvm_info("data_auto",$sformatf("%d",rsp.data_auto), UVM_LOW)
`uvm_info("data_noauto",$sformatf("%d",rsp.data_noauto), UVM_LOW)
req.print();
endtask
endclass
class seqr extends uvm_sequencer;
`uvm_component_utils(seqr)
function new(string name = "seqr", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass
class dri extends uvm_driver;
`uvm_component_utils(dri)
function new(string name = "dri", uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
uvm_sequence_item temp ;
uvm_object temp1;
item req,rsp;
phase.raise_objection(this);//进入run_phase需要先举手
seq_item_port.get_next_item(temp);
void'($cast(req,temp));
`uvm_info("driver","driver already recive item", UVM_LOW)
`uvm_info("data_auto",$sformatf("%d",req.data_auto), UVM_LOW)
`uvm_info("data_noauto",$sformatf("%d",req.data_noauto), UVM_LOW)
req.print();
//driver使用自带的TLM端口,向seqr的TLM端口使用get_next_item
//来获取一个对象,(get_next_item返回的是uvm_sequence_item
//句柄需要类型转换)
#1us;
//---------------------------------------------
//--此处省略driver解析item并向interface进行驱动
//---------------------------------------------
temp1 = req.clone();
void'($cast(rsp,temp1));
`uvm_info("clone:data_auto",$sformatf("%d",rsp.data_auto), UVM_LOW)
`uvm_info("clone:data_noauto",$sformatf("%d",rsp.data_noauto), UVM_LOW)
//克隆一个上一步接收到的对象
//(clone返回的居然是uvm_object的句柄,需要类型转换)
//!!clone只会克隆已经加入自动化域的属性的值,
//data_noauto不在自动化域内,在克隆时候,类声明时候的
//默认值0,而不是req的对象值50
//同样‘req’的sequence_id也不会被克隆,克隆时候得到的也
//是类中的声明初始值
rsp.set_sequence_id(req.get_sequence_id());
rsp.data_auto = rsp.data_auto + 100;
rsp.data_noauto = rsp.data_noauto + 100;
seq_item_port.item_done(rsp);
//get_sequence_id用于获取‘req’这个item所在sequence的id好
//然后使用set_sequence_id把id号交给‘rsp’这个item
//这样item_done这个方法就知道要把‘rsp’这个item发送给谁
//了
//细节来说,item_done这个方法的作用有两个
//1是:告知seq的finish_item,你别在那阻塞了,我都消化
// 掉了
//2是:向seqr的rspfifo中传递rsp这个对象
// 这样sequence里的get_response才能得到对象
// 要不然是得不到对象的
`uvm_info("driver","driver already send item", UVM_LOW)
`uvm_info("data_auto",$sformatf("%d",rsp.data_auto), UVM_LOW)
`uvm_info("data_noauto",$sformatf("%d",rsp.data_noauto), UVM_LOW)
phase.drop_objection(this);//退出run_phase需要先落手
endtask
endclass
class env extends uvm_env;
seqr seqr0;
dri dri0;
`uvm_component_utils(env)
function new(string name="env" ,uvm_component parent = null);
super.new(name,parent);
endfunction
//buildphase中例化sequencer 和 driver
function void build_phase(uvm_phase phase);
seqr0 = seqr::type_id::create("seqr0",this);
dri0 = dri::type_id::create("dri0",this);
endfunction
//connect_phase中连接sequencer和driver自带的一组TLM端口
function void connect_phase(uvm_phase phase);
dri0.seq_item_port.connect(seqr0.seq_item_export);
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);
seq seq0;
phase.raise_objection(this);//进入run_phase需要先举手
`uvm_info("test1",$sformatf("run"), UVM_LOW)
seq0 = new();
seq0.start(env0.seqr0);
//将seq0挂载到 env0的seqr0上
//一旦seq被挂载到了seqr上,那么这个seq就知道了他的m_seqencer是谁
//他的body任务也会自动执行
phase.drop_objection(this);//退出run_phase需要先落手
endtask
endclass
endpackage
//--------------------------------------module---------------------------------
module hardware1;
import pack1::*;
import uvm_pkg::*; //+UVM
initial begin
run_test("test1");
end
endmodule