UVM实战 卷I学习笔记9——UVM中的sequence(7)


sequence library

随机选择sequence

所谓sequence library,就是一系列sequence的集合。sequence_library类的原型为:

class uvm_sequence_library #(type REQ=uvm_sequence_item,RSP=REQ) 
extends uvm_sequence #(REQ,RSP);

sequence library派生自uvm_sequence,从本质上是sequence,根据特定算法随机选择注册在其中的一些sequence,并在body中执行这些sequence

一个sequence library的定义如下:

class simple_seq_library extends uvm_sequence_library#(my_transaction);
	function new(string name= "simple_seq_library");
		super.new(name);
		init_sequence_library();
	endfunction
	`uvm_object_utils(simple_seq_library)
	`uvm_sequence_library_utils(simple_seq_library);
endclass

在定义sequence library时要特别注意:

  • 一是从uvm_sequence派生时要指明此sequence library产生的transaction类型
  • 二是在其new函数中要调用init_sequence_library,否则其内部的候选sequence队列就是空的;
  • 三是要调用uvm_sequence_library_utils注册

sequence library在定义之后如果没有任何sequence注册到其中,是没有任何意义的。一个sequence在定义时使用宏`uvm_add_to_seq_lib来将其加入某个sequence library中

class seq0 extends uvm_sequence#(my_transaction);
	…
	`uvm_object_utils(seq0)
	`uvm_add_to_seq_lib(seq0, simple_seq_library)
	virtual task body();
		repeat(10) begin
			`uvm_do(req)
			`uvm_info("seq0", "this is seq0", UVM_MEDIUM)
		end
	endtask
endclass

uvm_add_to_seq_lib有两个参数:此sequence的名字和要加入的sequence library名字一个sequence可以加入多个不同的sequence library中

class seq0 extends uvm_sequence#(my_transaction);
	`uvm_object_utils(seq0)
	`uvm_add_to_seq_lib(seq0, simple_seq_library)
	`uvm_add_to_seq_lib(seq0, hard_seq_library)
	virtual task body();
		repeat(10) begin
			`uvm_do(req)
			`uvm_info("seq0", "this is seq0", UVM_MEDIUM)
		end
	endtask
endclass

同样的,可以有多个sequence加入同一sequence library中

class seq1 extends uvm_sequence#(my_transaction);
	…
	`uvm_object_utils(seq1)
	`uvm_add_to_seq_lib(seq1, simple_seq_library)
	virtual task body();
		repeat(10) begin
			`uvm_do(req)
			`uvm_info("seq1", "this is seq1", UVM_MEDIUM)
		end
	endtask
endclass

当sequence与sequence library定义好后,可以将sequence library作为sequencer的default sequence

function void my_case0::build_phase(uvm_phase phase);
	super.build_phase(phase);
	uvm_config_db#(uvm_object_wrapper)::set(this, "env.i_agt.sqr.main_phase",
							"default_sequence", simple_seq_library::type_id::get());
endfunction

执行代码会发现UVM随机从加入simple_seq_library的sequence中选择几个并顺序启动它们

控制选择算法

上节中sequence library随机从其sequence队列中选择几个执行。这是由其变量selection_mode决定的,这个变量的定义为:uvm_sequence_lib_mode selection_mode;

uvm_sequence_lib_mode是一个枚举类型,共有四个值:

typedef enum
{
	UVM_SEQ_LIB_RAND,
	UVM_SEQ_LIB_RANDC,
	UVM_SEQ_LIB_ITEM,
	UVM_SEQ_LIB_USER
} uvm_sequence_lib_mode;
  • UVM_SEQ_LIB_RAND就是完全的随机,上节例子就是这种算法;
  • UVM_SEQ_LIB_RANDC就是将加入的sequence随机排一个顺序,然后按照此顺序执行。这可以保证每个sequence执行一遍,在所有sequence被执行完一遍之前,不会有sequence被执行第二次,其配置方式如下:
function void my_case0::build_phase(uvm_phase phase);
	…
	uvm_config_db#(uvm_sequence_lib_mode)::set(this, "env.i_agt.sqr.main_phase",
							"default_sequence.selection_mode", UVM_SEQ_LIB_RANDC);
endfunction
  • UVM_SEQ_LIB_ITEMsequence library并不执行其sequence队列中的sequence,而是自己产生transaction。sequence library在此种情况下就是普通的sequence,只是其产生的transaction除了定义时施加的约束外,没有任何额外的约束
  • UVM_SEQ_LIB_USER用户自定义选择的算法。需用户重载select_sequence参数
