在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
楼主: doogo

[原创] 《UVM实战》24小时问答

[复制链接]
发表于 2016-3-27 11:17:17 | 显示全部楼层
楼主,问一个sv的disable fork 和 disable statement;的问题;
我看了sv的IEEE文档,里面对停止进程的描述非常简洁,所以对这两个东东的使用不是很了解;
我的理解是disable statement是用来停止 statement所描述的一个代码段落,如果这个段落已经执行完成,那么disable就没有任何作用了:例如
fork : state1_clr
    while(1)
    begin
        process_1();
    end
join_non
disable state1_clr;

这样disable不能停止 fork 中的while函数;只有用disable fork才能关闭下面的所有子进程;

而如果有多层fork相关进程的情况,事情变得又会复杂,所以不知道楼主是否有相关的资料或者博文可以
让我们学习下;
发表于 2016-3-27 19:26:15 | 显示全部楼层
本帖最后由 lazioprocn 于 2016-3-27 21:37 编辑

我发现一个uvm1.2的似疑的bug,想讨论下。简单的说,如果lock_list里面有两个不同的sequence,则一定会卡死掉。
例如如果三个sequence fork join 同时发到一个sequencer,其中第2第3个为lock的. 那么当第一个sequence 发完,而 driver 继续第二次 get_next_item() 由于所有的sequence 都得不到裁决一直等 会导致整个验证平台死掉。

具体为sequence1没有lock().那么等sequence1发送完毕,grant_queued_lockes()将sequence2,sequence3,lock()的sequence2,sequence3添加到lock_list中去。当driver调用m_choose_next_request时,判断is_blocked(arb_sequence_q.sequence_ptr ==0) 后才能return arb_sequence_q三个中间的一个index.而在 uvm_sequencer_base.svh 里面的 is_blocked()函数是这样写的:
// is_blocked
// ----------

function bit uvm_sequencer_base::is_blocked(uvm_sequence_base sequence_ptr);

  if (sequence_ptr == null)
    uvm_report_fatal("uvm_sequence_controller",
                     "is_blocked passed null sequence_ptr", UVM_NONE);

    foreach (lock_list) begin
      if ((lock_list.get_inst_id() !=
           sequence_ptr.get_inst_id()) &&
          (is_child(lock_list, sequence_ptr) == 0)) begin
        return 1;
      end
    end
    return 0;
endfunction

很显然,这时 lock_list 里面有 sequence2,sequence3, 而三个sequence 进去均会返回1,因为它判断两个 lock_list 只要有一个不等返回1,每个sequence要与所有的两个不同的 lock_list 相等才返回0,显然是不可能为0的。我认为可以这么改:

function bit uvm_sequencer_base::is_blocked(uvm_sequence_base sequence_ptr);

  if (sequence_ptr == null)
    uvm_report_fatal("uvm_sequence_controller",
                     "is_blocked passed null sequence_ptr", UVM_NONE);

    foreach (lock_list) begin
      if ((lock_list.get_inst_id() !=
           sequence_ptr.get_inst_id()) &&
          (is_child(lock_list, sequence_ptr) == 0)) begin
      end
      else
          return 0;
    end
    if(lock_list.size())
        return 1;   
    else
        return 0;
endfunction

也就是说当有 lock_list 有东西时,当 sequence 在 lock_list 里面,返回0,当判断完均不在 lock_list 里面才返回1.
发表于 2016-3-27 19:35:39 | 显示全部楼层
本帖最后由 lazioprocn 于 2016-3-27 19:58 编辑

另外我觉得 整个 lock的机制均有点问题,如果两个sequence 同时 fork join 发出到同样一个 sequencer ,设置裁决机制是有优先级的。
我认为应该sequence2 的优先级高,sequence2会先发,而且应该两个 sequence 均发到 lock_list 中。而实际如果sequence2 后调用后发到 arb_sequence_q中,那么现在的机制是 sequence1 的lock先能够自我裁决添加lock_list 并往下走到 uvm_do(), 而sequence2 则会卡在 lock()函数一直等待裁决,也就是在 driver 裁决的时候 sequence2的type 是 SEQ_TYPE_LOCK 类型的,不参与裁决。这样 会等到 sequence1  unlock()之后 sequence2 才有机会添加到lock_list并且调用 uvm_do改变 TYPE 类型。这样是否正确?
发表于 2016-3-27 20:09:59 | 显示全部楼层
本帖最后由 lazioprocn 于 2016-3-27 21:36 编辑

