A critical detail when using Tandem Configuration, specifically Tandem PCIe® , is to ensure that stage 1 and stage 2 PDI images remain paired. The fundamental solution splits a single implemented design image into two sections, and there is no mechanism to guarantee either section will pair successfully with a section from an independent design. It is the designer’s responsibility to keep the two stages in sync. AMD Versal™ adaptive SoC devices have safeguards in place to help with this effort.
AMD Versal™ adaptive SoC devices have safeguards in the form of unique identifiers (UID) that are checked by the PLM when stage 2 programming images are delivered. Four 32-bit fields are embedded in the PDI as described in the following table:
ID Name | Description | Defined by | PDI Mapping |
---|---|---|---|
Node ID | Defines the configuration node in the PL | Vivado | id (0x18) |
Unique ID | A unique hash value to identify the module | Vivado | unique_id (0x24) |
Parent ID | A reference to the Unique ID of the module that precedes the target module | Vivado | parent_unique_id (0x28) |
Function ID | Identification of the function residing in the target module | User | function_id (0x2c) |
The Node ID is a fixed value that is incremented for each partition in the design. The stage 1 image represents the initial configuration of the device and it is given an ID of 0x18700000. A value of 0x18700001 is assigned to stage 2 of the Tandem PCIe design. This value is useful in differentiating the partitions in the design, though the file sizes and contents also make this quite apparent. If DFX is also included, each node (RM) in the design has an incremented value starting with 0x18700002.
The Unique ID is a hash value generated automatically by Vivado. The value is deterministic, calculated by a number of factors within the design, so any change to a design’s results (code change, new synthesis, or implementation options, or design constraints) could produce a new unique ID for each design section.
The Parent ID is a reference to the unique ID of the module that precedes the current one. The Parent ID of the stage 1 design always be zero (0x00000000) as it is the first file to be programmed in any tandem design. The Parent ID of stage 2 is the unique ID of the stage 1 design it initially compiled with. This is the comparison done in the PLM to ensure compatibility between images. If DFX is also enabled in the tandem design, the Parent ID of each reconfigurable module PDI is the unique ID of stage 2 PDI, as the partial images must follow the stage 2 image.
The function ID is a user space to embed any custom unique identifier that can be parsed in the PDI header. Users can apply a 32-bit value by setting a property on the instance. This enables them to quickly differentiate functions contained in the programming images.
These unique identifiers are automatically stored in the Tandem PDI files generated by write_device_image. You can read these values in a number of ways, but the easiest way is to parse them using Bootgen. Call Bootgen with the -read option to see the details of the PDI contents. Find the four UID fields in the pl_cfi portion of the output.
bootgen -arch versal -read <pdi file>
Information seen in the stage 1 PDI:
...
--------------------------------------------------------------------------------
IMAGE HEADER (pl_cfi)
--------------------------------------------------------------------------------
pht_offset (0x00) : 0x00014a24 section_count (0x04) : 0x00000001
mHdr_revoke_id (0x08) : 0x00000000 attributes (0x0c) : 0x00001800
name (0x10) : pl_cfi
id (0x18) : 0x18700000 unique_id (0x24) : 0x738c16a7
parent_unique_id (0x28) : 0x00000000 function_id (0x2c) : 0x00000000
memcpy_address_lo (0x30) : 0x00000000 memcpy_address_hi (0x34) : 0x00000000
checksum (0x3c) : 0x10a2b15d
attribute list -
owner [plm] memcpy [no]
load [now] handoff [now]
dependentPowerDomains [spd][pld]
Information seen in the stage 2 PDI:
...
--------------------------------------------------------------------------------
IMAGE HEADER (pl_cfi)
--------------------------------------------------------------------------------
pht_offset (0x00) : 0x00000034 section_count (0x04) : 0x00000002
mHdr_revoke_id (0x08) : 0x00000000 attributes (0x0c) : 0x00001800
name (0x10) : pl_cfi
id (0x18) : 0x18700001 unique_id (0x24) : 0xf278b7b9
parent_unique_id (0x28) : 0x738c16a7 function_id (0x2c) : 0x00000000
memcpy_address_lo (0x30) : 0x00000000 memcpy_address_hi (0x34) : 0x00000000
checksum (0x3c) : 0x1e2b4392
attribute list -
owner [plm] memcpy [no]
load [now] handoff [now]
dependentPowerDomains [spd][pld]
Note how the Unique ID of the stage 1 output matches the Parent ID of the stage 2 output. These PDIs are from the same design and are therefore compatible.
This data can also be found via cdoutil by grepping for the string "ldr_set_image_info" in a Tandem or DFX PDI image. The four UID fields always be listed in the same order: Node ID, Unique ID, Parent ID, and Function ID. The stage 1 PDI has the UID information for the stage 1 domain (clearly identified by the Parent ID – the third field – set to 0) followed by the stage 2, whereas the stage 2 PDI only shows the UID information for the PL portion of the design, unless DFX is also enabled. If DFX is enabled, the stage 2 PDI lists all RMs in the design, each with an incrementing Node ID and a Parent ID pointing back to stage 2.
Example without DFX:
> cdoutil design_tandem1.pdi | grep ldr_set_image_info
ldr_set_image_info 0x18700000 0x738c16a7 0 0
ldr_set_image_info 0x18700001 0xf278b7b9 0x738c16a7 0
> cdoutil design_tandem2.pdi | grep ldr_set_image_info
ldr_set_image_info 0x18700001 0xf278b7b9 0x738c16a7 0
Example with DFX:
> cdoutil Versal_CPM_Tandem_PCIe_top_tandem1.pdi | grep ldr_set_image_info
ldr_set_image_info 0x18700000 0x6be3877e 0 0
ldr_set_image_info 0x18700001 0x9163c3cf 0x6be3877e 0
> cdoutil Versal_CPM_Tandem_PCIe_top_tandem2.pdi | grep ldr_set_image_info
ldr_set_image_info 0x18700001 0x9163c3cf 0x6be3877e 0
ldr_set_image_info 0x18700002 0xb01c9cde 0x9163c3cf 0
ldr_set_image_info 0x18700003 0xebb76422 0x9163c3cf 0
> cdoutil Versal_CPM_Tandem_PCIe_DFX_pl_bram_partial.pdi | grep ldr_set_image_info
ldr_set_image_info 0x18700002 0xb01c9cde 0x9163c3cf 0
During the stage 2 image load, the PLM examines these contents and confirms that the identifiers match. The Parent ID of the stage 2 must match the Unique ID of the stage 1 image already loaded in the Versal device. If they do not, a failure is reported and the stage 2 PDI is rejected before it is programmed, allowing the you to take corrective action. Following are example logs for passing and failing conditions:
Passing example:
[root@machine linux-kernel]# ll pdi/
-rw-r--r-- 1 root root 1426912 Apr 14 12:32 design_tandem2.pdi
[root@machine linux-kernel]# dma-to-device -d /dev/qdma65000-MM-0 -f ./pdi/design_tandem2.pdi -s 1426912 -a 0x102100000
size=1426912 Average BW = 36.272916 MB/sec
Failing example:
[root@machine linux-kernel]# ll pdi/
-rw-r--r-- 1 root root 1426912 Apr 14 12:32 design_tandem2.pdi
[root@machine linux-kernel]# dma-to-device -d /dev/qdma65000-MM-0 -f ./pdi/design_tandem2.pdi -s 1426912 -a 0x102100000
/dev/qdma65000-MM-0, W off 0x102100000, 0x15ecf0 failed -1.
write file: Input/output error