9
9
import re
10
10
import csv
11
11
import json
12
+ import math
12
13
from argparse import ArgumentParser
13
14
from copy import deepcopy
14
15
from prettytable import PrettyTable
16
+ from tools .arm_pack_manager import Cache
15
17
16
18
from utils import argparse_filestring_type , \
17
19
argparse_lowercase_hyphen_type , argparse_uppercase_type
@@ -506,7 +508,7 @@ def reduce_depth(self, depth):
506
508
507
509
export_formats = ["json" , "csv-ci" , "table" ]
508
510
509
- def generate_output (self , export_format , depth , file_output = None ):
511
+ def generate_output (self , export_format , depth , file_output = None , * args ):
510
512
""" Generates summary of memory map data
511
513
512
514
Positional arguments:
@@ -531,8 +533,9 @@ def generate_output(self, export_format, depth, file_output=None):
531
533
532
534
to_call = {'json' : self .generate_json ,
533
535
'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 )
536
539
537
540
if file_desc is not stdout :
538
541
file_desc .close ()
@@ -616,6 +619,71 @@ def generate_table(self, file_desc):
616
619
617
620
return output
618
621
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
+
619
687
toolchains = ["ARM" , "ARM_STD" , "ARM_MICRO" , "GCC_ARM" , "GCC_CR" , "IAR" ]
620
688
621
689
def compute_report (self ):
0 commit comments