TLM Interface Ports in e (Addition to clause 8)
This clause defines the support the e language provides for interface ports, used to implement Transaction Level Modeling (TLM) standard interfaces.
These ports facilitate the transfer of transactions between verification components, taking advantage of
the standardized, high level TLM communication mechanism.
interface_port
Purpose
Transfer transactions between e units or a combination of e units and external modules
Category
Unit member
Syntax
port-instance-name : [list of] direction interface_port of tlm-intf-type
[using prefix=prefix | using suffix=suffix] [is instance]
port-instance-name : [list of] export interface_port of tlm-intf-type [is instance]
Syntax Examples
e_packet : in interface_port of tlm_put of packet is instance;
p1 : out interface_port of tlm_nonblocking_transport of (packet, msg) is instance;
p2 : export interface port of tlm_blocking_put is instance; // export
Parameters
port-instance-name - A unique e identifier used to refer to the port or access its value.
direction - in or out. There is no default.
tlm-intf-type
For internal e TLM interface ports, the type (or types) you specify for the
interface can be any legal e type.
External e TLM interface ports support transactions of a struct (or class) type
only. Thus, for externally bound e TLM interface ports, the type (or types)
you specify for the interface must be legal e types that inherit from any_struct.
using prefix=prefix
using suffix=suffix
Applies for e TLM input ports only. Specifies a prefix or suffix string to be
attached to the predefined TLM methods for the given port.
Using a prefix or suffix ensures that there are no method name collisions if a port
contains more than instance of an e TLM interface port tied to the same TLM
interface.
(This syntax can be used only for the port instance members. It cannot be used in
other declarations, such as declarations for parameters or variables.)
Description
An e TLM interface port type is parameterized with a specific TLM interface type. For example, if you
define an e TLM interface port with the syntax
interface_port of tlm_nonblocking_put
, you have tied
that port to the tlm_nonblocking_put interface. You can then use the set of methods (functions)
predefined for that interface to exchange transactions.
Special Port Types
Export
An export interface port is a port whose enclosing unit does not implement the required interface methods. The interface methods are delegated to the connected unit. An export TLM input port in e is functionally equivalent to a
SystemVerilog or
SystemC export.
The following limitations apply to export interface ports:
- The port shall have an outbound connection.
- The port shall be connected (either directly or indirectly) to an input interface port or to an external port providing suitable interface functions.
- The port shall have no inbound connection.
- The port must be connected using the connect() (see below) method. The bind() constraints and the do_bind() routine are not applicable for it.
Analysis port
Analysis ports are ports featuring the tlm_analysis interface - a restricted write-only interface intended to share monitoring information for analysis purposes. They may have multiple outbound connections in support of broadcast implementations.
Defining Input e TLM interface ports
When a unit contains an instance member of an input TLM interface port, the unit must implement all
methods required by the TLM interface type of that input port. The list of methods is predefined
according to the standard TLM specification.
These methods must be defined before the port is defined. (If the methods and port are defined in the
same module, however, the order does not matter.) If any of the required methods is missing, a compile
time error shall be issued.
Example:
struct packet {
…
};
unit server {
// The following four lines define the four methods required
// by the TLM interface tlm_put.
put(value : packet)@sys.any is {…};
try_put(value: packet) : bool is {…};
can_put() : bool is {…};
ok_to_put() : tlm_event is {…};
packet_in : in interface_port of tlm_put of packet is instance;
};
In this example, the unit server implements the four methods/tasks which are required by the interface
tlm_put of packet.
See below for a description of interface method semantics.
Binding e TLM interface ports
Binding Rules for TLM interface ports
A TLM output port can be bound to a TLM input port if the interface type of the output port is either the
same as the interface type of the input port or subset of it (with exactly the same element type in the
template parameter).
For example, you can bind an output port of tlm_nonblocking_put to an input port of tlm_put, because
the tlm_nonblocking_put interface is a subset of the tlm_put interface.
Additionally:
- Empty and undefined bindings are supported for e TLM interface ports.
- Multiple binding is not supported for e TLM interface ports, except for analysis ports.
- Unification of ports bound to the same external port is not supported for e TLM interface ports.
-
External e TLM interface ports are implicitly bound to external if they have a non-empty
external_ovm_path().
Declarative and Procedural Binding
e TLM interface ports have to be bound before usage, similar to any other port. Binding can be done declaratively with keep bind()
constraints or procedurally with a do_bind() or do_bind_unit() pseudo-routines.
Editorial note: The bind syntax is the same as for other e ports - need a cross reference to the syntax definition in clause 8 (currently 8.7.2.1 for declarative bind). Need to add section about procedural bind to clause 8 (issue filed)
Syntax examples for declarative binding
keep bind(port1, port2);
keep bind(port3, external);
Syntax examples for procedural binding
connect_ports() is also {
do_bind(port1, port2);
do_bind(port3, external);
}
connect() - Language-Neutral Binding
External binding of TLM ports in a lnaguage-neutral way shall be supported by the simulation environment. The port method
connect() is provided for this purpose.
Use connect() when you want to bind two ports which are not both defined in
the same language. For example, you can use this method to bind a
SystemC port to a
SystemVerilog port
from e. For uniformity, connect() may be used to procedurally bind together e ports as well.
The connect() method shall be called once during the connect_ports() phase. The effect of this method is
immediate - it shall issue an error in case of any mismatch (wrong external path, mismatching interface types,
unsupported multiple binding, and so on).
Syntax of connect()
<port1-exp>.connect(<port2-exp>)
<port1-exp>.connect(empty|undefined)
<port1-exp>.connect(“external path”)
Syntax examples for connect()
env.agent[1].my_port.connect(env.agent[2].my_export)
env.agent.monitor.port.connect(empty);
Description
The following restrictions shall apply to connections created by calling connect().
If port1 is an output port:
- It can be connected to other e output port, e export port, or e input port.
- It can be connected to empty. In this case, this must be the only outbound connection it has. In this case, invoking a method on this port is like calling an empty method.
- In can be connected to undefined. In this case, this must be the only outbound connection it has. In this case, invoking a method on this port will cause to run time error.
- It can be connected to specific external port, by specifying the external port path. This external port can be of any direction.
If port1 is an export port:
It can be connected to other e export port or to other e input port
It can be connected to specific external port, by specifying the external port path. This external port must be input port or an export port.
Connecting to an external path:
- For SystemVerilog or SystemC, the external path must be quasi-static (full path from the top level scope).
- For e, the external path is an e-path, beginning with “sys”.
Supported TLM Interfaces
Editorial note: Need to introduce the type tlm_event as a built-in. Discuss whether it must remain in a special scope (tlm::tlm_event) or is it OK to migrate to main.
Supported Unidirectional TLM Interfaces
Note Nonblocking TLM interface calls are zero-delay calls. The blocking interface calls, which
correspond to e TCM methods, consume an additional Specman tick and one cycle of simulation time.
Table 1 Supported TLM Interfaces and Related Methods
Blocking Unidirectional Interfaces
TLM Interface | Interface Methods |
tlm_blocking_put of type |
put(value:type)@sys.any |
tlm_blocking_get of type |
get(value:*type)@sys.any |
tlm_blocking_peek of type |
peek(value:*type)@sys.any |
tlm_blocking_get_peek of type |
get(value:*type)@sys.any
peek(value:*type)@sys.any
|
Nonblocking Unidirectional Interfaces
TLM Interface | Interface Methods |
tlm_nonblocking_put of type
|
try_put(value:type) : bool
can_put() : bool
ok_to_put() : tlm_event
|
tlm_nonblocking_get of type
|
try_get(value:*type) : bool
can_get() : bool
ok_to_get() : tlm_event
|
tlm_nonblocking_peek of type
|
try_peek(value:*type) : bool
can_peek() : bool
ok_to_peek() : tlm_event
|
tlm_nonblocking_get_peek of type
|
try_get(value:*type) : bool
can_get() : bool
ok_to_get() : tlm_event
try_peek(value:*type) : bool
can_peek() : bool
ok_to_peek() : tlm_event
|
Combined Unidirectional Interfaces (Blocking and Nonblocking)
TLM Interface | Interface Methods |
tlm_put of type
|
put(value:type)@sys.any
try_put(value:type) : bool
can_put() : bool
ok_to_put() : tlm_event
|
tlm_get of type
|
get(value:*type)@sys.any
try_get(value:*type) : bool
can_get() : bool
ok_to_get() : tlm_event
|
tlm_peek of type
|
peek(value:*type)@sys.any
try_peek(value:*type) : bool
can_peek() : bool
ok_to_peek() : tlm_event
|
Supported Bidirectional TLM Interfaces
Note Nonblocking TLM interface calls are zero-delay calls. The blocking interface calls, which
correspond to e TCM methods, consume an additional Specman tick and one cycle of simulation time.
Table 2 Supported Bidirectional TLM Interfaces and Related Methods
Blocking Bidirectional Interfaces
TLM Interface | Interface Methods |
tlm_blocking_master of (req-type, rsp-type) |
put(value: req-type)@sys.any
get(value: *rsp-type)@sys.any
peek(value: *rsp-type)@sys.any
|
tlm_blocking_slave of (req-type, rsp-type)
|
put(value: rsp-type)@sys.any
get(value: *req-type)@sys.any
peek(value: *req-type)@sys.any
|
tlm_blocking_transport of (req-type, rsp-type)
|
transport(request: req-type,
response: *rsp-type)@sys.any
|
Nonblocking Bidirectional Interfaces
TLM Interface | Interface Methods |
tlm_nonblocking_master of (req-type, rsp-type)
|
try_put(value: req-type) : bool
can_put() : bool
ok_to_put() : tlm_event
try_get(value: *rsp-type): bool
can_get(): bool
ok_to_get(): tlm_event
try_peek(value: *rsp-type): bool
can_peek(): bool
ok_to_peek(): tlm_event
|
tlm_nonblocking_slave of (req-type, rsp-type)
|
try_put(value: rsp-type) : bool
can_put() : bool
ok_to_put() : tlm_event
try_get(value: *req-type): bool
can_get(): bool
ok_to_get(): tlm_event
try_peek(value: *req-type): bool
can_peek(): bool
ok_to_peek(): tlm_event
|
tlm_nonblocking_transport of (req-type, rsp-type)
|
nb_transport(request: req-type,
response: *rsp-type): bool
|
Combined Bidirectional Interfaces (Blocking plus Nonblocking)
TLM Interface | Interface Methods |
tlm_master of (req-type, rsp-type)
|
put(value: req-type)@sys.any
get(value: *rsp-type)@sys.any
peek(value: *rsp-type)@sys.any
try_put(value: req-type): bool
can_put(): bool
ok_to_put(): tlm_event
try_get(value: *rsp-type): bool
can_get(): bool
ok_to_get(): tlm_event
try_peek(value: *rsp-type): bool
can_peek(): bool
ok_to_peek(): tlm_event
|
tlm_slave of (req-type, rsp-type)
|
put(value: rsp-type)@sys.any
get(value: *req-type)@sys.any
peek(value: *req-type)@sys.any
try_put(value: rsp-type): bool
can_put(): bool
ok_to_put(): tlm_event
try_get(value: *req-type): bool
can_get(): bool
ok_to_get(): tlm_event
|
lm_transport of (req-type, rsp-type)
|
transport(request: req-type,
response: *rsp-type)@sys.any
nb_transport(request: req-type,
response: *rsp-type): bool
|
Supported Analysis TLM Interface
Table 3 Supported Analysis TLM Interface and Related Methods
TLM Interface | Interface Methods |
tlm_analysis of type
|
write(value : type)
|
Required Semantics of TLM Interface Methods
TLM Interface Methods need to be implemented for each interface type. These methods are activated in response to a port interface call. As users of the e language define new interface types, they will have to provide implementations to the interface methods. The following section defines the expected semantics of the various Interface Methods.
put(value:type)
The put() method passes on a value into the port, making it available for connected ports to read. This call shall block if the port is not ready to handle the transfer of the value.
try_put(value:type) : bool
The try_put() method is non-blocking. If the port is ready to handle a put operation, the value is passed on and the method returns TRUE. Otherwise the method returns FALSE, and the value is not passed on.
can_put() : bool
The can_put() method returns TRUE if the port is ready to handle a put operation (a call to put() will not block). FALSE is returned if the port is not ready to handle a put operation (a call to put() would block).
ok_to_put() : tlm_event
The method ok_to_put() returns an event that will trigger each time the port is ready to handle a put operation. The returned event may be used to invoke the user code producing the next put operation.
get(value:*type)
The get() method returns the value that is read from the port (the value is passed by reference in the parameter). This call blocks if no value is available to be read.
try_get(value:*type) : bool
The try_get() non-blocking method returns TRUE and the read value if the port can be read. FALSE is returned if the port is not ready to be read (the get() operation would block).
can_get() : bool
The method can_get() returns TRUE if a get operation can be performed without blocking. FALSE is returned otherwise.
ok_to_get() : tlm_event
The method ok_to_get() returns an event that will trigger each time the port is ready for a get operation (data is available for reading). The returned event can be used to trigger user code performing a get operation.
peek(value:*type)
The peek() method returns the next value ready to be read from a port. Peek() doesn't consume the value - a subsequent get() call will return the same value. Peek() shall block if no value is ready to be read, and return only when the next value is available.
try_peek(value:*type) : bool
The try_peek() non-blocking method returns TRUE and the read value if the port can be read. FALSE is returned if the port is not ready to be read (the peek() operation would block). This method doesn't consume the read value.
can_peek() : bool
The method can_peek() returns TRUE if a peek operation can be performed without blocking. FALSE is returned otherwise.
ok_to_peek() : tlm_event
The ok_to_peek() method returns an event that triggers each time the port is ready for a peek operation (data is available to be read). The returned event can be used to trigger user code that monitors (performs a non-destructive inspection) the ports output.
transport(request: req-type, response: *rsp-type)
The transport() method implements the equivalent of a procedure call, or a bidirectional atomic transfer. The first parameter contains the input to the procedure. The second parameter passes back the output (by reference). The method may consume time, depending on the user-level implementation of this method for a particular interface.
write(value : type)
The write() method passes on a value into an analysis port. The method is non-blocking, because analysis ports should always be ready to be written.