UVM-sequence和sequencer

1.sequence挂载sequencer

item对象的生命周期开始于sequence的body()方法,经历了随机化并穿越sequencer最终到达driver,直到被driver消化后,它的生命一般才结束

class flat_seq extends uvm_sequence;
...
task body();
	uvm_sequence_item tmp;
	bus_trans req, rsp;
	tmp = create_item(bus_trans::get_type(), m_sequencer, "req");
	void'($cast(req, tmp));
	start_item(req);
	req.randomize with {data == 10;};
	finish_item(req);
	void'($cast(rsp, tmp));
endtask
endclass
...
class test1 extends uvm_test;
	env e;
	`uvm_component_utils(test1)
	...
	function void build_phase(uvm_phase phase);
		e = env::type_id::create("e", this);
	endfunction
	task run_phase(uvm_phase phase);
		flat_seq seq;
		phase.raise_objection(phase);
		seq = new();
		seq.start(e.sqr);
		phase.drop_objection(phase);
	endtask
endclass

在这段例码中,主要使用两种方法:
1.针对将item挂载到sequence上的应用:

uvm_sequence::start_item(uvm_sequence_item item, int set_priority = -1, uvm_sequencer_base aequencer = null)
//应用
start_item(req)
  • 第一个参数:item对象
  • 第二个参数:优先级
  • 第三个参数:指定item和其parent sequence挂载到sequencer是否是一个,默认相同
uvm_sequence::finish_item(uvm_sequence_item, int set_priority = -1)
//应用
finish_item(req)
  • 第一个参数:item对象
  • 第二个参数:优先级

2.针对将sequence挂载到sequencer上的应用:

uvm_sequence::start(uvm_sequencer_base sequencer, uvm_sequencer_base parent_sequence = null, int this_priority = -1, bit call_pre_post = 1)
//应用
seq.start(e.sqr)
  • 第一个参数:sequencer的句柄
  • 第二个参数:上层sequence
  • 第三个参数:优先级
  • 第四个参数:建议使用默认值指定pre_body()和post_body()执行次序

通过uvm_sequence::start()来挂载root sequence,而在内部的child sequence则可以通过宏``uvm_do`来实现


2. sequencer 仲裁特性

class lock_seq extends uvm_sequence;
	...
	task body();
		bus_trans req;
		#10ns;
		m_sequence.lock(this);
		repeat(3) #10ns `uvm_do_with(req, {data inside {[100:100]};})
		m_sequence.unlock(this);
	endtask
endclass
class grap_seq extends uvm_sequence;
	...
	task body();
		bus_trans req;
		#10ns;
		m_sequence.grap(this);
		repeat(3) #10ns `uvm_do_with(req, {data inside {[200:200]};})
		m_sequence.ungrap(this);
	endtask
endclass
class top_seq extends uvm_sequence;
	...
	task body();
		child_seq seq1, seq2, seq3;
		lock_seq locks;
		grab_seq grabs;
		m_sequencer.set_arbitration(UVM_SEQ_ARB_STRICT_FIFO);
		fork
			`uvm_do_pri_with(seq1, 500, {base == 10;})
			`uvm_do_pri_with(seq2, 500, {base == 20;})
			`uvm_do_pri_with(seq3, 300, {base == 30;})
			`uvm_do_pri(locks, 300)
			`uvm_do(grabs)
		join
	endtask
endclass

uvm_sequence 自定义变量m_sequence

设置仲裁模式:

uvm_sequencer::set_arbitration(UVM_SEQ_ARB_TYPE val)
  • UVM_SEQ_ARB_FIFO: 默认模式。来自sequences的发送请求,按照FIFO先进先出的方式被依次授权和优先级没有关系
  • UVM_SEQ_ARB_WEIGHTED: 不同sequence的发送请求,将按照它们的优先级权重随机授权
  • UVM_SEQ_ARB_RANDOM: 不同的请求会被随机授权,而无视它们的抵达顺序和优先级
  • UVM_SEQ_ARB_STRICT_FIFO: 不同的请求会按照它们的优先级以及抵达顺序来依次授权,因此与优先级和抵达时间都有关
  • UVM_SEQ_ARB_STRICT_RANDOM: 不同的请求,会按照它们的最高优先级随机授权,与抵达时间无关
  • UVM_SEQ_ARB_USER: 用户可以自定义仲裁方法user_priority_arbitration()来裁定哪个sequence的请求被优先授权

锁定机制:lock()和grab()区别

  • lock():当sequencer按照仲裁机制授权给该sequence,一旦该sequence拿到授权,就不会将授权返回。只有当sequence执行 **unlock()** 时,才会释放这一锁定的权限
  • grab():grab()操作比lock()操作优先级要高,grab请求被放入sequencer仲裁队列的最前面,它几乎是一发出就拥有了sequencer的所有权,当已经有其它sequence获得授权时,grab()就无法获得授权

注意:

如果sequence使用了lock()或者grab()方法,必须在sequence结束前调用unlock()或者ungrab()方法来释放权限,否则sequencer会进入死锁状态而无法继续为其余sequence授权

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值