diff options
author | Sunny He <suhe@nvidia.com> | 2017-06-21 15:08:08 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-08-24 12:34:52 -0400 |
commit | cc64606a535edd9fd96487631f8ef583226fc575 (patch) | |
tree | e639f1496ab22b35fde90643abd2ddfc28a27bf5 /scripts | |
parent | 4b5b67d6d83430d8d670660b1dfc9cf024d60d88 (diff) |
gpu: nvgpu: debugfs code to dump HAL functions
Prints addresses of device-specific HAL functions to debugfs file
hal/gops.
The list of functions is produced by dumping the contents of the
gpu_ops substruct of the gk20a struct. This interface makes the
assumption that there are only function pointers in gpu_ops.
Companion Python script nvgpu_debug_hal.py analyzes gk20a.h to
determine operation counts and prettyify debugfs interface's
output.
Jira NVGPU-107
Change-Id: I0910e86638d144979e8630bbc5b330bccfd3ad94
Signed-off-by: Sunny He <suhe@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1542990
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/nvgpu_debug_hal.py | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/scripts/nvgpu_debug_hal.py b/scripts/nvgpu_debug_hal.py new file mode 100755 index 00000000..a56d66e3 --- /dev/null +++ b/scripts/nvgpu_debug_hal.py | |||
@@ -0,0 +1,123 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # | ||
3 | # Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify it | ||
6 | # under the terms and conditions of the GNU General Public License, | ||
7 | # version 2, as published by the Free Software Foundation. | ||
8 | # | ||
9 | # This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | # more details. | ||
13 | # | ||
14 | # usage: nvgpu_debug_hal.py [-h] [--csv] [--gk20a GK20A] [gops_filename] | ||
15 | # | ||
16 | # Analyze the HAL debugfs interface's output. With no arguments, prints out | ||
17 | # statistics on the gpu_ops struct based on analysis of gk20a.h | ||
18 | # | ||
19 | # positional arguments: | ||
20 | # gops_filename debugfs interface output file (from /d/gpu.0/hal/gops) | ||
21 | # | ||
22 | # optional arguments: | ||
23 | # -h, --help show this help message and exit | ||
24 | # --csv csv formatted output | ||
25 | # --gk20a GK20A path to gk20a.h | ||
26 | |||
27 | import argparse | ||
28 | import re | ||
29 | from os import environ | ||
30 | |||
31 | description_str = ('Analyze the HAL debugfs interface\'s output. ' | ||
32 | 'With no arguments, prints out statistics on the gpu_ops struct based on ' | ||
33 | 'analysis of gk20a.h') | ||
34 | |||
35 | parser = argparse.ArgumentParser(description=description_str); | ||
36 | parser.add_argument("--csv", help="csv formatted output", action="store_true"); | ||
37 | parser.add_argument("--gk20a", help="path to gk20a.h"); | ||
38 | parser.add_argument("gops_filename", help="debugfs interface output file (from /d/gpu.0/hal/gops)", nargs='?'); | ||
39 | args = parser.parse_args(); | ||
40 | |||
41 | if args.gk20a: | ||
42 | gk20a_h_path = args.gk20a | ||
43 | else: | ||
44 | top = environ.get('TOP'); | ||
45 | if top is None: | ||
46 | print("$TOP is undefined, unable to find gk20a.h"); | ||
47 | exit(-1); | ||
48 | gk20a_h_path = top + "/kernel/nvgpu/drivers/gpu/nvgpu/gk20a/gk20a.h" | ||
49 | |||
50 | def get_function_pointer_name(line): | ||
51 | matches = re.search('.*\(\*(?P<function_name>\w+)\)\(', line); | ||
52 | if matches is None: | ||
53 | return None | ||
54 | else: | ||
55 | return matches.group("function_name"); | ||
56 | |||
57 | # Build the list of gpu_ops member function pointers from gk20a.h | ||
58 | non_function_pointer_members = []; | ||
59 | formatted_members = []; | ||
60 | gops_members = dict(); | ||
61 | substruct_names = []; | ||
62 | lone_members = []; | ||
63 | with open(gk20a_h_path) as gk20a_h: | ||
64 | # Skip to start of gpu_ops struct | ||
65 | while gk20a_h.readline() != "struct gpu_ops {\n": | ||
66 | continue; | ||
67 | |||
68 | line = gk20a_h.readline(); | ||
69 | while line != "};\n": | ||
70 | # If this is a substruct | ||
71 | if re.match('\t+struct.+\{', line): | ||
72 | # Read the contents of the substruct | ||
73 | line = gk20a_h.readline(); | ||
74 | struct_contents = "" | ||
75 | while not re.match("\t*\} (\w+);", line): | ||
76 | struct_contents += line; | ||
77 | line = gk20a_h.readline(); | ||
78 | # Split out the substruct name and the function pointer names | ||
79 | struct_name = re.match("\t*\} (?P<struct_name>\w+);", line).group("struct_name"); | ||
80 | struct_members = re.findall(r".+?\(\s*\*\s*(\w+)\s*\).+?;", struct_contents, flags=re.DOTALL) | ||
81 | |||
82 | # Store the substruct as an entry | ||
83 | substruct_names.append(struct_name); | ||
84 | gops_members[struct_name] = struct_members; | ||
85 | # Format members | ||
86 | for member in struct_members: | ||
87 | formatted_members.append(struct_name + "." + member); | ||
88 | else: | ||
89 | # Lone members (function pointers or stuff not in a substruct) | ||
90 | match = re.match(".*\(\*(?P<function_name>\w+)\)\(", line); | ||
91 | if match is not None: | ||
92 | # It's a function pointer, keep track of it | ||
93 | lone_members.append(match.group("function_name")); | ||
94 | formatted_members.append(match.group("function_name")); | ||
95 | else: | ||
96 | # Not a function pointer, may also catch comments etc. | ||
97 | non_function_pointer_members.append(line.strip()); | ||
98 | line = gk20a_h.readline(); | ||
99 | if args.gops_filename: | ||
100 | # Interpret gops file | ||
101 | with open(args.gops_filename) as gops: | ||
102 | i = 0; | ||
103 | # Option for csv output | ||
104 | if args.csv: | ||
105 | format_string = '{0},{1}'; | ||
106 | else: | ||
107 | format_string = '{0:<60} = {1}'; | ||
108 | for line in gops: | ||
109 | print(format_string.format(formatted_members[i], line[:-1])); | ||
110 | i += 1; | ||
111 | else: | ||
112 | # Just print some stats on the gpu_ops struct | ||
113 | total = 0; | ||
114 | print("----- Lone Function Pointers -----"); | ||
115 | print("Count =", len(lone_members)); | ||
116 | total += len(lone_members); | ||
117 | for line in lone_members: | ||
118 | print(line); | ||
119 | print("----- Substruct Counts -----"); | ||
120 | for name in substruct_names: | ||
121 | print(name, "=", len(gops_members[name])); | ||
122 | total += len(gops_members[name]) | ||
123 | print("\n Total =", total); | ||