mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
Table output for segment size script (#8551)
* Table output for segment size script Also include maximum aka total for every segment key Re-format the file and clean-up the resulting data dict * revert to line output * used, percentage * unicodes * shorter desc, headers
This commit is contained in:
parent
8d5dda02f6
commit
da4a19fdac
196
tools/sizes.py
196
tools/sizes.py
@ -17,74 +17,156 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
|
||||||
|
|
||||||
def get_segment_hints(iram):
|
|
||||||
hints = {}
|
|
||||||
hints['ICACHE'] = ' - flash instruction cache'
|
|
||||||
hints['IROM'] = ' - code in flash (default or ICACHE_FLASH_ATTR)'
|
|
||||||
hints['IRAM'] = ' / ' + str(iram) + ' - code in IRAM (IRAM_ATTR, ISRs...)'
|
|
||||||
hints['DATA'] = ') - initialized variables (global, static) in RAM/HEAP'
|
|
||||||
hints['RODATA'] = ') / 81920 - constants (global, static) in RAM/HEAP'
|
|
||||||
hints['BSS'] = ') - zeroed variables (global, static) in RAM/HEAP'
|
|
||||||
return hints
|
|
||||||
|
|
||||||
def get_segment_sizes(elf, path):
|
def get_segment_sizes(elf, path, mmu):
|
||||||
sizes = {}
|
iram_size = 0
|
||||||
sizes['ICACHE'] = 0
|
iheap_size = 0
|
||||||
sizes['IROM'] = 0
|
icache_size = 32168
|
||||||
sizes['IRAM'] = 0
|
|
||||||
sizes['DATA'] = 0
|
for line in mmu.split():
|
||||||
sizes['RODATA'] = 0
|
words = line.split("=")
|
||||||
sizes['BSS'] = 0
|
if line.startswith("-DMMU_IRAM_SIZE"):
|
||||||
p = subprocess.Popen([path + "/xtensa-lx106-elf-size", '-A', elf], stdout=subprocess.PIPE, universal_newlines=True )
|
iram_size = int(words[1], 16)
|
||||||
lines = p.stdout.readlines()
|
elif line.startswith("-DMMU_ICACHE_SIZE"):
|
||||||
for line in lines:
|
icache_size = int(words[1], 16)
|
||||||
words = line.split()
|
elif line.startswith("-DMMU_SEC_HEAP_SIZE"):
|
||||||
if line.startswith('.irom0.text'):
|
iheap_size = int(words[1], 16)
|
||||||
sizes['IROM'] = sizes['IROM'] + int(words[1])
|
|
||||||
elif line.startswith('.text'): # Gets .text and .text1
|
sizes = [
|
||||||
sizes['IRAM'] = sizes['IRAM'] + int(words[1])
|
[
|
||||||
elif line.startswith('.data'): # Gets .text and .text1
|
"Variables and constants in RAM (global, static)",
|
||||||
sizes['DATA'] = sizes['DATA'] + int(words[1])
|
[
|
||||||
elif line.startswith('.rodata'): # Gets .text and .text1
|
{
|
||||||
sizes['RODATA'] = sizes['RODATA'] + int(words[1])
|
"DATA": 0,
|
||||||
elif line.startswith('.bss'): # Gets .text and .text1
|
"RODATA": 0,
|
||||||
sizes['BSS'] = sizes['BSS'] + int(words[1])
|
"BSS": 0,
|
||||||
|
},
|
||||||
|
80192,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Instruction RAM (IRAM_ATTR, ICACHE_RAM_ATTR)",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"ICACHE": icache_size,
|
||||||
|
"IHEAP": iheap_size,
|
||||||
|
"IRAM": 0,
|
||||||
|
},
|
||||||
|
65536,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
["Code in flash (default, ICACHE_FLASH_ATTR)", [{"IROM": 0}, 1048576]],
|
||||||
|
]
|
||||||
|
|
||||||
|
section_mapping = (
|
||||||
|
(".irom0.text", "IROM"),
|
||||||
|
(".text", "IRAM"),
|
||||||
|
(".data", "DATA"),
|
||||||
|
(".rodata", "RODATA"),
|
||||||
|
(".bss", "BSS"),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = [os.path.join(path, "xtensa-lx106-elf-size"), "-A", elf]
|
||||||
|
with subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) as proc:
|
||||||
|
lines = proc.stdout.readlines()
|
||||||
|
for line in lines:
|
||||||
|
words = line.split()
|
||||||
|
for section, target in section_mapping:
|
||||||
|
if not line.startswith(section):
|
||||||
|
continue
|
||||||
|
for group, (segments, total) in sizes:
|
||||||
|
if target in segments:
|
||||||
|
segments[target] += int(words[1])
|
||||||
|
assert segments[target] <= total
|
||||||
|
|
||||||
return sizes
|
return sizes
|
||||||
|
|
||||||
def get_mmu_sizes(mmu, sizes):
|
|
||||||
iram = 0x8000
|
def percentage(lhs, rhs):
|
||||||
sizes['ICACHE'] = 0x8000
|
return "{}%".format(int(100.0 * float(lhs) / float(rhs)))
|
||||||
lines = mmu.split(' ')
|
|
||||||
for line in lines:
|
|
||||||
words = line.split('=')
|
HINTS = {
|
||||||
if line.startswith('-DMMU_IRAM_SIZE'):
|
"ICACHE": "reserved space for flash instruction cache",
|
||||||
iram = int(words[1], 16)
|
"IRAM": "code in IRAM",
|
||||||
elif line.startswith('-DMMU_ICACHE_SIZE'):
|
"IHEAP": "secondary heap space",
|
||||||
sizes['ICACHE'] = int(words[1], 16)
|
"IROM": "code in flash",
|
||||||
return [iram, sizes]
|
"DATA": "initialized variables",
|
||||||
|
"RODATA": "constants",
|
||||||
|
"BSS": "zeroed variables",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def safe_prefix(n, length):
|
||||||
|
if n == length:
|
||||||
|
return "`--"
|
||||||
|
|
||||||
|
return "|--"
|
||||||
|
|
||||||
|
|
||||||
|
def prefix(n, length):
|
||||||
|
if n == length:
|
||||||
|
return "└──"
|
||||||
|
|
||||||
|
return "├──"
|
||||||
|
|
||||||
|
|
||||||
|
def filter_segments(segments):
|
||||||
|
used = 0
|
||||||
|
number = 0
|
||||||
|
available = []
|
||||||
|
|
||||||
|
for (segment, size) in segments.items():
|
||||||
|
if not size:
|
||||||
|
continue
|
||||||
|
used += size
|
||||||
|
number += 1
|
||||||
|
available.append((number, segment, size))
|
||||||
|
|
||||||
|
return (number, used, available)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description='Report the different segment sizes of a compiled ELF file')
|
parser = argparse.ArgumentParser(
|
||||||
parser.add_argument('-e', '--elf', action='store', required=True, help='Path to the Arduino sketch ELF')
|
description="Report the different segment sizes of a compiled ELF file"
|
||||||
parser.add_argument('-p', '--path', action='store', required=True, help='Path to Xtensa toolchain binaries')
|
)
|
||||||
parser.add_argument('-i', '--mmu', action='store', required=False, help='MMU build options')
|
parser.add_argument(
|
||||||
|
"-e",
|
||||||
|
"--elf",
|
||||||
|
action="store",
|
||||||
|
required=True,
|
||||||
|
help="Path to the Arduino sketch ELF",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-p",
|
||||||
|
"--path",
|
||||||
|
action="store",
|
||||||
|
required=True,
|
||||||
|
help="Path to Xtensa toolchain binaries",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-i", "--mmu", action="store", required=False, help="MMU build options"
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
sizes = get_segment_sizes(args.elf, args.path)
|
sizes = get_segment_sizes(args.elf, args.path, args.mmu)
|
||||||
[iram, sizes] = get_mmu_sizes(args.mmu, sizes)
|
|
||||||
hints = get_segment_hints(iram)
|
|
||||||
|
|
||||||
sys.stderr.write("Executable segment sizes:" + os.linesep)
|
for group, (segments, total) in sizes:
|
||||||
for k in sizes.keys():
|
number, used, segments = filter_segments(segments)
|
||||||
sys.stderr.write("%-7s: %-5d %s %s" % (k, sizes[k], hints[k], os.linesep))
|
|
||||||
|
|
||||||
return 0
|
print(f". {group:<8}, used {used} / {total} bytes ({percentage(used, total)})")
|
||||||
|
print("| SEGMENT BYTES DESCRIPTION")
|
||||||
|
for n, segment, size in segments:
|
||||||
|
try:
|
||||||
|
print(f"{prefix(n, number)} ", end="")
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
print(f"{safe_prefix(n, number)} ", end="")
|
||||||
|
print(f"{segment:<8} {size:<8} {HINTS[segment]:<16}")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user