UVM基础

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信息层级

typesdescription
UVM_FIFONormal information
UVM_WARNINGWarining
UVM_ERRORError information
UVM_fatalFatal information
filteringUVM_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()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UVM(Universal Verification Methodology)是一种用于验证芯片设计的标准方法学,UVM扩展(UVM Extension)是指在UVM基础上进行拓展,添加额外的功能或特性。 UVM本身提供了一种基于类的验证框架,实现了测试生成、重用性和可扩展性的目标。然而,在实际应用中,我们可能会遇到一些需要额外处理的特殊情况,这就需要通过UVM扩展来满足特定需求。 UVM扩展可以分为两种类型。一种是基于UVM的功能扩展,它通过添加新的类和方法,提供更多的验证功能。例如,我们可以添加额外的协议支持或者验证库,以适应特定芯片设计的验证需求。 另一种是基于UVM的验证方法扩展。这种扩展不涉及新的类或方法,而是对现有的UVM验证方法进行拓展、修改或个性化定制,以适应特殊的验证场景。比如,在UVM中可能缺少对某种特殊设计模式或协议的支持,我们可以通过UVM扩展来添加这些特性。 UVM扩展可以增加验证的灵活性和适用性,帮助我们更好地应对复杂的设计验证环境。它允许工程师根据具体需求定制化验证过程,提高测试覆盖率,减少误报和漏报的情况,从而提高设计验证的效率和质量。 总而言之,UVM扩展是在UVM基础上进一步进行拓展和改进,以满足特定的验证需求。通过添加新的功能或修改现有方法,UVM扩展能够帮助工程师更好地应对复杂的设计验证环境,提高设计验证的效率和质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值