Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 151 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

..
comment:: SPDX-License-Identifier: MIT
comment:: Copyright (C) 2024 Advanced Micro Devices, Inc.
comment:: Copyright (C) 2024-2026 Advanced Micro Devices, Inc.

============================
AIE Binary Utilities (AIEBU)
Expand Down Expand Up @@ -77,3 +77,153 @@ Compiled Libraries
Directory ``opt/xilinx/aiebu/lib``
* libaiebu.so
* libaiebu_static.a

ELF Format for AIE Architectures
================================

AIEBU generates ELF files for AIE control code. The ELF header contains OS/ABI
and ABI version fields that identify the target architecture and ELF format version.

OS/ABI Values
-------------

The OS/ABI field (``e_ident[EI_OSABI]``) identifies the target AIE architecture.
Values are chosen with high Hamming distance for robustness against bit flips.

.. list-table:: OS/ABI Values
:header-rows: 1
:widths: 25 15 60

* - Architecture
- Value (Hex)
- Description
* - aie2ps_group
- 0x46 (70)
- Legacy group ELF for AIE2PS/AIE4 family
* - aie2p
- 0x45 (69)
- AIE2P architecture
* - aie2ps
- 0x40 (64)
- AIE2PS specific (config with ``.target``)
* - aie4
- 0x4B (75)
- AIE4 architecture
* - aie4a
- 0x56 (86)
- AIE4A architecture variant
* - aie4z
- 0x69 (105)
- AIE4Z architecture variant

ELF ABI Version
---------------

The ABI version field (``e_ident[EI_ABIVERSION]``) uses major.minor encoding:
upper nibble = major version, lower nibble = minor version.

.. list-table:: ELF ABI Version Values
:header-rows: 1
:widths: 25 15 60

* - Version
- Value (Hex)
- Description
* - Non-config
- 0x02 (0.2)
- Non-config ELF (all architectures)
* - Legacy config (AIE2PS/AIE4)
- 0x03 (0.3)
- Config ELF without ``.target`` directive
* - AIE2P config (legacy)
- 0x10 (1.0)
- Legacy AIE2P config ELF (read-only, no longer written)
* - Config with .target
- 0x20 (2.0)
- Config ELF with ``.target`` directive or AIE2/AIE2P config

Behavior by Target Option
-------------------------

The following table shows how the ``-t`` option and ``.target`` directive
affect ELF version and OS/ABI:

.. list-table:: ELF Output by Target
:header-rows: 1
:widths: 30 20 15 35

* - -t Option
- .target in ASM
- ELF Version
- OS/ABI
* - aie2ps/aie4 (non-config)
- Any (ignored)
- 0x02
- aie2ps_group (0x46)
* - aie2ps_config/aie4_config
- Not present
- 0x03
- aie2ps_group (0x46)
* - aie2ps_config/aie4_config
- Present
- 0x20
- Based on .target value
* - aie2_config/aie2p_config
- N/A (binary input)
- 0x20
- aie2p (0x45)
* - aie2/aie2p (non-config)
- N/A (binary input)
- 0x02
- aie2p (0x45)

**Key points:**

* Non-config ELFs always use version 0x02, regardless of ``.target`` directive
* Config ELFs use version 0x20 only when ``.target`` directive is present
* Version 0x20 enables architecture-specific OS/ABI values

Version and OS/ABI Compatibility
--------------------------------

ELF readers use the ABI version to determine valid OS/ABI values:

* **Version 0x02 (non-config)**: OS/ABI must be ``aie2ps_group`` (0x46) or
``aie2p`` (0x45). Used for all non-config ELFs.

* **Version 0x03 (legacy config)**: OS/ABI must be ``aie2ps_group`` (0x46).
Used for AIE2PS/AIE4 config ELFs without ``.target`` directive.

* **Version 0x10 (AIE2P config - legacy)**: OS/ABI must be ``aie2p`` (0x45).
Legacy config for AIE2P. No longer written by assembler; supported for
reading existing ELF files only.

