zoukankan      html  css  js  c++  java
  • fork_join

    在systemverilog中可以用fork…… join、fork ……join_any、fork……join_none来实现多个线程的并发执行。

    1、父线程、子线程

    调用fork……join的线程为父线程,fork……join中并发执行的是子线程,子线程可有多个,父线程只有一个。

    无延时情况下竞争问题:

      1.无延时情况下,主线程无延时语句优先于子线程无延时语句先执行

      2.无延时优先于#0(零延时),无延时语句优先于零延时语句先执行。

    2、阻塞父线程

    (1)调用fork……join会阻塞父线程,直到子线程全部结束,才会启动父线程。

    program test;
        initial begin
            fork
                $display("child");  // fork下的子线程,并发执行
                $display("child");  // fork下的子线程,并发执行
                $display("child");  // fork下的子线程,并发执行
                #0 $display("child");  // fork下的子线程,并发执行
            join
            $display("father");    // begin块下的父线程,顺序执行
            $display("father");    // begin块下的父线程,顺序执行
            $display("father");    // begin块下的父线程,顺序执行
            #0 $display("father");    // begin块下的父线程,顺序执行
        end
    endprogram

    fork……join中有4个子线程,要执行完4个子线程后才会执行父线程,输出为:

     (2)、fork……join_any也会阻塞父线程,不过任意一个子线程结束后就执行父线程,且当父线程执行完所有的无延时语句后才会把权限交给子线程。遇到# N延时语句后子线程与父线程开始竞争。父线程有优先权,当父线程有权限后会优先执行完所有无延时语句,才会让子线程执行无延时语句。有延时语句父线程和子线程公开竞争。

    program test;
        initial begin
            fork
                $display("child");  // fork下的子线程,并发执行
                $display("child");  // fork下的子线程,并发执行
                $display("child");  // fork下的子线程,并发执行
                #0 $display("child");  // fork下的子线程,并发执行
            join_any
            $display("father");    // begin块下的父线程,顺序执行
            $display("father");    // begin块下的父线程,顺序执行
            $display("father");    // begin块下的父线程,顺序执行
            #0 $display("father");    // begin块下的父线程,顺序执行
        end
    endprogram

     (3)、fork……join_none不会阻塞父线程,且执行完父线程无延时的语句后才会将权限交给子线程。遇到# N的延时语句后,子线程与父线程开始竞争。父线程有优先权,当父线程有权限后会优先执行完所有无延时语句,才会让子线程执行无延时语句。有延时语句父线程和子线程公开竞争。

    program test;
        initial begin
            fork
                $display("child");  // fork下的子线程,并发执行
                $display("child");  // fork下的子线程,并发执行
                $display("child");  // fork下的子线程,并发执行
                #0 $display("child");  // fork下的子线程,并发执行
            join_none
            $display("father");    // begin块下的父线程,顺序执行
            $display("father");    // begin块下的父线程,顺序执行
            $display("father");    // begin块下的父线程,顺序执行
            #0 $display("father");    // begin块下的父线程,顺序执行
        end
    endprogram

     3、结束子线程

    (1)、disable lable结束lable所指定的线程和子线程。(可以结束fork,也可以结束begin)如果fork块进入多次,用disalbe lable的方式会结束所有的进程。比如一个task中有fork块,这个task调用多次,如果task中的某一次调用执行了disalbe语句,会disalbe掉多次调用的产生的所有线程。

    program test;
        initial begin
            fork:fork1
                $display("child");  // fork下的子线程,并发执行
                $display("child");  // fork下的子线程,并发执行
                $display("child");  // fork下的子线程,并发执行
                #0 $display("child");  // fork下的子线程,并发执行
                fork
                      $display("child");
                join
            join_none
            fork:fork2
                  $display("child21");
                  fork
                       #2 $dipslay("child22");
                  join
    #2 display("child23"); join_none #1 disable fork2; // 1ns后,结束fork2下的子线程 $display("father"); // begin块下的父线程,顺序执行 $display("father"); // begin块下的父线程,顺序执行 $display("father"); // begin块下的父线程,顺序执行 #0 $display("father"); // begin块下的父线程,顺序执行 end endprogram

     (2)disable fork

    disable fork语句会结束disable fork所在进程所生成出的所以子线程,及子线程的子线程。

    program test;
        initial begin
            fork:fork1
                $display("child");  // fork下的子线程,并发执行
                #2 $display("child");  // fork下的子线程,并发执行
                #2 $display("child");  // fork下的子线程,并发执行
                #2 $display("child");  // fork下的子线程,并发执行
                fork
                      #2 $display("child");
                join
            join_none
            fork:fork2
                  $display("child21");
                  fork
                       #2 $dipslay("child22");
                  join
                  #2 display("child23");
            join_none
            #1 disable fork;       // 1ns后,结束fork1和fork2下的子线程。
            $display("father");    // begin块下的父线程,顺序执行
            $display("father");    // begin块下的父线程,顺序执行
            $display("father");    // begin块下的父线程,顺序执行
            #0 $display("father");    // begin块下的父线程,顺序执行
        end
    endprogram 

     4、等待进程结束

    wait fork等待当前线程的所以子线程结束(不包括子线程的子线程。)

    program automatic test;
    
        initial begin
            fork
                #99 $display("#99");   // 等待这个子线程
                fork
                    #100 $display("#100"); // 不等待子线程的子线程
                join_none
            joine_none
            wait fork;
            $display("after waite");
        end
    
    endprogram

     5、for-fork:多线程的变量问题

    1、copy变量应该在fork内,且copy给automatic变量,线程例化后,先初始化这些变量后再例化其他线程。

    2、for-fork有变种,比如function中有fork,for来调用function

    class cbk;
    
        task run();
            for(int i=0; i<10; i++)begin
                fork
                    int j = i; // class 中的都是默认是automatic变量
                    begin
                        #10ns; 
                        $display(j); 
                    end
                join_none
            end
        endtask
    
    endclass

    x

  • 相关阅读:
    .net Core自定义中间件中读取Request.Body和Response.Body的内容?
    团队项目的Git分支管理规范
    .net core2.2升级3.1
    .net core EF获取SQL
    EF 查询扩展
    IIS Express启动不了的的解决方案
    AutoMapper
    mssql 数据库“查询处理器用尽了内部资源,无法生成查询计划。”问题的处理
    微服务九大特性
    Flink入门
  • 原文地址:https://www.cnblogs.com/yuandonghua/p/11990687.html
Copyright © 2011-2022 走看看