Adds a port upstream_ingress that implements the transaction_translator
interface. Port upstream_ingress receives all accesses before they
take any effect.
The transaction_translator_interface_t method translate
in port upstream_ingress can be overridden
to inspect/add/react to atoms in the transaction. When overridden, it is
recommended that the default implementation is called, such that
the transaction will flow onwards to the ultimate destination
(unless, of course, this is not desired).
The group ingress_blockers sits below the port upstream_ingress
in the object hierarchy. It serves the purpose of conditionally block downstream transactions.
Its method is_blocked iterates over all blockers in the group and blocks the transaction
if any of them evaluate to true. The owner of a blocker is responsible for
calling SIM_translation_changed on object upstream_ingress.obj when
its blocking conditions change. This is to ensure that any cached translations
in the system are discarded.
Blockers in this group are added as DML subgroups and must inherit the upstream_ingress_blocker
template. See the upstream_ingress_blocker template for more details.
The upstream_ingress_blocker template is meant to be inherited
by DML subgroups of the ingress_blockers group
in the pcie_upstream_ingress_handling template.
It requires the object to define method block_transaction.
Method block_transaction will be checked for each downstream transaction
to determine if the transaction can be forwarded.
blocker_name is used to identify the blocker in the logs when a transaction is blocked.block_transaction(const transaction_t *t, uint64 addr, access_t access) -> (bool)This method is called for each downstream transaction. If it returns true, the transaction is blocked and will not be forwarded to the destination. If it returns false, the transaction will be allowed to proceed.
Enables peer-to-peer (P2P) routing for multi-function and SR-IOV endpoint
devices. When a function issues an upstream transaction (memory or
ID-routed message), this template intercepts the transaction in the
upstream egress path and checks whether its destination matches
another function within the same device. If a match is found and
can_route_p2p permits it, the transaction is redirected to the
device’s own upstream_ingress port instead of being forwarded
upstream, effectively implementing device-local peer-to-peer routing.
The template supports matching against:
For memory transactions, routing is based on BAR address ranges. For ID-routed messages, routing is based on device ID (BDF) matching.
can_route_p2p(uint16 src_rid, uint16 target_rid, transaction_t *t, uint64 addr) -> (pcie_p2p_routing_decision_t, transaction_t *):
Called when a P2P-routable transaction matches a local function.
The meaning of the pcie_p2p_routing_decision_t return
value is interpreted as follows: PCIE_P2P_BLOCK means the transaction
shall not proceed at all, PCIE_P2P_ROUTE_UPSTREAM means it shall proceed
upstream, and PCIE_P2P_ROUTE_P2P means it shall be routed peer-to-peer.
Returns (PCIE_P2P_ROUTE_UPSTREAM, t) by default,
meaning P2P routing must be explicitly enabled by overriding this method.
The src_rid parameter is the requester ID of the originating function
and target_rid is the device ID of the matched destination function.