* **Version 0x20 (config with .target)**: All OS/ABI values are valid
(``aie2ps``, ``aie2p``, ``aie2ps_group``, ``aie4``, ``aie4a``, ``aie4z``).
Used for config ELFs with ``.target`` directive or AIE2/AIE2P config.

The ``.target`` directive in assembly source determines whether the new config
format (version 0x20) is used. For config ELFs, when ``.target`` is present,
the assembler validates it against the ``-t`` command-line option and sets
the specific OS/ABI value. Non-config ELFs always use legacy values regardless
of ``.target`` directive.

Constants Definition
--------------------

All OS/ABI and ELF version constants are defined in a single header file:

``src/cpp/elf/aie_elf_constants.h``

This file contains:

* ``osabi_aie2ps_group`` (0x46) - Legacy group ELF
* ``osabi_aie2p`` (0x45) - AIE2P
* ``osabi_aie2ps`` (0x40) - AIE2PS specific
* ``osabi_aie4`` (0x4B) - AIE4
* ``osabi_aie4a`` (0x56) - AIE4A
* ``osabi_aie4z`` (0x69) - AIE4Z
* ``elf_version_legacy`` (0x02) - Non-config
* ``elf_version_legacy_config`` (0x03) - Legacy config
* ``elf_version_aie2p_config`` (0x10) - Legacy AIE2P config (read-only)
* ``elf_version_config`` (0x20) - Config with .target
84 changes: 72 additions & 12 deletions src/cpp/analyzer/transform_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
// Copyright (C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.

#include <cstdint>
#include <cctype>
Expand Down Expand Up @@ -64,10 +64,40 @@ load_elf(const std::vector<char>& elf_data)
if (!m_elfio.load(istr))
throw error(error::error_code::invalid_input, "Failed to load ELF from buffer\n");

// Only AIE2PS/AIE4 legacy ELF and group ELF formats are supported
// Check ELF version and OS ABI compatibility
auto os_abi = m_elfio.get_os_abi();
if (os_abi != elf_amd_aie2ps_group)
throw error(error::error_code::invalid_input, "Only aie2ps/aie4 config elf supported\n");
auto abi_version = m_elfio.get_abi_version();

// ELF version and OS ABI compatibility:
// - Version 0x02 (non-config): aie2ps_group (0x46) or aie2p (0x45)
// - Version 0x03 (legacy config): aie2ps_group (0x46)
// - Version 0x10 (aie2p config): aie2p (0x45)
// - Version 0x20 (config with .target): all OS_ABI values supported
if (abi_version == elf_version_legacy) {
// Non-config ELF - aie2ps_group or aie2p
if (os_abi != osabi_aie2ps_group && os_abi != osabi_aie2p)
throw error(error::error_code::invalid_input, "Only aie2ps_group or aie2p elf supported for ELF version 0x02\n");
} else if (abi_version == elf_version_legacy_config) {
// Legacy config ELF - only aie2ps_group
if (os_abi != osabi_aie2ps_group)
throw error(error::error_code::invalid_input, "Only aie2ps_group elf supported for ELF version 0x03\n");
} else if (abi_version == elf_version_aie2p_config) {
// AIE2P config ELF - only aie2p
if (os_abi != osabi_aie2p)
throw error(error::error_code::invalid_input, "Only aie2p elf supported for ELF version 0x10\n");
} else if (abi_version == elf_version_config) {
// New config ELF with .target - all OS_ABI values supported
if (os_abi != osabi_aie2ps_group &&
os_abi != osabi_aie2ps &&
os_abi != osabi_aie2p &&
os_abi != osabi_aie4 &&
os_abi != osabi_aie4a &&
os_abi != osabi_aie4z)
throw error(error::error_code::invalid_input, "Only aie2ps/aie2p/aie4 family elf supported for ELF version 0x20\n");
} else {
throw error(error::error_code::invalid_input, "Unsupported ELF ABI version: 0x"
+ ELFIO::to_hex_string(abi_version) + "\n");
}
}

/**
Expand Down Expand Up @@ -978,19 +1008,49 @@ update_rela_sections(const std::vector<arginfo>& entries, const std::string& ker
std::vector<char>
transform_manager::
update_kernel_name(const std::string& orig_name, const std::string& new_name) {
// Validate ELF format: only support OS ABI 0x46 (elf_amd_aie2ps_group) and ABI version 0x3
// Validate ELF format based on version
auto os_abi = m_elfio.get_os_abi();
auto abi_version = m_elfio.get_abi_version();

if (os_abi != 0x46)
throw error(error::error_code::invalid_input,
"update_kernel_name only supports OS ABI 0x46 (AIE2PS/AIE4 group), got: 0x"
+ ELFIO::to_hex_string(os_abi));

if (abi_version != 0x3)
// ELF version and OS ABI compatibility:
// - Version 0x02 (non-config): aie2ps_group (0x46) or aie2p (0x45)
// - Version 0x03 (legacy config): aie2ps_group (0x46)
// - Version 0x10 (aie2p config): aie2p (0x45)
// - Version 0x20 (config with .target): all OS_ABI values supported
if (abi_version == elf_version_legacy) {
// Non-config ELF - aie2ps_group or aie2p
if (os_abi != osabi_aie2ps_group && os_abi != osabi_aie2p)
throw error(error::error_code::invalid_input,
"update_kernel_name only supports OS ABI 0x45/0x46 for ELF version 0x02, got: 0x"
+ ELFIO::to_hex_string(os_abi));
} else if (abi_version == elf_version_legacy_config) {
// Legacy config ELF - only aie2ps_group
if (os_abi != osabi_aie2ps_group)
throw error(error::error_code::invalid_input,
"update_kernel_name only supports OS ABI 0x46 for ELF version 0x03, got: 0x"
+ ELFIO::to_hex_string(os_abi));
} else if (abi_version == elf_version_aie2p_config) {
// AIE2P config ELF - only aie2p
if (os_abi != osabi_aie2p)
throw error(error::error_code::invalid_input,
"update_kernel_name only supports OS ABI 0x45 for ELF version 0x10, got: 0x"
+ ELFIO::to_hex_string(os_abi));
} else if (abi_version == elf_version_config) {
// New config ELF with .target - all OS_ABI values supported
if (os_abi != osabi_aie2ps_group &&
os_abi != osabi_aie2ps &&
os_abi != osabi_aie2p &&
os_abi != osabi_aie4 &&
os_abi != osabi_aie4a &&
os_abi != osabi_aie4z)
throw error(error::error_code::invalid_input,
"update_kernel_name only supports OS ABI 0x40/0x45/0x46/0x4B/0x56/0x69 for ELF version 0x20, got: 0x"
+ ELFIO::to_hex_string(os_abi));
} else {
throw error(error::error_code::invalid_input,
"update_kernel_name only supports ABI version 0x3, got: 0x"
"update_kernel_name only supports ABI version 0x02/0x03/0x10/0x20, got: 0x"
+ ELFIO::to_hex_string(abi_version));
}

// Locate required ELF sections
auto symtab = m_elfio.sections[".symtab"];
Expand Down
22 changes: 16 additions & 6 deletions src/cpp/analyzer/transform_manager.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
// Copyright (C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.

#ifndef AIEBU_TRANSFORM_MANAGER_H_
#define AIEBU_TRANSFORM_MANAGER_H_
Expand All @@ -10,6 +10,7 @@
#include <elfio/elfio.hpp>
#include "specification/aie2ps/isa.h"
#include "common/symbol.h"
#include "elf/aie_elf_constants.h"

namespace aiebu {

Expand Down Expand Up @@ -43,9 +44,6 @@ class transform_manager {
static constexpr size_t ctrlpkt_string_length = 8; // Length of ".ctrlpkt" prefix
static constexpr size_t ctrlcode_string_length = 13; // Length of "control-code" prefix

// AIE ELF OS ABI identifiers
static constexpr uint8_t elf_amd_aie2ps_group = 70; // AIE2PS/AIE4 group ELF format

// Register offset multiplier (2 for 32-bit registers = 64-bit offset)
static constexpr uint8_t num_32bit_register = 2;

Expand Down Expand Up @@ -240,7 +238,14 @@ class transform_manager {
/**
* @brief Load and validate ELF data
* @param elf_data Vector containing ELF binary data
* @throws error if ELF data is invalid or not AIE2PS/AIE4 format
*
* Supported ELF versions:
* - Version 0x02 (non-config): OS ABI 0x45/0x46 (aie2p, aie2ps_group)
* - Version 0x03 (legacy config): OS ABI 0x46 (aie2ps_group)
* - Version 0x10 (aie2p config): OS ABI 0x45 (aie2p)
* - Version 0x20 (config with .target): OS ABI 0x40/0x45/0x46/0x4B/0x56/0x69
*
* @throws error if ELF data is invalid or not supported format
*/
void load_elf(const std::vector<char>& elf_data);

