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
pull/5929/head
Christopher Haster 2018-01-23 17:26:48 -06:00
parent 4c07c1c830
commit 471d99c68f
3 changed files with 84 additions and 10 deletions

View File

@ -27,6 +27,7 @@ from os import linesep, remove, makedirs
from time import time
from intelhex import IntelHex
from json import load, dump
from tools.arm_pack_manager import Cache
from tools.utils import mkdir, run_cmd, run_cmd_ext, NotSupportedException,\
ToolException, InvalidReleaseTargetException, intelhex_offset
@ -547,19 +548,24 @@ def build_project(src_paths, build_path, target, toolchain_name,
memap_instance = getattr(toolchain, 'memap_instance', None)
memap_table = ''
if memap_instance:
# Write output to stdout in text (pretty table) format
memap_table = memap_instance.generate_output('table', stats_depth)
real_stats_depth = stats_depth if stats_depth is None else 2
memap_table = memap_instance.generate_output('table', real_stats_depth)
if not silent:
print memap_table
if not stats_depth:
memap_bars = memap_instance.generate_output('bars',
real_stats_depth, None,
getattr(toolchain.target, 'device_name', None))
print memap_bars
else:
print memap_table
# Write output to file in JSON format
map_out = join(build_path, name + "_map.json")
memap_instance.generate_output('json', stats_depth, map_out)
memap_instance.generate_output('json', real_stats_depth, map_out)
# Write output to file in CSV format for the CI
map_csv = join(build_path, name + "_map.csv")
memap_instance.generate_output('csv-ci', stats_depth, map_csv)
memap_instance.generate_output('csv-ci', real_stats_depth, map_csv)
resources.detect_duplicates(toolchain)

View File

@ -116,7 +116,7 @@ if __name__ == '__main__':
"--stats-depth",
type=int,
dest="stats_depth",
default=2,
default=None,
help="Depth level for static memory report")
# Local run

View File

@ -9,9 +9,11 @@ from os.path import basename, dirname, join, relpath, commonprefix
import re
import csv
import json
import math
from argparse import ArgumentParser
from copy import deepcopy
from prettytable import PrettyTable
from tools.arm_pack_manager import Cache
from utils import argparse_filestring_type, \
argparse_lowercase_hyphen_type, argparse_uppercase_type
@ -506,7 +508,7 @@ class MemapParser(object):
export_formats = ["json", "csv-ci", "table"]
def generate_output(self, export_format, depth, file_output=None):
def generate_output(self, export_format, depth, file_output=None, *args):
""" Generates summary of memory map data
Positional arguments:
@ -531,8 +533,9 @@ class MemapParser(object):
to_call = {'json': self.generate_json,
'csv-ci': self.generate_csv,
'table': self.generate_table}[export_format]
output = to_call(file_desc)
'table': self.generate_table,
'bars': self.generate_bars}[export_format]
output = to_call(file_desc, *args)
if file_desc is not stdout:
file_desc.close()
@ -616,6 +619,71 @@ class MemapParser(object):
return output
def generate_bars(self, file_desc, device_name=None):
""" Generates nice looking bars that represent the memory consumption
Returns: string containing nice looking bars
"""
# TODO add tty detection, and width detection probably
WIDTH = 72
try:
# NOTE this only works on linux
import sys, fcntl, termios, struct
height, width, _, _ = struct.unpack('HHHH',
fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ,
struct.pack('HHHH', 0, 0, 0, 0)))
WIDTH = min(width, WIDTH)
except Exception:
pass
text = self.subtotal['.text']
data = self.subtotal['.data']
bss = self.subtotal['.bss']
rom_used = self.mem_summary['total_flash']
ram_used = self.mem_summary['static_ram']
# No device_name = no cmsis-pack = we don't know the memory layout
if device_name is not None:
try:
cache = Cache(False, False)
cmsis_part = cache.index[device_name]
rom_avail = int(cmsis_part['memory']['IROM1']['size'], 0)
ram_avail = int(cmsis_part['memory']['IRAM1']['size'], 0)
except KeyError:
# If we don't have the expected regions, fall back to no device_name
device_name = None
PREFIXES = ['', 'K', 'M', 'G', 'T', 'P', 'E']
def unit(n, u='B', p=3):
if n == 0:
return '0' + u
scale = math.floor(math.log(n, 1024))
return '{1:.{0}g}{2}{3}'.format(p, n/(1024**scale), PREFIXES[int(scale)], u)
usage = "Text {} Data {} BSS {}".format(unit(text), unit(data), unit(bss))
avail = "ROM {} RAM {}".format(unit(rom_used), unit(ram_used))
output = ["{0} {1:>{2}}".format(usage, avail,
abs(WIDTH-len(usage)-1) if device_name is not None else 0)]
if device_name is not None:
for region, avail, uses in [
('ROM', rom_avail, [('|', text), ('|', data)]),
('RAM', ram_avail, [('|', bss), ('|', data)])]:
barwidth = WIDTH-17 - len(region)
used = sum(use for c, use in uses)
bars = [(c, (barwidth*use) // avail) for c, use in uses]
bars.append((' ', barwidth - sum(width for c, width in bars)))
bars = ''.join(c*width for c, width in bars)
output.append("{0} [{2:<{1}}] {3:>13}".format(
region, barwidth, bars,
"{}/{}".format(unit(used), unit(avail))))
return '\n'.join(output)
toolchains = ["ARM", "ARM_STD", "ARM_MICRO", "GCC_ARM", "GCC_CR", "IAR"]
def compute_report(self):