uvm_primer ch17线程间的通信
verilog线程间的通信
producer 和consumer的通信
使用put_it和get_it来进行通信协调;
module producer(output byte shared, input bit put_it, output bit get_it);
initial
repeat(3) begin
$display("Sent %0d", ++shared);
get_it = ~get_it;
@(put_it);
end
endmodule : producer
module consumer(input byte shared, output bit put_it, input bit get_it);
initial
forever begin
@(get_it);
$display("Received: %0d", shared);
put_it = ~put_it;
end
endmodule : consumer
module top;
byte shared;
producer p (shared, put_it, get_it);
consumer c (shared, put_it, get_it);
endmodule : top
oop的线程间通信协调
一般使用semaphores或者mailboxs;来进行;
uvm线程间通信协调
使用两个组件,隐藏细节
- ports 在uvm_component中构造的ports 对象,可以使我们在run_phase中和其他线程通信,使用put port给其他线程发数据,使用get port获取其他线程的数据;
- TLM fifo 这个TLM fifo 对象用来连接put port和get port; transaction-level modeling;这个fifo不仅能传transactions,还能传任意类型的数据;
TLM fifo仅保存一份数据元素;
blocking 模式
producer 产生一个数据,并put到fifo中,但是fifo只能存一份数据;当循环再次来到put的时候就blocking了;直到consumer使用get取走数据;同样当consumer get一个数据后,fifo空了,只能blocking,等下一个数据;
class producer extends uvm_component;
`uvm_component_utils(producer);
int shared;
uvm_put_port #(int) put_port_h;
function void build_phase(uvm_phase phase);
put_port_h = new("put_port_h", this);
endfunction : build_phase
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
task run_phase(uvm_phase phase);
phase.raise_objection(this);
repeat (3) begin
put_port_h.put(++shared);
$display("Sent %0d", shared);
end
phase.drop_objection(this);
endtask : run_phase
endclass : producer
class consumer extends uvm_component;
`uvm_component_utils(consumer);
uvm_get_port #(int) get_port_h;
int shared;
function void build_phase(uvm_phase phase);
get_port_h = new("get_port_h", this);
endfunction : build_phase
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
task run_phase(uvm_phase phase);
forever begin
get_port_h.get(shared);
$display("Received: %0d", shared);
end
endtask : run_phase
endclass : consumer
使用fifo连接
class communication_test extends uvm_test;
`uvm_component_utils(communication_test)
producer producer_h;
consumer consumer_h;
uvm_tlm_fifo #(int) fifo_h;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
producer_h = new("producer_h", this);
consumer_h = new("consumer_h", this);
fifo_h = new("fifo_h",this);
endfunction : build_phase
function void connect_phase(uvm_phase phase);
producer_h.put_port_h.connect(fifo_h.put_export);
consumer_h.get_port_h.connect(fifo_h.get_export);
endfunction : connect_phase
endclass : communication_test
uvm_tlm_fifo 和uvm_analysis_fifo区别
非blocking 模式
blocking模式适用于producer和consumer都是time-free的线程之间的通信协调;
当涉及clocking edge的时候,需要使用try_put()和try_get();
try_put()和try_get()返回一个bit告诉你put/get是否成功;
try_get返回1则打印;返回0则跳过去下一个clock edge;
class producer extends uvm_component;
`uvm_component_utils(producer);
int shared;
uvm_put_port #(int) put_port_h;
function void build_phase(uvm_phase phase);
put_port_h = new("put_port_h", this);
endfunction : build_phase
task run_phase(uvm_phase phase);
phase.raise_objection(this);
repeat (3) begin
#17;
put_port_h.put(++shared);
$display("%0tns Sent %0d", $time, shared);
end
#17;
phase.drop_objection(this);
endtask : run_phase
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
endclass : producer
class consumer extends uvm_component;
`uvm_component_utils(consumer);
uvm_get_port #(int) get_port_h;
virtual clk_bfm clk_bfm_i;
int shared;
function void build_phase(uvm_phase phase);
get_port_h = new("get_port_h", this);
clk_bfm_i = example_pkg::clk_bfm_i;
endfunction : build_phase
task run_phase(uvm_phase phase);
forever begin
@(posedge clk_bfm_i.clk);
if(get_port_h.try_get(shared)) //重点
$display("%0tns Received: %0d", $time,shared);
end
endtask : run_phase
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
endclass : consumer
问题
这个章节用producer和consumer解释了线程间的通信协调机制;
但是没有解释为啥ch16中monitor和scb之间的就是同一个线程;
这里的producer和consumer就是不同线程;