SystemVerilog中的Process(1)--- 产生进程的方式

2020-07-28 11:34:59 浏览数 (4)

来源| 杰瑞IC验证(ID:Jerry_IC)

|原创作者| 老黄鸭

Hello,everybody,本期由黄鸭哥给大家带来验证干货,猜猜这次会给你们带来什么干货呢。

黄鸭哥给你们整理了SystemVerilog中process的用法,这次的process也会分多期进行讲解,本期主要讲解的是SystemVerilog中产生进程的几种方式。

首先,process这个概念大家都不会陌生,进程嘛,有些小伙伴还可能会想到process的好搭档,thread。

那什么是进程呢?

什么是线程呢?

黄鸭哥先给大家普及下基本概念:

process,也就是进程,它是资源分配的最小单位;

thread,线程,它是cpu调度的最小单位。

为了加深大家的理解,我这里把进程比喻成一辆火车,线程比喻成一节车厢

1.线程必须在进程下执行,这句话怎么理解呢,大家都知道光有车厢肯定不行,必须得先有火车是吧 ,而火车是由一节一节车厢组成的。

2.不同进程间的数据很难共享,但是同一进程下的线程很容易共享某个数据。这句话又是什么意思呢?当我坐上一辆火车时,想要进行换乘就很麻烦,还得下车然后走换乘通道,但是要进入不同的车厢就很简单啦,你只需要往前走或者往后走就能跨越不同的车厢。

理解了线程和进程间的区别我们再来谈谈SystemVerilog对这两个的说明,SystemVerilog中介绍了在以下情况下可以产生thread:

图1

从图1中我们可以看到,initial…begin…end,final…begin…end,4个always procedure,3个fork procedure和dynamic process都可以产生线程,这里黄鸭哥挑了两个常用的重点跟大家聊聊。

Initial procedure我们都知道,但是什么是final procedure呢?

final和initial含义差不多,只是initial是在仿真0时刻自动执行,而final procedure刚好相反,是在仿真结束的时候才会执行。

final procedure是不消耗仿真时间的,且可以有多个final procedure,多个final procedure的执行顺序是随机的,我们来看个例子:

图2

图3

由图2和图3我们可以看到:

当仿真正常结束或者显示的调用系统函数$finish都会导致仿真结束,仿真结束后将会执行final procedure

除了仿真正常结束或者显式调用$finish,SystemVerilog还可以支持仿真工具的交互式停止引起的仿真结束,例如:当进行vcs的ucli:quit这个交互退出命令时,也会调用final procedure,感兴趣的小伙伴可以自己去尝试尝试。

再回到产生thread的方式,其中有一种是always,这个procedure大家都很熟悉了,不管是module中还是我们的interface中都可以调用always,但是,always或者一些forever等循环语句中很容易出现infinity loop,即我们所说的死循环,比如:

图4

图4中的两个例子都是典型的infinity loop,这种错误几乎每一个初学者都会碰到过,但是大家都清楚造成死循环的根本原因吗?

要说明这个问题,我们得先知道一个点,那就是仿真是基于event的,而不是基于时间的。

我们在进行仿真时,其实是仿真器根据rtl和你的bench生成对应的一个仿真模型,仿真模型里面包含了大量的并发的process,那么每个process是怎么执行的呢?

难道和计算机的操作系统一样,都是按照时间片来执行,每个prcocess获取到时间片就会往前推进,直到时间片消耗完?

答案是否定的,我们的仿真器不按这个套路来,它也是有时间片,每个process要执行也是要获取时间片的。

但是,不同点在于process获取到时间片后就会一直执行,时间片不会消耗完毕,而是要等到触发消耗时间的语句:#,@,wait等才会释放时间片给别的process。

所以,死循环就是这么来的,大家一定要记住消耗时间这个重点。

还有一点,黄鸭哥要给大家一个建议,我们刚刚说了那么几种可以产生thread的方式,initial,final,always,fork等语句块。

但是,这些都可以认为,既是产生thread的方式,也是产生process的方式。

为什么这么说呢?

SystemVerilog中对process和thread的解释太过模糊。

我的建议是,不要区分process和thread,统一认为是process,thread则是子process,这样能避免我们被SystemVerilog给带跑偏了。

最后

我们回顾下今天的要点:

  1. SystemVerilog中不区分process和thread,统一为process;
  2. process和thread的区别,即process和子process的区别;
  3. 产生子process的多种方式;
  4. final进程的含义;
  5. 仿真其实是基于event的,而不是时间;
  6. 编写代码时避免造成死循环。

快乐的时光总是很短暂,又到了说拜拜的时候了,下次黄鸭哥将给你们讲述你们不知道的process隐藏的一些功能。

——The End——

0 人点赞