SystemVerilog for循環中的fork join_none

 

module test;

   initial begin
      main();
   end

   task main();
      // fork join_any block1
      fork
         #5 $display("THREAD 1 %0t", $time);
         #25 $display("THREAD 2 %0t", $time);
      join_any
      dev_state();
      $display("After task call %0t", $time);
      #100 $finish;
   endtask

   task dev_state();
      // fork join_any block2
      fork
         #5 $display("THREAD 3 %0t", $time);
         #10 $display("THREAD 4 %0t", $time);
      join_any
      disable fork;
   endtask

   initial begin
      $display("debug point fork_1");
      fork_1();
      $display("debug point fork_2");
      fork_2();
      $display("debug point fork_3");
      fork_3();
      $display("debug point fork_4");
      fork_4();      
   end
   
   task fork_1();
      for(int i = 0; i < 16; i++) begin
         fork 
            // begin
            automatic int index =i;       
            send(index);
            // end 
         join_none 
      end
      wait fork;
   endtask

   task fork_2();
      for(int i = 0; i < 16; i++) begin
         fork 
            // begin
            automatic int index;
            index = i;          
            send(index);
            // end 
         join_none         
      end
      wait fork;
   endtask

   task fork_3();
      for(int i = 0; i < 16; i++) begin
         fork 
            begin
               automatic int index;
               index = i;         
               send(index);
            end 
         join_none 
      end
      wait fork;      
   endtask

   task fork_4();
      for(int i = 0; i < 16; i++) begin
         automatic int index;
         index = i;         
         fork 
            begin
               send(index);
            end 
         join_none 
      end
      wait fork;      
   endtask

   task send(int j);
      $display("driving port %0d" , j);
   endtask


endmodule
all : clean comp run sim.log 

clean:
	\rm -rf simv* csrc *.key
comp:
	vcs -full64 test.sv -sverilog
run:
	simv -l sim.log
debug point fork_1
driving port 0
driving port 1
driving port 2
driving port 3
driving port 4
driving port 5
driving port 6
driving port 7
driving port 8
driving port 9
driving port 10
driving port 11
driving port 12
driving port 13
driving port 14
driving port 15
debug point fork_2
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
debug point fork_3
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
debug point fork_4
driving port 0
driving port 1
driving port 2
driving port 3
driving port 4
driving port 5
driving port 6
driving port 7
driving port 8
driving port 9
driving port 10
driving port 11
driving port 12
driving port 13
driving port 14
driving port 15
THREAD 1 5
THREAD 3 10
After task call 10

 

使用以上Makefile和test.sv文件,運行仿真,仿真結果如下

可以看到雖然都是fork join_none wait fork但是每一個fork_x task的打印結果是不同的。這是爲什麼呢?

不同之處在於變量index的生存週期,以及何時爲該變量分配變量i的值的時間。

意識到將有16個併發變量名爲index,只有一個名爲i。在情況1)和2)中,每次進入fork / join_none塊時都會創建index變量。在派生fork / join_none中的任何進程之前發生。在情況1)中,變量初始化也發生在fork / join_none中的任何進程之前。您需要記住的是,自動變量是在輸入時創建的,並在執行它們所在的塊中的任何過程語句之前被初始化。因此,在情況1)中,每個索引變量在每次循環迭代中都獲得i的當前值。
在情況2)中,您將初始化移到了單獨的過程分配語句中。 fork / join_none中的每個語句將成爲新的子進程,並且直到當前父線程掛起後,該子進程纔開始執行。現在,for循環會生成16個線程,然後在i的值爲16時在wait fork處掛起。(正如我之前說過的,如果send(index)看到單位值0或分配的值16,這是一個競賽。
在情況3)中,現在在一個begin / end塊內聲明index變量,這是fork / join_none的單個語句。因此,直到所有16個進程都已生成並且i的值爲16時,才創建索引變量。

任何自動變量的生命週期都將在其塊及其所有嵌套塊的生命週期結束時結束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章