目录
1 线程的使用
2 线程的控制
wait fork 和 disable fork
3 线程间的通信
概述
event事件 (@边沿阻塞和wait触发 通知的需求)
semaphore旗语(semaphore的操作 资源共享的需求)
mailbox信箱(mailbox信箱的操作 数据通信的需求)
通信要素的比较
线程就是独立运行的程序。verilog中对initial语句块主要有两种分组方式:
begin ...end:中的语句顺序执行
fork...join中的语句以并发方式执行
在sv中,新增了fork...join_any fork...join_none 语句,其区别如下图
wait fork :等待所有子线程结束
disable 线程名:指定需要停止的线程
disable fork:停止当前线程中衍生出来未执行的所有子线程。
注意:若没有disable,则task会结束,但内部未完成的线程仍将执行。
测试平台中所有的线程都需要同步并交换数据。
一个线程需要等待另一个线程--------------->> 事件event
多个线程可能同时访问同一个资源-------->> 旗语semophore
线程之间可能需要交换数据---------------->> 信箱mailbox
所有这些数据交换和同步称为线程间的通信(IPC Interprocsss Communication)
event事件是静态对象,用于事件的同步,它不需要new()函数
触发事件的操作符: ->, 它不会阻塞线程, 通常使用在等待事件之后
等待事件操作符分为两种:@边沿敏感和wait电平敏感
semaphore可以实现对同一资源的访问控制,通常来说应该遵循互斥访问原则,避免出现多个线程同时访问同一资源,进而导致的线程异常。
存中创建semaphore时,类似于创建了一个篮子(bucket),篮子中包含了一定数量的钥匙(keys),要获取共享的资源,必须从篮子中获取一把或多把钥匙,在获取完资源后必须将钥匙放回到篮子中;如果此时另一个线程试图获取篮子中的资源,必须等到桶中有足够多的钥匙的时候才能进行,否则会一直阻塞在这里。
semaphore是SV内建的类,因此也需要声明句柄(即,创建旗语)和调用new()函数
主要有三种基本操作方法:
semaphore sem; //创建一个semaphore(声明一个句柄)
semaphore_name = new(1); //分配一把钥匙
sem.get(1); //获取一把钥匙
...
sem.put(1); //处理完事务后,放回钥匙
如果想要获取一把钥匙而不希望被阻塞,可以使用try_get()函数,它返回1表示有足够多的钥匙,返回0则表示钥匙不够
线程之如果传递信息,可以使用mailbox.。Mailbox也是SV内建的类,也需要声明句柄(即,创建邮箱)和调用new()函数来例化,若不指定大小,则信箱容量为无限大。
mailbox的操作方法也分为阻塞和非阻塞:
peek()可以拷贝信箱中的数据而不移除它,若信箱为空,也会阻塞。
mailbox和queue有相近之处 :
其他特性:如果要显示的限定mailbox中的数据类型,可以使用mailbox #(type = T)方式来声明
sv中的三种通信方式event、semaphore、mailbox都可以来解决进程间同步问题,但分别适用于不同的场景需求