Skip to content

Supporting custom section from config.json#191

Open
HimanshuChoudhary-Xilinx wants to merge 6 commits intoXilinx:main-gefrom
HimanshuChoudhary-Xilinx:custom_section
Open

Supporting custom section from config.json#191
HimanshuChoudhary-Xilinx wants to merge 6 commits intoXilinx:main-gefrom
HimanshuChoudhary-Xilinx:custom_section

Conversation

@HimanshuChoudhary-Xilinx
Copy link
Collaborator

@HimanshuChoudhary-Xilinx HimanshuChoudhary-Xilinx commented Dec 9, 2025

Problem solved by the commit

Supporting custom section from config.json + testcase

sample json: test/aie2ps-ctrlcode/eff_net_coal/config.json in PR
Output: test/aie2ps-ctrlcode/eff_net_coal/eff_net_coal.gold in PR

Bug / issue (if any) fixed, which PR introduced the bug, how it was discovered

How problem was solved, alternative solutions (if any) and why they were rejected

Risks (if any) associated the changes in the commit

What has been tested and how, request additional testing if necessary

Documentation impact (if any)

All custom section have section type "SHT_LOUSER+1"
customer_section->section_name is the section name in elf

Config.json

{
    "xrt-kernels": [
      {
        "name" : "DPU",
       "arguments" : [
        {
          "name" : "arg0",
          "type" : "char *",
          "offset" : "0x00"
        },
        {
          "name" : "arg1",
          "type" : "char *",
          "offset" : "0x08"
        },
        {
          "name" : "arg2",
          "type" : "char *",
          "offset" : "0x10"
        },
        {
          "name" : "arg3",
          "type" : "char *",
          "offset" : "0x18"
        }
        ],
        "instance" : [
            {
              "id" : "vadd",
              "ctrl_code_file" : "./ml_asm/merged_control.asm"
            },
            {
              "id" : "va123",
              "ctrl_code_file" : "./ml_asm/merged_control.asm"
            }
        ]
      },
      {
       "name" : "RESNET",
       "arguments" : [
        {
          "name" : "arg0",
          "type" : "char *",
          "offset" : "0x00"
        },
        {
          "name" : "arg1",
          "type" : "char *",
          "offset" : "0x08"
        },
        {
          "name" : "arg2",
          "type" : "char *",
          "offset" : "0x10"
        },
        {
          "name" : "arg3",
          "type" : "char *",
          "offset" : "0x18"
        }
        ],
        "instance" : [
            {
              "id" : "rescc",
              "ctrl_code_file" : "./ml_asm/merged_control.asm"
            },
            {
              "id" : "res123",
              "ctrl_code_file" : "./ml_asm/merged_control.asm"

            }
        ]
      }
    ],
    "customer_section": [
      {
       "section_name": "ALL",
       "path": "./asm/pdi.asm"
      }
    ]
}

Global level

  1. Its not part of any group
  2. type will be SHT_LOUSER+1
