SPRUJ28E November 2021 – September 2024 AM68 , AM68A , TDA4AL-Q1 , TDA4VE-Q1 , TDA4VL-Q1
The PCIe subsystem includes the VMAP module that can be programed to map (convert) the incoming 16-bit PCIe requestID + 2-bit PCIe AT bits to the 16-bit CBA virtID + 2-bit CBA atype attributes.
Figure 12-65 shows the block diagram of the VMAP module. The blocks shown in the diagram are replicated for the read and write AXI channels. However, there is only one set of configuration registers in the VMAP module and these are shared by both the read and write channel logic.
The RequestID Clamp block is used to clamp the incoming requestID to a maximum value. This block compares the incoming PCIe requestID[15:12] masked with the virtid_mask[3:0] to an expected value. Bit [19] BDF_MODE in PCIE_VMAP_DEFMAP is used to set the value to virtid_force[3:0] or 4’h0. The clamped_requestid is set to the maximum value of FFFFh if the comparison is false. The clamped_requestid value is later used downstream by the PVU or SMMU in the SoC.
Each of the VMAP modules includes a set of 32 match and mask registers. Software can enable the registers to be used for the mapping by setting the [0] EN bit in PCIE_VMAP_CTRL_j registers. Software can also program the [15-0] RID and [31-16] MASK bit fields in PCIE_VMAP_REQID_j registers to indicate the incoming PCIe requestid that needs to be matched. The [11-0] VID and [17-16] ATYPE bit fields in PCIE_VMAP_VIRTID_j registers are used to program the required CBA virtID and Atype fields in case of a match. In order to prevent a spurious match, the [15-0] RID and [31-16] MASK bit fields in PCIE_VMAP_REQID_j registers should be set up before the [0] EN bit in PCIE_VMAP_CTRL_j registers is set. The same sets of registers are used for both read and write transactions.
The Match logic with Priority Encoding block compares the incoming PCIe requestID with the values programmed in the VMAP control registers and sets the value of the virtid_int and atype_int variables. For every incoming PCIe transaction, the incoming PCIe requestID[11:0] bits are masked with the PCIE_VMAP_REQID_j[31-16] MASK bit field and compared against each of the thirty two values indicated by PCIE_VMAP_REQID_j[15-0] RID that are enabled. The location of the first match of this comparison operation is used to select the [11-0] VID and [17-16] ATYPE bit fields in PCIE_VMAP_VIRTID_j registers. This is used as the virtid_int and atype_int values for the downstream logic. In case none of the enabled [15-0] RID and [31-16] MASK bit fields in PCIE_VMAP_REQID_j registers pairs match the incoming requestID, the value in [11-0] DEF_VID and [17-16] DEF_ATYPE bit fields in PCIE_VMAP_DEFMAP registers is used.
The VirtID and Atype Fix block uses the incoming PCIe AT_bits along with the matched and clamped values of the requestID from the downstream blocks to set the final values of the virtID, catype and cflush attributes for the particular CBA transaction. The values of the virtID, catype and cflush are determined based on the following criteria:
The PCIE implementation in the device uses the direct_mode workaround. This forces the cvirtID and catype to 0 when the incoming transaction matches the criteria outlined in (1) above.
The system Interconnect only supports 12-bits of virtid. As a result, only virtid[11:0] from the PCIe VMAP module will be used in the system and virtid[15:12] is not connected.
The pseudo-code for the virtID mapping algorithm implemented is described below.
// Requestid Clamp
// Note: only the low 4 bits of virtid_force & virtid_mask are used in the current PCIe wrapper
// virtid_mask[7:4] should always be 1
// virtid_mask[n] of 1 means use the virtid_force value for this bit
// virtid_mask[n] of 0 means use the requestID value for this bit, virtid_force[n] should be 0
// Bit [19] BDF_MODE in PCIE_VMAP_DEFMAP specifies if we are using
// 0 based bus numbers (0) or offset bus numbers (1)
expected_value[3:0] = PCIE_VMAP_DEFMAP[19] BDF_MODE ? virtid_force[3:0] : 4’h0;
if (requestID[15:12] & virtid_mask[3:0] == expected_value[3:0] )
{
clamped_requestID[15:0] = requestID[15:0];
}
else
{
clamped_requestID[15:0] = FFFFh];
}
// Match Logic with Priority Encoding
for n in 0 to 31 do
if (PCIE_VMAP_CTRL_j[0] EN == 1h &&
(requestID & PCIE_VMAP_REQID_j[31-16] MASK) == PCIE_VMAP_REQID_j[15-0] RID )
{
found[n] = true;
}
else
{
found[n] = false;
}
done
// priority encoder for 32 results from above
// uses lowest numbered match
// also outputs a bool specifying if any match was found
all_miss = true;
for n in 0 to 31 do
if (found[n])
{
virtid_int[11:0] = PCIE_VMAP_VIRTID_j[11-0] VID;
atype_int[1:0] = PCIE_VMAP_VIRTID_j[17-16] ATYPE;
all_miss = false;
break;
}
done
// Use the default if no match is found
if (all_miss)
{
virtid_int[11:0] = PCIE_VMAP_DEFMAP[11-0] DEF_VID;
atype_int[1:0] = PCIE_VMAP_DEFMAP[17-16] DEF_ATYPE;
}
// VirtID and Atype Fix
if (AT_bits == 0x2) // Is this a pre-translated address?
{
// Is this EP using SMMU and is ATS enabled?
if (atype_int == 2h && PCIE_VMAP_DEFMAP[20] == 0h )
{
if (direct_mode == 1h) //
{
// yes, send directly to destination address
atype[1:0] = 2’h0; // Direct
virtid[15:0] = 16’h0; // should not matter
flush = 1’b0; // don’t turn on the flush bit
at_cba = 1’b0; // Not used
}
else
{
// no, send to SMMU TBU for processing
atype[1:0] = 2’h2; // //SMMU
virtid[15:0] = clamped_requestID[15:0]; //Use the correct StreamID
flush = 1’b0; // don’t turn on the flush bit
at_cba = 1’b1; // Indicate a pre-translated address
}
}
else
{
// All other cases should error the transaction for pre-translated transaction
// PVU & Direct should not see any pre-translated requests
// SMMU with ATS disables also errors
atype[1:0] = 2’h2; // use VirtSS to force the error
virtid[15:0] = 16’h0; // should not matter
flush = 1’b1; // force the error
at_cba = 1’b1; // should nott matter
}
}
else
{
// This transaction is not pre-translated
atype[1:0] = atype_int //use the atype from the register
flush = 1’b0; // don’t force an n error
at_cba = 1’b0; // this is not pre-e- translated
if (atype_int == 2’h2)
{
// this is SMMU, use the clamped RequestID
virtid[15:0] = clamped_requestID[15:0];
}
else
{
// this is not SMMU, use the value from the register
virtid[11:0] = virtid_int[11:0];
virtid[15:12] = 4’h0;
}
}