From 077b0c24613723215173ca57b7501e4b4b571b31 Mon Sep 17 00:00:00 2001 From: Chintalagiri Shashank Date: Wed, 21 Mar 2018 21:15:52 +0530 Subject: [PATCH] Collapsed vector regions and sections in the output. --- README.rst | 33 ++++++++++++------- fpvgcc/fpv.py | 3 ++ fpvgcc/gccMemoryMap.py | 74 +++++++++++++++++++++++++++++++++++++++++- fpvgcc/wui/__init__.py | 30 +++++++++++++++++ requirements.txt | 1 - setup.py | 2 +- 6 files changed, 128 insertions(+), 15 deletions(-) diff --git a/README.rst b/README.rst index 91913ad..c01853b 100644 --- a/README.rst +++ b/README.rst @@ -32,18 +32,27 @@ assembly listings. dynamic memory allocation is anyway avoided when possible. -.. note:: - This script was first written based on the format of mapfiles - generated by ``msp430-elf-gcc, v4.9.1``. Over time, it was modifed to - accept elements found in mapfiles generated by later versions and gcc-based - toolchains for other platforms. - - Still, remember that the file parsing was implemented by observing the - content of real mapfiles, and not based on a file format specification. - Even with toolchains it was written to support, there are large sections - of the file that are not actually used. Due to this, the outputs generated - are not always accurate. Various boundary conditions result in minor errors - in size reporting. +Known Issues +------------ + +This script was first written based on the format of mapfiles +generated by ``msp430-elf-gcc, v4.9.1``. Over time, it was modifed to +accept elements found in mapfiles generated by later versions and gcc-based +toolchains for other platforms. + +Still, remember that the file parsing was implemented by observing the +content of real mapfiles, and not based on a file format specification. +Even with toolchains it was written to support, there are large sections +of the file that are not actually used. Due to this, the outputs generated +are not always accurate. Various boundary conditions result in minor errors +in size reporting. + +The following more serious issues are known. They should be fixed at some +point, but for the moment I've chosen to work around them : + + - Having two C filenames with the same name (or generating the same + obj name) in your tree will cause parsing to break on some + platforms / toolchains. Links diff --git a/fpvgcc/fpv.py b/fpvgcc/fpv.py index 6a90605..21dc128 100644 --- a/fpvgcc/fpv.py +++ b/fpvgcc/fpv.py @@ -289,6 +289,9 @@ def linkermap_get_newnode(name, sm, allow_disambig=True, except TypeError: print("Error getting new node : {0}".format(name)) raise + except RuntimeError: + print("Runtime Error getting new node : {0}".format(name)) + exit(0) newnode = linkermap_get_newnode( '{0}.{1}'.format(name, objfile.replace('.', '_')), sm, allow_disambig=False, objfile=objfile, at_fill=True) diff --git a/fpvgcc/gccMemoryMap.py b/fpvgcc/gccMemoryMap.py index bd71dc8..b919745 100644 --- a/fpvgcc/gccMemoryMap.py +++ b/fpvgcc/gccMemoryMap.py @@ -224,19 +224,33 @@ def __repr__(self): class GCCMemoryMap(SizeNTree): + # This really needs to be cleaned up. Most of the code here is pretty much an + # example of what NOT to do. node_t = GCCMemoryMapNode + collapse_vectors = True def __init__(self): self.memory_regions = [] + self._vector_regions = [] + self._vector_sections = [] self.aliases = LinkAliases() super(GCCMemoryMap, self).__init__() @property def used_regions(self): ur = ['UNDEF'] + if self.collapse_vectors: + self._vector_regions = [] + ur.append('VEC') for node in self.root.all_nodes(): if node.region not in ur: - ur.append(node.region) + if self.collapse_vectors: + if 'VEC' not in node.region: + ur.append(node.region) + elif node.region not in self._vector_regions: + self._vector_regions.append(node.region) + else: + ur.append(node.region) ur.remove('UNDEF') ur.remove('DISCARDED') return ur @@ -314,6 +328,9 @@ def used_sections(self): sum([n.children for n in self.top_level_nodes if n.region == 'UNDEF'], []) if node.region != 'DISCARDED' and node.size > 0] + if self.collapse_vectors: + self._vector_sections = [x for x in sections if 'vec' in x] + sections = ['.*vec*'] + [x for x in sections if 'vec' not in x] return sections @property @@ -338,6 +355,8 @@ def get_symbol_fp(self, symbol): return r def get_symbol_fp_rgn(self, symbol, region): + if self.collapse_vectors and region == "VEC": + return self.get_symbol_fp_rgnvec(symbol) rv = 0 for node in self.root.all_nodes(): if node.name == symbol: @@ -346,6 +365,15 @@ def get_symbol_fp_rgn(self, symbol, region): rv += node.leafsize return rv + def get_symbol_fp_rgnvec(self, symbol): + rv = 0 + for node in self.root.all_nodes(): + if node.name == symbol: + if 'VEC' in node.region: + if node.leafsize is not None: + rv += node.leafsize + return rv + def get_objfile_fp(self, objfile): r = [] for rgn in self.used_regions: @@ -353,6 +381,8 @@ def get_objfile_fp(self, objfile): return r def get_objfile_fp_rgn(self, objfile, region): + if self.collapse_vectors and region == "VEC": + return self.get_objfile_fp_rgnvec(objfile) rv = 0 for node in self.root.all_nodes(): if node.objfile == objfile: @@ -361,6 +391,15 @@ def get_objfile_fp_rgn(self, objfile, region): rv += node.leafsize return rv + def get_objfile_fp_rgnvec(self, objfile): + rv = 0 + for node in self.root.all_nodes(): + if node.objfile == objfile: + if 'VEC' in node.region: + if node.leafsize is not None: + rv += node.leafsize + return rv + def get_objfile_fp_secs(self, objfile): r = [] for section in self.used_sections: @@ -374,6 +413,8 @@ def get_arfile_fp_secs(self, arfile): return r def get_objfile_fp_sec(self, objfile, section): + if section == '.*vec*': + return self.get_objfile_fp_secvec(objfile) rv = 0 for node in self.get_node(section).all_nodes(): if node.objfile == objfile: @@ -381,7 +422,18 @@ def get_objfile_fp_sec(self, objfile, section): rv += node.leafsize return rv + def get_objfile_fp_secvec(self, objfile): + rv = 0 + for section in self._vector_sections: + for node in self.get_node(section).all_nodes(): + if node.objfile == objfile: + if node.leafsize is not None: + rv += node.leafsize + return rv + def get_arfile_fp_sec(self, arfile, section): + if section == '.*vec*': + return self.get_objfile_fp_secvec(arfile) rv = 0 for node in self.get_node(section).all_nodes(): if node.arfile == arfile: @@ -389,6 +441,15 @@ def get_arfile_fp_sec(self, arfile, section): rv += node.leafsize return rv + def get_arfile_fp_secvec(self, arfile): + rv = 0 + for section in self._vector_sections: + for node in self.get_node(section).all_nodes(): + if node.arfile == arfile: + if node.leafsize is not None: + rv += node.leafsize + return rv + def get_arfile_fp(self, arfile): r = [] for rgn in self.used_regions: @@ -396,6 +457,8 @@ def get_arfile_fp(self, arfile): return r def get_arfile_fp_rgn(self, arfile, region): + if self.collapse_vectors and region == "VEC": + return self.get_arfile_fp_rgnvec(arfile) rv = 0 for node in self.root.all_nodes(): if node.arfile == arfile: @@ -404,6 +467,15 @@ def get_arfile_fp_rgn(self, arfile, region): rv += node.leafsize return rv + def get_arfile_fp_rgnvec(self, arfile): + rv = 0 + for node in self.root.all_nodes(): + if node.arfile == arfile: + if 'VEC' in node.region: + if node.leafsize is not None: + rv += node.leafsize + return rv + class MemoryRegion(object): def __init__(self, name, origin, size, attribs): diff --git a/fpvgcc/wui/__init__.py b/fpvgcc/wui/__init__.py index d2adf38..bff1852 100644 --- a/fpvgcc/wui/__init__.py +++ b/fpvgcc/wui/__init__.py @@ -21,3 +21,33 @@ """ Docstring for __init__.py """ + +from bokeh.plotting import figure, output_file, show +from bokeh.models import Range1d + +# prepare some data +x = [0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0] +y0 = [i**2 for i in x] +y1 = [10**i for i in x] +y2 = [10**(i**2) for i in x] + +# output to static HTML file +output_file("log_lines.html") + +# create a new plot +p = figure( + tools="pan,box_zoom,reset,save", y_axis_type="log", + y_range=Range1d(0.001, 10**11, bounds='auto'), title="log axis example", + x_axis_label='sections', y_axis_label='particles' +) + +# add some renderers +p.line(x, x, legend="y=x") +p.circle(x, x, legend="y=x", fill_color="white", size=8) +p.line(x, y0, legend="y=x^2", line_width=3) +p.line(x, y1, legend="y=10^x", line_color="red") +p.circle(x, y1, legend="y=10^x", fill_color="red", line_color="red", size=6) +p.line(x, y2, legend="y=10^x^2", line_color="orange", line_dash="4 4") + +# show the results +show(p) diff --git a/requirements.txt b/requirements.txt index 03339bb..280774f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -bokeh six prettytable sphinx diff --git a/setup.py b/setup.py index ac29dba..12716b0 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ def read(fname): setup( name="fpvgcc", - version="0.8.0", + version="0.8.1", author="Chintalagiri Shashank", author_email="shashank@chintal.in", description="Analysing code footprint on embedded microcontrollers "