Section Headers:
[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
 [ 1] .shstrtab            STRTAB       00000000 311d5a 002480  0        0   0  1
 [ 2] .strtab              STRTAB       00000000 3141da 00003a  0        0   0  0
 [ 3] .symtab              SYMTAB       00000000 314214 000070 16        2   1  4
 [ 4] ALL                  SHT_LOUSER+1 00000000 004580 00007a  0 WA     0   0 16

Copilot AI review requested due to automatic review settings December 9, 2025 16:13
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for custom sections from config.json at three hierarchical levels: global, kernel, and instance. Custom sections are defined in JSON configuration files and loaded from external files, allowing additional data to be embedded in the final ELF output.

Key Changes:

  • Added parsing logic for "customer_section" arrays from JSON at global, kernel, and instance levels
  • Implemented data structures to track custom sections throughout the preprocessing and encoding pipeline
  • Integrated custom section writers into the ELF generation process

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/cpp/preprocessor/preprocessor_input.h Added custom section storage and accessor methods to base preprocessor input class
src/cpp/preprocessor/aie2ps/aie2ps_preprocessor_input.h Implemented custom section parsing and storage at all three levels for AIE2PS
src/cpp/preprocessor/aie2ps/aie2ps_preprocessor.h Propagated custom sections from input to output during preprocessing
src/cpp/preprocessor/aie2ps/aie2ps_preprocessed_output.h Added custom section storage and accessors to preprocessed output classes
src/cpp/preprocessor/aie2/aie2_blob_preprocessor_input.h Added custom section data structures and parsing helper for AIE2
src/cpp/preprocessor/aie2/aie2_blob_preprocessor_input.cpp Implemented custom section parsing from JSON for AIE2 at all levels
src/cpp/preprocessor/aie2/aie2_blob_preprocessor.h Propagated custom sections from input to output in AIE2 preprocessor
src/cpp/preprocessor/aie2/aie2_blob_preprocessed_output.h Added custom section storage structures to AIE2 output classes
src/cpp/encoder/aie2ps/aie2ps_encoder.h Integrated custom sections into section writers during encoding
src/cpp/encoder/aie2/aie2_blob_encoder.h Added custom section writers to AIE2 encoder output
src/cpp/elf/aie2ps/aie2ps_elfwriter.h Included custom sections in ELF generation for AIE2PS
src/cpp/elf/aie2/aie2_blob_elfwriter.h Included custom sections in ELF generation for AIE2
src/cpp/common/writer.h Added custom section storage and accessor methods to writer classes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +116 to +118
const auto& pt_customer_sections = pt.get_child_optional("customer_section");
if (pt_customer_sections) {
for (const auto& [sec_unused, section] : pt_customer_sections.get()) {
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'pt_customer_sections' variable name to 'pt_custom_sections' for consistency.

Suggested change
const auto& pt_customer_sections = pt.get_child_optional("customer_section");
if (pt_customer_sections) {
for (const auto& [sec_unused, section] : pt_customer_sections.get()) {
const auto& pt_custom_sections = pt.get_child_optional("customer_section");
if (pt_custom_sections) {
for (const auto& [sec_unused, section] : pt_custom_sections.get()) {

Copilot uses AI. Check for mistakes.
Comment on lines +423 to +431
// Helper to parse customer_section array from JSON
std::map<std::string, std::vector<uint8_t>> parse_customer_sections(
const boost::property_tree::ptree& pt,
const std::vector<std::string>& paths)
{
std::map<std::string, std::vector<uint8_t>> custom_sections;
const auto& pt_customer_sections = pt.get_child_optional("customer_section");
if (pt_customer_sections) {
for (const auto& [sec_unused, section] : pt_customer_sections.get()) {
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'customer_sections' to 'custom_sections'.

Suggested change
// Helper to parse customer_section array from JSON
std::map<std::string, std::vector<uint8_t>> parse_customer_sections(
const boost::property_tree::ptree& pt,
const std::vector<std::string>& paths)
{
std::map<std::string, std::vector<uint8_t>> custom_sections;
const auto& pt_customer_sections = pt.get_child_optional("customer_section");
if (pt_customer_sections) {
for (const auto& [sec_unused, section] : pt_customer_sections.get()) {
// Helper to parse custom_section array from JSON
std::map<std::string, std::vector<uint8_t>> parse_custom_sections(
const boost::property_tree::ptree& pt,
const std::vector<std::string>& paths)
{
std::map<std::string, std::vector<uint8_t>> custom_sections;
const auto& pt_custom_sections = pt.get_child_optional("custom_section");
if (pt_custom_sections) {
for (const auto& [sec_unused, section] : pt_custom_sections.get()) {

Copilot uses AI. Check for mistakes.
Comment on lines +429 to +431
const auto& pt_customer_sections = pt.get_child_optional("customer_section");
if (pt_customer_sections) {
for (const auto& [sec_unused, section] : pt_customer_sections.get()) {
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'pt_customer_sections' variable name to 'pt_custom_sections' for consistency.

Suggested change
const auto& pt_customer_sections = pt.get_child_optional("customer_section");
if (pt_customer_sections) {
for (const auto& [sec_unused, section] : pt_customer_sections.get()) {
const auto& pt_custom_sections = pt.get_child_optional("customer_section");
if (pt_custom_sections) {
for (const auto& [sec_unused, section] : pt_custom_sections.get()) {

Copilot uses AI. Check for mistakes.
Comment on lines +992 to +994
const auto& pt_customer_sections = pic.get_child_optional("customer_section");
if (pt_customer_sections) {
for (const auto& [sec_unused, section] : pt_customer_sections.get()) {
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'pt_customer_sections' variable name to 'pt_custom_sections' for consistency.

Suggested change
const auto& pt_customer_sections = pic.get_child_optional("customer_section");
if (pt_customer_sections) {
for (const auto& [sec_unused, section] : pt_customer_sections.get()) {
const auto& pt_custom_sections = pic.get_child_optional("customer_section");
if (pt_custom_sections) {
for (const auto& [sec_unused, section] : pt_custom_sections.get()) {

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

protected: // NOLINT
std::map<std::string, std::map<std::string, std::shared_ptr<asm_preprocessor_input>>> m_preprocessor_input;
// Global level custom sections
std::map<std::string, std::vector<uint8_t>> m_global_custom_sections;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_global_custom_sections' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  std::map<std::string, std::vector<uint8_t>> m_global_custom_sections;
                                              ^

// Global level custom sections
std::map<std::string, std::vector<uint8_t>> m_global_custom_sections;
// Kernel level custom sections: kernel_name -> section_name -> data
std::map<std::string, std::map<std::string, std::vector<uint8_t>>> m_kernel_custom_sections;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_kernel_custom_sections' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  std::map<std::string, std::map<std::string, std::vector<uint8_t>>> m_kernel_custom_sections;
                                                                     ^

// Kernel level custom sections: kernel_name -> section_name -> data
std::map<std::string, std::map<std::string, std::vector<uint8_t>>> m_kernel_custom_sections;
// Instance level custom sections: kernel_name -> instance_name -> section_name -> data
std::map<std::string, std::map<std::string, std::map<std::string, std::vector<uint8_t>>>> m_instance_custom_sections;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_instance_custom_sections' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  std::map<std::string, std::map<std::string, std::map<std::string, std::vector<uint8_t>>>> m_instance_custom_sections;
                                                                                            ^

protected:
std::map<std::string, std::vector<char>> m_data;
std::map<std::string, std::vector<char>> m_controlpkt;
std::map<std::string, std::vector<uint8_t>> m_custom_data;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_custom_data' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  std::map<std::string, std::vector<uint8_t>> m_custom_data;
                                              ^

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

{
protected: // NOLINT
std::map<std::string, std::map<std::string, std::shared_ptr<asm_preprocessor_input>>> m_preprocessor_input;
// Global level custom sections
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_preprocessor_input' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  std::map<std::string, std::map<std::string, std::shared_ptr<asm_preprocessor_input>>> m_preprocessor_input;
                                                                                        ^

std::map<std::string, std::map<std::string, std::shared_ptr<asm_preprocessor_input>>> m_preprocessor_input;
// Global level custom sections
std::map<std::string, std::vector<uint8_t>> m_global_custom_sections;
// Kernel level custom sections: kernel_name -> section_name -> data
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_global_custom_sections' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  std::map<std::string, std::vector<uint8_t>> m_global_custom_sections;
                                              ^

std::map<std::string, std::vector<uint8_t>> m_global_custom_sections;
// Kernel level custom sections: kernel_name -> section_name -> data
std::map<std::string, std::map<std::string, std::vector<uint8_t>>> m_kernel_custom_sections;
// Instance level custom sections: kernel_name -> instance_name -> section_name -> data
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_kernel_custom_sections' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  std::map<std::string, std::map<std::string, std::vector<uint8_t>>> m_kernel_custom_sections;
                                                                     ^

std::map<std::string, std::map<std::string, std::vector<uint8_t>>> m_kernel_custom_sections;
// Instance level custom sections: kernel_name -> instance_name -> section_name -> data
std::map<std::string, std::map<std::string, std::map<std::string, std::vector<uint8_t>>>> m_instance_custom_sections;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_instance_custom_sections' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  std::map<std::string, std::map<std::string, std::map<std::string, std::vector<uint8_t>>>> m_instance_custom_sections;
                                                                                            ^

@sonals sonals self-requested a review December 17, 2025 00:46
Copy link
Member

@sonals sonals left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be so complicated. Can we not just add key/value pair API where the key is section name and value is the content? The client should deal with "Added parsing logic for "customer_section" arrays from JSON at global, kernel, and instance levels"

@larry9523
Copy link
Collaborator

This should not be so complicated. Can we not just add key/value pair API where the key is section name and value is the content? The client should deal with "Added parsing logic for "customer_section" arrays from JSON at global, kernel, and instance levels"

I am thinking the similar approach. We can just have the key(customer section name)/value(customer section blob) as a section in ELF. We can make use of the .group feature.

  1. if it does not point to any group symbol, it is the global section.
  2. if it points to a group symbol, it belongs to a kernel
  3. if it points to a instance symbol, it belongs to a instance
    The parsing logic should be in xrt::elf APIs

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

sec_data.set_type(ELFIO::SHT_PROGBITS);
if (buffer->get_type() == code_section::custom) {
sec_data.set_type(SHT_CUSTOM_SECTION);
sec_data.set_info(info_index);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: narrowing conversion from 'ELFIO::Elf_Word' (aka 'unsigned int') to signed type 'int' is implementation-defined [bugprone-narrowing-conversions]

      sec_data.set_info(info_index);
                        ^

constexpr int phdr_align = 8;
constexpr int program_header_static_count = 2;
constexpr int program_header_dynamic_count = 3;
constexpr int SHT_CUSTOM_SECTION = ELFIO::SHT_LOUSER + 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: narrowing conversion from constant value 2147483649 (0x80000001) of type 'Elf_Word' (aka 'unsigned int') to signed type 'int' is implementation-defined [bugprone-narrowing-conversions]

constexpr int SHT_CUSTOM_SECTION = ELFIO::SHT_LOUSER + 1;
                                   ^

@larry9523
Copy link
Collaborator

@HimanshuChoudhary-Xilinx this looks much cleaner. Thanks!
Can we update the document in a bit detail?

  1. from user point of view, what is the mapping between the name in config.json and section name in elf?
  2. A bit detail (ELF spec) between the sh_info and entries in symbol table.
  3. Should we combine sh_link as well to make it more informative, where it should point to symbol table section while sh_info points to kernel or instance?

Signed-off-by: Himanshu Choudhary <Himanshu.Choudhary@amd.com>
@HimanshuChoudhary-Xilinx
Copy link
Collaborator Author

@HimanshuChoudhary-Xilinx this looks much cleaner. Thanks! Can we update the document in a bit detail?

  1. from user point of view, what is the mapping between the name in config.json and section name in elf?
  2. A bit detail (ELF spec) between the sh_info and entries in symbol table.
  3. Should we combine sh_link as well to make it more informative, where it should point to symbol table section while sh_info points to kernel or instance?

Update

@larry9523
Copy link
Collaborator

@HimanshuChoudhary-Xilinx this looks much cleaner. Thanks! Can we update the document in a bit detail?

  1. from user point of view, what is the mapping between the name in config.json and section name in elf?
  2. A bit detail (ELF spec) between the sh_info and entries in symbol table.
  3. Should we combine sh_link as well to make it more informative, where it should point to symbol table section while sh_info points to kernel or instance?

Update

@HimanshuChoudhary-Xilinx this looks much cleaner. Thanks! Can we update the document in a bit detail?

  1. from user point of view, what is the mapping between the name in config.json and section name in elf?
  2. A bit detail (ELF spec) between the sh_info and entries in symbol table.
  3. Should we combine sh_link as well to make it more informative, where it should point to symbol table section while sh_info points to kernel or instance?

Update

Looks good.

One more question. Do we require customized sections in all level should have unique name? If so, we may want to put them into the ELF spec too.

@sonals
Copy link
Member

sonals commented Mar 12, 2026

I still feel this is more specialized than it should be. Can we not have a simple key/value pair design where the key is defined by the user? The user can define the naming schema, etc. So essentially this reduces to supporting only the Global level.

Signed-off-by: Himanshu Choudhary <Himanshu.Choudhary@amd.com>
Signed-off-by: Himanshu Choudhary <Himanshu.Choudhary@amd.com>
Signed-off-by: Himanshu Choudhary <Himanshu.Choudhary@amd.com>
Signed-off-by: Himanshu Choudhary <Himanshu.Choudhary@amd.com>
@larry9523 larry9523 requested a review from sonals March 23, 2026 21:05
Copy link
Member

@sonals sonals left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be a lot of code duplication where we re-implement a logic for all the supported platform types. Can we not move the repeated methods to base classes?

Signed-off-by: Himanshu Choudhary <Himanshu.Choudhary@amd.com>
@HimanshuChoudhary-Xilinx
Copy link
Collaborator Author

There seems to be a lot of code duplication where we re-implement a logic for all the supported platform types. Can we not move the repeated methods to base classes?

moved common code to common area

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

class config_writer_base : public writer
{
protected:
std::vector<std::shared_ptr<writer>> m_global_custom_sections;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_global_custom_sections' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  std::vector<std::shared_ptr<writer>> m_global_custom_sections;
                                       ^

const file_artifact* m_artifacts = nullptr;
protected: // NOLINT
std::map<std::string, std::map<std::string, std::shared_ptr<asm_preprocessor_input>>> m_preprocessor_input;
global_custom_section_storage m_global_custom_sections;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_global_custom_sections' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  global_custom_section_storage m_global_custom_sections;
                                ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants