欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2021-03-23 UVM简单平台的构成与搭建

程序员文章站 2022-07-04 20:05:18
...

创建一个简单UVM平台:

UVM平台的主要组件:

结构组件

  • uvm_component
    1. uvm_test;
    2. uvm_env;
    3. uvm_scoreboard;
    4. uvm_agent;
    5. uvm_sequence;
    6. uvm_monitor;
    7. uvm_driver

组件之间的通信

    1. uvm_*_port;
    2. uvm_*_inmport;
    3. uvm_*_export;
    4. uvm_*_fifo_*;
    5. uvm_*_socket;

事务

    1. uvm_sequence_item;
    2. uvm_sequence;

1. 创建transaction

//从uvm_sequence_item库中创建自定义my_transaction类
class my_transaction extends uvm_sequence_item;
//为激励成员指定rand属性,随机化
	rand bit [3:0] sa;
	rand bit [3:0] da;
	rand reg [7:0] payload[$];
//将自定义事务类在uvm中注册
	`uvm_object_utils_begin(transaction)
		`uvm_field_int(sa,UVM_ALL_ON);
		...
	`uvm_object_utils_end
//约束项,控制随机成员的随机范围
	constraint Limit{
		sa inside {[0:15]};
		da inside {[0:15]};
		payload.size() inside {[2:4]};
		}
//构造函数new
	function new (string name = "my_transaction");
		super.new(name);
	endfunction
endclass

2. 创建sequence

  • 产生事务对象,并控制
  • 一般一种sequence 产生一种类型事务,产生多种类型事务很少见;
//使用参数化类扩展uvm_sequence库产生自定义my_sequence类
class my_sequence extends uvm_sequnence #(my_transaction);
//将自定义my_seuence类在uvm库中注册
	`uvm_object_utils(my_sequence)
//创建构造函数new
	function new(string name = "my_sequence");
	super.new(name);
	endfunction
//最重要的的body()函数,产生和控制事务;
	virtual task body();
//raise标志开始产生事务
		if (starting_phase != null )
			starting_phase.raise_pbjection;
//产生事务10次,req是产生事务对象的指针
		repeat(10)
//uvm库中宏uvm_do,开始产生事务
		`uvm_do(req)
//drop标志事务产生结束
		if (starting_phase != null )
		starting_phase.drop_objection;
	endtask
endclass

3. 创建sequencer

  • sequence和sequence_item并不属于结构的一部分他们是组件中流动的数据流;
  • sequencer的作用:
    • 启动sequence;
    • 将sequence产生的事务对象item发送到uvm的组件中(也就是driver);
//使用typedef在uvm_sequencer下定义需要传递my_transaction的my_sequencer;
typedef uvm_sequencer #(my_transaction) my_sequencer;

4. 创建driver

  • 从sequencer中获取transaction;
  • 将transaction分解为DUT可以接受的pin级信号;
  • 将转化后的pin级信号按照DUT总线协议的方式驱动给DUT;
    所有的平台组件都使用`uvm_component_utils进行注册其他的使用uvm_object_utils注册
//创建自定义my_driver
class my_driver entends uvm_driver #(my_transaction);
//注册
	`uvm_component_utils(my_driver)
//构造new函数,并指定父对象
	function new(string name = "my_sequence",uvm_component parent);
		super.new(name,parent);
	endfunction
//实现driver的功能
	virtual task run_phase(uvm_phase phase);
//driver是不停工作的
		forever begin
//从sequencer获取transaction,req指向my_transaction
			seq_item_port.get_next_item(req);
//执行一个简单的打印操作
			`uvm_info("DRV_RUN_PHASE",req_sprint(),UVM_MEDIUM)
			#100;
//通知sequencer事务处理完毕
			seq_item_port.item_done();
		end
	endtask
endclass

5. 创建monitor

  • 监视接口信号,捕获接口上活动的事务,并且将pin级的信号事务转化为事务级的数据包,之后将这些数据包发送的analysis组件(scoreboard,reference model等)进行分析和产生报告。
  • 通过TLM-port机制与其他组件通信。
