SV中的線程


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM