日常记录(42)TLM、

TLM的put

my_case的main_phase中设定了raise_objection,并延时1000仿真单位后,drop,后续代码中的main_phase不设定raise和drop。

TLM的demo,(port->export->imp)

在A和B之间通信,首先在env中构建对应的实例(在不同的phase中),

然后给连接,A的port给数据到B的export中。

   A   A_inst;
   B   B_inst;
A_inst = A::type_id::create("A_inst", this);
B_inst = B::type_id::create("B_inst", this);

   A_inst.A_port.connect(B_inst.B_export);

A中,

定义port,使用put发送。

   uvm_blocking_put_port#(my_transaction) A_port;

   A_port = new("A_port", this);

      tr = new("tr");
      assert(tr.randomize());
      A_port.put(tr);

B中,

定义export,imp,进行连接,使用imp接收,其中imp连接到其put函数,最终连接到B的put函数。

   uvm_blocking_put_export#(my_transaction) B_export;
   uvm_blocking_put_imp#(my_transaction, B) B_imp;

   B_export = new("B_export", this);
   B_imp = new("B_imp", this);

   B_export.connect(B_imp);


function void B::put(my_transaction tr);
   `uvm_info("B", "receive a transaction", UVM_LOW) 
   tr.print();
endfunction

  

port->imp

env中连接

   A_inst.A_port.connect(B_inst.B_imp);

A不变

   uvm_blocking_put_port#(my_transaction) A_port;

   A_port = new("A_port", this);

      tr = new("tr");
      assert(tr.randomize());
      A_port.put(tr);

B只有imp,然后是put函数

   uvm_blocking_put_imp#(my_transaction, B) B_imp;
   B_imp = new("B_imp", this);

function void B::put(my_transaction tr);
   `uvm_info("B", "receive a transaction", UVM_LOW) 
   tr.print();
endfunction

  

注意:blocking_put类型,使用了put函数。如果是nonblocking_put,使用需要try_put和can_put两个函数;如果只有put,则需要以上三个函数。

如果为get类型,则需要对应的get函数。peek同理。get和peek同时(如blocking_get_peek),则同样结合二者需要的函数定义。

如果为transport,对应transport函数,非阻塞使用nb_transport函数。

阻塞部分不仅可以定义成函数,还可以定义成任务。

 

export->imp

env中,

   A   A_inst;
   B   B_inst;

      A_inst = A::type_id::create("A_inst", this);
      B_inst = B::type_id::create("B_inst", this);

   A_inst.A_export.connect(B_inst.B_imp);

A中,

main_phase中为什么不用raise_objection

   uvm_blocking_put_export#(my_transaction) A_export;

   A_export = new("A_export", this);

      tr = new("tr");
      assert(tr.randomize());
      A_export.put(tr);

B不变

   uvm_blocking_put_imp#(my_transaction, B) B_imp;
   B_imp = new("B_imp", this);

function void B::put(my_transaction tr);
   `uvm_info("B", "receive a transaction", UVM_LOW) 
   tr.print();
endfunction

  

port->port->imp

C的port发送给A的port,然后A的port发送给B的imp

env中,

   A   A_inst;
   B   B_inst;

      A_inst = A::type_id::create("A_inst", this);
      B_inst = B::type_id::create("B_inst", this);

   A_inst.A_port.connect(B_inst.B_imp);

C中,

   uvm_blocking_put_port#(my_transaction) C_port;

   C_port = new("C_port", this);

task C::main_phase(uvm_phase phase);
   my_transaction tr;
   repeat(10) begin
      #10;
      tr = new("tr");
      assert(tr.randomize());
      C_port.put(tr);
   end
endtask

A中,

由谁发出数据,就由谁作为主动连接的connect调用。

   C C_inst;
   uvm_blocking_put_port#(my_transaction) A_port;
A_port = new("A_port", this); C_inst = C::type_id::create("C_inst", this); C_inst.C_port.connect(this.A_port);

B中,不变

   uvm_blocking_put_imp#(my_transaction, B) B_imp;

   B_imp = new("B_imp", this);

function void B::put(my_transaction tr);
   `uvm_info("B", "receive a transaction", UVM_LOW) 
   tr.print();
endfunction

  

port->export->export->imp

env中,

   A   A_inst;
   C   C_inst;

      A_inst = A::type_id::create("A_inst", this);
      C_inst = C::type_id::create("B_inst", this);

   A_inst.A_port.connect(C_inst.C_export);

A中,

   uvm_blocking_put_port#(my_transaction) A_port;

   A_port = new("A_port", this);

      tr = new("tr");
      assert(tr.randomize());
      A_port.put(tr);