我发现一个uvm1.2的似疑的bug,想讨论下。如果三个sequence fork join 同时发到一个sequencer,其中第2第3个为lock的,第一个没有lock().那么等第一个sequence发送完毕,grant_queued_lockes()同时将lock()的sequence2,sequence3添加到lock_list中去。当driver调用m_choose_next_request时,判断is_blocked(arb_sequence_q.sequence_ptr ==0) 后才能return arb_sequence_q三个中间的一个index.而目前 is_block()的函数是这样的:
function bit uvm_sequencer_base::is_blocked(uvm_sequence_base sequence_ptr);

  if (sequence_ptr == null)
    uvm_report_fatal("uvm_sequence_controller",
                     "is_blocked passed null sequence_ptr", UVM_NONE);

    foreach (lock_list) begin
      if ((lock_list.get_inst_id() !=
           sequence_ptr.get_inst_id()) &&
          (is_child(lock_list, sequence_ptr) == 0)) begin
        return 1;
      end
    end
    return 0;
endfunction


很显然,如果 lock_list 有两个的情况,那么返回的必为1,应为任意一个sequence进去必定与一个 lock_list 不等,这样的话三个sequence均会返回1,也就是说没有能够对任意一个sequence进行裁决。系统会一直等待裁决而发不出任意一个sequence。
我觉得应该这样改:
// is_blocked
// ----------

function bit uvm_sequencer_base::is_blocked(uvm_sequence_base sequence_ptr);

  if (sequence_ptr == null)
    uvm_report_fatal("uvm_sequence_controller",
                     "is_blocked passed null sequence_ptr", UVM_NONE);

    foreach (lock_list) begin
      if ((lock_list.get_inst_id() !=
           sequence_ptr.get_inst_id()) &&
          (is_child(lock_list, sequence_ptr) == 0)) begin
      end
      else
          return 0;
    end
    if(lock_list.size())
        return 1;   
    else
        return 0;
endfunction

如果 lock_list有数,并且任意一个sequence与 lock_list相等返回0,两个均不等,返回1.不知道是否正确理解的,谢谢指教。不好意思跟上上面的重复了,一开始发的没显示出来
发表于 2016-4-8 15:50:01 | 显示全部楼层
感谢分享 看看
发表于 2016-4-8 16:23:35 | 显示全部楼层
嗯嗯 不错,看看
发表于 2016-4-14 19:47:00 | 显示全部楼层
uvm寄存器模型的backdoor访问是否支持VHDL?
如果支持的话路径如何设置?
发表于 2016-4-16 14:46:51 | 显示全部楼层
回复 1# doogo

在阅读UVM实战卷一时有如下代码:



  1. class my_case0 extends base_test;
  2.    function new(string name = "my_case0", uvm_component parent = null);
  3.    ...
  4. endclass


  5. function void my_case0::build_phase(uvm_phase phase);
  6.   ...
  7.    uvm_config_db#(uvm_object_wrapper)::set(this,
  8.                                            "env.i_agt.sqr.main_phase",
  9.                                            "default_sequence",
  10.                                            case0_sequence::type_id::get());
  11. endfunction


复制代码


但是build_phase执行顺序是至上而下,执行到my_case0时,env,agent,sequencer中的built_phase,没有执行,换句话说就是env,agent,sequencer实例并不存在(没有被new),但是在my_case0中的built_phase的uvm_config_db中的参数使用了env,agent,sequencer实例,这里不太明白,请赐教。非常感谢
发表于 2016-5-23 11:12:12 | 显示全部楼层
刚看完四章,楼主的书写得非常好,很通俗易懂,希望有后续的书出来
发表于 2016-5-23 15:01:08 | 显示全部楼层
写卷二的话加上1.2的新内容吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

×

小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-7 04:48 , Processed in 0.022959 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表