学习目标:
SV绿皮书第七章:线程以及线程间的通信
学习内容:
1.线程中的自动变量
initial begin
for(int j=0;j<3;j++)
fork
automatic int k=j; //创建索引的拷贝
$write(k); //打印拷贝值
join_none
#0 $display;
end
2.SV中的事件可以像参数一样传递给子程序
class Generator;
event done;
function new(event done); //从测试平台中传来事件
this.done=done;
endfunction
task run();
fork
begin
... //创建事务
->done; //告知测试程序任务已完成
end
join_none
endtask
endclass
program automatic test;
event gen_done;
Generator gen;
initial begin
gen=new(gen_done); //测试程序实例化
gen.run(); //运行事务处理器
wait(gen_done.triggered()); //等待任务结束
end
endprogram
3.等待多个事件
最容易方法:wait fork(问题:需要等待所有子线程)->可以在父线程中使用for循环来等待每个事件(问题:所有线程按顺序完成)->创建一个新线程并从中衍生子线程,然后保证每个线程阻塞在每个发生器的一个事件上
//使用wait fork等待多个线程
event done[N_GENERATORS]
initial begin
foreach (gen[i]) begin
gen[i]=new(); //创建n个发生器
gen[i].run(done[i]); //使它们开始运行
end
//通过等待每个事件来等待所有发生器完成
foreach(gen[i])
fork
automatic int k=i;
wait(done[k].triggered());
join_none
wait fork; //等待所有触发事件完成
end
//另一种方法:记录下已触发事件的数量
event done[N_GENERATORS];
int done_count;
initial begin
foreach(gen[i]) begin
gen[i]=new(); //创建n个发生器
gen[i].run(done[i]); //使它们开始运行
end
//等待所有发生器完成
foreach(gen[i])
fork
automatic int k=i;
begin
wait(done[k].triggered());
done_count++;
end
join_none
wait(done_count=N_GENERATORS); //等待触发
end
//使用线程计数(仅对运行着的发生器进行计数)来等待多个线程
class Generator;
static int thread_count=0;
task run();
thread_count++; //启动另一个线程
fork
begin
//省略
thread_count--; //工作完成时,对线程数减计数
end
join_none
endtask
endlcass
Generator gen[N_GENERATORS];
initial begin
//创建n个发生器
foreach(gen[i])
gen[i]=new();
//启动它们
foreach(gen[i])
gen[i].run();
//等待所有发生器完成
wait(Generator ::thread_count==0);
end
4.信箱size是0或者没有指定,则信箱是无限大的
5.信箱中可以放入句柄,但不能是对象
6.“蓝图模式”:每个句柄都指向不同的对象,这种类型的发生器被称为蓝图模式
7.线程同步:使用定容信箱和peek(探视)(缺点:无法在生产方放入第一个事务的时候让它阻塞,所以提前一个时间)、使用信箱和事件、使用两个信箱、变量或者旗语来阻塞线程完成同步(没有信息交换)
问题:
学习时间:
4/16
早:9-11