SV中線程之間的通信可以讓驗證組件之間更好的傳遞transaction。
SV對verilog建模方式的擴展:1) fork.....join 必須等到塊內的所有線程都執行結束后,才能繼續執行塊后的語句。(所以使用的很少)
2) fork.....join_none 先執行塊后的線程,而后再執行塊內的線程。不會產生塊后的線程必須等塊內線程的情形。
3) fork.....join_any 只要塊內的線程有一個執行結束,就執行塊之后的線程。
需要說明一下,begin.....end之間的順序操作,只要先前的進程已經開始執行,那之后的進程就會開始執行。在2例中a = b線程先於c = a線程執行,但倆者都是在
零時刻執行,因為阻塞賦值都是一個仿真時間區域,所以最后的結果是c = b;如果改成a <= b;因為同一個仿真時刻,阻塞賦值在非阻塞賦值之前,所
以最后的結果是c = a; a <= b; (未仿真檢測)
在例1中,0時刻a = b線程被#2阻塞,c=a線程因為a = b還未執行結束也阻塞。2個仿真單位之后,a=b線程結束,開始c = a線程,被#3阻塞,又
過3個仿真單位后,執行結束。
begin begin
#2 a = b; a = b;
#3 c = a; c = a;
end end
線程中的自動變量:兩種用法,#0會阻塞$display任務,而讓for循環在仿真時刻0時,就先於$display執行好。
initial begin initial begin
for(int j=0;j<3;j++) for(int j=0;j<3;j++) begin
fork int k = j;
automatic int k = j; fork
$write(k); $write(k);
join_none join_none end
#0$display; #0$display;
end end
停止一個線程:
task check_trans(Transaction tr);
fork begin
fork:time_out
begin
wait(bus.cb.addr == tr.addr);
$display("@%0t:Address Match", $time);
end
#TIME_OUT $display("@%0t:Error", $time);
join
join_any
disable time_out //進程塊名
endtask
事件通信:1)同verilog一樣的,@, ->操作符,邊沿阻塞。因為event是零脈沖,所以這種方式,當->在@之前時,同一個event不能被發現觸發。
->>在nonblocking的區域執行觸發
2)SV擴展的電平檢測triggered()函數。wait(e1.triggered()),在當前時間的最后執行,保證如果當前時間有觸發,則不會引起阻塞
在驗證經常將event參數放在類的new的參數列表中,同mailbox一樣,之后會說到。這樣方便直接在頂層通過event或mailbox連接構件。
旗語互斥訪問:semaphore來創建,new函數構建,put獲得一個,get得到一個,得不到或放不進時,阻塞進程。try_get(),同get但是不會被阻塞。
郵箱通信:mailbox來創建,new函數來構建,put移出數據,get移入數據,peek對FIFO數據的copy不會移入移出。mailbox內存放的是句柄不會是對象。
mailbox默認都是typeless的,這樣在producer和consumer之間,可能會出現類型出錯的情況,這樣只能在run_time中發現錯誤;
使用參數化的mailbox,可以在compile的時候,就發現在這個問題;
local static mailbox #(uvm_phase) m_phase_hopper = new(); 只接受phase類型的指針;
mailbox內自定義的函數,num(),put()/try,get/try()
class Generator; class Driver;
Transactin tr; Transactin tr;
mailbox mbx; mailbox mbx;
function new(mailbox mbx) function new(mailbox mbx)
this.mbx = mbx; this.mbx = mbx;
endfunction endfunction
task run(int count); task run(int count);
repeat(count) begin repeat(count) begin
tr = new(); mbx.get(tr);
assert(tr.randomize); ........
mbx.put(tr); ..........
end
endtask
endclass endclass
program automatic mailbox_example(arbif......)
'include "Generator.sv"
'include "Driver.sv"
'include "Transaction.sv"
mailbox mbx;
Generator gen;
Driver drv;
int count;
initial begin
count = $urandom_range(50);
mbx = new();
gen = new(mbx); //gen與drv同一個mailbox來傳遞transaction
drv = new(mbx);
......................
end