第七章:线程以及线程间的通信

通过Verilog去模拟硬件电路的活动,时序逻辑通过时钟沿来激活,组合逻辑的输出则随着输入的变化而变化。所有的这些并发活动在Verilog的寄存器传输级描述中都是通过initial和always块语句、实例化和连续赋值语句来模拟的。测试平台使用许多并发的进程对RTL级进行描述。在测试平台里,大多数语句块被模拟成事务处理器,并运行在各自的进程里。不同的线程之间需要交换信息进行线程间的通信,本章将分为线程和线程间的通信这两个部分进行介绍。

7.1 线程的使用

所有的线程都可以用在模块和程序块中,但是实际上测试平台隶属程序块。模块中的initial和always块,在程序块中都可以通过initial和initial+forever加以描述。
Verilog中有begin/end和fork/join两种方式对语句执行的顺序进行分组。在SystemVerilog中又新增加了fork/jion_none和fork/join_any这两种语句。
并发的三种进程
三种结构,语句块中所有语句并发运行,区别如下:

  • fork...join:所有语句块都执行完后才能继续块后续的处理。
  • fork...join_any:当第一个语句(所有进程中运行最快的一个)完成后,父进程才继续执行。
  • fork...join_none:父进程与其同时执行。
  • begin...end:顺序执行,通常有嵌套在fork语句当中。
7.1.1 创建进程

有了fork语句块以后我们就可以在class中创建线程,在SystemVerilog中,你可以动态地创建线程,而且不用等到他们都执行完毕。
在类中创建多个线程

7.1.2 线程中的自动变量

当你使用循环来创建线程时,如果在进入下一轮循环之前没有保存变量值,便会碰到一个常见却又难以被发现的漏洞。下面我们通过一个例子来加以说明。
循环内嵌fork...join_none产生多线程
结果
通常使用automatic来避免这个问题。
自动变量
结果
自动变量可以在program中声明,如下:
外部声明自动变量

7.1.3 等待所有衍生线程

SystemVerilog中,当程序中所有的initial块执行完毕以后,仿真器就停止了。
如果有多个线程,可以使用wait fork语句来等待所有的子线程结束。

7.1.4 线程间共享变量

SystemVerilog中,如果你忘记声明某个变量,那么它会到更高层次的作用范围寻找,直至找到匹配的声明。
特别是在for循环中,变量i如果忘记声明,那么将会导致线程间的变量共享,而这些并不是我们希望的。
使用共享程序变量导致的漏洞
解决方法:

  • 在for循环里面对循环变量进行声明。
  • 尽可能使用foreach循环语句。

7.2 停止线程

SystemVerilog中可以使用disable语句来停止线程。

7.2.1 停止单个线程

停止一个线程

7.2.2 停止多个线程

SystemVerilog引入disable fork语句使你能够停止从当前线程中衍生出来的所有子线程。
限制disable fork的作用范围
可以通过带有标号的disable来明确指定你想要停止的进程。
使用带标号的disable来停止线程

7.2.3 禁止被多次调用的任务

当你从某个块内部禁止该快的时候,如果该任务已经被多个线程调用,禁止其中一个将导致他们全部被禁止。下面通过一个例子来说明一下。
使用disable标号来停止一个任务

  • 任务被调用三次,衍生出来3个进程,
  • 三个进程都启动了,但是由于线程0里面的disable语句,使得这些线程最终都没有完成
原文地址:https://www.cnblogs.com/xuqing125/p/9556446.html