class simple_seq_library extends uvm_sequence_library#(my_transaction);
	function new(string name= "simple_seq_library");
		super.new(name);
		init_sequence_library();
	endfunction
	`uvm_object_utils(simple_seq_library)
	`uvm_sequence_library_utils(simple_seq_library);
	virtual function int unsigned select_sequence(int unsigned max);
		static int unsigned index[$];
		static bit inited;
		int value;
		if(!inited) begin
			for(int i = 0; i <= max; i++) begin
				if((sequences[i].get_type_name() == "seq0") ||
					(sequences[i].get_type_name() == "seq1") ||
					(sequences[i].get_type_name() == "seq3"))
				index.push_back(i);
			end
			inited = 1;
		end
		value = $urandom_range(0, index.size() - 1);
		return index[value];
	endfunction
endclass
  • 假设有4个sequence加入了sequence library中:seq0、seq1、seq2和seq3。
  • 由于各种原因不想使用seq2。上述代码的select_sequence第一次被调用时初始化index队列,把seq0、seq1和seq3在sequences中的索引号存入其中。
  • 之后从index中随机选择一个值返回,相当于是从seq0、seq1和seq3随机选一个执行。
  • sequences是sequence library中存放候选sequence的队列。select_sequence传入参数max,select_sequence函数必须返回一个介于0到max之间的数值。如果sequences队列的大小为4,那么传入的max的数值是3,而不是4。

控制执行次数

上面代码执行的次数都是10次,这是由sequence library内部的两个变量控制的:

int unsigned min_random_count=10;
int unsigned max_random_count=10;

sequence library会在min_random_count和max_random_count之间随意选择一个数来作为执行次数。当selection_mode为UVM_SEQ_LIB_ITEM时,会产生10个item;其他模式时,将会顺序启动10个sequence。可设置这两个值为其他值来改变迭代次数

function void my_case0::build_phase(uvm_phase phase);
	…
	uvm_config_db#(uvm_object_wrapper)::set(this, "env.i_agt.sqr.main_phase",
							"default_sequence", simple_seq_library::type_id::get());
	uvm_config_db#(uvm_sequence_lib_mode)::set(this, "env.i_agt.sqr.main_phase",
							"default_sequence.selection_mode", UVM_SEQ_LIB_ITEM);
	uvm_config_db#(int unsigned)::set(this, "env.i_agt.sqr.main_phase",
							"default_sequence.min_random_count", 5);
	uvm_config_db#(int unsigned)::set(this, "env.i_agt.sqr.main_phase",
							"default_sequence.max_random_count", 20);
endfunction

上述设置将会产生最多20个,最少5个transaction

使用sequence_library_cfg

使用3个config_db设置迭代次数和选择算法稍显麻烦。UVM提供uvm_sequence_library_cfg对sequence library进行配置。它一共有三个成员变量:

class uvm_sequence_library_cfg extends uvm_object;
	`uvm_object_utils(uvm_sequence_library_cfg)
	uvm_sequence_lib_mode selection_mode;
	int unsigned min_random_count;
	int unsigned max_random_count;
	…
endclass

通过配置如上三个成员变量,并将其传递给sequence library就可对sequence library进行配置:

function void my_case0::build_phase(uvm_phase phase);
	uvm_sequence_library_cfg cfg;
	super.build_phase(phase);
	cfg = new("cfg", UVM_SEQ_LIB_RANDC, 5, 20); //notice
	uvm_config_db#(uvm_object_wrapper)::set(this, "env.i_agt.sqr.main_phase",
						"default_sequence", simple_seq_library::type_id::get());
	uvm_config_db#(uvm_sequence_library_cfg)::set(this, "env.i_agt.sqr.main_phase",
						"default_sequence.config", cfg);
endfunction

除使用专门的cfg外,还有一种简单的配置方法是启动sequence时,在对sequence library进行实例化后,对其中的变量进行赋值

function void my_case0::build_phase(uvm_phase phase);
	simple_seq_library seq_lib;
	super.build_phase(phase);
	seq_lib = new("seq_lib");
	seq_lib.selection_mode = UVM_SEQ_LIB_RANDC;
	seq_lib.min_random_count = 10;
	seq_lib.max_random_count = 15;
	uvm_config_db#(uvm_sequence_base)::set(this, "env.i_agt.sqr.main_phase",
											"default_sequence", seq_lib);
endfunction
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值