01 Arbitrary
在UVM中,多個(gè)sequence可以同時(shí)被綁定到相同的sequencer并啟動(dòng)。這種測(cè)試場(chǎng)景在實(shí)際中是存在的,比如在模擬同一個(gè)總線master口上的不同類型的數(shù)據(jù)流時(shí),可以將符合這些不同類型的數(shù)據(jù)流的sequence綁定到同一個(gè)sequencer,并啟動(dòng)它們,以構(gòu)造出復(fù)雜的測(cè)試場(chǎng)景。
這樣一來(lái),在驗(yàn)證環(huán)境運(yùn)行中就會(huì)出現(xiàn)競(jìng)爭(zhēng)的問題,當(dāng)多個(gè)sequence同時(shí)企圖向下游發(fā)transaction的時(shí)候,sequencer需要能夠決定處理這些transaction的順序。而給出答案的,是sequencer內(nèi)建的仲裁機(jī)制。
下面給出一個(gè)簡(jiǎn)單的UVM例程:例程同時(shí)啟動(dòng)三個(gè)sequence(seq_0, seq_1, seq_2),它們會(huì)往同一個(gè)sequencer發(fā)transaction,并且在啟動(dòng)的時(shí)候還分配了權(quán)重值(start方法的第三個(gè)參數(shù)),每個(gè)sequence會(huì)循環(huán)發(fā)送4個(gè)transaction。
在Env中例化sequencer和driver,并完成連接。例程中在driver拿到transaction之后,會(huì)根據(jù)transaction的成員變量id和index打印出來(lái)當(dāng)前transaction產(chǎn)生自哪個(gè)sequence,以及是循環(huán)的第幾次。
仿真結(jié)果如下,可以看得出來(lái)在沒有配置仲裁算法的情況下,即使我們?yōu)閟equence都分配了權(quán)重值,sequencer對(duì)三個(gè)sequence還是“雨露均沾”:
實(shí)際上,UVM給我們預(yù)設(shè)了六種仲裁算法供選擇,同時(shí)保留了用戶自定義的接口。默認(rèn)情況下,使用的仲裁算法是UVM_SEQ_ARB_FIFO,嚴(yán)格按照先進(jìn)先出的原則來(lái)做選擇,所以才會(huì)出現(xiàn)上面說的,仿真結(jié)果跟權(quán)重值沒有關(guān)系。關(guān)于仲裁算法,需要根據(jù)實(shí)際測(cè)試場(chǎng)景來(lái)做出選擇。
那么如何配置仲裁算法?在代碼中,可以通過調(diào)用sequencer的方法set_arbitration()來(lái)對(duì)仲裁算法進(jìn)行配置。比如在上面例程env_demo類的build_phase函數(shù)的最后一行,可以加上sqr.set_arbitration(UVM_SEQ_ARB_WEIGHTED)來(lái)配置仲裁算法,仿真結(jié)果我貼在下面,可以看到,我們分配的權(quán)重值開始起作用了:
02 LockingMechanism
Locking mechanism指的是sequence對(duì)sequencer的占用,sequence可以優(yōu)先獲得sequencer的使用權(quán)限,并且在它自己釋放之前,其他sequence無(wú)法通過該sequencer和driver發(fā)送transaction。
Sequence搶占功能同樣來(lái)源于測(cè)試場(chǎng)景的需求,應(yīng)用于當(dāng)有某個(gè)sequence需要優(yōu)先并獨(dú)占sequencer的時(shí)候,比如對(duì)中斷(interrupt)的處理。如下圖所示,當(dāng)sequence_2占用了sequencer之后,其他sequence在sequence_2釋放之前將無(wú)法聯(lián)系上sequencer。
UVM提供了兩種搶占方法:lock和grab。lock方式會(huì)等待仲裁機(jī)制正常調(diào)度到該sequence(即將請(qǐng)求放在仲裁隊(duì)里的最后),并占用該sequencer直到sequence調(diào)用unlock()來(lái)解鎖;grab方式則會(huì)使該sequence在下一輪仲裁中被執(zhí)行(即將請(qǐng)求放在仲裁隊(duì)列的最前面),并占用該sequencer直到sequence調(diào)用unlock()和ungrab()。
Sequencer被某個(gè)sequence搶占了之后,我們可以通過調(diào)用它的成員方法來(lái)獲取當(dāng)前的狀態(tài)信息。比如,可以在sequence的body()里面使用m_sequencer.is_grabbed()函數(shù)來(lái)看當(dāng)前sequencer是不是被誰(shuí)鎖住了;還可以使用m_sequencer.current_grabber()函數(shù)來(lái)獲得當(dāng)前鎖住sequencer的sequence句柄;還有其他函數(shù)可以使用,具體可以參考UVM的手冊(cè)。
關(guān)于lock和grab的使用在其他地方有很多示例代碼,這里將基于上面的例程,展示UVM 1.2潛藏的一個(gè)bug。先在上述代碼中seq_demo_0類的body()任務(wù)的入口和出口處,分別加上lock()和unlock(),如上圖所示,然后進(jìn)行仿真,就會(huì)發(fā)現(xiàn):最終只有seq_0搶先鎖住了sequencer,雖然我們?cè)赽ody()的最后調(diào)用了unlock(),但是seq_1和seq_2在seq_0結(jié)束之后依然搶不到鎖,仿真最后結(jié)束在UVM timeout,如下圖:
這是一個(gè)UVM的bug,問題的根源在uvm_sequencer_base的源碼中,當(dāng)有多個(gè)sequence在lock_list隊(duì)列里面時(shí),調(diào)用m_wait_for_available_sequence()方法獲取sequence句柄會(huì)使代碼掛死。該UVM issue已經(jīng)有人提交到了accellera,具體可以參見參考資料2。這個(gè)bug在UVM 2017-1.1或者UVM 2020中可能已經(jīng)修掉了,有興趣的讀者可以自己試一下。鑒于目前有很多代碼是基于UVM 1.2構(gòu)建的,用戶在使用lock/grab的時(shí)候需要特別注意這個(gè)bug。
03Sequence Interrupt
在處理器等數(shù)字系統(tǒng)中,通常硬件中斷都是由某個(gè)信號(hào)脈沖或者電平來(lái)觸發(fā),并通過中斷控制仲裁之后,由控制器發(fā)送給處理器進(jìn)行處理。
在Sequence中的中斷操作也類似,分兩部分實(shí)現(xiàn):第一部分是將通過虛擬接口監(jiān)視中斷源信號(hào)的變化,以實(shí)現(xiàn)軟硬件的隔離;第二部分是在主sequence中發(fā)起一個(gè)監(jiān)視進(jìn)程(monitor process),在等到中斷到來(lái)之后啟動(dòng)用作中斷處理的sequence。
另外,Sequence一旦被啟動(dòng),通常不會(huì)去想著將它異常結(jié)束(通過seq.kill()或者seqr.stop_sequences()調(diào)用),否則我們需要更加復(fù)雜的實(shí)現(xiàn)去查看當(dāng)前driver是否空閑,以確保sequencer跟driver的握手機(jī)制不出問題。如果有必要將sequence提前結(jié)束,建議在sequence內(nèi)部去做條件判斷和處理。
審核編輯:劉清
-
處理器
+關(guān)注
關(guān)注
68文章
19259瀏覽量
229653 -
控制器
+關(guān)注
關(guān)注
112文章
16332瀏覽量
177812 -
UVM
+關(guān)注
關(guān)注
0文章
182瀏覽量
19167 -
FIFO存儲(chǔ)
+關(guān)注
關(guān)注
0文章
103瀏覽量
5968
原文標(biāo)題:SystemVerilog | UVM | Sequence的仲裁和鎖定,還有要避開UVM的bug
文章出處:【微信號(hào):處芯積律,微信公眾號(hào):處芯積律】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論