//创建自定义my_monitor
class my_monitor entends uvm_monitor;
//注册
	`uvm_component_utils(my_monitor)
//构造new函数,并指定父对象
	function new(string name = "",uvm_component parent);
		super.new(name,parent);
	endfunction
//完成monitor操作
	virtual task run_phase(uvm_phase phase);
//driver是不停工作的
		forever begin
//执行一个简单的打印操作
			`uvm_info("MON_RUN_PHASE","MONITOR RUN!",UVM_MEDIUM)
			#100;
		end
	endtask
endclass

6. 创建agent

  • agent封装了sequenncer、driver、monitor;
  • agent需要实例化封装对象并将其连接起来;
  • agent有passive(只包含monitor,而没有driver 和 sequencer,没有驱动DUT的能力)和active;
//创建自定义master_agent
class master_agent entends uvm_agent;
//注册
	`uvm_component_utils(master_agent)
//例化封装对象,产生句柄
	my_sequencer	m_seqr;
	my_driver		m_driv;
	my_monitor		m_moni	
//构造new函数,并指定父对象
	function new(string name = "",uvm_component parent);
		super.new(name,parent);
	endfunction
//完成monitor操作
	virtual function void run_phase(uvm_phase phase);
//进入buildphase
		super.build_phase(phase);
//当为active模式才创建sequencer和driver的对象,is_active默认为UVM_ACTIVE
		if(is_active == UVM_ACTIVE) begin
//使用uvm的工厂机制创建对象,类型名::类型名的静态成员::类型名静态成员的静态函数
			my_seqr = my_sequencer::type_id::create("m_seqr",this);
			my_driv = my_driver :: type_id::create("m_driv",this);
		end
//不管是不是active模式,monitor的对象都应该被创建
		m_moni = monitor::type_id::create("m_moni",this);
//重载connect_phase
		virtual function void connect_phase(uvm_phase phase);
			if(is_active == UVM_ACTIVE) 
//使用TLM机制,连接sequencer与driver
				m_driv.seq_item_port.connect.(m_seqr.seq_item_export);
		endfunction
	endtask

7. 创建environment

  • environment封装、例化agent、reference module、scoreboard,并将其连接;
  • 监视接口信号,捕获接口上活动的事务,并且将pin级的信号事务转化为事务级的数据包,之后将这些数据包发送的analysis组件(scoreboard,reference model等)进行分析和产生报告。
  • 通过TLM-port机制与其他组件通信。
//创建自定义my_env
class my_env entends uvm_environment;
//注册
	`uvm_component_utils(my_env)
//实例化master_agent
	master_agent my_agent;
//构造new函数,并指定父对象
	function new(string name = "",uvm_component parent);
		super.new(name,parent);
	endfunction
//重载build_phase
	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
//使用工厂机制创建agent对象
		m_agent = master_agent::type_id::create("m_agent",this);
	endfunction
endclass
//只例化了agent,monitor,reference module没有被例化

8. 创建testcase

  • 实例化和配置env;
  • 需要指定要启动的sequence;
//创建自定义my_test
class my_test entends uvm_test;
//注册
	`uvm_component_utils(my_test)
//实例化my_test
	my_test m_test;
//构造new函数,并指定父对象
	function new(string name = "",uvm_component parent);
		super.new(name,parent);
	endfunction
//重载build_phase
	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
//使用工厂机制创建env对象
		m_env = my_env::type_id::create("m_env",this);
//为sequencer指定一个需要启动的sequence,
		uvm_config_db#(uvm_object_wrapper)::set(this, "*.m_seqr.run_phase","default_sequence",my_sequence::get_type());
	endfunction
//打印测试平台的组件的层次结构topology
	virtual function void start_of_simulation_phase(uvm_phase phase);
		super.start_of_simulation_phase(phase);
//树形结构
		uvm_top.print_topology(uvm_default_tree_printer);
//表格结构
		//uvm_top.print_topology(uvm_default_table_printer);
	endfunction
endclass

8. 测试平台的启动

program automatic test;
	import uvm_pkt.sv::*;
	`include "uvm_macros.svh"
	//包含以上所有创建文件
	`include "..."
	initial begin
	run_test();
	end
endmodule
相关标签: #B站来源的学习