UVM中的sequence

sequence基础

1.

如果将激励放在driver的main_phase中,是可行的,但是如果要对激励作修改,那么扩展性较差,所以我们将激励改为放在sequence中去写。

driver就负责驱动激励就好了,而具体是什么样的激励,应该由sequence去完成。

2.

当定义完一个sequence后,可以使用start任务将其启动。

my_sequence my_seq;
my_seq = my_sequence::type_id::create("my_seq");
my_seq.start(sequencer);

除了上述直接启动之外,还可以使用default_sequence启动。

uvm_config_db#(uvm_object_wrapper)::set(this,
	"env.i_agt.sqr.main_phase",
	"default_sequence",
	case0_sequence::type_id::get());

还可以先实例化要启动的sequence,之后再通过default_sequence启动:

function void my_case0::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

当一个sequence启动后会自动执行sequencebody任务。其实,除了body外,还会自动调用sequencepre_bodypost_body

class case0_sequence extends uvm_sequence #(my_transaction);
virtual task pre_body();
	`uvm_info("sequence0", "pre_body is called!!!", UVM_LOW)
endtask
virtual task post_body();
	`uvm_info("sequence0", "post_body is called!!!", UVM_LOW)
endtask
virtual task body();
	#100;
	`uvm_info("sequence0", "body is called!!!", UVM_LOW)
endtask
`uvm_object_utils(case0_sequence)
endclass

上述的sequence在执行时,会打印出:

# UVM_INFO my_case0.sv(11) @ 0: uvm_test_top.env.i_agt.sqr@@cseq [sequence0] pre_body is called!!!
# UVM_INFO my_case0.sv(22) @ 100000: uvm_test_top.env.i_agt.sqr@@cseq [sequence0] body is called!!!
# UVM_INFO my_case0.sv(15) @ 100000: uvm_test_top.env.i_agt.sqr@@cseq [sequence0] post_body is called

sequence的仲裁机制

1.

UVM支持在同一个sequencer上可以启动多个sequence。

在my_sequencer上同时启动了两个sequence:sequence1和sequence2,代码如下所示:

task my_case0::main_phase(uvm_phase phase);
	sequence0 seq0;
	sequence1 seq1;
	seq0 = new("seq0");
	seq0.starting_phase = phase;
	seq1 = new("seq1");
	seq1.starting_phase = phase;
	fork
		seq0.start(env.i_agt.sqr);
		seq1.start(env.i_agt.sqr);
	join
endtask

其中sequence0的定义为:

class sequence0 extends uvm_sequence #(my_transaction);
	virtual task body();
		repeat (5) begin
			`uvm_do(m_trans)
			`uvm_info("sequence0", "send one transaction", UVM_MEDIUM)
		end
		#100;
	endtask
	`uvm_object_utils(sequence0)
endclass

sequence1的定义为:

class sequence1 extends uvm_sequence #(my_transaction);
	virtual task body();
		repeat (5) begin
			`uvm_do_with(m_trans, {m_trans.pload.size < 500;})
			`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
		end
		#100;
	endtask
	`uvm_object_utils(sequence1)
endclass

运行如上代码后,会显示两个sequence交替产生transaction:

# UVM_INFO my_case0.sv(15) @ 85900: uvm_test_top.env.i_agt.sqr@@seq0 [sequence0] send one transaction
# UVM_INFO my_case0.sv(37) @ 112500: uvm_test_top.env.i_agt.sqr@@seq1 [sequence1] send one transaction
# UVM_INFO my_case0.sv(15) @ 149300: uvm_test_top.env.i_agt.sqr@@seq0 [sequence0] send one transaction
# UVM_INFO my_case0.sv(37) @ 200500: uvm_test_top.env.i_agt.sqr@@seq1 [sequence1] send one transaction
# UVM_INFO my_case0.sv(15) @ 380700: uvm_test_top.env.i_agt.sqr@@seq0 [sequence0] send one transaction
# UVM_INFO my_case0.sv(37) @ 436500: uvm_test_top.env.i_agt.sqr@@seq1 [sequence1] send one transaction

但这里存在sequencer的仲裁算法:

