注1:上圖有些問題,其中uvm_sequencer內的uvm_seq_item_pull_port應該改為uvm_seq_item_pull_imp;
1.sequencer與driver通信基礎
(1) 一個sequence在向sequencer發送transaction前,會先向sequencer發送一個請求, sequencer把這個請求放在一個仲裁隊列中. sequencer主要做兩件事情: 檢測仲裁隊列里是否有某個sequence發送transaction的請求; 檢測driver是否申請transaction.
(1.1) 如果仲裁隊列里有發送請求,但driver沒有申請transaction, 那么sequencer將會一直處於等待driver的狀態,直到driver申請新的transaction; 此時sequencer同意sequence的發送請求, sequence在得到sequencer的批准后, 產生出一個transaction並交給sequencer, 后者把這個transaction交給driver;
(1.2)如果仲裁隊列中沒有發送請求,但是driver向sequencer申請新的transaction,那么sequencer將會處於等待sequence的狀態,一直到有sequence遞交發送請求,sequencer馬上同意這個請求, sequence產生transaction並交給sequencer, 最終driver獲得這個transaction;
(1.3)如果仲裁隊列中有發送請求,同時driver也在向sequencer申請新的transaction,那么將會同意發送請求, sequence產生transaction並交個sequencer, 最終driver獲得這個transaction.
(2) driver與sequencer之間的TLM通信采用get模式,即由driver發起請求,從sequencer一端獲得item, 再由sequencer將其傳遞給driver(driver獲取的REQ sequence_item來源於sequencer的request FIFO);
(3) 由於driver是請求發起端,sequencer是請求響應端,所以二者例化的端口分別如下:
(4) driver消化完當前的request后,可以通過以下幾種方式發送response(driver返回的RSP sequence_item放到sequencer的response FIFO);:
(4.1) 方法一:item_done (input RSP rsp_arg=null)方法來告知sequence此次傳輸已經結束. 參數中的RSP可以選擇填入.
driver使用get_next_item得到一個transaction時, sequencer也保留一份剛發送出的transaction; 當出現sequencer發出了transaction, 而driver沒有收到的情況時, sequencer會把保留的這份transaction再發送出去. 如果在下次調用get_next_item前, item_done被調用, 那么sequencer就認為driver已經得到了這個transaction,將會把這個transaction刪除. 這是為了增加可靠性而使用的握手機制.
(4.2) 方法二:driver也可以通過put_response()或者put()方法來單獨發送response.
(4.3) 方法三:發送response可以通過成對的uvm_driver.rsp_port和uvm_sequencer.rsp_export端口來完成. (uvm_driver.rsp_port.write(RSP)).
2.seqr與driver交互的方法
注:get_next_item/get/peek會導致sequencer發起仲裁過程,接着返回有效的sequence_item句柄;
2.1 get_next_item
(1)阻塞,直到sequencer的request FIFO中有可用的REQ sequence_item,該方法返回一個REQ句柄;
(2) get_next_item實現了driver-seqr握手協議的一半,當握手協議完成時,需要調用item_done();在調用item_done之前,再次調用get_next_item會導致協議錯誤,並引起driver-seqr死鎖;
2.2 try_next_item
(1) get_next_item的非阻塞變形;當seqr的request FIFO內有可用的REQ sequence_item時,會返回REQ句柄;當seqr的request FIFO內沒有可用的REQ sequence_item時,會返回null;
(2)如果try_next_item返回一有效的REQ句柄,后面需要調用item_done完成握手;
2.3 item_done
(1) 用來通知sequence當前的sequence item已經消化完畢;
(2) 如果item_done傳遞了一個RSP sequence_item句柄作為參數,那么該RSP sequence item句柄將會被放到sequencer的response FIFO內; 然后,再傳遞給sequence;
2.4 peek
2.5 get
(1) 完全可以用來代替get_next_item;
(2) get/peek/put完全是繼承基類的方法;
2.6 put/put resonse
(1)put采用blocking方式將response發送回sequence;
(2)put_response采用nonblocking方式將response發送回sequence;
2.7 set_id_info
(1) 當有多個sequences通過sequencer和一個driver交互時,sequencer負責哪個sequence的哪個sequence_item傳遞給driver;當driver創建了response sequence_item后,該response sequence_item需要route到正確的sequence. UVM通過給每一個sequence_item的id成員變量賦值,來判斷其parent sequence; sequencer也會使用這些id變量將response sequence_item route到正確的parent sequence.
(2)在調用start_item時,sequencer會為request sequence_item設置id信息; response sequence_item需要copy request sequence_item的id信息,以便於它能夠route到正確的sequence上,set_id_info提供了這樣的功能;
2.8 wait_for_sequences
(1) 等待當前的sequence直到產生下一個有效的item;
3.seqr與driver通信示例一
注1:該示例中,seqr和driver的REQ與RSP類型均采用默認類型uvm_sequence_item,當然還可以指定REQ與RSP的類型,后續需要補充示例;
4.seqr與driver通信示例二
5.seqr與driver通信示例三