数字验证学习笔记——SystemVerilog芯片验证20 ——线程间的通信

一、线程间的通信

  • 测试平台中的所有线程都需要同步交换数据
  • 一个线程需要等待另一个。
  • 多个线程可能同时访问同一个资源。
  • 线程之间可能需要交换数据。
  • 所有这些数据交换和同步称之为线程间的通信(IPC)

1.1 event 事件

  • Verilog 中,一个线程总是要等待一个带@操作符的事件。这个操作符是边沿敏感的,所以它总是阻塞着、等待事件的变化。
  • 其他线程可以通过 **->**操作符来触发事件,结束对第一个线程的阻塞。
  • 这就像在打电话时,一个人等待另一个人的呼叫。

1.1.1 event的边沿阻塞

在这里插入图片描述
event e1,e2; 创建对象,不需要new();
在这里插入图片描述
——>e1,相当于在这个时刻打出电话,如果此时对方没有@e1,就是及时接电话,将会错失这次电话。
在这里插入图片描述
在这里插入图片描述
@检测现在事件有没有触发过,wait就是检测事件现在有没有触发过 以及 之前有没有触发过。

1.1.2 通知的需求

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
此时display中@e_speedup不可以替换成wait(e_speedup.triggered),因为wait(e_speedup.triggered)是电平触发,只要触发一次之后,使用wait(e_speedup.triggered),都满足要求。

1.2 semaphore旗语

  • semaphore 可以实现对 同一资源 的访问控制。
  • 对于初学者而言,无论线程之间在共享什么资源,都应该使用semaphore 等资源访问控制的手段,以此避免可能出现的问题。
  • semaphore有三种基本操作。**new()方法可以创建一个或者多个钥匙的semaphore,使用get()可以获取一个或者多个钥匙,而put()**可以返回一个或者多个钥匙。
  • 如果你试图获取一个semaphore而希望不被阻塞,可以使用**try_get()**函数。它返回1表示有足够多的钥匙,而返回0则表示钥匙不够。

1.2.1 semaphore的操作

在这里插入图片描述

  • 线程之间除了“发球”和“接球”这样的打乒乓以外,还有更深入的友谊,比如公用一些资源。
  • 对于线程间共享资源的使用方式,应该遵循 互斥访问(mutexaccess)原则
  • 控制共享资源的原因在于,如果不对其访问做控制,可能会出现多个线程对同一资源的访问,进而导致不可预期的数据损坏和线程异常,这种现象称之为“线程不安全”。
  • 还是以这辆BYD为主角,如果丈夫和妻子都要开这辆车,而这辆车只有一把钥匙的话,只能以一定的顺序先后使用,才可以解决开车的问题。

资源共享的需求
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3 mailbox信箱

  • 线程之间如果传递信息,可以使用mailbox
  • mailbox和队列queue有相近之处。
  • mailbox是一种对象,因此也需要使用new() 来例化。例化时有一个可选的参数size来限定其存储的最大数量
    如果size是0或者没有指定,则信箱是无限大的,可以容纳任意多的条目。
  • 使用**put()可以把数据放入mailbox,使用get()**可以从信箱移除数据。
  • 如果信箱为满,则put()会阻塞;如果信箱为空,则get()会阻塞。
  • **peek()**可以获取对信箱里数据的拷贝而不移除它。
  • 线程之间的同步方法需要注意,那些是阻塞方法,那些是非阻塞方法,即哪些是立即返回的,而哪些可能需要等待时间的。

1.3.1 在线程间使用信箱通信

在这里插入图片描述
在这里插入图片描述

  • 对于一辆车子而言,如果要实时显示这辆车子的状态,会需要多个仪表。显示的参数包括车速、油量、发动机的转速和温度等,这些参数涉及到了各个传感器到汽车控制中枢的通信。
  • 如果我们继续通过上面这辆BYD,来模拟不同传感器(线程)到车的中央显示的通信,可以利用SV的mailbox(信箱)来满足多个线程之间的数据通信
    在这里插入图片描述
    3个mailbox 分别是温度、速度、油量;
    在这里插入图片描述
  • 对于mailbox的用法,与FIFO的使用很相似。如果我们将上面的mailbox用队列来替代的话,则可以修改为下面的代码。
    在这里插入图片描述
    如果不加ref,只相当于拷贝了tmp_q,传输到dispaly任务中,任务中对tmp_q的操作不会反应了到外部的tmp_q。
    在这里插入图片描述
    调用阻塞方法,只可以在task中调用,因为阻塞方法是耗时的。

对于mailbox变量的操作,在传递形式参数时,实际传递并拷贝的是mailbox的指针;而在第二个例子中的task_dispaly(),
关于queue的形式参数声明是ref方向,因为如果采用默认的input方向,那么传递过程中发生的是数组的拷贝,以致于方法
内部对queue的操作不会影响外部queue本身。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值