问题描述
在测试 dut 的注错 feature 时,我的测试内容写在了 test case 的 main_phase 中。main_phase 明明已经走到了 phase.drop_objection(this),为什么 case 无法退出,而且仿真时间还一直在往前走?
文章目录
问题排查与分析
1. 是否出现了while(1) #0 死锁的情况?
仿真时间在往前走,可以确定没有出现 while(1) #0 的情况。
2. 该 case 的 main_phase 中是否存在隐藏的 object 在 raise objection 后还没有 drop ?
为了防止 main_phase drop objection 后存在隐藏的 object 在 raise objection 且没有 drop,在该 case main_phase 的 phase.drop_objection 之后,采用以下方法获取所有 raise objection 的 object,并强制全部 drop 掉。
virtual function void drop_all_objection(uvm_phase phase);
uvm_objection m_objection;
uvm_object m_object[$];
m_objection = phase.get_objection();
m_objection.get_objectors(m_object);
foreach (m_object[i]) begin
while (m_objection.get_objection(m_object[i]) != 0) begin
m_objection.drop_objection(m_object[i]);
`uvm_info(get_name(), $sformatf("Drop this objection: %s", m_object[i].get_full_name()), UVM_LOW)
end
end
endfunction : drop_all_objection
采用以上方法 drop main_phase 中的所有 objection,发现问题仍未解决,且无任何改善。通过 drop_objection 时候的 log 也能看到,在 phase.drop_objection 之后进一步调用 drop_all_objection(phase),并没有 get 到任何已经 raise 的 objection。
注意:采用强行 drop 所有 objection 的方案时,若被 drop 的 object 在其他组件中继续被调用,会报 The object xxx is being used before it was constructed/allocated。
3. 所有 component 中的 main_phase 都执行完了吗?
在个人写的验证 uvc 中 grep main_phase,发现 uvc 中全部使用的 run_phase,并没有其他 main_phase 在执行。继续在 phase 中添加打印,或者在仿真参数中添加 +UVM_PHASE_TRACE 来 trace phase 执行情况,发现所有 component 的 main_phase 都执行完了。
4. 是否在 post_main_phase、pre_shutdown_phase、shutdown_phase 或 post_shutdown_phase 中 raise 了 objection 且一直没有退出?
采用 +UVM_PHASE_TRACE来 trace phase 执行情况,phase 已经走到了 post_shutdown_phase。即便如此,case 仍然无法退出。
5. run_phase 中有没有 raise_objection?退出了吗?
种种迹象表明,问题并非出在 12 个小 phase,得排查下 run_phase。考虑到 12 个小 phase 和 run_phase 是并行执行的,12 个小 phase 无法退出,一定是哪个地方的 run_phase raise objection 了。祭出 objection debug 的大杀器: +UVM_OBJECTION_PHASE 。果然,在 timeout 之后,报出 run phase 中 axi vip 的 master driver 丢出了 outstanding objection,但没有收全 response。拨开云雾见青天,水落石出了!
注意,用 +UVM_OBJECTION_PHASE 来 trace objection 时,一定要耐心。由于 objection 太多,很难在 log 里看出到底是哪个 objection 没有被 drop。此时,可以让 case 多跑一会儿,等 case timeout 之后,会统计 objection 情况。
解决方案
考虑到测试用例本来就是注错的 case,axi request 发出去后,是等不到 response 的,也就是说,axi vip 中的 run_phase 永远不会正常执行完毕。vip 的 run_phase 不好改,我又不能不让它跑,那该如何让这个 case 优雅地退出呢?有以下两个方案:
- 方案一:把 axi vip 的 response 等待时间减小,这样 vip 能够早点报错,然后仿真选项中把这个 timeout 报错 demote 掉。此方案稍显复杂。
- 方案二:main_phase 中测试完毕后,直接 jump 到 final_phase。反正 main_phase 中我的测试目的已经达到了,我管你 vip run_phase 有没有正常跑完。加之我的 case 本来就是给异常情况造的注错 case,我测完直接 jump 到 final_phase 不过分吧。
注意:方案二中,一开始我是不想 jump 到 final_phase 这么远的,想着 jump 到 extract_phase 让 run_phase 退出就好。奈何 jump 到 extract_phase 后,case 仍然无法正常退出,时间紧迫,也没来得及细察原因,各位有兴趣的可以试一下。
问题回顾
虽然 case 的 main_phase 执行完了,但由于 axi vip 的run_phase 没有授权 response,导致 case 没有按照预期退出。可以采用 phase jump 的方式跳出。
事出反常必有妖。既然是在造一个异常的 case,就要做好心理准备来解决各种异常问题。代码没有感情但讲道理,所有的看似不讲道理,都是在讲一套我们没考虑到的道理。