1、線(xiàn)程的使用
1.1程序和模塊
? module (模塊)作為SV從Verilog繼承過(guò)來(lái)的概念,自然地保持了它的特點(diǎn)除了作為RTL模型的外殼包裝和實(shí)現(xiàn)硬件行為, 在更高層的集成層面,模塊之間也需要通信和同步。
? 對(duì)于硬件的過(guò)程塊,它們之間的通信可理解為不同邏輯/時(shí)序塊之間的通信或者同步,是通過(guò)信號(hào)的變化來(lái)完成的。
? 從硬件實(shí)現(xiàn)的角度來(lái)看,Verilog通過(guò)always,initial過(guò)程語(yǔ)句塊和信號(hào)數(shù)據(jù)連接實(shí)現(xiàn)進(jìn)程間通信。
? 我們可以將不同的module作為獨(dú)立的程序塊,他們之間的同步通過(guò)信號(hào)的變化(event觸發(fā))、等待特定事件(時(shí)鐘周期)或者時(shí)間(固定延時(shí))來(lái)完成。
如果按照軟件的思維理解硬件仿真,仿真中的各個(gè)模塊首先是獨(dú)立運(yùn)行的線(xiàn)程(thread)。
模塊(線(xiàn)程)在仿真一開(kāi)始便并行執(zhí)行, 除了每個(gè)線(xiàn)程會(huì)依照自身內(nèi)部產(chǎn)生的事件來(lái)觸發(fā)過(guò)程語(yǔ)句塊之外, 也同時(shí)依靠相鄰模塊間的信號(hào)變化來(lái)完成模塊之間的線(xiàn)程同步。
? 線(xiàn)程即獨(dú)立運(yùn)行的程序。
? 線(xiàn)程需要被觸發(fā), 可以結(jié)束或者不結(jié)束。
? 在module中的initial和always,都可以看做獨(dú)立的線(xiàn)程,它們會(huì)在仿真0時(shí)刻開(kāi)始,而選擇結(jié)束或者不結(jié)束。
? 硬件模型中由于都是always語(yǔ)句塊 , 所以可以看成是多個(gè)獨(dú)立運(yùn)行的線(xiàn)程, 而這些線(xiàn)程會(huì)一直占用仿真資源, 因?yàn)樗鼈儾⒉粫?huì)結(jié)束。
? 軟件測(cè)試平臺(tái)中的驗(yàn)證環(huán)境都需要由initial語(yǔ)句塊去創(chuàng)建, 而在仿真過(guò)程中, 驗(yàn)證環(huán)境中的對(duì)象可以創(chuàng)建和銷(xiāo)毀, 因此軟件測(cè)試端的資源占用是動(dòng)態(tài)的。
軟件環(huán)境中的initial塊對(duì)語(yǔ)句有兩種分組方式 , 使用begin ... end或fork... join。
begin ... end的語(yǔ)句以順序的方式執(zhí)行,而fork...join中的語(yǔ)句則以并發(fā)方式執(zhí)行。
與fork... join類(lèi)似的并行方式語(yǔ)句還包括fork...join_any,fork...join_none.
? 線(xiàn)程的執(zhí)行軌跡是呈樹(shù)狀結(jié)構(gòu)的, 即任何的線(xiàn)程都應(yīng)該有父線(xiàn)程。
? 父線(xiàn)程可以開(kāi)辟若干個(gè)子線(xiàn)程, 父線(xiàn)程可以暫?;蛘呓K止子線(xiàn)程。
? 當(dāng)子線(xiàn)程終止時(shí), 父線(xiàn)程可以繼續(xù)執(zhí)行。
? 當(dāng)父線(xiàn)程終止時(shí), 其所開(kāi)辟的所有子線(xiàn)程都應(yīng)當(dāng)會(huì)終止。
2、線(xiàn)程的控制
2.1 fork.... join
//fork...join initial begin $display("@%0t:start fork... join example", $time); #10 $display("@%0t:sequential after #10", $time); fork $display("@%Ot: parallel start", $time); #50 $display("@%0t:parallel after #50", $time); #10 $display("@%0t: parallel after #lO", $time); begin #30 $display("@%0t:sequential after #30", $time); #10 $display("@%0t:sequential after #10", $time); end join $display ("@%0t:after join", $time); #80 $display("@%0t: finish after #80", $time); end?
打印代碼:
@0: start fork... join example
@10: sequential after #10
@10: parallel start
@20: parallel after #10
@40: sequential after #30
@50: sequential after #10
@60: parallel after #50
@60: after join
@140: finish after #80
2.2 fork...join_any
//fork...join_any initial begin $display("@%0t:start fork... join_any example", $time); #10 $display("@%0t:sequential after #10", $time); fork $display("@%Ot: parallel start", $time); #50 $display("@%0t:parallel after #50", $time); #10 $display("@%0t: parallel after #lO", $time); begin #30 $display("@%0t:sequential after #30", $time); #10 $display("@%0t:sequential after #10", $time); end join_any $display ("@%0t:after join", $time); #80 $display("@%0t: finish after #80", $time); end
打印代碼:
@0: start fork... join_any example
@10: sequential after #10
@10: parallel start
@10: after join_any
@20: parallel after #10
@40: sequential after #30
@50: sequential after #10
@60: parallel after #50
@90: finish after #80
2.3 fork...join_none
//fork...join_none initial begin $display("@%0t:start fork... none example", $time); #10 $display("@%0t:sequential after #10", $time); fork $display("@%Ot: parallel start", $time); #50 $display("@%0t:parallel after #50", $time); #10 $display("@%0t: parallel after #lO", $time); begin #30 $display("@%0t:sequential after #30", $time); #10 $display("@%0t:sequential after #10", $time); end join_none $display ("@%0t:after join_none", $time); #80 $display("@%0t: finish after #80", $time); end
打印代碼:
@0: start fork... join_none example
@10: sequential after #10
@10: after join_none
@10: parallel start
@20: parallel after #10
@40: sequential after #30
@50: sequential after #10
@60: parallel after #50
@90: finish after #80
2.4 等待所有衍生線(xiàn)程
? 在SV中, 當(dāng)程序中的initial塊全部執(zhí)行完畢, 仿真器就退出了。
? 如果我們希望等待fork塊中的所有線(xiàn)程執(zhí)行完畢再退出結(jié)束initial塊, 我們可以使用wait fork語(yǔ)句來(lái)等待所有子線(xiàn)程結(jié)束。
task run_threads; ... fork check_trans(trl); //線(xiàn)程1 check_trans(tr2); //線(xiàn)程2 check_trans(tr3); //線(xiàn)程3 join_none ... //等待所有fork中的線(xiàn)程結(jié)束再退出task wait fork; endtask
2.5 停止單個(gè)線(xiàn)程
在使用了fork.. join_any或者fork... join_none以后,我們可以使用disable來(lái)指定需要停止的線(xiàn)程。
parameter TIME_OUT = 1000; task check_trans{Transaction tr); fork begin //等待回應(yīng),或者達(dá)到某個(gè)最大時(shí)延 fork: timeout_block begin wait(bus.cb.addr == tr.addr); $display("@%0t: Addr match %d", $time, tr.addr); end #TIME_ OUT $display ("@%0t:Error: timeout, $time); join_any disable timeout_block; end join_none endtask
2.6 停止多個(gè)線(xiàn)程
disable fork可以停止從當(dāng)前線(xiàn)程中衍生出來(lái)的所有子線(xiàn)程。
initial begin check_trans(trO); //線(xiàn)程0 //創(chuàng)建一個(gè)線(xiàn)程來(lái)限制disable fork的作用范圍 fork//線(xiàn)程1 begin check_trans(trl); //線(xiàn)程2 fork//線(xiàn)程3 check_trans(tr2); / /線(xiàn)程4 join //停止線(xiàn)程1-4, 單獨(dú)保留線(xiàn)程0 #(TIME_OUT/2) disable fork end join end
2.7 停止被多次調(diào)用的任務(wù)
如果你給某—個(gè)任務(wù)或者線(xiàn)程指明標(biāo)號(hào), 那么當(dāng)這個(gè)線(xiàn)程被調(diào)用多次以后 , 如果通過(guò)disable去禁止這個(gè)線(xiàn)程標(biāo)號(hào), 所有衍生的同名線(xiàn)程都將被禁止。
task wait_for_time_out(int id); if (id == 0) fork begin #2; $display("@%0t:disable wait_for_time_out"' $time); disable wait_for_time_out; end join_none fork : just_a_little begin $display ("@%0t:%m: %0d entering thread", $time, id); #TIME_OUT; $display("@%0t:%m: %0d done", $0ime, id); end join_none endtask initial begin wait_for_time_out(0); // Spawn thread 0 wait_for_time_out(1); // Spawn thread 1 wait_for_time_out(2); // Spawn thread 2 #(TIME_OUT*2) $display("@%0t:All done", $time); end
? 任務(wù)wait_for_time_out被調(diào)用了三次, 從而衍生了三個(gè)線(xiàn)程。
? 線(xiàn)程0在#2延時(shí)之后禁止了該任務(wù),而由于三個(gè)線(xiàn)程均是“ 同名”線(xiàn)程, 因此這些線(xiàn)程都被禁止了, 最終也都沒(méi)有完成。
內(nèi)容來(lái)源:IC修真院優(yōu)秀學(xué)員
審核編輯:湯梓紅
-
Verilog
+關(guān)注
關(guān)注
28文章
1351瀏覽量
110074 -
時(shí)鐘
+關(guān)注
關(guān)注
10文章
1733瀏覽量
131446 -
RTL
+關(guān)注
關(guān)注
1文章
385瀏覽量
59761 -
程序
+關(guān)注
關(guān)注
117文章
3785瀏覽量
81004 -
線(xiàn)程
+關(guān)注
關(guān)注
0文章
504瀏覽量
19675
原文標(biāo)題:IC學(xué)霸筆記 | SV線(xiàn)程
文章出處:【微信號(hào):IC修真院,微信公眾號(hào):IC修真院】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論