UVM基础
1.UVM概念
(1)是一套完整的UVM库文件;
提供一套完整的UVM库文件:
公共元素(包括类型定义、变量、函数和任务)
核心基类(Core Base Classes)
报告类(Reporting Classes)
工厂类(Factory Classes)
组件类(Component Classes)
寄存器类(Register Layer Classes)
序列类(Sequence Classes)
序列器类(Sequencer Classes)
事务级模型类(TLM Classes)
线程同步类(Synchronization Classes)
宏(Macro)
2.UVM message
(1)uvm信息层级
types | description |
---|---|
UVM_FIFO | Normal information |
UVM_WARNING | Warining |
UVM_ERROR | Error information |
UVM_fatal | Fatal information |
filtering | UVM_NONE,UVM_LOW,UVM_MEDIUM,UVM_HIGH,UVM_FULL,UVM_DEBUG |
为什么只有UVM_INFO会有fliterng?原因:太多的info被放在整个testbench中,如果全部要答应,数量十分巨大,需要filtering掉一些不太重要的info.但是warning、error、fatal信息是十分重要的,特别是error和fatal是十分重要的,通常是环境有问题或者DUT有bug征兆。
`define uvm_info(ID,MSG,VRBOSITY)
`define uvm_warning(ID,MSG)
`define uvm_error(ID,MSG)
`define uvm_fatal(ID,MSG)
typedef enum{
UVM_NONE =0,
UVM_LOW = 100,
UVM_MEDIUM = 200,
UVM_HIGH = 300,
UVM_FULL = 400,
UVM_DBUG = 500
}uvm_verbosity
默认的冗余度阈值为UVM_MEDIUM,所有小于等于阈值的消息都会显示,否则不会显示。uvm_warning,uvm_error,uvm_fatal的冗余度为UVM_NONE.fatal结束仿真
`uvm_info(get_full_name(),$sformatf("post_send_tr =%s”,req.sprtint()),UVM_MEDIUM);
`uvm_info("msg","message in driver MEDIUM",UVM_MEDIUM);
`uvm_info(get_full_name(),$sformatf("req_num = %d",req_num));
`uvm_info("msg","message in case HIGH","UVM_HIGH");
`uvm_info("msg","message in case LOW1","LOW");
`uvm_warning("warning","message in case warning");
`uvm_error("warning","message in case error");
`uvm_fatal("warning","message in case fatal");
(2)设置uvm信息阈值
apb_env.mst_agt.set_report_verbosity_level(UVM_LOW);设置drv里消息的阈值为low
apb_env.mst_agt.set_report_verbosity_level_hier(UVM_HIGH);递归设置agt及其下所有component的冗余度阈值为high
apb_env.mst_agt.set_report_id_verbosity("MSG",UVM_HIGH);设置agt消息ID=MSG的消息阈值为high
apb_env.mst_agt.set_report_id_verbosity_hier("MSG",UVM_HIGH);递归设置agt及其下所有component消息ID的冗余度阈值为high
<sim command>+UVM_VERBOSITY = UVM_HIGH //命令行设置冗余度,把test及其下所有的component的冗余度设置为high
<sim command>+UVM_VERBOSITY = HIGH
(3)重载打印信息的严重性
apb_env.mst_agt.drv_set_report_severity_override(UVM_WARNING,UVM_ERROR);//设置drv中所有的warning显示为error
apb_env.mst_agt.drv_set_report_severity_id_override(UVM_WARNING,"MSG",UVM_ERROR);
<sim command>+uvm_set_severity = <comp,<id>,<current severity>,<new severity>
<sim command>+uvm_set_severity = "uvm_test_top.apb_env.mst_agt.drv,MSG,UVM_WARNING,UVM_ERROR"
<sim command>+uvm_set_severity = "uvm_test_top.apb_env.mst_agt.drv,_ALL_,UVM_WARNING,UVM_ERROR"//设置所有ID
(4)打印输出到文件
class base_test extends uvm_test;
apb-environmentapb_env;
UVM_FILE default_file;
UVM_FILE warning_file;
UVM_FILE id1_file;
UVM_FILE warning_id1_file;
virtual function void start_of-simulation_phase(uvm_phase phase);
default_file = $fopen("default_file","w");
warning_file = $fopen("warning_file","w");
id1_file = $fopen("id1_file","w");
warning_id1_file = $fopen("warning_id1_file","w");
apb_env.mst_agt.mon.set_report_severity_action(UVM_FIFO,UVM_DISPLAY|UVM_LOG);
apb_env.mst_agt.mon.set_report_severity_action(UVM_WARNING,UVM_DISPLAY|UVM_LOG);
apb_env.mst_agt.mon.set_report_severity_action(UVM_ERROR,UVM_DISPLAY|UVM_COUNT|UVM_LOG);
apb_env.mst_agt.mon.set_report_severity_action(UVM_FATAL,UVM_DISPLAY|UVM_LOG);
apb_env.mst_agt.mon.set_report_default_file(default_file);
endfunction
virtual function void final_phase(uvm_phase phase);
$fclose(default_file);
$fclose(warning_file);
$fclose(id1_file);
$fclose(warning_id1_file);
endfunction
apb_env.mst_agt.mon.set_report_default_file(default_file);
apb_env.mst_agt.mon.set_report_severity_file(UVM_WARNING,warning_file);
apb_env.mst_agt.mon.set_report_id_file("id1",id1_file);
apb_env.mst_agt.mon.set_report_severity_id_file(UVM_WARNING,"id1",warning_id1_file);
3.UVM组件
3.1 factory
UVM工厂是允许用户通过任何继承的子类的对象来代替现有的类对象,以提高测试平台的灵活性和可扩展性的机制。
一般来说运用factory的步骤可分为:
.将类注册到工厂
.在例化前设置覆盖对象和类型
. 创建对象
(1)注册
class my_transaction extends uvm_sequence_item;
`uvm_object_utils_begin(my_transaction)
`uvm_field_int(dmac,UVM_ALL_ON)
`uvm_field_int(smac,UVM_ALL_ON)
`uvm_field_int(ether_type,UVM_ALL_ON)
`uvm_field_array_int(pload,UVM_ALL_ON)
`uvm_field_int(crc,UVM_ALL_ON)
`uvm_object_utils_end
endclass
class my_transaction extends uvm_sequence_item;
`uvm_object_utils(my_transaction)
endclass
1.Object
`uvm_object_utils()
//把一个直接或间接派生自uvm_object的class注册到factory
`uvm_object_param_utils
把一个直接或间接派生自uvm_object的参数的class注册到factory.
2.Componnet
`uvm_component_utils()
`uvm_component_param_utils()
(2)创建
1.创建uvm_component对象
comp_type::type_id::create(string name,uvm_component parent);
2.创建uvm_object对象
object_type::type_id::create(string name);
3.每一个对象在例化的时候都应该有一个名字
4.在每个层次中例化的组件名称,应该独一无二
class my_env extends uvm_env;
my_agent i_agt;
my_scoreboard scb;
function new(string name="my_env",uvm_component parent);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
i_agt = my_agent::type_id::create("i_agt",this);
i_agt.is_active = UVM_ACTIVE;
scb = my_scoreboard::type_id::create("scb",this);
endfucntion
(3)覆盖
function void set_type_override_by_type(uvm_object_wrapper orifinal_type,uvm_object_wrapper override_type,bit replace=1)
function void set_type_override_by_name(uvm_object_wrapper orifinal_name,uvm_object_wrapper override_name,bit replace=1)
function void set_inst_override_by_type(uvm_object_wrapper orifinal_type,uvm_object_wrapper override_type,string full_inst_path)
function void set_inst_override_by_name(uvm_object_wrapper orifinal_name,uvm_object_wrapper override_name,string full_inst_path)
//类型覆盖:UVM所有层次结构下的原有类型都被新类型所覆盖
//实例覆盖:在某些位置中的原有类型会被新类型所覆盖掉
uvm_object_wrapper:注册后某一个类在工厂中注册时的句柄
replace:在有多个覆盖时,如果已经有覆盖存在:1.新的覆盖会替代旧的覆盖0,该覆盖不会发生
static function void set_type_override_by_type(uvm_object_wrapper orifinal_type,uvm_object_wrapper override_type,bit replace=1)
function void set_inst_override_by_type(string relative_inst_path uvm_object_rapper original_type,uvm_object_wrapper override_type)
static function void set_type_override(string original_type_name,string override_type_name,bit_replace=1)
function void set_inst_override(string relative_inst_path ,string original_type_name,string override_type_name)
+uvm_set_inst_override =<req_type>,<override_type>,<full_inst_path>
+uvm_set_type_override =<req_type>,<override_type>,[<replace>]
3.2 sequencer
(1)使用sequencer
1.class gpio_sequencer extends uvm_sequencer #(gpio_transfer);
//定义gpio_sequencer扩展自uvm_sequencer,且指定其事务类型为gpio_transfer
2.`uvm_component_utils(gpio_sequencer)
//注册到工厂
3.function new(string name,uvm_component parent);
4.super.new(name,parent);
5.endfunction:new
endclass:gpio_sequencer
typedef uvm_sequencer #(gpio_transfer)gpio_sequencer;
(2)virtual sequencer
virtual sequencer 控制其他的sequencer
virtual sequencer并不和任何driver相连
virtual sequencer本身并不处理item
3.3 driver
class uvm_driver #(type REQ = uvm_sequence_item,type RSP=REQ)
virtual task get_next_item(output REQ reg_arg);//blocking
virtual task try_next_item(output REQ reg_arg) //non blocking
virtual function void item_done(RSP rsp_arg = null) //non blocking
class gpio_driver extends uvm_driver #(gpio_transfer);
//派生自uvm_driver,参数gpio_transfer
virtual gpio_if gpio_if;
`uvm_component_utils(gpio_driver)
fucntion new(string name,uvm_component parent);
super.connect_phase(phase);
if(!uvm_config_db#(virtual gpio_if)::get(this,"gpio_if",gpio_if))
`uvm_error("NOVIF",{"virtual interface must be set for:",get_full_name(),".gpio_if"})
endfunction:connect_phase
virtual task run_phase(uvm phase phase);
get_and_drive();
endtask:run_phase
virtual protected task get_and_drive();
gpio_transfer this_trans;
@(posedge gpio_if.n_p_reset);
forever begin
@(posedge gpio_if.pclk);
seq_item_port.get_next_item(req);
if(!$cast(this_trans,req))
`uvm_fatal("CASTFL","Failed to cast req to this_trans in get_and_drive")
drive_data(this_trans);
seq_item_port.item_done();
end
endtask:get_and_drive
endclass:gpio_driver
3.4 monitor
uvm_monitor在uvm_component的基础上没有增加任何东西
virtual class uvm_monitor extends uvm_component;
function new(string name,uvm_component parent);
endfunction
const static string type_name = "uvm_monitor";
virtual function string get_type_name();
return type_name;
endfunction
endclass
class my_monitor extends uvm_monitor;
`uvm_component_utils(my_monitor)
virtual dut_if vif;
bit enable_check = 1;
uvm_analysis_port#(my_data) mon_analysis_port;
function new(string name,uvm_component parent=null);
super.new(name,parent);
endfunction
endclass
3.5 scoreboard
.uvm_scoreboard在uvm-component的基础上没有任何增加的东西
.scoreboard比较DUT输出是否与reference model期望的一致
class gpio_scoreboard exends uvm_scoreboard;
gpio_transfer expect_queue[$];
uvm_blocking_get_port #(gpio_transfer) exp_port;
uvm_blocking_get_port #(gpio_transfer) act_port;
`uvm_component_utils(gpio_scoreboard)
function new(string name ="",uvm_component parent =null);
super.new(name,parent);
endfunction:new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
exp_port = new("exp_port",this);
act_port = new("act_port",this);
endfunction
virtual task main_phase(uvm_phase phase);
gpio_transfer get_expect,get_actual,tmp_tran;
bit result;
super.nain_phase(phase);
while(1)begin
exp_port.get(get_expect);
expect_queue.push_back(get_expect);
end
while(1)begin
act_pot.get(get_actual)
end
endtask:main_phase
endclass:gpio_scoreboard
class my_env extends uvm_env;
my_agent i_agt;
my_agent o_agt;
my_model mdl;
my_scoreboard scb;
uvm_tlm_analysis_fifo #(my_transaction) agt_scb_fifo;
uvm_tlm_analysis_fifo #(my_transaction) agt_mdl_fifo;
uvm_tlm_analysis_fifo #(my_transaction) mdl_scb_fifo;
function void build_phase(uvm_phase phase);
i_agt= my_agent::type_id::create("i_agt",this);
o_agt= my_agent::type_id::create("o_agt",this);
mdl= my_model::type_id::create("mdl",this);
scb= my_scoreboard::type_id::create("scb",this);
agt_scb_fifo = new("agt_scb_fifo",this);
agt_mdl_fifo = new("agt_mdl_fifo",this);
mdl_scb_fifo = new("mdl_scb_fifo",this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
i_agt.ap.connect(agt_mdl_fifo.analysis_export);
mdl.port.connect(agt_mdl_fifo.blocking_get_export);
i_agt.ap.connect(mdl_scb_fifo.analysis_export);
scb.ex_pport.connect(mdl_scb_fifo.blocking_get_export);
o_agt.ap.connect(agt_scb_fifo.analysis_export);
scb.act_port.connect(agt_scb_fifo.blocking_get_export);
endfunction
endclass
(2)scoreboard_imp
`uvm_analysis_imp_decl(_iagt)
`uvm_analysis_imp_decl(_oagt)
class my_scoreboard extends uvm-scoreboard;
`uvm_component_utils(my_scoreboard)
function new(string name ="my_scoreboard",uvn_component parnent);
super.new(name,parent);
endfunction
uvm_analysis_imp_iagt#(apb_pkt,my_scoreboard)exp_port;
uvm_analysis_imp_oagt#(apb_pkt,my_scoreboard)act_port;
fucntion void build_phase(uvm_phase phase);
exp_port = new("exp_port",this);
act_port = new("act_port",this);
endfunction
virtual function void write_iagt(apb_trans data);
`uvm_info("write",$sformatf("Data received = 0x%oh",data),UVM_MEDIUM)
endfunction
virtual function void write_oagt(apb_trans data);
endfunction
endclass
//在scoreboard中定义imp被动接收事务
class my_env extends uvm_env;
my_agent i_agt;
my_agent o_agt;
my_scoreboard scb;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
scb=my_scoreboard::type_id::create("scb",this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
i_agt.analysis_port.connect(scb.exp_port);
o_agt.analysis_port.connect(scb.act_port);
endfunction
`uvm_component_utils(my_env)
endclass
//将scb的imp与i_agt的port连接到一起
3.6 uvm_agent
//派生自uvm_agent
class gpio_agent extends uvm_agent;
gpio_driver driver;
gpio_sequencer sequencer;
gpio_monitor monitor;
`uvm_component_utils(gpio_agent)
function new(string name,uvm_component parent);
super.new(name,parent);
endfunction:new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
monitor=gpio_monitor::type_id::create("monitor",this);
sequencer = gpio_sequencer::type_id::create("sequencer",this);
driver=gpio_driver::type_id::create("driver",this);
end
endfunction:build_phase
function void connect_phase(uvm_phase phase)
driver.seq_item_port.connect(sequencer.seq_item_export);
enfunction:connect_phase
endclass:gpio_agent
3.7 env
class my_env extends uvm_env;
my_agent i_agt;
my_agent o_agt;
my_agent mdl;
my_scoreboard scb;
reg_model rm;
my_adapter reg_sqr_adapter
my_vsqr v_sqr;
uvm_tlm_analysis_fifo #(my_transaction) agt_scb_fifo;
uvm_tlm_analysis_fifo #(my_transaction) agt_mdl_fifo;
uvm_tlm_analysis_fifo #(my_transaction) mdl_scb_fifo;
function new(string name="my_env",uvm_component parent);
super.new(name,parent);
endfunction
extern virtual function void build_phase(uvm_phase phase);
extern virtual function void connect_phase(uvm_phase phase);
function void my_env::build_phase(uvm_phase);
super.build_phase(phase);
i_agt = my_agent::type_id::create("i_agt",this);
o_agt = my_agent::type_id::create("o_agt",this);
i_agt.is_active = UVM_ACTIVE;
o_agt.is_active = UVM_PASSIVE;
mdl = my_model::type_id::create("mdl",this);
scb=my_scoreboard::type_id::create("scb",this);
agt_scb_fifo = new("agt_scb_fifo",this);
agt_mdl_fifo = new("agt_mdl_fifo",this);
mdl_scb_fifo = new("mdl_scb_fifo",this);
v_sqr=my_vsqr::type_id::create("v_sqr",this);
rm=req_model::type_id::create("rm",this);
rm.configure(null,"");
rm.build();
rm.lock_model();
rm.reset()
reg_sqr_adapter = new("reg_sqr_adapter");
endfunction
function void my_env::connect_phase(uvm_phase phase);
super.connect_phase(phase);
v_sqr.p_my_sqr = i_agt.sqr;
v_sqr.p_rm =this.rm;
mdl.p_rm = this.rm;
rm.default_map.set_sequencer(env.bus_agt.sqr,reg_sqr_adapter);
rm.default_map.set_auto_predict(1);
i_agt.ap.connect(agt_mdl_fifo.analysis_export);
mdl.port.connect(agt_mdl_fifo.blocking_get_export);
mdl.ap.connect(mdl_scb_fifo.analysis_export);
scb.exp_port.connect(mdl_scb_fifo.blocking_get_export);
o_agt.ap.connect(agt_scb_fifo.analysis_export);
scb.act_port.connect(agt_scb_fifo.blocking_get_export);
endfunction
3.8 uvm_test
uvm_test派生自uvm_component类,没有增加新的功能
uvm_test决定验证环境的结构和连接,也决定者使用哪一个测试序列
+UVM_TESTNAME=<testcase_string>选择test case
uvm_root::run_test(<testcase_string>)选择test case
class base_test extends uvm_test;
uart_environment uart_env;
apb_environment apb_env;
my_vsqr v_sqr;
reg_model rm;
my_adapter reg_sqr_adapter;
my_scoreboard scb;
fucntion new(string name="base_test",uvm_component parent =null);
super.new(name,parent);
endfunction
exterrn virtual function void build_phase(uvm_phase phase);
exterrn virtual function void connect_phase(uvm_phase phase);
exterrn virtual function void report_phase(uvm_phase phase);
function void base_test::build_phase(uvm_phase phase);
super.build_phase(phase);
uart_env=uart_environment::type_id::create("uart_env",this);
apb_env=apb_environment::type_id::create("apb_env",this);
v_sqr=my_vsqr::type_id::create("v_sqr",this);
endfunction
function void base_test::connect_phase(uvm_phase phase);
super.connect_phase(phase);
v_sqr.p_uart_sqr = uart_env.agt.sqr;
v_sqr.p_apb_slv_sqr = apb_env.slave_agt.sqr;
endfunction
base_test类:扩展自uvm_test,例化和配置整个环境
my_case0类:扩展自base_test,特殊场景配置,如指定要运行的sequence,覆盖率、检查等参数
class my_case0 extends base_test;
function new(string name="my_case0",uvm_coomponent parent =null);
super.new(name,parent);
endfunciton
extern virtual function void build_phase(uvm_phase phase);
`uvm_component_utils(my_case0)
endclass
function void my_case0::build_phase(uvm_phas phase);
super.build_phase(phase);
uvm_config_db#(uvm_object_wrapper)::set(this,"v_sqr.main_phase","default_sequence",case0_vseq::type_id::get())
endfunction
3.9 run_test
model top_tb;
initial begin
run_test();
end
endmodule
<sim_cmd>…+UVM_TEST_NAME=my_case0
4 phase与object
4.1 phase 概述
4.2 objction
希望代码在一个地方停下来
5 transaction
5.1 uvm-sequence_item
uvm_transaction类:是uvm中事务的基本类,继承uvm_object的所有方法外,增加了timing和recording的接口
uvm_sequence_item用户定义的事务的基类,同时也是uvm_sequence的基类,提供了使用强大sequence机制的基本功能
class my_transaction extends uvm_sequence_item;
rand bit[47:0] dmac;
rand bit[47:0] smac;
rand bit[15:0] ether_type;
rand byte pload[];
rand bit[31:0] crc;
rand bit crc_err;
`uvm_object_utils_begin(my_transaction)
`uvm_field_int(dmac,UVM_ALL_ON)
`uvm_field_int(smac,UVM_ALL_ON)
`uvm_field_int(ether_type,UVM_ALL_ON)
`uvm_field_array_int(pload,UVM_ALL_ON)
`uvm_field_int(crc,UVM_ALL_ON+UVM_NOCOMPARE)
`uvm_field_int(crc_err,UVM_ALL_ON|UAM_NOPACK)
`uvm_object_utils_end
constraint pload_cons{
pload.size>=46;
pload.size<=1500;
}
constraint crc_err_cons{
soft crr_err == 0;
}
function new(string name="my_transaction");
super.new();
endfunction
function bit[31:0] calc_crc();
endfunction
function void post_randomize();
if(crc_err)
else
crc=calc_crc;
endfunction
6. uvm_sequence
class apb_sequence wxtends uvm_sequence#(apb_trans);
`uvm_object_utils(apb_sequence)
function new(string name = "apb_sequence");
super.new(name);
endfunction
virtual task prebody();
if(get_parent_sequence()==null&&starting_phase!=null)
starting_phase.raise_objection(this);
endtask
virtual task prebody();
if(get_parent_sequence()==null&&starting_phase!=null)
starting_phase.drop_objection(this);
endtask
virtual task body();
repeat(10)begin
`uvm_do_with(req,{req.dir==WR;req.addr ==8'haa;req.data==8'h55});
end
endtask
endclass
6.2启动sequence
//使用start任务启动sequence
class case_0 extends base_test;
`uvm_component_utils(case_0)
function new(string name="case_0",uvm_component parent = null);
super.new(name,parent);
endfunction
task main_phase(uvm_phase phase);
apb_sequence seq;
super.main_phase(phase);
seq=apb_sequence::type_id::create("seq");
seq.starting_phase = phase;
seq.start(apb_env.mst_agt.sqr);
`uvm_info(get_full_name(),$formatf("end_case"),UVM_INFO);
endtask
endclass
//使用default_sequence方式启动,会自动设置seq.starting_phase
class case_1 extends base_test;
`uvm_component_utils(case_1)
function new(string name="case_1",uvm_component parent = null);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(uvm_object_wrapper)::set(this,"apb_env.mst_agt.sqr.main_phase","default_sequence",apb_sequence::type_d:;get());
endclass
6.3 m_sequence
//定义在uvm_sequence_item中的类型为uvm_sequencer_base的指针,最终
//会调用set_sequencer将m_sequencer指向真正的sequencer
class uvm_sequence_item extends uvm_transaction;
local int m_sequenc_id=-1;
protected bit m_use_sequence_info;
protected uvm_sequencer_base m_sequencer;
protected uvm_sequence_base m_parent_sequence;
static bit issued1,issued2;
bit print_sequence_info;
virtual function void set_sequencer(uvm_sequencer_base sequencer);
m_sequencer=sequencer;
m_set_p_sequencer();
endfunction
fucntion uvm_sequencer_base get_sequencer();
return m_sequencer();
endfunction
6.3 p_sequencer
//方法是可以通过sequencer,但是sequence里的sqr成员是类型为uvm_sequencer_base的m_sequencer。
//而通常我们真正用的是自定义sequencer,比如apb sequencer,跟m_sequencer类型不同,所以不能通过m_sequencer访问真正的sqr,需要做一个类型装换$cast();
//这样是不是很麻烦,uvm用一个宏帮我们处理了这一切
`uvm_declare_p_sequencer(SEQUENCER)
task body()
apb_sequencer my_sequencer;
$cast(my_sequencer,m_sequencer);
repeat(10)begin
`uvm_do_with(apb_trans,{apb_trans.m_addr == my_sequencer.addr;apb_trans.m_pwdata ==my_sequencer.wdata;})
endtask
class apb_sequence extends uvm_sequence#(apb_trans);
`uvm_object_utils(apb_sequence)
`uvm_declare_p_sequencer(apb_sequencer)
endclass
class apb_wr_seq extends apb_sequence;
`uvm_object_utils(apb_wr_seq)
function new(string name = "apb_wr_seq");
super.new(name);
endfunction:new
virtual task body();
super.body;
`uvm_info(get_full_name(),$psprintf("Enter body"),UVM_LOW)
m_seq = apb_base_seq::type_id::create("m_seq");
m_seq.randomize() with{m_paddr==32'h1;m_pwrite==1;m_pstrb==4'hf;m_pwdata[0]==1'h1;};
m_seq.strat(p_sequencer);
`uvm_info(get_type_name(),$psprintf("Quit body ..."),UVM_LOW)
endtask:body
endclass:apb_wr_seq
6.4
class apb_seq_1 extends uvm_sequence#(apb_trans);
rand bit[31:0] req_num;
constraint req_num_c {req_num == 1;}
`uvm_sequence_utils_begin(apb_seq_1),apb_sequencer)
`uvm_field_int(req_num,UVM_ALL_ON)
`uvm_sequence_utils_end
class apb_seq_2 extends uvm_sequence#(apb_trans);
`uvm_sequence_utils(apb_seq_2,apb_sequencer)
function new(string name="apb_seq_2");
super.new(name);
endfunction
virtual task body();
req=new();
`uvm_info("seq","seq_2",UVM_INFO);
start_item(req);
req.addr='h222;
finish_item(req);
#10us;
p_sequencer.get_parent().print();
endtask
class apb_sequence extends uvm_sequence#(apb_trans);
apb_seq_1 seq1;
apb_seq_2 seq2;
`uvm_sequence_utils(apb_sequence,apb_sequencer)
function new(string name="apb_sequence")
super.new(name);
endfunction
virtual task body();
seq1=new();
seq2=new();
req=new();
seq1.randomze();
fork
begin
seq.start(p_sequencer);
end
begin
seq.start(p_sequencer);
end
begin
start_item(req);
req.addr='h333;
finsh_item(req);
end
join
endtask
6.5 virtual sequence
class my_virtual_seq extends uvm_sequence;
`uvm_object_utils(my_virtual_seq)
`uvm_declare_p_sequencer(my_virtual_sequencer)
function new(string name ="my_virtual_seq")
super.new(name);
endfunction
apb_rd_wr_seq m_apb_rd_wr_seq;
wb_reset_seq m_apb_wb_reset_seq;
pcie_gen_seq m_pcie_gen_seq;
task pre_body();
m_apb_rd_wr_seq = apb_rd_wr_seq::type_id::create("m_apb-rd_wr_seq");
m_wb_reset_seq = wb_reset_seq::type_id::create("m_wb_reset_seq");
m_pcie_gen_seq = pcie_gen_seq::type_id::create("m_price_gen_seq");
endtask
task body();
m_apb_rd_wr_seq.start(p_sequencer.m_apb_seqr);
fork
m_wb_reset_seq.start(p_sequencer.m_wb_seqr);
m_prie_gen_seq.start(p_sequencer.m_pcie_seqr);
join
endtask
endclass
6.6最顶层sequence中控制objection
virtual task pre_start();
if(get_parent_sequence()==null&&starting_phase!=null)
starting_phase.raise_objection(this);
endtask
virtual task post_start();
if(get_parent_sequence()==null&&starting_phase!=null)
starting_phase.drop_objection(this);
endtask
endtask
//在sequence中定义的rand类型变量给其中的transaction传递约束时,变量的名字一定域transaction中相应域的名字相同。
class sub_sequence extends uvm_sequence #(apb_trans);
rand bit[31:0] addr_s;
virtual task body();
apb_trans tr;
for(int i=0;i<5;i++)begin
`uvm_do_with(tr,{tr.addr==addr_s;tr.data==i;})
end
class vir_sequence extends uvm_sequence;
virtual task body();
sub_sequence sub_seq;
`uvm_do_on_with(sub_seq,p_sequencer.apb_mst_sqr,{sub_seq.addr_s=='h000000;})
endtask
7.uvm_do
//1.创建一个实例
//2.把实例进行随机化
//3.随机化后的实例发送给sequencer
`uvm_create(item)
sequencer.wait_for_grant(prior)
this.pre_do(1)
item.randomize()
this.mid_do(item)
sequencer.send_requenst(item)
sequencer.wait_for_item_done()
this.post_do(item)
`uvm_create(sub_seq)
sub_seq.randomize()
sub_seq.pre_start()
this.pre_do(0)
this.mid_do(sub_seq)
sub_seq.body()
this.post_do(sub_seq)
sub_seq.post_start()