(转)systemverilog学习之 FORK JOIN语句
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://mathon.blogbus.com/logs/2050927.html
发现了一个不错的VERILOG学习网站,以后可以经常去看一下
fork...join能够从它的每一个并行语句中产生并发进程。
fork...join块的声明语法如下:
par_block ::= // 引用自附录A.6.3 fork [: block_identifier] {block_item_declaration} {statement_or_null} join_keyword [: block_identifier] join_keyword ::= join | join_any | join_none
语法 9-1—Fork...join块语法(摘录自附录A)
fork...join块可以指定一条或多条语句,每一条语句都应该作为并发进程执行。Verilog fork...join块总是引起执行fork语句的进程阻塞直到所有分支进程中止。通过加入join_any和join_none关键字,SystemVerilog提供了三种选择来指定父进程何时恢复执行。
表 9-1: fork...join控制选项
选项 |
描述 |
join |
父进程会阻塞直到这个分支产生的所有进程结束。 |
join_any |
父进程会阻塞直到这个分支产生的任意一个进程结束。 |
join_none |
父进程会继续与这个分支产生的所有进程并发执行。在父线程执行一条阻塞语句之前,产生的进程不会启动执行。 |
在定义一个fork...join块的时候,将整个分叉封装在一个begin...end块中会引起整个块作为单个进程执行,其中每条语句顺序地执行。
fork begin statement1; // 一个带有2条语句的进程 statement2; end join
在下面的例子中,包含两个进程分支,第一个等待20ns,第二个等待命名事件eventA被触发。因为指定了join关键字,父进程应该阻塞直到这两个进程结束;也就是说,直到过了20ns并且eventA被触发。
fork begin $display("First Block\n"); #20ns; end begin $display("Second Block\n"); @eventA; end join
在一个fork...join语句的关联文中使用return语句是非法的,并且会导致一个编译错误。例如:
task wait_20; fork #20; return; // 非法的:不能返回;任务位于另外一个进程中 join_none endtask
只要fork...join块作用范围内声明的自动变量进入它们的作用范围,在产生任何进程之前,这些自动变量应该被初始化成它们的初始值。这些变量对于循环结构产生的进程存储唯一的、每次都交互的数据非常有用。例如:
initial for(int j = 1; j <= 3; ++j) fork automatic int k = j; // 对每一个j值的本地拷贝 #k $write("%0d", k); begin automatic int m = j; // m的值是不确定的 ... end join_none
上面的例子的输出为:123。
另:http://verificationacademy.com/forum/main-ovm-forum/10089-practicle-application-fork-joinnone
Whenever you fork, you spawn off a set of new concurrent child processes from a parent process. The difference between the join, join_any, and join_none statements is in what the parent process does after the children are spawned off.
join - parent process blocks (waits) until all child processes complete and return, then it continues to the next statement after the join
join_any - parent process blocks (waits) until any child completes (i.e. the first to complete), then it continues to the next statement after the join_any
join_none - parent process does not block. Execution continues to the next statement after the join_none. Child processes are scheduled to start, but do not start until the parent encounters a blocking statement (#, @, wait)
join_none is useful when you want to start off a bunch of on-going processes, such as monitor processes that independently watch for interesting activity, or when you want to start up several independent stimulus generation processes. In both cases, you don't really care about when or even if the child processes finish.
join_any is useful when you want to start a child process, but you want to have a "timeout" so that execution in the parent can continue after either the child finished, or the timeout time has expired, whichever comes firs