Expand Down Expand Up @@ -296,7 +301,12 @@ class transform_manager {
* For C++ mangled names, matches the exact identifier (e.g., "DPU" matches "_Z3DPUPcPc"
* but not "_Z4DPU1PcPc"). Automatically updates length prefixes (_Z3DPU -> _Z4XCVB).
* For non-mangled names, does exact string matching.
* Only supports OS ABI 0x46 and ABI version 0x3.
*
* Supported ELF versions:
* - Version 0x02 (non-config): OS ABI 0x45/0x46 (aie2p, aie2ps_group)
* - Version 0x03 (legacy config): OS ABI 0x46 (aie2ps_group)
* - Version 0x10 (aie2p config): OS ABI 0x45 (aie2p)
* - Version 0x20 (config with .target): OS ABI 0x40/0x45/0x46/0x4B/0x56/0x69
*
* @throws error if format unsupported, sections missing, or name not found
*/
Expand Down
12 changes: 9 additions & 3 deletions src/cpp/assembler/aiebu_assembler.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright (C) 2024-2025, Advanced Micro Devices, Inc. All rights reserved.
// Copyright (C) 2024-2026, Advanced Micro Devices, Inc. All rights reserved.
#include "assembler.h"
#include "elfwriter.h"
#include "encoder.h"
Expand Down Expand Up @@ -69,8 +69,11 @@ aiebu_assembler(buffer_type type,
elf_data = a.process(buffer1, libs, libpaths, patch_json, buffer2, {}, &artifacts);
m_output_type = aiebu::aiebu_assembler::buffer_type::elf_aie2_config;
}
else if (m_type == buffer_type::asm_aie4)
else if (m_type == buffer_type::asm_aie4 ||
m_type == buffer_type::asm_aie4a ||
m_type == buffer_type::asm_aie4z)
{
// All aie4 family uses same elf_type - specific OSABI determined from .target directive
aiebu::assembler a(assembler::elf_type::aie4_asm);
elf_data = a.process(buffer1, libs, libpaths, patch_json, {}, {}, &artifacts);
m_output_type = aiebu::aiebu_assembler::buffer_type::elf_aie4;
Expand All @@ -81,8 +84,11 @@ aiebu_assembler(buffer_type type,
elf_data = a.process(buffer1, libs, libpaths, patch_json, buffer2, {}, &artifacts);
m_output_type = aiebu::aiebu_assembler::buffer_type::elf_aie2ps_config;
}
else if (m_type == buffer_type::aie4_config)
else if (m_type == buffer_type::aie4_config ||
m_type == buffer_type::aie4a_config ||
m_type == buffer_type::aie4z_config)
{
// All aie4 family config uses same elf_type - specific OSABI determined from .target directive
aiebu::assembler a(assembler::elf_type::aie4_config);
elf_data = a.process(buffer1, libs, libpaths, patch_json, buffer2, {}, &artifacts);
m_output_type = aiebu::aiebu_assembler::buffer_type::elf_aie4_config;
Expand Down
Loading