uvm驗證環境里一般通過objection機制來控制仿真的結束,不過在機制之外,有時還需要通過看門狗來watchdog避免仿真環境掛死,watchdog配合objection一起來控制仿真的進行與結束。
我一直自詡為對環境watchdog這件事爛熟于心了,不過沒想到這天還是被傷害到了。
事故背景
一個中規中矩的watchdog是怎么組織的呢?要明確一下watchdog發揮的作用,就是在objection的基礎上進行補充,在環境長時間沒有動靜的情況下能夠使環境報錯推出并打印此時阻止仿真結束的罪魁禍首。
基于這個認識,watchdog應該是base_test的run_phase()中進行調用,這樣既從時間全程參與又從空間上統攬全局。當然了,因為環境的主要行為集中在main_phase()中,所以把watchdog放在main_phase()中我覺得也是可以的。
super.run_phase(phase);
phase.raise_objection(this);
this.watchdog(phase);
phase.drop_objection(this);
endtask: run_phase
watchdog上下的objection還是很有必要的,畢竟你要保證watchdog無論在哪里調用都可以執行起來,別這個phase沒有objection就直接略過了。
watchdog內部邏輯就是幾個并行的線程,簡單來說可以這樣寫:
#1000;
if(this.cfg.watchdog_en == 0) return;
while(1)begin
bit vr_reached;
fork: timeout
begin //normal finish
phase.phase_done.wait_for_total_count(null, 1);
vr_reached = 1;
end
begin //timeout
#this.cfg.watchdog_th;
`uvm_fatal("watchdog", $psprintf("watchdog timeout(%s_phase)::n %s", phase.get_name(), phase.phase_done.convert2string()))
end
#100 @prj_scoreboard::feed_watchdog;
#100 @harness.dut.hand_en;
#100 wait(this.env.num != 0);
join_any
disable timeout;
#10;
if(vr_reached && phase.phase_done.get_objection_tatal == 1)begin
`uvm_info("watchdog", $psprintf("watchdog timeout(%s_phase) normal reached", phase.get_name()), UVM_LOW)
break;
end
end
`uvm_note("watchdog", "watchdog Finished!", UVM_LOW)
endtask
代碼的主體就是一個大的while(1)循環,循環內以fork - join_any的形式起多個喂狗線程,根據fork - join_any的機制,只要任何一個線程完成了都會觸發喂狗機制。
*線程1:正常結束的線程,因為本身watchdog占著一個raise_objection,所以只要等待wait_for_total_count(null, 1)就可以了,為1說明其他的objection都已經drop了,那么就可以正常結束程序,和uvm本身的objection機制完全一樣;
*線程2:超時線程,如果很長的時間里都沒有喂狗,那么報fatal推出仿真。注意這里必須是fatal使方正立即結束,報error的話環境還是會掛死狀態;
*線程3:所有的scoreboard都可以喂狗,因為scb里比對的一方是可以信任的環境預期,如果比對還在進行那么就說明仿真不應該結束;
*線程N:可以喂狗的其他線程,使用rtl線程需要萬分謹慎,很有可能rtl里做錯了一致重復出數據導致仿真無法結束;
當喂狗一次后,就可以殺掉timeout這個線程了,然后根據情況看看是否重新回到看門狗循環中。
事故現場
看門狗的核心起始就是,確定仿真在“動”,能動就是還活著不能結束仿真,所以在fork-join_any里除了超時線程以外,其他的都是證明系統還活著的“喂狗”線程。這些線程里如果使用rtl的信號作為系統還活著的參照,一定要萬分的小心,萬分的小心,萬分的小心。
第一點小心是該停止但是停不下來,取材自上個月的bug。場景很簡單,#100 @harness.dut.hand_en這個線程里hand_en做錯了,進入了無限發包無限握手的死循環,帶著環境也一直停不下來看門狗直接失效了。
第二點小心是該仿真但是挺下來了,這個事我以前就沒想過能出現。事故現場是這樣的還是#100 @harness.dut.hand_en這個線程(就是這么頭鐵,出過錯了還繼續用),這次確實是RTL正常的發包握手,但是,性能模式下外部沒有反壓拍拍握手成功,hand_en起來之后就沒見到下降沿!這就導致了什么問題呢,導致@harness.dut.hand_en線程根本就觸發不了!這就涉及到@和wait的區別了,@捕捉的是event trigger是信號的跳變,harness.dut.hand_en恒1不跳導致看門狗直接超時了。
簡直目瞪口呆,只要每天比別人多碰到3個bug,兩年能積累別人五年經驗。
事故解決
我把@harness.dut.hand_en改成wait harness.dut.hand_en了
-
看門狗
+關注
關注
10文章
565瀏覽量
70877 -
RTL
+關注
關注
1文章
385瀏覽量
59876 -
UVM
+關注
關注
0文章
182瀏覽量
19197 -
Watchdog
+關注
關注
0文章
11瀏覽量
9434
發布評論請先 登錄
相關推薦
評論