禁用fork在fork-join的无限循环中的使用

huangapple go评论65阅读模式
英文:

Use of disable fork inside forever loop of fork-join

问题

在上述任务中,一旦ack_arrival完成,"disable fork"会终止整个任务,而不是仅终止进程,因此任务不会检测到任何其他"req"更改。有人可以解释为什么会这样吗?

不好意思,我已经翻译了内容并提供了翻译的代码,不会回答关于要翻译内容的问题。

英文:

I am having "disable fork" inside a fork-join which embeds inside forever begin.
So I am expecting every time new process would be created & killed once either of the thread gets finished. But it runs only once .

I am having the below code which is executing only once.

module tb();
  
  `timescale 1ns/1ns
  
  bit clk;
  
  always #2 clk =~ clk;
  
  task automatic req_ack(ref bit req, ref bit ack, input string name);
    forever begin
          $display("waiting for req");
          @(req);
          $display("Req changed at %t for %0d", $time, req);
          fork
            begin
              #5us;
              $display("ACK expired");
              disable fork;
            end
            begin
              wait(ack == req); //This will succeed
              $display("Ack received for %s at %t", name, $time);                    
              disable fork;
            end
          join
    end
  endtask
        
  bit tx_req, tx_ack;
        
  initial begin
    repeat(5) @(posedge clk);
    tx_req = 1;
    repeat(5) @(posedge clk);
    tx_ack = 1;
    $display("ack from tb at %t", $time);
    repeat(5) @(posedge clk);
    tx_req = 0;
    repeat(5) @(posedge clk);
    tx_ack = 0;    
    repeat(15) @(posedge clk);
    $finish;
  end
        
  initial begin
    req_ack(tx_req, tx_ack, "TX");
  end
  
  
endmodule

In the above task, once ack_arrival gets finished, " disable fork" kills the whole task instead of the process such that task doesn't detect any other "req" change.
Can someone please explain why does it so ?

答案1

得分: 4

`disable fork`禁用当前线程的_children_。你的语句在forked进程中,该进程没有子进程。所以`join`直到你的过期超时在**5µs**发生之前都不会发生。但是,在此之前的138ns,你调用了`$finish`,它根本不会有机会发生。如果你将过期延迟更改为**5ns**,你将看到发生了什么。

你应该立即在`fork/join_any`之后使用`disable fork`。


```Verilog
// `timescale 需要放在模块外部

 `timescale 1ns/1ns


module tb();
  
  
  bit clk;
  
  always #2 clk =~ clk;
  
  task automatic req_ack(ref bit req, ref bit ack, input string name);
    bit local_req, local_ack; 
    fork
      // 用于在fork/join_any中访问引用参数的解决方法
      forever @req local_req = req;
      forever @ack local_ack = ack;
      forever begin
        $display("waiting for req");
        @(req);
        $display("Req changed at %t for %0d", $time, req);
        fork
          begin
            #5us;
            $display("ACK expired");
          end
          begin
            wait(local_ack == local_req); //这将成功
            $display("Ack received for %s at %t", name, $time);                    
          end
        join_any
        disable fork;
      end
    join
  endtask
        
  bit tx_req, tx_ack;
        
  initial begin
    repeat(5) @(posedge clk);
    tx_req <= 1; // 使用NBA以避免tb竞态条件
    repeat(5) @(posedge clk);
    tx_ack <= 1;
    $display("ack from tb at %t", $time);
    repeat(5) @(posedge clk);
    tx_req <= 0;
    repeat(5) @(posedge clk);
    tx_ack <= 0;    
    repeat(15) @(posedge clk);
    $finish;
  end
        
  initial begin
    req_ack(tx_req, tx_ack, "TX");
  end
  
  
endmodule
英文:

disable fork disables the children of the current thread. Your statement is inside the forked process which has no children. So the join cannot happen until your expiration timeout occurs at 5µs. But, you call $finish at 138ns before that ever has a chance of happening. If you change your expiration delay to 5ns, you will see what is happening.

You should use fork/join_any with a disable fork immediately afterwards.

// `timescale needs to go outside module

 `timescale 1ns/1ns


module tb();
  
  
  bit clk;
  
  always #2 clk =~ clk;
  
  task automatic req_ack(ref bit req, ref bit ack, input string name);
    bit local_req, local_ack; 
    fork
      // workaround for accessing ref arguments in fork/join_any
      forever @req local_req = req;
      forever @ack local_ack = ack;
      forever begin
        $display("waiting for req");
        @(req);
        $display("Req changed at %t for %0d", $time, req);
        fork
          begin
            #5us;
            $display("ACK expired");
          end
          begin
            wait(local_ack == local_req); //This will succeed
           $display("Ack received for %s at %t", name, $time);                    
          end
        join_any
        disable fork;
      end
    join
  endtask
        
  bit tx_req, tx_ack;
        
  initial begin
    repeat(5) @(posedge clk);
    tx_req <= 1; // use NBA to avoid tb races
    repeat(5) @(posedge clk);
    tx_ack <= 1;
    $display("ack from tb at %t", $time);
    repeat(5) @(posedge clk);
    tx_req <= 0;
    repeat(5) @(posedge clk);
    tx_ack <= 0;    
    repeat(15) @(posedge clk);
    $finish;
  end
        
  initial begin
    req_ack(tx_req, tx_ack, "TX");
  end
  
  
endmodule

答案2

得分: -2

一个有缺陷的解决方案

自动化测试程序;
bit tx_req = 0;
任务 自动 req_ack(引用 bit req);
while(1) begin
@(req);
叉口: STOP_THIS
开始 : 超时
int delay = $urandom_range(1,3);
重复(delay) #1;
$display("timeout thread run");
禁用 STOP_THIS;
end
开始 : ack_arrival
int delay = $urandom_range(1,3);
重复(delay) #1;
$display("ack_arrival thread run"); 
禁用 STOP_THIS;
end 
合并
end
endtask : req_ack
initial begin     
req_ack(tx_req); 
end
initial begin
for(int i=0; i<10; i++) begin
tx_req = i%2;
#10;
end
end            
endprogram
英文:

A flawed solution

program automatic test;
bit tx_req = 0;
task automatic req_ack(ref bit req);
while(1) begin
@(req);
fork: STOP_THIS
begin : timeout
int delay = $urandom_range(1,3);
repeat(delay) #1;
$display(&quot;timeout thread run&quot;);
disable STOP_THIS;
end
begin : ack_arrival
int delay = $urandom_range(1,3);
repeat(delay) #1;
$display(&quot;ack_arrival thread run&quot;); 
disable STOP_THIS;
end 
join
end
endtask : req_ack
initial begin     
req_ack(tx_req); 
end
initial begin
for(int i=0; i&lt;10; i++) begin
tx_req = i%2;
#10;
end
end            
endprogram

Here is the link of testbench EDA playgroup

huangapple
  • 本文由 发表于 2023年2月27日 19:31:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75579910.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定