UVM 使用start_item和finish_item指定sequencer发送item,比uvm_do_on更灵活。

我们使用uvm_do_on(item,sqr)是可以指定那个sequencer发送此。而且uvm_do系列宏第一个参数即可以是sequence也可以是transaction,当是sequence时使用start任务来启动sequence,当是transaction时使用start_item和finish_item来发送transaction。

1.uvm_do局限性:uvm_do系列宏封装的太好但是灵活性更差。比如场景:

要发送的transaction很复杂(有很多signal),我们需要精细化制定其中每个signal的值,并且我们还需要指定那个sequencer来发送此transaction给driver,此时使用uvm_do_on_with(item,sqr,{})宏的话就会很麻烦,因为其对item会做随机化,然后我们只能在约束{}中指定每个signal的值。这样会写一系列的长串代码。那么可不可以定制好item0之后使用item.copy(item0)呢,但是copy也只能在mid_do函数做,因为uvm_do_on_with(item,sqr,{})是会去new一个新的item,如果你在uvm_do_on_with之前去做那么new item之后item的值有不是item0中的值了。所以我们只能在uvm_do_on_with的内部随机之后去执行copy,uvm提供的虚函数mid_do就是在随机之后finish_item之前执行的,所以我们可以重载mid_do,在mid_do中对item进行赋值。但是如果我在一个virtual sequence中需要将item构造好之后发送给不同sequencer呢,这样你重写的copy只能有一个,对于不同的sequencer可能需要构造的值又不一样。所以这样做会越来越麻烦。(如果不想对transaction某个)

2.start_item,finish_item灵活性

我们可以直接调用start_item和finish_item来构造transaction并发送。但是我看的书籍和资料上都只是使用start_item(item)。对于上面需要指定sequencer的场景好像并不适用。但是实际上start_item的uvm源码中是给了sequencer这个参数的,只是其默认值设置为null。

 经过试验,start_item是可以直接给定要发送item的sequencer的。方法有两种。

1.使用时需要先new一个item,然后在使用语句start_item(item,-1,sqr)。

2.使用时先用宏`uvm_create_on(item,sqr),然后在使用start_item(item)。这种方式不需要new一个item,因为`uvm_create_on(item,sqr)会自动去new一个item并和sqr绑定。

代码如下(其中px_tr包含了px_tr_img和px_tr_gain相同的部分):

  • 8
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`start_item`函数是UVM中序列化对象的一种机制,用于将序列化对象插入到序列执行队列中。以下是UVM中`start_item`的源代码: ```systemverilog function bit uvm_sequence_base::start_item (uvm_sequence_item item, uvm_sequencer_base sequencer, bit set_priority = 0, string source_file = "", int source_line = 0); uvm_sequence_item item_copy; uvm_tlm_transaction_base t; uvm_component comp = get_parent(); uvm_phase phase; if (!item) `uvm_fatal("NOITEM","Attempting to start a NULL sequence_item") if (!sequencer) `uvm_fatal("NOSEQ","Attempting to start a sequence_item with a NULL sequencer") if (comp is uvm_root) begin `uvm_warning("SEQROOT",{"Attempt to start sequence '",get_type_name(), "' outside of a phase process. Ignored."}) return 0; end // Create a copy of the item if(item.try_clone(item_copy) == 0) begin `uvm_error("CLONE", {"Unable to clone sequence item '",item.get_type_name(),"'"}) return 0; end // Check for TLM analysis ports if(item_copy.get_type_name() == "uvm_tlm_analysis_port_base") begin t = item_copy; t.set_source_info(source_file, source_line); t.analysis_imp.connect(item_copy.analysis_export); t.write(t); return 1; end // Set the item's sequencer item_copy.set_sequencer(sequencer); // Set the item's source info item_copy.set_source_info(source_file, source_line); // Set the item's priority if (set_priority) item_copy.set_priority(m_priority); // If in a run phase, start the item phase = comp.get_phase(); if (phase != null && phase.get_name() == "run") begin if (!sequencer.start_item(item_copy)) begin `uvm_error("NOSEQITEM", {"Failed to start sequence item ", item_copy.get_type_name()," with sequencer ", sequencer.get_type_name()}) return 0; end end else m_req_q.push_back(item_copy); return 1; endfunction ``` 此函数接收四个参数: - `item`:要插入序列执行队列中的序列化对象。 - `sequencer`:将序列化对象插入到其执行队列中的UVM序列器。 - `set_priority`:指示是否应将`item`的优先级设置为该序列的优先级。 - `source_file`和`source_line`:指示从哪个源代码文件和行开始创建序列化对象。 该函数首先检查传递的参数是否有效。然后,它会复制序列化对象并将其设置在传递的`sequencer`中。如果序列化对象是一个TLM分析端口,则该函数会将其连接到分析导出,并通过`write`函数写入分析对象。如果在运行阶段,则该函数将使用传递的`sequencer`启动序列化对象。否则,它将序列化对象插入到要求队列中。函数返回1表示成功,返回0表示失败。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值