关于UVM中的sequence(四)

5、sequence中使用config::db

在sequence中获取参数

能够调用config_db::get的前提是已经进行了set。sequence本身是一个uvm_object,它无法像uvm_component那样出现在 UVM树中,从而很难确定在对其进行设置时的第二个路径参数。所以在sequence中使用config_db::get函数得到参数的最大障碍是路径问题。

在UVM中使用get_full_name()可以得到一个component的完整路径,同样的,此函数也可以在一个sequence中被调用,尝试 着在一个sequence的body中调用此函数,并打印出返回值,其结果大体如下:

这个路径是由两个部分组成:此sequence的sequencer的路径,及实例化此sequence时传递的名字。

因此,可以使用如下的方式 为一个sequence传递参数:

set函数的第二个路径参数里面出现了通配符,这是因为sequence在实例化时名字一般是不固定的,而且有时是未知的(比如 使用default_sequence启动的sequence的名字就是未知的),所以使用通配符。

在sequence中以如下的方式调用config_db::get函数:

在get函数原型中,第一个参数必须是一个component,而sequence不是一个component, 所以这里不能使用this指针,只能使用null或者uvm_root::get()。前文已经提过,当使用null时,UVM会自动将其替换为 uvm_root::get(),再加上第二个参数get_full_name(),就可以完整地得到此sequence的路径,从而得到参数。

在sequence中设置参数

与获取参数相比,在sequence中使用config_db::set设置参数就比较简单。有了在top_tb中设置virtual interface的经验,读者 在这里可以使用类似的方式为UVM树中的任意结点传递参数:

wait_modified的使用

在上一节的例子中,向scoreboard传递了一个cmp_en的参数,scoreboard可以根据此参数决定是否对收到的transaction进行检 查。在做一些异常用例测试的时候,经常用到这种方式。

但是关键是如何在scoreboard中获取这个参数。 在以前的章节中,scoreboard都是在build_phase中调用get函数,并且调用的前提是参数已经被设置过。一个sequence是在task phase中运行的,当其设置一个参数的时候,其时间往往是不固定的。

 针对这种不固定的设置参数的方式,UVM中提供了wait_modified任务,它的参数有三个,与config_db::get的前三个参数完全一样。当它检测到第三个参数的值被更新过后,它就返回,否则一直等待在那里。其调用方式如下:

7、response的使用

put_response与get_response

sequence机制提供了一种sequence→sequencer→driver的单向数据传输机制。但是在复杂的验证平台中,sequence需要根据 driver对transaction的反应来决定接下来要发送的transaction,换言之,sequence需要得到driver的一个反馈。sequence机制提供对这 种反馈的支持,它允许driver将一个response返回给sequence。

如果需要使用response,那么在sequence中需要使用get_response任务:

在driver中,则需要使用put_response任务:

这里的关键是设置set_id_info函数,它将req的id等信息复制到rsp中。由于可能存在多个sequence在同一个sequencer上启动的情况,只有设置了rsp的id等信息,sequencer才知道将response返回给哪个sequence。

除了使用put_response外,UVM还支持直接将response作为item_done的参数:

response的数量问题

通常来说,一个transaction对应一个response,但是事实上,UVM也支持一个transaction对应多个response的情况,在这种情况 下,在sequence中需要多次调用get_response,而在driver中,需要多次调用put_response:

当存在多个response时,将response作为item_done参数的方式就不适用了。由于一个transaction只能对应一个item_done,所以 使用多次item_done(rsp)是会出错的。 response机制的原理是driver将rsp推送给sequencer,而sequencer内部维持一个队列,当有新的response进入时,就推入此队列。但是此队列的大小并不是无限制的,在默认情况下,其大小为8。当队列中有8个response时,如果driver再次向此队列推送新的response,UVM就会给出如下错误提示:

UVM_ERROR @ 1753500000: uvm_test_top.env.i_agt.sqr@@case0_sequence [uvm_test_top.env.i_agt.sqr.case0_sequence] Response queue overflow, response was dropped

因此,如果在driver中每个transaction后都发送一个response,而sequence又没能及时get_response,sequencer中的response队列就存在溢出的风险。

rsp与req类型不

前面所有的例子中,response的类型都与req的类型完全相同。UVM也支持response与req类型不同的情况。 uvm_driver、uvm_sequencer与uvm_sequence的原型分别是:

在前面章节的例子中只向它们传递了一个参数,因此response与req的类型是一样的。如果要使用不同类型的rsp与req,那么 driver、sequencer与sequence在定义时都要传入两个参数:

之后,可以使用put_response来发送response:

使用get_response来接收response:

response handler

前面讲述的get_response和put_response是一一对应的。当在sequence中启动get_response时,进程就会阻塞在那里,一直到 response_queue中被放入新的记录。如果driver能够马上将response通过put_response的方式传回sequence,那么sequence被阻塞的进 程就会得到释放,可以接着发送下一个transaction给driver。但是假如driver需要延时较长的一段时间才能将transaction传回,在此期 间,driver希望能够继续从sequence得到新的transaction并驱动它,但是由于sequence被阻塞在了那里,根本不可能发出新的 transaction。 发生上述情况的主要原因为sequence中发送transaction与get_response是在同一个进程中执行的,假如将二者分离开来,在不同 的进程中运行将会得到不同的结果。在这种情况下需要使用response_handler:

由于response handler功能默认是关闭的,所以要使用response_handler,首先需要调用use_response_handler函数,打开sequence 的response handler功能。 当打开response handler功能后,用户需要重载虚函数response_handler。此函数的参数是一个uvm_sequence_item类型的指针, 需要首先将其通过cast转换变成my_transaction类型,之后就可以根据rsp的值来决定后续sequence的行为。

使用response_handler之后,body任务中就没有和response相关的语句了,从而实现了分开处理的目的。

另类的response

无论是put/get_response或者response_handler,都是新建了一个transaction,并将其返回给sequence。事实上,当一个uvm_do语 句执行完毕后,其第一个参数并不是一个空指针,而是指向刚刚被送给driver的transaction。利用这一点,可以实现一种另类的 response:

driver中向req中的成员变量赋值,而sequence则检测这个值:

  • 28
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 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
发出的红包

打赏作者

汶.z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值