线程
两种分组语句:
begin/end:串行执行
fork/jion:并行执行
join,join_none,join_any
- join
必须要执行完程序段内所有的进程才会跳出
在上述程序中理论上两个$display没有先后关系,但是仿真器会先后输出两句话(输出顺序无参考价值),因此应当尽量避免这种写法。整个程序段在至少经过20ns并且eventA执行完毕后才会跳出。
-
** join_any**
等到任何一个进程执行完毕即可跳出,但是剩下的进程会继续执行
-
join_none
程序段内的进程不会影响后续的语句,相当于和后面的程序完全并行。 -
实例
join_none与join_any的时序相同
fork结束语句
- wait fork
用于等待所有之前的fork程序段内的子线程执行完毕。 - disable fork
用于在跳出fork程序段后,结束所有fork程序段下未执行完毕的子线程以及子线程的子线程。通常与join_any或者join_none连用。
事件
线程通过@符号等待事件的触发(verilog常用),对边沿敏感;
线程通过->符号触发事件,并且触发某个事件后将会释放所有正在等待此事件的线程。
***此程序段结果不确定
Event
- trigger
事件用于同步线程,并且事件可以作为一个句柄传递。
触发状态本身是无法观察到的,只能通过触发后所产生的信号/效果判断,机理类似于信号边沿触发DFF。 - non-blocking event trigger
使用->>符号触发事件,触发后形成类似于assign的非阻塞赋值效果 - wait for event
若想要释放@之前的线程,判断语句本身必须要在@之后的事件之前生效,若事件触发完毕才进入判断语句,则无法触发@语句,线程依然被阻塞。
- wait_order()
等待事件按照一定的顺序完成触发
wait_order(a,b,c)相当于a->b->c - event variables
若线程1等待事件1时,将事件2赋值给事件1,则线程1将永远不会被释放,因为此时已经不存在线程1所等待的“事件1”,事件1已经被merge到事件2当中。
若要避免此状况,可以将赋值语句放在父线程即fork/jion外面,则事件1和事件2的merge过程会事先完成,不会使线程等待空事件的事情发生。
- Reclaiming events
Semaphore(旗语)
当多个进程申请同一个资源的时候就需要用到旗语,可以解决资源使用的冲突。
1.可以用new()创建钥匙,括号内的数字可以限定钥匙的数量,即限定同时访问资源的人数;
2.get()可以获取钥匙,可指定获取的个数;put()可以归还钥匙
3.try_get()在获取钥匙的同时不会阻塞进程的进行
Mailbox(信箱)
用于在进程之间交换信息,工作机理类似于FIFO。
mailbox的常用函数如上图所示,与semaphore类似 。