SEQ_ARB_FIFO,
SEQ_ARB_WEIGHTED,
SEQ_ARB_RANDOM,
SEQ_ARB_STRICT_FIFO,
SEQ_ARB_STRICT_RANDOM,
SEQ_ARB_USER
  • 在默认情况下sequencer的仲裁算法是SEQ_ARB_FIFO。它会严格遵循先入先出的顺序,而不会考虑优先级。
  • SEQ_ARB_WEIGHTED是加权的仲裁;
  • SEQ_ARB_RANDOM是完全随机选择;
  • SEQ_ARB_STRICT_FIFO是严格按照优先级的,当有多个同一优先级的sequence时,按照先入先出的顺序选择;
  • SEQ_ARB_STRICT_RANDOM是严格按照优先级的,当有多个同一优先级的sequence时,随机从最高优先级中选择;
  • SEQ_ARB_USER则是用户可以自定义一种新的仲裁算法。

因此,若想使优先级起作用,应该设置仲裁算法为SEQ_ARB_STRICT_FIFO或者SEQ_ARB_STRICT_RANDOM

因此,my_case0代码改为如下:

task my_case0::main_phase(uvm_phase phase);
	env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);
	fork
		seq0.start(env.i_agt.sqr);
		seq1.start(env.i_agt.sqr);
	join
endtask

经过如上的设置后,会发现直到sequence1发送完transaction后,sequence0才开始发送。
除transaction有优先级外,sequence也有优先级的概念。可以在sequence启动时指定其优先级:

task my_case0::main_phase(uvm_phase phase);
	env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);
	fork
		seq0.start(env.i_agt.sqr, null, 100);
		seq1.start(env.i_agt.sqr, null, 200);
	join
endtask

start任务的第一个参数是sequencer,第二个参数是parent sequence,可以设置为null,第三个参数是优先级,如果不指定则此值为-1,它同样不能设置为一个小于-1的数字。

运行上述代码,会发现sequence1中的transaction完全发送完后才发送sequence0中的transaction。

2.

lock操作,就是sequence向sequencer发送一个请求,这个请求与其他sequence发送transaction的请求一同被放入sequencer的仲裁队列中。当其前面的所有请求被处理完毕后,sequencer就开始响应这个lock请求,此后sequencer会一直连续发送此sequence的transaction,直到unlock操作被调用。从效果上看,此sequencer的所有权并没有被所有的sequence共享,而是被申请lock操作的sequence独占了。一个使用lock操作的sequence为:

class sequence1 extends uvm_sequence #(my_transaction);
	virtual task body();
		repeat (3) begin
			`uvm_do_with(m_trans, {m_trans.pload.size < 500;})
			`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
		end
   	     lock();
		`uvm_info("sequence1", "locked the sequencer ", UVM_MEDIUM)
		repeat (4) begin
			`uvm_do_with(m_trans, {m_trans.pload.size < 500;})
			`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
		end
		`uvm_info("sequence1", "unlocked the sequencer ", UVM_MEDIUM)
		unlock();
		repeat (3) begin
			`uvm_do_with(m_trans, {m_trans.pload.size < 500;})
			`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
		end
	endtask
endclass

将此sequence1与代码清单6-10中的sequence0使用代码清单6-9的方式在env.i_agt.sqr上启动,会发现在lock语句前,sequence0和seuquence1交替产生transaction;在lo

  • 7
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UVM sequence 的 response 用于表示 sequence 执行的结果或产生的数据。一般情况下,response 是一个包含所需信息的类对象,可以包含任何需要传递给其他组件或者验证环境的数据。 在 sequence ,可以通过以下方式设置 response: 1. 在 sequence 定义一个 response 对象,并在需要的时候为其赋值。 2. 将 response 对象作为任务或函数的参数传递给其他组件,以便其他组件可以读取该对象的值。 另外,response 对象通常被定义为一个 transaction 类,其包含需要传递的所有字段。这样可以方便地传递多个数据项,并且可以轻松地扩展和维护代码。 例如,以下是一个简单的 sequence 示例,展示了如何使用 response: ```systemverilog class MySequence extends uvm_sequence #(MyTransaction); `uvm_object_utils(MySequence) task body(); MyTransaction txn; // 设置 txn 的字段值 // ... // 设置 response response = txn; endtask endclass ``` 在上述示例,`MyTransaction` 是一个自定义的 transaction 类,它包含了需要传递的字段。在 `body()` 函数,我们创建了一个 `MyTransaction` 对象 `txn` 并设置其字段的值。然后,将其赋值给 `response` 对象。 这样,在 sequence 执行完成后,其他组件就可以通过读取 `response` 对象来获取执行结果或产生的数据。 希望这个回答能够帮到你!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值