module tb1;
task automatic exe(int id, int t);
$display("@%t exe[%d] entered",$time,id);
#(t*1ns);
$display("@%t exe[%d] exited",$time,id);
endtask
initial begin//initial 触发一个线程
fork
exe(1,10);
exe(2,20);
join_none
fork
exe(3,30);
exe(4,60);
join
wait fork;//等待这个线程内所有的fork结束
$display("all fork exited");
end
endmodule
module tb2;
task automatic exe(int id, int t);
$display("@%t exe[%d] entered",$time,id);
#(t*1ns);
$display("@%t exe[%d] exited",$time,id);
endtask
initial begin//initial 触发一个线程
fork
exe(1,10);
exe(2,20);
join_none
fork
exe(3,30);
exe(4,60);
join_none
#40 disable fork;//等待四十个时间单位,关闭这个线程中所有的fork
$display("all fork exited");
end
endmodule
module tb3;
task automatic exe(int id, int t);
$display("@%t exe[%d] entered",$time,id);
#(t*1ns);
$display("@%t exe[%d] exited",$time,id);
endtask
initial begin//initial 触发一个线程
fork:a_fork
exe(1,10);
exe(2,20);
join_any
disable a_fork;//上面有任何一个线程结束,就关闭fork,结束所有的线程
$display("fork exited");
end
endmodule
module tb4;
//bit e1,e2,e3;
event e1,e2,e3;
//task wait_event(bit e,string name);
task wait_event(event e,string name);
//注意这里的参数问题
//如果是事件的话,这里的参数传递的是句柄,因此该任务根据句柄的指向,仍然能捕捉到事件
//但如参数是个bit 或者logic的话,该任务线程触发时,进传递了触发时刻logic的值,因此线程就不能捕捉它的变化了
$display("@%t start wait event %s",$time,name);
@e;
$display("@%t after wait event %s",$time,name);
endtask
initial begin
fork
wait_event(e1,"e1");
wait_event(e2,"e2");
wait_event(e3,"e3");
join
end
initial begin
fork
begin #10 -> e1; end
begin #20 -> e2; end
begin #30 -> e3; end
// begin #10 e1 = !e1; end
// begin #20 e2 = !e2; end
// begin #30 e3 = !e3; end
join
end
endmodule
module tb5;
semaphore mem_acc_key;
int unsigned mem[int unsigned];
task automatic write(int unsigned addr, int unsigned data);
mem_acc_key.get();
#1ns
mem[addr] = data;
mem_acc_key.put();
endtask
task automatic read(int unsigned addr, int unsigned data);
mem_acc_key.get();
if(mem.exists(addr)) begin
data = mem[addr];
end
else begin
data = 'x;
end
mem_acc_key.put();
endtask
initial begin
int unsigned data1 = 100;
int unsigned data2 = 100;
mem_acc_key = new(1);
forever begin
fork
begin
#10ns;
write('h10,data1+100);
$display("write data = %d",data1);
end
begin
#10ns;
read('h10,data2);
$display("read data = %d",data2);
end
join
end
end
endmodule
module tb6
mailbox #(int) mb;//定义一个信箱,#(int)表示只存放int型
initial begin
int data_in,data_out;
mb = new(8);
forever begin
case($urandom()%2)
0:begin
#10ns
data_in = $urandom_range(0,15);
mb.try_put(data_in);
$display("put data: %d",data_in);
end
1:begin
#10ns
if(mb.num()>0)begin
mb.get(data_out);
end
$display("get data: %d",data_out);
end
endcase
end
end
endmodule
//关于多态(虚方法)
//子类与父类有同名方法,将子类的句柄赋值给父类后,此时父类句柄指向子类
//一般情况下父类句柄是检索不到子类中的变量或者方法的,因此调用父类和子类的同名方法时,仍然是调用的父类的方法
//但如果子类的方法(这里讨论的是同名方法)加了virtual,则使得父类能够调用子类的方法(以及该方法涉及的变量,但是子类父类中尽量不要定义同名变量)
//简而言之 子类加virtual 能够使父类能检索到子类域里的方法
//virtual只能给方法添加,变量不行
路科v0,第九周,事件、旗语、信箱、多态-虚方法,练习代码
于 2023-09-28 15:21:35 首次发布