Loading

# [UVM实战review] sequence

[UVM实战review] sequence

启动sequence方式总结

  • default sequence 方式,不实例化

    uvm_config_db#(uvm_obejct_wrapper)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", case0_sequence::type_id::get())	
    
  • 先例化sequence,再通过default sequence启动

// 在case的build phase中set config db
function case0_test::build_phase(uvm_phase phase)
	case0_sequence cseq;
	super.build_phase(phase);
	cseq = new("cseq");
	
	uvm_config_db #(uvm_sequence_base) ::set(this, "env.i_agt.sqr.main_phase", "default_sequence", cseq);
endfunction
  • 除此以外就是在case中显示创建sequence然后start了。

仲裁机制

可以在同一个sequencer上启动多个sequence,默认情况下会交替产生trans,uvm_do_pri marco could change the priority.pri越高,优先级越大。

设置完优先级并不代表所有高的trans一定比低优先级的trans先发送,这个与sequencer的仲裁算法有关。

SEQ_ARB_FIFO, 	// default 
SEQ_ARB_WEIGHTED,	// 加权仲裁
SEQ_ARB_RANDOM,			// 完全随机选择
SEQ_ARB_STRICT_FIFO,    // 是严格按照优先级的,当有多个同一优先级的sequence时,按照先入先出的顺序选择
SEQ_ARB_STRICT_RANDOM   // 是严格按照优先级的,当有多个同一优先级的sequence时,随机从最高优先级中选择
SEQ_ARB_USER		    // 则是用户可以自定义一种新的仲裁算法

// HOW TO SET?
// in case main phase or run phase

env.i_agt.set_arbitration(SEQ_STRICT_FIFO)

lock and grab

lock

当其前面的所有请求被处理完毕后,sequencer就开始响应这个lock请求,此后sequencer会一直连续发送此sequence的
transaction,直到unlock操作被调用。lock请求前所有的trans执行完了之后才响应,给发起lock请求的sequence独占,等这个sequence unlock了,再响应别的sequence

grab

优先级更高,直接放在仲裁队列最前面,不管前面trans先完成就直接拥有所有权。

sequence marco

`uvm_do(SEQ_OR_ITEM)
`uvm_do_pri(SEQ_OR_ITEM, PRIORITY)
`uvm_do_with(SEQ_OR_ITEM, CONSTRAINTS)
`uvm_do_pri_with(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS)
`uvm_do_on(SEQ_OR_ITEM, SEQR)
`uvm_do_on_pri(SEQ_OR_ITEM, SEQR, PRIORITY)
`uvm_do_on_with(SEQ_OR_ITEM, SEQR, CONSTRAINTS)
`uvm_do_on_pri_with(SEQ_OR_ITEM, SEQR, PRIORITY, CONSTRAINTS)

// 上面所有的宏都是基于`uvm_do_on_pri_with on对应的是seqr,pri是优先级,with是约束

uvm_rand_send意义

uvm_rand_send系列宏及uvm_send系列宏的意义主要在于,如果一个transaction占用的内存比较大,那么很可能希望前后两次发送的transaction都使用同一块内存,只是其中的内容可以不同,这样比较节省内存。

pre_do mid_do post_do 与 start_item finish_item关系

pre_do is task, post_do and mid_do is function.

sequencer.wait_for_grant(prior)  (task) \ start_item \
parent_seq.pre_do(1)			 (task) /             \
											`          uvm_do* macros
parent_seq.mid_do(item) 	     (func) \                /
sequencer.send_request(item)      (func) \  finish_item /
sequencer.wait_for_item_done()    (task) /
parent_seq.post_do(item)          (func) /

嵌套sequence

当约束很多的时候,单纯总constraint来入手会导致维护起来很麻烦,可以使用嵌套sequence,子sequence产生不同的trans,在顶层body只需要将m_sequencer设置为子sequence的start参数就可以

p_sequencer

由于m_sequencer是uvm_sequencer_base类型的,所以不能索引到sequncer的成员变量,需要使用``uvm_declare_p_sequencer(SEQUENCER_TYPE)`来进行转换

virtual sequencer

virtual的含义在于其统一调度的意思,自身不发送trans,只是控制别的sequence。对应的需要有virtual sequencer。

posted @ 2022-08-03 23:00  pu1se  阅读(130)  评论(0)    收藏  举报