Sockets group together all the necessary core interfaces for transportation and binding, allowing more generic usage models than just TLM core interfaces.
A socket is like a port or export; in fact it is derived from the same base class as ports and export, namely uvm_port_base #(IF). However, unlike a port or export a socket provides both a forward and backward path. Thus you can enable asynchronous (pipelined) bi-directional communication by connecting sockets together. To enable this, a socket contains both a port and an export. Components that initiate transactions are called initiators, and components that receive transactions sent by an initiator are called targets. Initiators have initiator sockets and targets have target sockets. Initiator sockets can connect to target sockets. You cannot connect initiator sockets to other initiator sockets and you cannot connect target sockets to target sockets.
|Blocking (b_transport)||completes the entire transaction within a single method call|
|Non-blocking (nb_transport)||describes the progress of a transaction using multiple nb_transport() method calls going back-and-forth between initiator and target|
In general, any component might modify a transaction object during its lifetime (subject to the rules of the protocol). Significant timing points during the lifetime of a transaction (for example: start of response- phase) are indicated by calling nb_transport() in either forward or backward direction, the specific timing point being given by the phase argument. Protocol-specific rules for reading or writing the attributes of a transaction can be expressed relative to the phase. The phase can be used for flow control, and for that reason might have a different value at each hop taken by a transaction; the phase is not an attribute of the transaction object.
A call to nb_transport() always represents a phase transition. However, the return from nb_transport() might or might not do so, the choice being indicated by the value returned from the function (UVM_TLM_ACCEPTED versus UVM_TLM_UPDATED). Generally, you indicate the completion of a transaction over a particular hop using the value of the phase argument. As a shortcut, a target might indicate the completion of the transaction by returning a special value of UVM_TLM_COMPLETED. However, this is an option, not a necessity.
The transaction object itself does not contain any timing information by design. Or even events and status information concerning the API. You can pass the delays as arguments to b_transport()/ nb_transport() and push the actual realization of any delay in the simulator kernel downstream and defer (for simulation speed).
Since sockets are derived from uvm_port_base #(IF) they are created and connected in the same way as port, and exports. Create them in the build phase and connect them in the connect phase by calling connect(). Initiator and target termination sockets are on the ends of any connection. There can be an arbitrary number of pass-through sockets in the path between initiator and target. Some socket types must be bound to imps implementations of the transport tasks and functions. Blocking terminator sockets must be bound to an implementation of b_transport(), for example. Nonblocking initiator sockets must be bound to an implementation of nb_transport_bw() and nonblocking target sockets must be bound to an implementation of nb_transport_fw(). Typically, the task or function is implemented in the component in which the socket is instantiated and the component type and instance are provided to complete the binding.
Consider for example a consumer component with a blocking target socket.
class consumer extends uvm_component; tlm2_b_target_socket #(consumer, trans) target_socket; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build(); target_socket = new("target_socket", this, this); endfunction task b_transport(trans t, uvm_tlm_time delay); #5; uvm_report_info("consumer", t.convert2string()); endtask endclass
The interface task b_transport() is implemented in the consumer component. The consumer component type is used in the declaration of the target socket. This informs the socket object the type of the object that contains the interface task, in this case b_transport(). When the socket is instantiated “this” is passed in twice, once as the parent just like any other component instantiation and again to identify the object that holds the implementation of b_transport(). Finally, in order to complete the binding, an implementation of b_transport() must be present in the consumer component. Any component that has either a blocking termination socket, a nonblocking initiator socket, or a nonblocking termination socket must provide implementations of the relevant components. This includes initiator and target components as well as interconnect components that have these kinds of sockets. Components with pass-through sockets do not need to provide implementations of any sort. Of course, they must ultimately be connected to sockets that do that the necessary implementations.
|Call to b_transport()||start-of-life of transaction|
|Return from b_transport()||end-of-life of transaction|
|Phase argument to nb_transport()||timing point within lifetime of transaction|
|Return value of nb_transport()||whether return path is being used (also shortcut to final phase)|
|Response status within transaction object||protocol-specific status, success/failure of transaction|
On top of this, TLM-2.0 defines a generic payload and base protocol to enhance interoperability for models with a memory-mapped bus interface.
It is possible to use the interfaces described above with user-defined transaction types and protocols for the sake of interoperability. However, TLM-2.0 strongly recommends either using the base protocol off-the-shelf or creating models of specific protocols on top of the base protocol.
The UVM 1.2 standard only defines and supports this TLM2 style interface for SystemVerilog to SystemVerilog communication. Mixed language TLM communication is saved for future extension.
|TLM2 Interfaces, Ports, Exports and Transport Interfaces Subset|
|Sockets group together all the necessary core interfaces for transportation and binding, allowing more generic usage models than just TLM core interfaces.|
Transaction-level communication between components is handled via its ports, exports, and imps, all of which derive from this class.
virtual class uvm_port_base #( type IF = uvm_void ) extends IF