1#!/usr/bin/env fbpython 2# Copyright (c) Meta Platforms, Inc. and affiliates. 3# All rights reserved. 4# 5# This source code is licensed under the BSD-style license found in the 6# LICENSE file in the root directory of this source tree. 7 8import argparse 9import csv 10import io 11import os 12import shutil 13import subprocess 14import tempfile 15from pathlib import Path 16 17XTENSA_ROOT = os.environ["XTENSA_TOOLCHAIN"] 18XTENSA_VER = os.environ["TOOLCHAIN_VER"] 19XTENSA_TOOLS = os.path.join(XTENSA_ROOT, f"{XTENSA_VER}/XtensaTools") 20XTENSA_SYSTEM = os.path.join(XTENSA_TOOLS, "config") 21XTENSA_CORE = os.environ["XTENSA_CORE"] 22 23 24def parse_sections(dsp_dir, dsp_exe): 25 """ 26 >>> xt-size dsp_mu_polling_hifi4 --radix=16 -A 27 dsp_mu_polling_hifi4 : 28 section size addr 29 .UserExceptionVector.literal 0x4 0x24000000 30 .ResetVector.text 0x14c 0x24020000 31 .WindowVectors.text 0x16c 0x24020400 32 .Level2InterruptVector.text 0x8 0x2402057c 33 .Level3InterruptVector.text 0x8 0x2402059c 34 .DebugExceptionVector.text 0xc 0x240205bc 35 .NMIExceptionVector.text 0x4 0x240205dc 36 .KernelExceptionVector.text 0x8 0x240205fc 37 .UserExceptionVector.text 0xc 0x2402061c 38 .DoubleExceptionVector.text 0x8 0x2402063c 39 .rodata 0x398 0x200000 40 .text 0x4c6c 0x2003a0 41 .clib.data 0x4 0x20500c 42 .rtos.percpu.data 0x310 0x205010 43 .data 0x880 0x205320 44 .bss 0x6b8 0x205ba0 45 .debug_aranges 0x2c8 0x0 46 .debug_info 0x4367 0x0 47 .debug_abbrev 0xf54 0x0 48 .debug_line 0x36e9 0x0 49 .debug_frame 0x1f4 0x0 50 .debug_str 0x1986 0x0 51 .debug_loc 0x15ba 0x0 52 .xt.prop 0x4a10 0x0 53 .xt.lit 0x110 0x0 54 .xtensa.info 0x218 0x0 55 .comment 0x5f 0x0 56 .debug_ranges 0x100 0x0 57 Total 0x1717f 58 """ 59 cmd = f"{XTENSA_TOOLS}/bin/xt-size {dsp_dir}/{dsp_exe} --radix=16 -A" 60 print(f"Executing command:\n {cmd}\n") 61 p = subprocess.run(cmd.split(" "), capture_output=True) 62 print(p.stdout.decode()) 63 lines = p.stdout.decode().strip().split("\n") 64 print(lines) 65 lines = [line for line in lines if line != ""] 66 lines = lines[2:-1] 67 lines = "\n".join(lines) 68 69 f = io.StringIO(lines) 70 reader = csv.reader(f, delimiter=" ", skipinitialspace=True) 71 ret_list = [(section, int(addr, 16)) for section, size, addr in reader] 72 print(lines) 73 print(ret_list) 74 return ret_list 75 76 77def xt_objcopy_sections(dsp_dir, dsp_exe, output_obj_path, obj_name, sections): 78 xt_objcopy = f"{XTENSA_TOOLS}/bin/xt-objcopy" 79 xtensa_args = f"--xtensa-system={XTENSA_SYSTEM} --xtensa-core={XTENSA_CORE}" 80 81 cmd = f"{xt_objcopy} {xtensa_args} -O binary {dsp_dir}/{dsp_exe} {output_obj_path}/{obj_name} " 82 cmd += " ".join([f"--only-section={section}" for section in sections]) 83 84 print(cmd) 85 subprocess.run(cmd.split(" "), check=True) 86 87 88def main(): 89 parser = argparse.ArgumentParser() 90 parser.add_argument("dsp_exe_path", help="Xtensa DSP executable path") 91 parser.add_argument("output_dir", help="output directory") 92 args = parser.parse_args() 93 94 dsp_exe_dir = os.path.dirname(args.dsp_exe_path) 95 dsp_exe = os.path.basename(args.dsp_exe_path) 96 97 Path(args.output_dir).mkdir(parents=True, exist_ok=True) 98 99 sections = parse_sections(dsp_exe_dir, dsp_exe) 100 101 DATA_SECTION_START = 0x200000 102 NCACHE_SECTION_START = 0x20060000 103 TEXT_SECTION_START = 0x24000000 104 105 ncache_sections = [ 106 section 107 for section, addr in sections 108 if addr >= NCACHE_SECTION_START and addr < TEXT_SECTION_START 109 ] 110 111 data_sections = [ 112 section 113 for section, addr in sections 114 if addr < NCACHE_SECTION_START and addr >= DATA_SECTION_START 115 ] 116 117 text_sections = [ 118 section for section, addr in sections if addr >= TEXT_SECTION_START 119 ] 120 121 if len(ncache_sections): 122 dirpath = tempfile.mkdtemp() 123 xt_objcopy_sections( 124 dsp_exe_dir, 125 dsp_exe, 126 dirpath, 127 "dsp_ncache_release.bin", 128 ncache_sections, 129 ) 130 # copy files over 131 shutil.copyfile( 132 os.path.join(dirpath, "dsp_ncache_release.bin"), 133 os.path.join(args.output_dir, "dsp_ncache_release.bin"), 134 ) 135 shutil.rmtree(dirpath) 136 137 dirpath = tempfile.mkdtemp() 138 139 xt_objcopy_sections( 140 dsp_exe_dir, 141 dsp_exe, 142 dirpath, 143 "dsp_text_release.bin", 144 text_sections, 145 ) 146 147 # copy files over 148 shutil.copyfile( 149 os.path.join(dirpath, "dsp_text_release.bin"), 150 os.path.join(args.output_dir, "dsp_text_release.bin"), 151 ) 152 shutil.rmtree(dirpath) 153 154 dirpath = tempfile.mkdtemp() 155 156 xt_objcopy_sections( 157 dsp_exe_dir, 158 dsp_exe, 159 dirpath, 160 "dsp_data_release.bin", 161 data_sections, 162 ) 163 164 # copy files over 165 shutil.copyfile( 166 os.path.join(dirpath, "dsp_data_release.bin"), 167 os.path.join(args.output_dir, "dsp_data_release.bin"), 168 ) 169 shutil.rmtree(dirpath) 170 171 172if __name__ == "__main__": 173 main() 174