【原创】systemverilog 线程中的fork使用

systemverilog 内容庞杂,需要不停的花时间,不停的思考与练习。保持谦虚不急不躁的心态,稳步学习。路漫漫其修远兮,吾将上下而求索。

实际硬件中,时序逻辑通过时钟沿激活,组合逻辑的输出则随着输入的变化而变化。在测试平台的环境里,大多数语句块被模拟成事务处理器,并运行在各自的线程里。
Systemverilog 每个线程总是会跟相邻的线程通信。这里涉及到测试平台组成问题。环境类需要知道发生器什么时候完成任务,以便及时终止测试平台中还在运行的线程。这个过程需要用线程间通信IPC来完成。
常见的线程通信有:event,wait,Systemverilog mailbox,Systemverilog semaphone。
注意:在systemverilog中 线程thread,进程process是一个东西

一:线程的使用
systemverilog在verilog基础上扩展两种线程:

fork
...
join

fork
...
join_none

fork
...
join_any

测试平台通过已有的结构来实现线程间的通信,同步以及对线程 的控制。
下面列举systemverilog for verification的代码进一步说明用法加深理解
fork_join:

VCS运行结果:

记得我第一次做这个example时,人是晕的,下面来重新理一理:
begin....end是顺序执行,从上至下执行,如果带延时肯定按照延时来
fork...join是并行执行,只有当fork块的代码全部执行完毕,才会往下走。
fork...begin...end...join 带延时这个问题,即便join后面的内容发生时间再前,同样也不会执行。

-----------------------------------------分割线----------------------------------------------

fork...join_none:产生线程
fork...join_none在调度其块内语句时,父线程继续执行。代码与fork...join一致

注意:fork...join_none后面那一条语句执行早于块内任何一条语句。

-----------------------------------------分割线----------------------------------------------

fork...join_any:实现线程同步
fork...join_any 第一个语句完成后,父线程才继续执行,其他停顿的线程也继续。代码与fork...join一致

fork...join_any的代码中display("after join_any")完成于并发块内第一个语句之后。

-----------------------------------------分割线----------------------------------------------

二:动态线程:使用fork_join_none 可以开启一个线程,比如随机事务发生器的代码。使用fork...join_none可以使代码不发生阻塞
绿皮书183示例代码:

class Gen_drive
  task run(int n);
  Packet  p;
  fork
      repeat(n)begin
      p = new();
      assert(p.randomzie());
      transmit(p);
      end
  join_none;
  endtask
  task trnansmit(input Packet p);
  ...
  endtask
endclass
Gen_drive gen;
initial beign
    gen = new();
    gen.run(10);
    ...
end

以上代码并不是在new()函数中启动的,构造函数只用来对数值进行初始化,并不启动任何线程,把构造函数同真正进行事务处理的代码分开,允许在开始执行事务处理代码之前修改任何变量,这样,就可以引入错误检测,修改缺省值或变更代码的行为。

任务run通过fork..join_none块启动了一个线程,用于具体事务处理,该线程不是在父类中启动,而是run之后产生的。

在动态线程中,任务被调用,就可以产生一个线程总线以获取匹配的事务地址。在并发线程中务必使用自动变量来保存数值。

错误示例:

program mo_auto;
  initial begin
      for(int j = 0;j < 3;j ++)
          fork
              $write(j);
          join_none
      #0 $display("\n");
  end
endprogram
posted @ 2021-10-31 17:28  肆月黄妙之  阅读(1107)  评论(0编辑  收藏  举报