C中,

   B B_inst;

   uvm_blocking_put_export#(my_transaction) C_export;

   C_export = new("C_export", this);
   B_inst = B::type_id::create("B_inst", this); 

   this.C_export.connect(B_inst.B_export);

B中,

   uvm_blocking_put_export#(my_transaction) B_export;
   uvm_blocking_put_imp#(my_transaction, B) B_imp;

   B_export = new("B_export", this);
   B_imp = new("B_imp", this);

   B_export.connect(B_imp);

function void B::put(my_transaction tr);
   `uvm_info("B", "receive a transaction", UVM_LOW) 
   tr.print();
endfunction

  

TLM的get、transport、non_blocking

(get)A的imp->export->B的port(数据流向)

B为动作的发起者,A为被动从imp发送数据的动作接收者(B的port,A的export,A的imp控制流向)

imp作为动作的最终点。

my_env中,

   A   A_inst;
   B   B_inst;

      A_inst = A::type_id::create("A_inst", this);
      B_inst = B::type_id::create("B_inst", this);

   B_inst.B_port.connect(A_inst.A_export);

B中,

   uvm_blocking_get_port#(my_transaction) B_port;

   B_port = new("B_port", this);

      B_port.get(tr);
      `uvm_info("B", "get a transaction", UVM_LOW) 
      tr.print();

A中,

   uvm_blocking_get_export#(my_transaction) A_export;
   uvm_blocking_get_imp#(my_transaction, A) A_imp;
   my_transaction tr_q[$];


A_export = new("A_export", this);
A_imp = new("A_imp", this);


A_export.connect(A_imp);


task A::get(output my_transaction tr);
   while(tr_q.size() == 0) #2;
   tr = tr_q.pop_front();
endtask

task A::main_phase(uvm_phase phase);
   my_transaction tr;
   repeat(10) begin
      #10;
      tr = new("tr");
      tr_q.push_back(tr); 
   end
endtask

  

(transport)A的transport->B的imp(数据双向)

动作从A->B

在env中,

   A   A_inst;
   B   B_inst;

      A_inst = A::type_id::create("A_inst", this);
      B_inst = B::type_id::create("B_inst", this);

   A_inst.A_transport.connect(B_inst.B_imp);

在A中,

   uvm_blocking_transport_port#(my_transaction, my_transaction) A_transport;

   A_transport = new("A_transport", this);

task A::main_phase(uvm_phase phase);
   my_transaction tr;
   my_transaction rsp;
   repeat(10) begin
      #10;
      tr = new("tr");
      assert(tr.randomize());
      A_transport.transport(tr, rsp);
      `uvm_info("A", "received rsp", UVM_MEDIUM)
      rsp.print();
   end
endtask

在B中,

   uvm_blocking_transport_imp#(my_transaction, my_transaction, B) B_imp;

   B_imp = new("B_imp", this);

task B::transport(my_transaction req, output my_transaction rsp);
   `uvm_info("B", "receive a transaction", UVM_LOW) 
   req.print();
   //do something according to req
   #5;
   rsp = new("rsp");
endtask

  

non_blocking通信。A的port->B的imp

env中,常规

   A   A_inst;
   B   B_inst;

      A_inst = A::type_id::create("A_inst", this);
      B_inst = B::type_id::create("B_inst", this);

   A_inst.A_port.connect(B_inst.B_imp);

A中,

可以直接使用try_put即可,附带了判断功能,通过则直接发送

   uvm_nonblocking_put_port#(my_transaction) A_port;

   A_port = new("A_port", this);

task A::main_phase(uvm_phase phase);
   my_transaction tr;
   repeat(10) begin
      tr = new("tr");
      assert(tr.randomize());
      while(!A_port.can_put()) #10;
      void'(A_port.try_put(tr));
   end
endtask

B中,

需要定义can_put和try_put函数。然后接收过程中,使用非阻塞(获取数据暂存队列),然后调用队列。

   uvm_nonblocking_put_imp#(my_transaction, B) B_imp;
   my_transaction tr_q[$];

   B_imp = new("B_imp", this);

function bit B::can_put();
   if(tr_q.size() > 0)
      return 0;
   else 
      return 1;
endfunction

function bit B::try_put(my_transaction tr);
   `uvm_info("B", "receive a transaction", UVM_LOW) 
   if(tr_q.size() > 0)
      return 0;
   else begin
      tr_q.push_back(tr);
      return 1;
   end
endfunction

task B::main_phase(uvm_phase phase);
    my_transaction tr;
    while(1) begin
       if(tr_q.size() > 0)
          tr = tr_q.pop_front();
       else
          #25;
    end
endtask

  

analysis的port

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

上一篇:剑指 Offer 42. 连续子数组的最大和


下一篇:条件随机场CRF(42)