The user application first asserts a value on cfg_interrupt_msi_int
, as shown in the previous figure. The core asserts
cfg_interrupt_msi_sent
to indicate that the
interrupt is accepted and the core sends an MSI Memory Write TLP.
The MSI request is either a 32-bit addressable Memory Write TLP or a 64-bit addressable Memory Write TLP. The address is taken from the Message Address and Message Upper Address fields of the MSI Capability Structure, while the payload is taken from the Message Data field. These values are programmed by system software through configuration writes to the MSI Capability structure. When the core is configured for Multi-Vector MSI, system software can permit Multi-Vector MSI messages by programming a non-zero value to the Multiple Message Enable field.
The type of MSI TLP sent (32-bit addressable or 64-bit addressable) depends on the value of the Upper Address field in the MSI capability structure. By default, MSI messages are sent as 32-bit addressable Memory Write TLPs. MSI messages use 64-bit addressable Memory Write TLPs only if the system software programs a non-zero value into the Upper Address register.
When Multi-Vector MSI messages are enabled, the user application can
override one or more of the lower-order bits in the Message Data field of each
transmitted MSI TLP to differentiate between the various MSI messages sent upstream. The
number of lower-order bits in the Message Data field available to the user application
is determined by the lesser of the value of the Multiple Message Capable field, as set
in the IP catalog, and the Multiple Message Enable field, as set by system software and
available as the cfg_interrupt_msi_mmenable[2:0]
core
output. The core masks any bits in cfg_interrupt_msi_select
which are not configured by system software
through Multiple Message Enable.
This pseudo code shows the processing required:
// Value MSI_Vector_Num must be in range: 0 £ MSI_Vector_Num £ (2^cfg_interrupt_mmenable)-1
if (cfg_interrupt_msienable) { // MSI Enabled
if (cfg_interrupt_mmenable > 0) { // Multi-Vector MSI Enabled
cfg_interrupt_msi_int[MSI_Vector_Num] = 1;
} else { // Single-Vector MSI Enabled
cfg_interrupt_msi_int[MSI_Vector_Num] = 0;
}
} else {
// Legacy Interrupts Enabled
}
For example:
- If
cfg_interrupt_mmenable[2:0] == 000b
, that is, 1 MSI Vector Enabled,cfg_interrupt_msi_int = 01h;
- If
cfg_interrupt_mmenable[2:0] == 101b
, that is, 32 MSI Vectors Enabled,cfg_interrupt_msi_int = {32'b1 << {MSI_Vector#}}
;
where MSI_Vector#
is a 5-bit value and
is allowed to be 00000b ≤ MSI_Vector# ≤ 11111b
.
If Per-Vector Masking is enabled, first verify that the vector being signaled is not masked in the Mask register. This is done by reading this register on the Configuration interface (the core does not look at the Mask register).