Skip to content

Commit 471d99c

Browse files
committed
Added pretty bar printing for compile output
Looks like this: Building project mbed-os-prettyoutput (ARCH_PRO, GCC_ARM) Scan: . Scan: env Scan: mbed Scan: FEATURE_LWIP Text 70.5KB Data 2.72KB BSS 7.43KB ROM 73.2KB RAM 10.1KB ROM [||||||| ] 73.2KB/512KB RAM [|||||||||||||||| ] 10.1KB/32KB Image: BUILD/ARCH_PRO/GCC_ARM/mbed-os-prettyoutput.bin If you build a target without a cmsis-pack it looks like this: Building project mbed-os-prettyoutput (ARM_BEETLE_SOC, GCC_ARM) Scan: . Scan: env Scan: mbed Scan: FEATURE_BLE Text 99KB Data 2.84KB BSS 13KB ROM 102KB RAM 15.8KB Image: BUILD/ARM_BEETLE_SOC/GCC_ARM/mbed-os-prettyoutput.bin And the old behaviour of displaying the memap table can be brought back by passing the --stats-depth parameter
1 parent 4c07c1c commit 471d99c

File tree

3 files changed

+84
-10
lines changed

3 files changed

+84
-10
lines changed

tools/build_api.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from time import time
2828
from intelhex import IntelHex
2929
from json import load, dump
30+
from tools.arm_pack_manager import Cache
3031

3132
from tools.utils import mkdir, run_cmd, run_cmd_ext, NotSupportedException,\
3233
ToolException, InvalidReleaseTargetException, intelhex_offset
@@ -547,19 +548,24 @@ def build_project(src_paths, build_path, target, toolchain_name,
547548
memap_instance = getattr(toolchain, 'memap_instance', None)
548549
memap_table = ''
549550
if memap_instance:
550-
# Write output to stdout in text (pretty table) format
551-
memap_table = memap_instance.generate_output('table', stats_depth)
552-
551+
real_stats_depth = stats_depth if stats_depth is None else 2
552+
memap_table = memap_instance.generate_output('table', real_stats_depth)
553553
if not silent:
554-
print memap_table
554+
if not stats_depth:
555+
memap_bars = memap_instance.generate_output('bars',
556+
real_stats_depth, None,
557+
getattr(toolchain.target, 'device_name', None))
558+
print memap_bars
559+
else:
560+
print memap_table
555561

556562
# Write output to file in JSON format
557563
map_out = join(build_path, name + "_map.json")
558-
memap_instance.generate_output('json', stats_depth, map_out)
564+
memap_instance.generate_output('json', real_stats_depth, map_out)
559565

560566
# Write output to file in CSV format for the CI
561567
map_csv = join(build_path, name + "_map.csv")
562-
memap_instance.generate_output('csv-ci', stats_depth, map_csv)
568+
memap_instance.generate_output('csv-ci', real_stats_depth, map_csv)
563569

564570
resources.detect_duplicates(toolchain)
565571

tools/make.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
"--stats-depth",
117117
type=int,
118118
dest="stats_depth",
119-
default=2,
119+
default=None,
120120
help="Depth level for static memory report")
121121

122122
# Local run

tools/memap.py

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
import re
1010
import csv
1111
import json
12+
import math
1213
from argparse import ArgumentParser
1314
from copy import deepcopy
1415
from prettytable import PrettyTable
16+
from tools.arm_pack_manager import Cache
1517

1618
from utils import argparse_filestring_type, \
1719
argparse_lowercase_hyphen_type, argparse_uppercase_type
@@ -506,7 +508,7 @@ def reduce_depth(self, depth):
506508

507509
export_formats = ["json", "csv-ci", "table"]
508510

509-
def generate_output(self, export_format, depth, file_output=None):
511+
def generate_output(self, export_format, depth, file_output=None, *args):
510512
""" Generates summary of memory map data
511513
512514
Positional arguments:
@@ -531,8 +533,9 @@ def generate_output(self, export_format, depth, file_output=None):
531533

532534
to_call = {'json': self.generate_json,
533535
'csv-ci': self.generate_csv,
534-
'table': self.generate_table}[export_format]
535-
output = to_call(file_desc)
536+
'table': self.generate_table,
537+
'bars': self.generate_bars}[export_format]
538+
output = to_call(file_desc, *args)
536539

537540
if file_desc is not stdout:
538541
file_desc.close()
@@ -616,6 +619,71 @@ def generate_table(self, file_desc):
616619

617620
return output
618621

622+
def generate_bars(self, file_desc, device_name=None):
623+
""" Generates nice looking bars that represent the memory consumption
624+
625+
Returns: string containing nice looking bars
626+
"""
627+
628+
# TODO add tty detection, and width detection probably
629+
WIDTH = 72
630+
try:
631+
# NOTE this only works on linux
632+
import sys, fcntl, termios, struct
633+
height, width, _, _ = struct.unpack('HHHH',
634+
fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ,
635+
struct.pack('HHHH', 0, 0, 0, 0)))
636+
WIDTH = min(width, WIDTH)
637+
except Exception:
638+
pass
639+
640+
text = self.subtotal['.text']
641+
data = self.subtotal['.data']
642+
bss = self.subtotal['.bss']
643+
rom_used = self.mem_summary['total_flash']
644+
ram_used = self.mem_summary['static_ram']
645+
646+
# No device_name = no cmsis-pack = we don't know the memory layout
647+
if device_name is not None:
648+
try:
649+
cache = Cache(False, False)
650+
cmsis_part = cache.index[device_name]
651+
rom_avail = int(cmsis_part['memory']['IROM1']['size'], 0)
652+
ram_avail = int(cmsis_part['memory']['IRAM1']['size'], 0)
653+
except KeyError:
654+
# If we don't have the expected regions, fall back to no device_name
655+
device_name = None
656+
657+
PREFIXES = ['', 'K', 'M', 'G', 'T', 'P', 'E']
658+
def unit(n, u='B', p=3):
659+
if n == 0:
660+
return '0' + u
661+
662+
scale = math.floor(math.log(n, 1024))
663+
return '{1:.{0}g}{2}{3}'.format(p, n/(1024**scale), PREFIXES[int(scale)], u)
664+
665+
usage = "Text {} Data {} BSS {}".format(unit(text), unit(data), unit(bss))
666+
avail = "ROM {} RAM {}".format(unit(rom_used), unit(ram_used))
667+
output = ["{0} {1:>{2}}".format(usage, avail,
668+
abs(WIDTH-len(usage)-1) if device_name is not None else 0)]
669+
670+
if device_name is not None:
671+
for region, avail, uses in [
672+
('ROM', rom_avail, [('|', text), ('|', data)]),
673+
('RAM', ram_avail, [('|', bss), ('|', data)])]:
674+
barwidth = WIDTH-17 - len(region)
675+
676+
used = sum(use for c, use in uses)
677+
bars = [(c, (barwidth*use) // avail) for c, use in uses]
678+
bars.append((' ', barwidth - sum(width for c, width in bars)))
679+
bars = ''.join(c*width for c, width in bars)
680+
681+
output.append("{0} [{2:<{1}}] {3:>13}".format(
682+
region, barwidth, bars,
683+
"{}/{}".format(unit(used), unit(avail))))
684+
685+
return '\n'.join(output)
686+
619687
toolchains = ["ARM", "ARM_STD", "ARM_MICRO", "GCC_ARM", "GCC_CR", "IAR"]
620688

621689
def compute_report(self):

0 commit comments

Comments
 (0)