前面我写过一篇关于event的文章。SystemVerilog中event,今天再来说点新花样。本次仿真使用的仿真器是VCS2019.06
前面讲到,关于event一般来说有两种触发方式--wait以及@。其中@需要捕捉到事件event产生的瞬间,稍纵即逝,而wait(event.triggered)则不需要管时间。但是在有的情况下,我们是只能够用@的,比如需要捕捉到事件的多次发生,此种情况下如果使用wait(event.triggered)是不行的,因为它只需要捕捉到一次就会一直为高,因此需要使用@。
今天的重点是来探究下fork...join到底是怎么执行的,虽然我们一直说fork...join块是并行执行的,但是再怎么样,亲兄弟也得分个一二三不是,还是有先后顺序的。当然,如果涉及到阻塞赋值,非阻塞赋值等,则又和调度有关,这个在前面的文章中也提到过--systemverilog之program与module。今天抛开这些,只看相同的情况下,是怎么执行语句的。
首先还是看下面的例子:
ex1:
仿真结果为:
上述结果说明线程2中的@并没有被触发,说明可能原因是event_a触发时,@还没有执行。所以应该是从前往后执行的,我再把线程1和线程2换个位置,如果执行了,那么应该就验证了猜想。
ex2:
仿真结果如下:
上述结果证明了我的猜想。但是这并不是全部。
我看到过这样一段代码,关于wait(event.triggered)和fork...join的,如下所示:
从前面代码就可得知,在上述代码中,block3是不可能被触发的,但是其他block的执行顺序是否能想明白呢?
首先放仿真结果:
有没有很惊讶为什么是4、1、2的顺序。我给的解释是:fork...join中同一时刻的代码是顺序执行的,因此事件触发的那个时刻,已经先询问过block1和block2,发现他们两条件还不满足,那就先等着吧,然后事件触发了,但是基于fork...join同一时刻是顺序执行的呀,不可能回去问他们你们打不打印?这多不公平!所以先让后面的语句执行完,这时候到block3了,发现它错过了,那它就得在这等一辈子(阻塞)了。然后询问block4,发现它的条件成立了,那行,你就打印吧。好了,一圈下来执行完了。然后回过去看,刚刚那两兄弟条件满不满足,结果发现满足了,那行,你们俩也打印吧。这时候还是按先后顺序,打印1和2。(以上为个人见解,不一定保证正确哦)。
当然,我稍微改下代码,代码如下:
上述代码执行后,仿真结果为2--4--1。如下所示:
看着这意思,好像以后的顺序都是4在1前面了,所以wait(event.triggered)有改变fork...join执行先后顺序的能力。
我再多加一句代码,看下是否真如我所说:
仿真结果如我所料,block3还在苦苦的等待:
但是,下面这个结果就有点出乎意料...
代码如下:
仿真结果是:
我给的解释是:在fork...join块中,在不同时刻执行的语句,则按照时刻的先后顺序执行;对于在同一时刻执行的语句,如果该线程只是刚刚开始执行,换句话说,它是该线程的第一句执行语句,那么则按代码写法的先后顺序执行;对于在同一时刻执行的语句,如果它不是该线程的第一句执行语句,则按照各线程间最近一次执行的先后顺序,执行本次代码的先后顺序。
End