1# 2# Copyright (c) 2020 Arm Limited. 3# 4# SPDX-License-Identifier: MIT 5# 6# Permission is hereby granted, free of charge, to any person obtaining a copy 7# of this software and associated documentation files (the "Software"), to 8# deal in the Software without restriction, including without limitation the 9# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10# sell copies of the Software, and to permit persons to whom the Software is 11# furnished to do so, subject to the following conditions: 12# 13# The above copyright notice and this permission notice shall be included in all 14# copies or substantial portions of the Software. 15# 16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22# SOFTWARE. 23# 24# 25#!/usr/bin/env python 26import re 27import os 28import sys 29import argparse 30import fnmatch 31import logging 32 33import json 34import glob 35 36logger = logging.getLogger("acl_tracing") 37 38# Returns the files matching the given pattern 39def find(path, pattern): 40 matches = [] 41 for root, dirnames, filenames, in os.walk(path): 42 for filename in fnmatch.filter(filenames, pattern): 43 matches.append(os.path.join(root,filename)) 44 return matches 45 46# Returns the class name (Core or Runtime) and arguments of the given function 47def get_class_and_args(function): 48 decl = " ".join(function_signature) 49 m = re.match("void ([^:]+)::configure\(([^)]*)\)", decl) 50 if m: 51 assert m, "Can't parse '%s'" % line 52 class_name = m.group(1) 53 args = m.group(2) 54 #Remove comments: 55 args = re.sub("\/\*.*?\*\/","",args) 56 #Remove templates 57 args = re.sub("<.*?>","",args) 58 logger.debug(args) 59 arg_names = [] 60 for arg in args.split(","): 61 m = re.match(".*?([^ &*]+)$", arg.strip()) 62 arg_names.append(m.group(1)) 63 logger.debug(" %s" % m.group(1)) 64 return (class_name, arg_names) 65 else: 66 return ('','') 67 68# Adds the tracepoints to the source file for the given function 69def do_insert_tracing(source, function, fd): 70 logger.debug("Full signature = %s" % " ".join(function_signature)) 71 class_name, arg_names = get_class_and_args(function) 72 if len(arg_names): 73 assert len(arg_names), "No argument to configure for %s ?" % class_name 74 spaces = re.match("([ ]*)void", function[0]).group(1) 75 fd.write("%s CREATE_TRACEPOINT(%s, \"%s\", this, TracePoint::Args()" % (spaces, source, class_name)) 76 for arg in arg_names: 77 fd.write("<<%s" % arg) 78 fd.write(");\n") 79 else: 80 print('Failed to get class name in %s ' % " ".join(function_signature)) 81 82 83if __name__ == "__main__": 84 parser = argparse.ArgumentParser( 85 formatter_class=argparse.RawDescriptionHelpFormatter, 86 description="Post process JSON benchmark files", 87 ) 88 89 parser.add_argument("-D", "--debug", action='store_true', help="Enable script debugging output") 90 args = parser.parse_args() 91 logging_level = logging.INFO 92 if args.debug: 93 logging_level = logging.DEBUG 94 logging.basicConfig(level=logging_level) 95 logger.debug("Arguments passed: %s" % str(args.__dict__)) 96 for f in find("src","*.cpp"): 97 logger.debug(f) 98 fd = open(f,'r+') 99 lines = fd.readlines() 100 contains_configure = False 101 for line in lines: 102 if re.search(r"void.*::configure\(",line): 103 contains_configure = True 104 break 105 if not contains_configure: 106 continue 107 fd.seek(0) 108 fd.truncate() 109 function_signature = None 110 insert_tracing = False 111 start = True 112 for line in lines: 113 write = True 114 if start: 115 if not (line.startswith("/*") or line.startswith(" *") or line.startswith("#") or len(line.strip()) == 0): 116 start = False 117 fd.write("#include \"arm_compute/core/TracePoint.h\"\n") 118 elif not function_signature: 119 if re.search(r"void.*::configure\(",line): 120 function_signature = [ line.rstrip() ] 121 else: 122 if re.search("[ ]*{$", line): 123 insert_tracing = True 124 else: 125 function_signature.append(line.rstrip()) 126 if write: 127 fd.write(line) 128 if insert_tracing: 129 if "/core/" in f: 130 source = "TracePoint::Layer::CORE" 131 elif "/runtime/" in f: 132 source = "TracePoint::Layer::RUNTIME" 133 else: 134 assert "Can't find layer for file %s" %f 135 do_insert_tracing(source, function_signature, fd) 136 insert_tracing = False 137 function_signature = None 138