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就是不同线程;

猜你喜欢

转载自blog.csdn.net/weixin_39060517/article/details/113093319