sv标准研读第十五章-进程间同步与通信

书接上回:

sv标准研读第十四章-clocking block

第15章 进程间的同步和通信

15.1 概览

-semaphores

-mailboxes

-named events

15.2 综述

简单的进程间通信可以通过named events来实现,有event trigger和event control过程,分别需要依赖符号->和@,但是named events只能实现静态对象的同步通信,更复杂的进程间通信需要一些机制来实现,比如旗语机制和mailbox机制。

旗语和mailbox是内建类,已经放在了std package里,因此可以直接使用。

15.3旗语

旗语的使用:只有先拿到旗语的key,进程才能够继续往下执行,当key不够时,其他进程处于等待状态,直到key被归还回来。

旗语的声明:

旗语的创建:

获取旗语的key:

归还旗语的key:

没有阻塞获取旗语的key:

15.3.1 new()

函数原型:

作用:创建指定数量key的旗语对象,默认key数量为0。

15.3.2 put()

函数原型:

作用:归还key,默认归还数量是1。

15.3.3 get()

函数原型:

作用:获取key,默认获取数量是1。

15.3.4 try_get()

函数原型:

作用:无阻塞获取key,默认获取数量是1。

15.4 mailbox

作用:实现进程间的通信

进程1可以把message放入mailbox,然后另一个进程去检索mailbox 里的meaasge,从而完成了进程间的通信。

Mailbox实际上就是由一个有边界或者无边界的queue组成。如果是有边界的mailbox,当mailbox里的queue满了时,想要继续存储meaasge到mailbox的进程就会被挂起,直到指定数量的空间被释放出来。无界queue组成的mailbox就不会出现进程被挂起的现象。

Mailbox声明:

Mailbox创建:

将message放入mailbox:

无阻塞将message放入mailbox:

获取mailbox里的message:

无阻塞获取mailbox里的message:

获取mailbox里message的数量:

15.4.1 new()

Bound参数为0时,表示创建一个无界queue的mailbox;否则,bound的值就是queue的size。

15.4.2 num()

获取mailbox里message的数量。

15.4.3 put()

往mailbox里放message。如果mailbox是满的,进程会被挂起直到空间被释放出来。存入顺序是FIFO的顺序。

15.4.4 try_put()

无阻塞的往mailbox里放message,因此这个函数只有对有界mailbox才有意义。如果mailbox没满,函数会返回一个正整数,如果满了,会返回0。存入顺序是FIFO的顺序。

15.4.5 get()

获取message。如果mailbox是空的,进程会被挂起直到有message;如果message类型和mailbox里message类型不一致,会报一个run-time error。

15.4.6 try_get()

无阻塞获取message。如果mailbox是空的,返回0,如果类型不匹配,返回一个负整数,如果mailbox不空且数据类型匹配,返回一个正整数。

15.4.7 peek()

Peek和get的区别是,前者是复制,后者是移出。如果mailbox是空的,进程会被挂起直到有message;如果message类型和mailbox里message类型不一致,会报一个run-time error。

15.4.8 try_peek()

无阻塞复制message。如果mailbox是空的,返回0,如果类型不匹配,返回一个负整数,如果mailbox不空且数据类型匹配,返回一个正整数。

15.4.9 参数化的mailbox

默认情况下,mailbox是无参数的,因此mailbox可以用来传递任何类型的message,一旦写入的message和获取message的类型不匹配,会在run-time阶段报error。

但是也可以创建一个参数化的mailbox,那么这个mailbox就只能传递指定参数类型的message,并且在编译阶段就会检查相关写入和获取message函数的参数类型,如果类型不匹配,就会报编译错误。

举例:

参数化mailbox和普通mailbox一样都有前面几节介绍的函数。

15.5 named events

当声明数据类型是event时,就表明这是一个named event。

Named event有触发和等待的动作,触发可以用符号->/->>实现;等待可以用符号@/wait()实现。

15.5.1 触发一个事件

语法:

触发的作用是使等待该事件的阻塞进程被解除。

->>是针对非阻塞事件的,作用是触发一个非阻塞事件的执行,可以加上delay控制。

15.5.2 等待一个事件

使用@符号等待一个事件被触发。

注意->语句要在@语句之后执行。否则@语句会一直被阻塞。

15.5.3内置的触发方法

方法原型:

如果在当前time step,事件被触发过了,那么调用该函数会返回1,否则返回0。如果事件为null,返回0。

这个方法一般是搭配wait()方法使用的,如下:

和前面的->/@组合不同的是,wait()/trigged()方法无需强制规定wait()语句必须出现在triggered()语句之前,它也可以和trigger()语句在同一个timestep执行,当wait()和triggered()同时发生时,wait()阻塞进程始终会被解除。

举例:

上面第一个fork里,@语句在trigger()语句之前执行,这是保证@语句阻塞的前提条件,所以能够跳出fork;第二个fork,->和wait是同时刻执行,也能跳出fork。

15.5.4 事件排序:wait_order()

wait_order构造挂起调用进程,直到所有指定的事件都按照给定的顺序(从左到右)被触发,或者任何未被触发的事件被乱序触发,从而导致操作失败。

为了使wait_order成功,在序列中的任何一点,后续事件都应按规定的顺序触发,这些事件在此时都不应被触发,否则序列将已经失败。前面的事件并不局限于只发生一次。换句话说,一旦事件按照规定的顺序发生,就可以再次触发它,而不会导致构造失败。

只有列表中的第一个事件可以等待持久triggered事件。

当失败时所采取的操作取决于是否指定了可选的action_block else语句(失败语句)。如果指定了它,则在失败时执行该else语句。如果未指定fail语句,则失败将生成run-time错误。

举例1:

挂起当前进程,直到事件a、b和c按照a - > b - > c的顺序触发。如果事件触发的顺序乱了,则会产生run-time错误。

举例2:

在本例中,fail语句指定在失败时显示一条用户消息,但不生成错误。

15.5.5 named event可使用的操作符

事件可以使用赋值操作符,相当于将事件句柄传递给另一个事件,二者共享queue。

15.5.5.1 merging event

当使用赋值操作符时,相当于将两个事件进行了合并。使用->触发了任意一个事件都会导致两个阻塞进程被解除。举例:

15.5.5.2 回收event

当event被赋值为null时,任何对该事件的trigger都不起作用。举例:

15.5.5.3事件比较

只允许下面几种比较:

-和null或者其他事件使用==比较

-和null或者其他事件使用!=比较

-和null或者其他事件使用===比较

-和null或者其他事件使用!==比较

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值