文章目录
1. 线程使用
- Verilog硬件模型如下:
- ABC。initial中若有forever就不会结束
1.1 什么是线程
- ABCD。不添加时钟就没有连锁的事件被触发,处理起来会飞快。
1.2 概念澄清
2. 线程控制
- T123分别是子线程,执行时间不同。
2.1 fork join
- 块中所有线程并行开始,全部执行完毕后继续执行后续。
2.2 fork join_any
- 块中所有线程并行开始,执行完毕运行时间最短的线程后继续执行后续。
2.3 fork join_none
- 块中所有线程并行开始,无需等待,立刻继续执行后续。
- A。例如 fork join_none,执行完join_none后面的一个$display之后就会执行end,那么块中所有线程都没有机会继续执行而直接被终结。B同理。
2.4 等待所有线程衍生
- wait fork会等待3个线程执行完毕后退出。
- disable会终止某线程以及其派生的子线程。
- 一个fork就开辟一个新线程,调用一个新任务也会开辟新线程。
- 下面列中,错误地将3个同名线程都停止了:
3. 线程间通信
3.1 概述
3.2 event事件
- event后声明两个变量e1/e2就相当于创建了新的对象,不需要用new。
- ->e1代表触发e1这个事件。
- trigger()相当于为event增加了一个延迟处理功能,检测事件是否发生了,而不是等待这个事件发生的一刻。
- 使用单bit的标志位也可以实现线程的同步。
- BC。
3.2 semaphore 旗语
- sem=new(),则没有钥匙。
- 某一时间段,只有一个sequencer可以驱动总线。
- get/put必须成对出现,若忘记归还钥匙,那么就会出现死锁。
- ABCD。一开始初始化有一把钥匙,若不小心多还了钥匙,那钥匙就变多了。
- 下面的例子解决了钥匙虚增的问题,并且没有用到旗语。
3.3 mailbox信箱
- 产生了三个数据,想要接受4个数据,最后会阻塞。
- 信箱容量为1,保证放1拿1,放2拿2,同一个时间只有一个对象。对内存比较友好。
- ABCD
- 要让队列安全运行,必须保证队列的size()>0.
- 要是想在display中对队列操作(q.pop_front()),那么参数列表中必须使用ref int q[$],表示队列指针。若不加ref相当于把队列做了一个拷贝,display中对队列的操作不影响外部的队列。
- BC.
- event主要用于解决事件同步,semaphore用于解决对统一资源访问的冲突,mailbox用于线程通信。
4. 三种同步要素进程同步实例
4.1 event同步双向握手
4.2 semaphore同步
- 也可以没有钥匙,这时候需要有人先put钥匙。