| Section: 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. |
| |
| 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. |
| |
| The UVM TLM2 subset provides the following two transport interfaces: |
| |
| 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). |
| |
| Use Models: |
| 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. |
| |
| Example: |
| | 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. |
| |
| In summary: |
| 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. |