Interconnection of ports for UVM TLM communication

Connection between PORT and EXPORT

As shown in the figure, ABCD has four ports to communicate between A and B, and between C and D. In order to achieve this goal, A connection relationship must be established between A and B and between C and D. otherwise, how does A know to communicate with B rather than with C or D? So be sure to establish A connection before communication.

If a wants to communicate with B (a is the initiator), it can be written as A.port.connect (B.export), but it cannot be written as B.export.connect (A.port). Because in the process of communication, a is the initiator and B is the passive undertaker. The primary and secondary order of communication is also applicable to connection. Only the initiator can call the connect function, while the passive bearer is used as the connect parameter.

Use the above method to establish the connection between A.PORT and B.EXPORT. The code of a is:

class A extends uvm_component;
   `uvm_component_utils(A)
   uvm_blocking_put_port#(my_transaction) A_port;
   ...
endclass

function void A::build_phase(uvm_phase phase);
   super.build_phase(phase);
   A_port = new("A_port", this);
endfunction

task A::main_phase(uvm_phase phase);
endtask

Where a_ When port is instantiated, the first parameter is the name, and the second parameter is a UVM_ Parent node variable of component type.

The code of B is similar to that of A. the connection between the two is established in env as follows:

class my_env extends uvm_env;
   A   A_inst;
   B   B_inst;
  ...
   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      A_inst = A::type_id::create("A_inst", this);
      B_inst = B::type_id::create("B_inst", this);
   endfunction
endclass

function void my_env::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   A_inst.A_port.connect(B_inst.B_export);
endfunction

Note: PORT and EXPORT are just like a door. They are only used for passage. It is impossible to store a transaction. They have no storage function and do not do other operations except forwarding. Therefore, this transaction must be handled by B_export is processed by a subsequent component. In UVM, IMP is also a PORT to complete this subsequent processing.

Connection between PORT and IMPORT

With IMP, the connection between the previous PORT and EXPORT can be realized. The following figure shows the role of component in connection

Codes for A and B are:

class A extends uvm_component;
   `uvm_component_utils(A)

   uvm_blocking_put_port#(my_transaction) A_port;
...
endclass
...
task A::main_phase(uvm_phase phase);
   my_transaction tr;
   repeat(10) begin
      #10;
      tr = new("tr");
      assert(tr.randomize());
      A_port.put(tr);
   end
endtask
//------------------------------------------------------------------------------------------
class B extends uvm_component;
   `uvm_component_utils(B)

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

function void B::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   B_export.connect(B_imp);
endfunction

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

In B's code, the key is to implement a put function / task. If it is not implemented, an error prompt will be given

In UVM, only IMP can be the end of the connection relationship. If PORT or EXPORT is used as the end point, an error will be reported.
A_ The put operation of port will eventually fall on the put of B. Therefore, a task / function named put should be defined in B.

When B is completed in B_ After IMP and put are defined, connect in env_ Phase requires Aport and B_imp is connected together:

function void my_env::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   A_inst.A_port.connect(B_inst.B_imp);
endfunction

Connection between EXPORT and IMP

PORT can be connected with IMP, and the same EXPORT can also be connected with IMP. the connection method is exactly the same as that of PORT and IMP. The connection between EXPORT and IMP was completed before, but in that connection, EXPORT is only used as an intermediate link. Here, EXPORT is used as the starting point of the connection.

Except A_port becomes B_ There is no change except export. A task named put must also be defined in B.

Connection between PORT and PORT

In the previous connections, there were connections between different types of ports (PORT and imp, PORT and EXPORT, EXPORT and IMP), and there was no hierarchical relationship. In UVM, hierarchical connection is supported,

In the above figure, PORT in A and C and IMP in B. UVM supports the connection of C's PORT to A's PORT and finally to B's imp.
Codes for C and A are as follows:

class C extends uvm_component;
   `uvm_component_utils(C)
   uvm_blocking_put_port#(my_transaction) C_port;
  ...
endclass

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
//-------------------------------------------------------------------------------------------
class A extends uvm_component;
   `uvm_component_utils(A)

   C C_inst;
   uvm_blocking_put_port#(my_transaction) A_port;
...
endclass

function void A::build_phase(uvm_phase phase);
   super.build_phase(phase);
   A_port = new("A_port", this);
   C_inst = C::type_id::create("C_inst", this);
endfunction

function void A::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   C_inst.C_port.connect(this.A_port);
endfunction

task A::main_phase(uvm_phase phase);

endtask

Other codes only need to modify the port type, and others are the same;

The connection between PORT and PORT is not limited to two layers, but can have infinite layers.

Connection between EXPORT and EXPORT

In the following figure, PORT is in A, EXPORT is in B and C, and IMP is in B. UVM supports the connection of C's EXPORT to B's EXPORT and finally to B's IMP.

A. B code is the same as before, and C code and env code are as follows:

class C extends uvm_component;
   `uvm_component_utils(C)
   B B_inst;
   uvm_blocking_put_export#(my_transaction) C_export;
...
endclass

function void C::build_phase(uvm_phase phase);
   super.build_phase(phase);
   C_export = new("C_export", this);
   B_inst = B::type_id::create("B_inst", this); 
endfunction

function void C::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   this.C_export.connect(B_inst.B_export);
endfunction

task C::main_phase(uvm_phase phase);
endtask
//-------------------------------------------------------------------------------------------
function void my_env::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   A_inst.A_port.connect(C_inst.C_export);
endfunction

Similarly, the connection between EXPORT and EXPORT is not limited to two layers, but also infinite layers.

This note is compiled with reference to the actual combat of UVM, roaming guide for chip verification and a verification video. It is only for learning and experience exchange. If infringement is involved, please inform me and I will deal with it at the first time.

Tags: microchip systemverilog

Posted on Tue, 16 Nov 2021 04:00:48 -0500 by merrittj