Used by devices that simulate a single PCIe function with a Type 0
header. Implements the pcie_device
interface, defines a pcie_config
bank,
and an upstream_target
connect. Also defines a phy
port that handles
transactions related to the PCIe physical layer.
Similar to pcie_endpoint
but doesn't define a pcie_config
bank. Can be
used by devices that simulate multiple functions. A device using this
template must define at least one bank that is an instance of the
physical_config_bank
template. Also defines a phy
port that handles
transactions related to the PCIe physical layer.
Implements the pcie_device
interface, with default methods for connect and
disconnect that finds all instances of physical_config_bank
in this device
and lets them map/demap themselves and their resources in the upstream
target.
Assumes that there is a connect upstream_target
which it sets/clears
when the device is connected/disconnected.
Base template for register banks that implement a PCIe configuration
header. Defines the registers that are common to both Type 0 and Type 1
headers, as well as many utility methods. Typically not used
directly. Inherit one of the derived templates, e.g. type_0_bank
or
type_1_bank
instead.
Uses the following parameters
function
: The PCIe function number that this bank will use, default 0update_function(uint16 device_id)
Updates the mapping of this function's configuration header in the upstream target, using the parameter device_id.
del_function()
Removes the current mapping (if any) of this function's configuration header in the upstream target.
get_device_id() -> (uint16)
Returns the Device ID of this function, as known by the upstream target. Uses the parameter pcie_obj which defaults to obj.
get_pasid() -> (uint32)
Returns the currently configured PASID, if this device has the PASID capability structure.
del_mappings(pcie_type_t type)
Deletes all BAR mappings of type type, that this function has added.
update_mappings(pcie_type_t type)
Updates all BAR mappings of type type, that this function has added.
lock_hwinit_registers()
Locks all registers that use the template hwinit
unlock_hwinit_registers()
Unlocks all registers that use the template hwinit
raise_legacy_interrupt()
Raises the PCIe Legacy Interrupt pin INTx, as configured in the
interrupt_pin
register and if enabled in the status.ins
register
field.
lower_legacy_interrupt()
Lowers the PCIe Legacy Interrupt pin INTx, as configured in the
interrupt_pin
register
issue_transaction(transaction_t *t, uint64 addr) -> (pcie_error_t)
Low-level method for issuing a transaction into some PCIe address space.
Prepends required PCIe atoms to a transaction before issuing it to
upstream_target
.
Utility methods for reading and writing PCIe Memory data. Reads or
writes PCIe Memory data in upstream_target.map_target
.
memory.read(uint64 addr, uint64 size) -> (pcie_error_t, uint64)
memory.read_bytes(uint64 addr, buffer_t buf) -> (pcie_error_t)
memory.write(uint64 addr, uint64 value, uint64 size) -> (pcie_error_t)
memory.write_bytes(uint64 addr, bytes_t bytes) -> (pcie_error_t)
The following methods handle receiving messages. Their default
implementations are meant to be overridden by devices that wish to
handle the particular type of message. Unless otherwise noted, the
default implementation logs an unimpl message and returns
false
, which indicates a 'Completer Abort'.
message.operation(transaction_t *t, uint64 addr) -> (bool)
Main method for receiving messages. Inspects the message type and redirects to the appropriate method for handling that specific message.
message.ats_invalidate(transaction_t *t, uint64 addr) -> (bool)
message.prs_request(transaction_t *t, uint64 addr) -> (bool)
message.prs_response(transaction_t *t, uint64 addr) -> (bool)
These three methods redirect to their *_received
counterparts in
the ats_capability
group, if present.
message.vendor_defined_type_1(transaction_t *t, uint64 addr) -> (bool)
PCIe demands that Vendor Defined Type 1 messages are silently
ignored, if not implemented. This method logs unimpl on level 2
and returns true
, by default.
message.pm_active_state_nak(transaction_t *t, uint64 addr) -> (bool)
message.pm_turn_off(transaction_t *t, uint64 addr) -> (bool)
message.unlock(transaction_t *t, uint64 addr) -> (bool)
message.set_slot_power_limit(transaction_t *t, uint64 addr) -> (bool)
message.vendor_defined_type_0(transaction_t *t, uint64 addr) -> (bool)
message.hot_plug(transaction_t *t, uint64 addr) -> (bool)
Hot Plug messages are obsolete, according to PCIe, but must be silently ignored. This method logs unimpl on level 2 and returns 2, by default.
message.unknown(transaction_t *t, uint64 addr, pcie_message_type_t code) -> (bool)
This method handles message types that are unknown to
message.operation
, and gets the message type as a parameter.
The following methods can be used to send PCIe messages. The addr parameter contains the 8-byte address-field of the message. As in a real world TLP, the Device ID is the upper bits (63 through 48) of the address, while the lower bits may hold other message-specific information. The type and route parameters indicate the message type and the routing information.
For message.send_bytes
the additional parameter bytes is used
for sending data in the message payload.
For message.send_custom
the additional parameter extra_atoms is used
for devices to append additional required atoms that are not added automatically
by the library. These could be vendor specific atoms,
the destination segment atom (Sim_Atom_Id_pcie_destination_segment), etc.
message.send(uint64 addr, pcie_message_type_t type, pcie_msg_route_t route) -> (pcie_error_t)
message.send_bytes(uint64 addr, pcie_message_type_t type, pcie_msg_route_t route, bytes_t bytes
message.send_custom(uint64 addr, pcie_message_type_t type, pcie_msg_route_t route, bytes_t bytes, atom_t extra_atoms[]
transaction_access(transaction_t *t, uint64 offset, void *aux) -> (exception_type_t)
Entrypoint for access into the bank. Redirects to message or default
bank operation, depending on the type of the transaction. The pointer to
the transaction is passed as aux
to the default operation, allowing
lower level methods to inspect and set atoms. Sets the pcie_error_ret
atom if present, and not set by lower level methods.
Base-template for physical functions, type 0 and 1. Inherits config_bank.
Inherits physical_config_bank and adds Type 0 specific registers.
Implements the HwInit access restrictions, as described in the PCIe specification.
Uses the following parameters:
writable_after_reset
: Is the register or field writable after reset, default falsewritable_once_only
: Is the register or field writable once only, default trueCan be used to implement an object that is similar to the Base Address Registers in the PCIe configuration header.
The parameter type indicates in which upstream address space the resource
should be mapped. If the type is PCIE_Type_Memory
or PCIE_Type_IO
the
register will be called to update its resources when command.mem
and
command.io
, respectively, is written. If this is not desired, type can
be set to PCIE_Type_Other
and the parameter map_type can be used to
indicate in which address space the resource should be mapped.
The parameter map_obj indicates which object will be mapped.
Users of this template must:
get_map_info() -> (map_info_t)
enabled() -> (bool)
Implements the common functionality for Memory and I/O Base Address Registers as specified in PCIe. It has a single unsized field address.
The parameter map_obj indicates which object will be mapped.
The parameter size_bits defaults to 12 and defines the number of address bits that this base address register uses. If a Resizable BAR capability is present and indicates that it controls the size of this BAR the size from the relevant RBAR Control register will be used instead.
Users of this template must:
enabled() -> (bool)
Implements a Memory Base Address Register as specified in PCIe.
The parameter map_obj indicates which object will be mapped.
The parameter size_bits defaults to 12 and defines the number of address bits that this base address register uses. If a Resizable BAR capability is present and indicates that it controls the size of this BAR the size from the relevant RBAR Control register will be used instead.
Users of this template must:
Implements an I/O Base Address Register as specified in PCIe.
The parameter map_obj indicates which object will be mapped.
The parameter size_bits defaults to 12 and defines the number of address bits that this base address register uses. If a Resizable BAR capability is present and indicates that it controls the size of this BAR the size from the relevant RBAR Control register will be used instead.
Users of this template must:
Defines a register expansion_rom_base
, as defined in PCIe. Additionally,
creates a group expansion
which holds sub objects for a ROM and an image,
sized according to the parameter size_bits, which defaults to 11. The ROM
will be mapped in PCIe Memory Space, when enabled.
Users of this template must:
Defines a pseudo-connect upstream_target
, used by many other PCIe
templates.