~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/pmu-events/jevents.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/perf/pmu-events/jevents.py (Version linux-6.12-rc7) and /tools/perf/pmu-events/jevents.py (Version linux-6.2.16)


  1 #!/usr/bin/env python3                              1 #!/usr/bin/env python3
  2 # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-      2 # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
  3 """Convert directories of JSON events to C cod      3 """Convert directories of JSON events to C code."""
  4 import argparse                                     4 import argparse
  5 import csv                                          5 import csv
  6 from functools import lru_cache                << 
  7 import json                                         6 import json
  8 import metric                                       7 import metric
  9 import os                                           8 import os
 10 import sys                                          9 import sys
 11 from typing import (Callable, Dict, Optional,      10 from typing import (Callable, Dict, Optional, Sequence, Set, Tuple)
 12 import collections                                 11 import collections
 13                                                    12 
 14 # Global command line arguments.                   13 # Global command line arguments.
 15 _args = None                                       14 _args = None
 16 # List of regular event tables.                << 
 17 _event_tables = []                             << 
 18 # List of event tables generated from "/sys" d     15 # List of event tables generated from "/sys" directories.
 19 _sys_event_tables = []                             16 _sys_event_tables = []
 20 # List of regular metric tables.               << 
 21 _metric_tables = []                            << 
 22 # List of metric tables generated from "/sys"  << 
 23 _sys_metric_tables = []                        << 
 24 # Mapping between sys event table names and sy << 
 25 _sys_event_table_to_metric_table_mapping = {}  << 
 26 # Map from an event name to an architecture st     17 # Map from an event name to an architecture standard
 27 # JsonEvent. Architecture standard events are      18 # JsonEvent. Architecture standard events are in json files in the top
 28 # f'{_args.starting_dir}/{_args.arch}' directo     19 # f'{_args.starting_dir}/{_args.arch}' directory.
 29 _arch_std_events = {}                              20 _arch_std_events = {}
                                                   >>  21 # Track whether an events table is currently being defined and needs closing.
                                                   >>  22 _close_table = False
 30 # Events to write out when the table is closed     23 # Events to write out when the table is closed
 31 _pending_events = []                               24 _pending_events = []
 32 # Name of events table to be written out       << 
 33 _pending_events_tblname = None                 << 
 34 # Metrics to write out when the table is close << 
 35 _pending_metrics = []                          << 
 36 # Name of metrics table to be written out      << 
 37 _pending_metrics_tblname = None                << 
 38 # Global BigCString shared by all structures.      25 # Global BigCString shared by all structures.
 39 _bcs = None                                        26 _bcs = None
 40 # Map from the name of a metric group to a des << 
 41 _metricgroups = {}                             << 
 42 # Order specific JsonEvent attributes will be      27 # Order specific JsonEvent attributes will be visited.
 43 _json_event_attributes = [                         28 _json_event_attributes = [
 44     # cmp_sevent related attributes.               29     # cmp_sevent related attributes.
 45     'name', 'topic', 'desc',                   !!  30     'name', 'pmu', 'topic', 'desc', 'metric_name', 'metric_group',
 46     # Seems useful, put it early.                  31     # Seems useful, put it early.
 47     'event',                                       32     'event',
 48     # Short things in alphabetical order.          33     # Short things in alphabetical order.
 49     'compat', 'deprecated', 'perpkg', 'unit',  !!  34     'aggr_mode', 'compat', 'deprecated', 'perpkg', 'unit',
 50     # Longer things (the last won't be iterate     35     # Longer things (the last won't be iterated over during decompress).
 51     'long_desc'                                !!  36     'metric_constraint', 'metric_expr', 'long_desc'
 52 ]                                                  37 ]
 53                                                    38 
 54 # Attributes that are in pmu_metric rather tha << 
 55 _json_metric_attributes = [                    << 
 56     'metric_name', 'metric_group', 'metric_exp << 
 57     'desc', 'long_desc', 'unit', 'compat', 'me << 
 58     'default_metricgroup_name', 'aggr_mode', ' << 
 59 ]                                              << 
 60 # Attributes that are bools or enum int values << 
 61 _json_enum_attributes = ['aggr_mode', 'depreca << 
 62                                                    39 
 63 def removesuffix(s: str, suffix: str) -> str:      40 def removesuffix(s: str, suffix: str) -> str:
 64   """Remove the suffix from a string               41   """Remove the suffix from a string
 65                                                    42 
 66   The removesuffix function is added to str in     43   The removesuffix function is added to str in Python 3.9. We aim for 3.6
 67   compatibility and so provide our own functio     44   compatibility and so provide our own function here.
 68   """                                              45   """
 69   return s[0:-len(suffix)] if s.endswith(suffi     46   return s[0:-len(suffix)] if s.endswith(suffix) else s
 70                                                    47 
 71                                                    48 
 72 def file_name_to_table_name(prefix: str, paren !!  49 def file_name_to_table_name(parents: Sequence[str], dirname: str) -> str:
 73                             dirname: str) -> s << 
 74   """Generate a C table name from directory na     50   """Generate a C table name from directory names."""
 75   tblname = prefix                             !!  51   tblname = 'pme'
 76   for p in parents:                                52   for p in parents:
 77     tblname += '_' + p                             53     tblname += '_' + p
 78   tblname += '_' + dirname                         54   tblname += '_' + dirname
 79   return tblname.replace('-', '_')                 55   return tblname.replace('-', '_')
 80                                                    56 
 81                                                << 
 82 def c_len(s: str) -> int:                          57 def c_len(s: str) -> int:
 83   """Return the length of s a C string             58   """Return the length of s a C string
 84                                                    59 
 85   This doesn't handle all escape characters pr     60   This doesn't handle all escape characters properly. It first assumes
 86   all \\ are for escaping, it then adjusts as  !!  61   all \ are for escaping, it then adjusts as it will have over counted
 87   \\. The code uses \000 rather than \0 as a t     62   \\. The code uses \000 rather than \0 as a terminator as an adjacent
 88   number would be folded into a string of \0 (     63   number would be folded into a string of \0 (ie. "\0" + "5" doesn't
 89   equal a terminator followed by the number 5      64   equal a terminator followed by the number 5 but the escape of
 90   \05). The code adjusts for \000 but not prop     65   \05). The code adjusts for \000 but not properly for all octal, hex
 91   or unicode values.                               66   or unicode values.
 92   """                                              67   """
 93   try:                                             68   try:
 94     utf = s.encode(encoding='utf-8',errors='st     69     utf = s.encode(encoding='utf-8',errors='strict')
 95   except:                                          70   except:
 96     print(f'broken string {s}')                    71     print(f'broken string {s}')
 97     raise                                          72     raise
 98   return len(utf) - utf.count(b'\\') + utf.cou     73   return len(utf) - utf.count(b'\\') + utf.count(b'\\\\') - (utf.count(b'\\000') * 2)
 99                                                    74 
100 class BigCString:                                  75 class BigCString:
101   """A class to hold many strings concatenated     76   """A class to hold many strings concatenated together.
102                                                    77 
103   Generating a large number of stand-alone C s     78   Generating a large number of stand-alone C strings creates a large
104   number of relocations in position independen     79   number of relocations in position independent code. The BigCString
105   is a helper for this case. It builds a singl     80   is a helper for this case. It builds a single string which within it
106   are all the other C strings (to avoid memory     81   are all the other C strings (to avoid memory issues the string
107   itself is held as a list of strings). The of     82   itself is held as a list of strings). The offsets within the big
108   string are recorded and when stored to disk      83   string are recorded and when stored to disk these don't need
109   relocation. To reduce the size of the string     84   relocation. To reduce the size of the string further, identical
110   strings are merged. If a longer string ends-     85   strings are merged. If a longer string ends-with the same value as a
111   shorter string, these entries are also merge     86   shorter string, these entries are also merged.
112   """                                              87   """
113   strings: Set[str]                                88   strings: Set[str]
114   big_string: Sequence[str]                        89   big_string: Sequence[str]
115   offsets: Dict[str, int]                          90   offsets: Dict[str, int]
116   insert_number: int                           << 
117   insert_point: Dict[str, int]                 << 
118   metrics: Set[str]                            << 
119                                                    91 
120   def __init__(self):                              92   def __init__(self):
121     self.strings = set()                           93     self.strings = set()
122     self.insert_number = 0;                    << 
123     self.insert_point = {}                     << 
124     self.metrics = set()                       << 
125                                                    94 
126   def add(self, s: str, metric: bool) -> None: !!  95   def add(self, s: str) -> None:
127     """Called to add to the big string."""         96     """Called to add to the big string."""
128     if s not in self.strings:                  !!  97     self.strings.add(s)
129       self.strings.add(s)                      << 
130       self.insert_point[s] = self.insert_numbe << 
131       self.insert_number += 1                  << 
132       if metric:                               << 
133         self.metrics.add(s)                    << 
134                                                    98 
135   def compute(self) -> None:                       99   def compute(self) -> None:
136     """Called once all strings are added to co    100     """Called once all strings are added to compute the string and offsets."""
137                                                   101 
138     folded_strings = {}                           102     folded_strings = {}
139     # Determine if two strings can be folded,     103     # Determine if two strings can be folded, ie. let 1 string use the
140     # end of another. First reverse all string    104     # end of another. First reverse all strings and sort them.
141     sorted_reversed_strings = sorted([x[::-1]     105     sorted_reversed_strings = sorted([x[::-1] for x in self.strings])
142                                                   106 
143     # Strings 'xyz' and 'yz' will now be [ 'zy    107     # Strings 'xyz' and 'yz' will now be [ 'zy', 'zyx' ]. Scan forward
144     # for each string to see if there is a bet    108     # for each string to see if there is a better candidate to fold it
145     # into, in the example rather than using '    109     # into, in the example rather than using 'yz' we can use'xyz' at
146     # an offset of 1. We record which string c    110     # an offset of 1. We record which string can be folded into which
147     # in folded_strings, we don't need to reco    111     # in folded_strings, we don't need to record the offset as it is
148     # trivially computed from the string lengt    112     # trivially computed from the string lengths.
149     for pos,s in enumerate(sorted_reversed_str    113     for pos,s in enumerate(sorted_reversed_strings):
150       best_pos = pos                              114       best_pos = pos
151       for check_pos in range(pos + 1, len(sort    115       for check_pos in range(pos + 1, len(sorted_reversed_strings)):
152         if sorted_reversed_strings[check_pos].    116         if sorted_reversed_strings[check_pos].startswith(s):
153           best_pos = check_pos                    117           best_pos = check_pos
154         else:                                     118         else:
155           break                                   119           break
156       if pos != best_pos:                         120       if pos != best_pos:
157         folded_strings[s[::-1]] = sorted_rever    121         folded_strings[s[::-1]] = sorted_reversed_strings[best_pos][::-1]
158                                                   122 
159     # Compute reverse mappings for debugging.     123     # Compute reverse mappings for debugging.
160     fold_into_strings = collections.defaultdic    124     fold_into_strings = collections.defaultdict(set)
161     for key, val in folded_strings.items():       125     for key, val in folded_strings.items():
162       if key != val:                              126       if key != val:
163         fold_into_strings[val].add(key)           127         fold_into_strings[val].add(key)
164                                                   128 
165     # big_string_offset is the current locatio    129     # big_string_offset is the current location within the C string
166     # being appended to - comments, etc. don't    130     # being appended to - comments, etc. don't count. big_string is
167     # the string contents represented as a lis    131     # the string contents represented as a list. Strings are immutable
168     # in Python and so appending to one causes    132     # in Python and so appending to one causes memory issues, while
169     # lists are mutable.                          133     # lists are mutable.
170     big_string_offset = 0                         134     big_string_offset = 0
171     self.big_string = []                          135     self.big_string = []
172     self.offsets = {}                             136     self.offsets = {}
173                                                   137 
174     def string_cmp_key(s: str) -> Tuple[bool,  << 
175       return (s in self.metrics, self.insert_p << 
176                                                << 
177     # Emit all strings that aren't folded in a    138     # Emit all strings that aren't folded in a sorted manner.
178     for s in sorted(self.strings, key=string_c !! 139     for s in sorted(self.strings):
179       if s not in folded_strings:                 140       if s not in folded_strings:
180         self.offsets[s] = big_string_offset       141         self.offsets[s] = big_string_offset
181         self.big_string.append(f'/* offset={bi    142         self.big_string.append(f'/* offset={big_string_offset} */ "')
182         self.big_string.append(s)                 143         self.big_string.append(s)
183         self.big_string.append('"')               144         self.big_string.append('"')
184         if s in fold_into_strings:                145         if s in fold_into_strings:
185           self.big_string.append(' /* also: '     146           self.big_string.append(' /* also: ' + ', '.join(fold_into_strings[s]) + ' */')
186         self.big_string.append('\n')              147         self.big_string.append('\n')
187         big_string_offset += c_len(s)             148         big_string_offset += c_len(s)
188         continue                                  149         continue
189                                                   150 
190     # Compute the offsets of the folded string    151     # Compute the offsets of the folded strings.
191     for s in folded_strings.keys():               152     for s in folded_strings.keys():
192       assert s not in self.offsets                153       assert s not in self.offsets
193       folded_s = folded_strings[s]                154       folded_s = folded_strings[s]
194       self.offsets[s] = self.offsets[folded_s]    155       self.offsets[s] = self.offsets[folded_s] + c_len(folded_s) - c_len(s)
195                                                   156 
196 _bcs = BigCString()                               157 _bcs = BigCString()
197                                                   158 
198 class JsonEvent:                                  159 class JsonEvent:
199   """Representation of an event loaded from a     160   """Representation of an event loaded from a json file dictionary."""
200                                                   161 
201   def __init__(self, jd: dict):                   162   def __init__(self, jd: dict):
202     """Constructor passed the dictionary of pa    163     """Constructor passed the dictionary of parsed json values."""
203                                                   164 
204     def llx(x: int) -> str:                       165     def llx(x: int) -> str:
205       """Convert an int to a string similar to    166       """Convert an int to a string similar to a printf modifier of %#llx."""
206       return str(x) if x >= 0 and x < 10 else  !! 167       return '0' if x == 0 else hex(x)
207                                                   168 
208     def fixdesc(s: str) -> str:                   169     def fixdesc(s: str) -> str:
209       """Fix formatting issue for the desc str    170       """Fix formatting issue for the desc string."""
210       if s is None:                               171       if s is None:
211         return None                               172         return None
212       return removesuffix(removesuffix(removes    173       return removesuffix(removesuffix(removesuffix(s, '.  '),
213                                        '. '),     174                                        '. '), '.').replace('\n', '\\n').replace(
214                                            '\"    175                                            '\"', '\\"').replace('\r', '\\r')
215                                                   176 
216     def convert_aggr_mode(aggr_mode: str) -> O    177     def convert_aggr_mode(aggr_mode: str) -> Optional[str]:
217       """Returns the aggr_mode_class enum valu    178       """Returns the aggr_mode_class enum value associated with the JSON string."""
218       if not aggr_mode:                           179       if not aggr_mode:
219         return None                               180         return None
220       aggr_mode_to_enum = {                       181       aggr_mode_to_enum = {
221           'PerChip': '1',                         182           'PerChip': '1',
222           'PerCore': '2',                         183           'PerCore': '2',
223       }                                           184       }
224       return aggr_mode_to_enum[aggr_mode]         185       return aggr_mode_to_enum[aggr_mode]
225                                                   186 
226     def convert_metric_constraint(metric_const << 
227       """Returns the metric_event_groups enum  << 
228       if not metric_constraint:                << 
229         return None                            << 
230       metric_constraint_to_enum = {            << 
231           'NO_GROUP_EVENTS': '1',              << 
232           'NO_GROUP_EVENTS_NMI': '2',          << 
233           'NO_NMI_WATCHDOG': '2',              << 
234           'NO_GROUP_EVENTS_SMT': '3',          << 
235       }                                        << 
236       return metric_constraint_to_enum[metric_ << 
237                                                << 
238     def lookup_msr(num: str) -> Optional[str]:    187     def lookup_msr(num: str) -> Optional[str]:
239       """Converts the msr number, or first in     188       """Converts the msr number, or first in a list to the appropriate event field."""
240       if not num:                                 189       if not num:
241         return None                               190         return None
242       msrmap = {                                  191       msrmap = {
243           0x3F6: 'ldlat=',                        192           0x3F6: 'ldlat=',
244           0x1A6: 'offcore_rsp=',                  193           0x1A6: 'offcore_rsp=',
245           0x1A7: 'offcore_rsp=',                  194           0x1A7: 'offcore_rsp=',
246           0x3F7: 'frontend=',                     195           0x3F7: 'frontend=',
247       }                                           196       }
248       return msrmap[int(num.split(',', 1)[0],     197       return msrmap[int(num.split(',', 1)[0], 0)]
249                                                   198 
250     def real_event(name: str, event: str) -> O    199     def real_event(name: str, event: str) -> Optional[str]:
251       """Convert well known event names to an     200       """Convert well known event names to an event string otherwise use the event argument."""
252       fixed = {                                   201       fixed = {
253           'inst_retired.any': 'event=0xc0,peri    202           'inst_retired.any': 'event=0xc0,period=2000003',
254           'inst_retired.any_p': 'event=0xc0,pe    203           'inst_retired.any_p': 'event=0xc0,period=2000003',
255           'cpu_clk_unhalted.ref': 'event=0x0,u    204           'cpu_clk_unhalted.ref': 'event=0x0,umask=0x03,period=2000003',
256           'cpu_clk_unhalted.thread': 'event=0x    205           'cpu_clk_unhalted.thread': 'event=0x3c,period=2000003',
257           'cpu_clk_unhalted.core': 'event=0x3c    206           'cpu_clk_unhalted.core': 'event=0x3c,period=2000003',
258           'cpu_clk_unhalted.thread_any': 'even    207           'cpu_clk_unhalted.thread_any': 'event=0x3c,any=1,period=2000003',
259       }                                           208       }
260       if not name:                                209       if not name:
261         return None                               210         return None
262       if name.lower() in fixed:                   211       if name.lower() in fixed:
263         return fixed[name.lower()]                212         return fixed[name.lower()]
264       return event                                213       return event
265                                                   214 
266     def unit_to_pmu(unit: str) -> Optional[str    215     def unit_to_pmu(unit: str) -> Optional[str]:
267       """Convert a JSON Unit to Linux PMU name    216       """Convert a JSON Unit to Linux PMU name."""
268       if not unit:                                217       if not unit:
269         return 'default_core'                  !! 218         return None
270       # Comment brought over from jevents.c:      219       # Comment brought over from jevents.c:
271       # it's not realistic to keep adding thes    220       # it's not realistic to keep adding these, we need something more scalable ...
272       table = {                                   221       table = {
273           'CBO': 'uncore_cbox',                   222           'CBO': 'uncore_cbox',
274           'QPI LL': 'uncore_qpi',                 223           'QPI LL': 'uncore_qpi',
275           'SBO': 'uncore_sbox',                   224           'SBO': 'uncore_sbox',
276           'iMPH-U': 'uncore_arb',                 225           'iMPH-U': 'uncore_arb',
277           'CPU-M-CF': 'cpum_cf',                  226           'CPU-M-CF': 'cpum_cf',
278           'CPU-M-SF': 'cpum_sf',                  227           'CPU-M-SF': 'cpum_sf',
279           'PAI-CRYPTO' : 'pai_crypto',            228           'PAI-CRYPTO' : 'pai_crypto',
280           'PAI-EXT' : 'pai_ext',               << 
281           'UPI LL': 'uncore_upi',                 229           'UPI LL': 'uncore_upi',
282           'hisi_sicl,cpa': 'hisi_sicl,cpa',       230           'hisi_sicl,cpa': 'hisi_sicl,cpa',
283           'hisi_sccl,ddrc': 'hisi_sccl,ddrc',     231           'hisi_sccl,ddrc': 'hisi_sccl,ddrc',
284           'hisi_sccl,hha': 'hisi_sccl,hha',       232           'hisi_sccl,hha': 'hisi_sccl,hha',
285           'hisi_sccl,l3c': 'hisi_sccl,l3c',       233           'hisi_sccl,l3c': 'hisi_sccl,l3c',
286           'imx8_ddr': 'imx8_ddr',                 234           'imx8_ddr': 'imx8_ddr',
287           'imx9_ddr': 'imx9_ddr',              << 
288           'L3PMC': 'amd_l3',                      235           'L3PMC': 'amd_l3',
289           'DFPMC': 'amd_df',                      236           'DFPMC': 'amd_df',
290           'UMCPMC': 'amd_umc',                 << 
291           'cpu_core': 'cpu_core',                 237           'cpu_core': 'cpu_core',
292           'cpu_atom': 'cpu_atom',                 238           'cpu_atom': 'cpu_atom',
293           'ali_drw': 'ali_drw',                << 
294           'arm_cmn': 'arm_cmn',                << 
295       }                                           239       }
296       return table[unit] if unit in table else    240       return table[unit] if unit in table else f'uncore_{unit.lower()}'
297                                                   241 
298     def is_zero(val: str) -> bool:             << 
299         try:                                   << 
300             if val.startswith('0x'):           << 
301                 return int(val, 16) == 0       << 
302             else:                              << 
303                 return int(val) == 0           << 
304         except e:                              << 
305             return False                       << 
306                                                << 
307     def canonicalize_value(val: str) -> str:   << 
308         try:                                   << 
309             if val.startswith('0x'):           << 
310                 return llx(int(val, 16))       << 
311             return str(int(val))               << 
312         except e:                              << 
313             return val                         << 
314                                                << 
315     eventcode = 0                                 242     eventcode = 0
316     if 'EventCode' in jd:                         243     if 'EventCode' in jd:
317       eventcode = int(jd['EventCode'].split(',    244       eventcode = int(jd['EventCode'].split(',', 1)[0], 0)
318     if 'ExtSel' in jd:                            245     if 'ExtSel' in jd:
319       eventcode |= int(jd['ExtSel']) << 8         246       eventcode |= int(jd['ExtSel']) << 8
320     configcode = int(jd['ConfigCode'], 0) if '    247     configcode = int(jd['ConfigCode'], 0) if 'ConfigCode' in jd else None
321     eventidcode = int(jd['EventidCode'], 0) if << 
322     self.name = jd['EventName'].lower() if 'Ev    248     self.name = jd['EventName'].lower() if 'EventName' in jd else None
323     self.topic = ''                               249     self.topic = ''
324     self.compat = jd.get('Compat')                250     self.compat = jd.get('Compat')
325     self.desc = fixdesc(jd.get('BriefDescripti    251     self.desc = fixdesc(jd.get('BriefDescription'))
326     self.long_desc = fixdesc(jd.get('PublicDes    252     self.long_desc = fixdesc(jd.get('PublicDescription'))
327     precise = jd.get('PEBS')                      253     precise = jd.get('PEBS')
328     msr = lookup_msr(jd.get('MSRIndex'))          254     msr = lookup_msr(jd.get('MSRIndex'))
329     msrval = jd.get('MSRValue')                   255     msrval = jd.get('MSRValue')
330     extra_desc = ''                               256     extra_desc = ''
331     if 'Data_LA' in jd:                           257     if 'Data_LA' in jd:
332       extra_desc += '  Supports address when p    258       extra_desc += '  Supports address when precise'
333       if 'Errata' in jd:                          259       if 'Errata' in jd:
334         extra_desc += '.'                         260         extra_desc += '.'
335     if 'Errata' in jd:                            261     if 'Errata' in jd:
336       extra_desc += '  Spec update: ' + jd['Er    262       extra_desc += '  Spec update: ' + jd['Errata']
337     self.pmu = unit_to_pmu(jd.get('Unit'))        263     self.pmu = unit_to_pmu(jd.get('Unit'))
338     filter = jd.get('Filter')                     264     filter = jd.get('Filter')
339     self.unit = jd.get('ScaleUnit')               265     self.unit = jd.get('ScaleUnit')
340     self.perpkg = jd.get('PerPkg')                266     self.perpkg = jd.get('PerPkg')
341     self.aggr_mode = convert_aggr_mode(jd.get(    267     self.aggr_mode = convert_aggr_mode(jd.get('AggregationMode'))
342     self.deprecated = jd.get('Deprecated')        268     self.deprecated = jd.get('Deprecated')
343     self.metric_name = jd.get('MetricName')       269     self.metric_name = jd.get('MetricName')
344     self.metric_group = jd.get('MetricGroup')     270     self.metric_group = jd.get('MetricGroup')
345     self.metricgroup_no_group = jd.get('Metric !! 271     self.metric_constraint = jd.get('MetricConstraint')
346     self.default_metricgroup_name = jd.get('De << 
347     self.event_grouping = convert_metric_const << 
348     self.metric_expr = None                       272     self.metric_expr = None
349     if 'MetricExpr' in jd:                        273     if 'MetricExpr' in jd:
350       self.metric_expr = metric.ParsePerfJson( !! 274        self.metric_expr = metric.ParsePerfJson(jd['MetricExpr']).Simplify()
351     # Note, the metric formula for the thresho << 
352     # and > have incorrect precedence.         << 
353     self.metric_threshold = jd.get('MetricThre << 
354                                                   275 
355     arch_std = jd.get('ArchStdEvent')             276     arch_std = jd.get('ArchStdEvent')
356     if precise and self.desc and '(Precise Eve    277     if precise and self.desc and '(Precise Event)' not in self.desc:
357       extra_desc += ' (Must be precise)' if pr    278       extra_desc += ' (Must be precise)' if precise == '2' else (' (Precise '
358                                                   279                                                                  'event)')
359     event = None                               !! 280     event = f'config={llx(configcode)}' if configcode is not None else f'event={llx(eventcode)}'
360     if configcode is not None:                 << 
361       event = f'config={llx(configcode)}'      << 
362     elif eventidcode is not None:              << 
363       event = f'eventid={llx(eventidcode)}'    << 
364     else:                                      << 
365       event = f'event={llx(eventcode)}'        << 
366     event_fields = [                              281     event_fields = [
367         ('AnyThread', 'any='),                    282         ('AnyThread', 'any='),
368         ('PortMask', 'ch_mask='),                 283         ('PortMask', 'ch_mask='),
369         ('CounterMask', 'cmask='),                284         ('CounterMask', 'cmask='),
370         ('EdgeDetect', 'edge='),                  285         ('EdgeDetect', 'edge='),
371         ('FCMask', 'fc_mask='),                   286         ('FCMask', 'fc_mask='),
372         ('Invert', 'inv='),                       287         ('Invert', 'inv='),
373         ('SampleAfterValue', 'period='),          288         ('SampleAfterValue', 'period='),
374         ('UMask', 'umask='),                      289         ('UMask', 'umask='),
375         ('NodeType', 'type='),                 << 
376         ('RdWrMask', 'rdwrmask='),             << 
377         ('EnAllCores', 'enallcores='),         << 
378         ('EnAllSlices', 'enallslices='),       << 
379         ('SliceId', 'sliceid='),               << 
380         ('ThreadMask', 'threadmask='),         << 
381     ]                                             290     ]
382     for key, value in event_fields:               291     for key, value in event_fields:
383       if key in jd and not is_zero(jd[key]):   !! 292       if key in jd and jd[key] != '0':
384         event += f',{value}{canonicalize_value !! 293         event += ',' + value + jd[key]
385     if filter:                                    294     if filter:
386       event += f',{filter}'                       295       event += f',{filter}'
387     if msr:                                       296     if msr:
388       event += f',{msr}{msrval}'                  297       event += f',{msr}{msrval}'
389     if self.desc and extra_desc:                  298     if self.desc and extra_desc:
390       self.desc += extra_desc                     299       self.desc += extra_desc
391     if self.long_desc and extra_desc:             300     if self.long_desc and extra_desc:
392       self.long_desc += extra_desc                301       self.long_desc += extra_desc
393     if arch_std:                               !! 302     if self.pmu:
394       if arch_std.lower() in _arch_std_events: !! 303       if self.desc and not self.desc.endswith('. '):
395         event = _arch_std_events[arch_std.lowe !! 304         self.desc += '. '
396         # Copy from the architecture standard  !! 305       self.desc = (self.desc if self.desc else '') + ('Unit: ' + self.pmu + ' ')
397         for attr, value in _arch_std_events[ar !! 306     if arch_std and arch_std.lower() in _arch_std_events:
398           if hasattr(self, attr) and not getat !! 307       event = _arch_std_events[arch_std.lower()].event
399             setattr(self, attr, value)         !! 308       # Copy from the architecture standard event to self for undefined fields.
400       else:                                    !! 309       for attr, value in _arch_std_events[arch_std.lower()].__dict__.items():
401         raise argparse.ArgumentTypeError('Cann !! 310         if hasattr(self, attr) and not getattr(self, attr):
                                                   >> 311           setattr(self, attr, value)
402                                                   312 
403     self.event = real_event(self.name, event)     313     self.event = real_event(self.name, event)
404                                                   314 
405   def __repr__(self) -> str:                      315   def __repr__(self) -> str:
406     """String representation primarily for deb    316     """String representation primarily for debugging."""
407     s = '{\n'                                     317     s = '{\n'
408     for attr, value in self.__dict__.items():     318     for attr, value in self.__dict__.items():
409       if value:                                   319       if value:
410         s += f'\t{attr} = {value},\n'             320         s += f'\t{attr} = {value},\n'
411     return s + '}'                                321     return s + '}'
412                                                   322 
413   def build_c_string(self, metric: bool) -> st !! 323   def build_c_string(self) -> str:
414     s = ''                                        324     s = ''
415     for attr in _json_metric_attributes if met !! 325     for attr in _json_event_attributes:
416       x = getattr(self, attr)                     326       x = getattr(self, attr)
417       if metric and x and attr == 'metric_expr !! 327       if x and attr == 'metric_expr':
418         # Convert parsed metric expressions in    328         # Convert parsed metric expressions into a string. Slashes
419         # must be doubled in the file.            329         # must be doubled in the file.
420         x = x.ToPerfJson().replace('\\', '\\\\    330         x = x.ToPerfJson().replace('\\', '\\\\')
421       if metric and x and attr == 'metric_thre !! 331       s += f'{x}\\000' if x else '\\000'
422         x = x.replace('\\', '\\\\')            << 
423       if attr in _json_enum_attributes:        << 
424         s += x if x else '0'                   << 
425       else:                                    << 
426         s += f'{x}\\000' if x else '\\000'     << 
427     return s                                      332     return s
428                                                   333 
429   def to_c_string(self, metric: bool) -> str:  !! 334   def to_c_string(self) -> str:
430     """Representation of the event as a C stru    335     """Representation of the event as a C struct initializer."""
431                                                   336 
432     s = self.build_c_string(metric)            !! 337     s = self.build_c_string()
433     return f'{{ { _bcs.offsets[s] } }}, /* {s}    338     return f'{{ { _bcs.offsets[s] } }}, /* {s} */\n'
434                                                   339 
435                                                   340 
436 @lru_cache(maxsize=None)                       << 
437 def read_json_events(path: str, topic: str) ->    341 def read_json_events(path: str, topic: str) -> Sequence[JsonEvent]:
438   """Read json events from the specified file.    342   """Read json events from the specified file."""
                                                   >> 343 
439   try:                                            344   try:
440     events = json.load(open(path), object_hook !! 345     result = json.load(open(path), object_hook=JsonEvent)
441   except BaseException as err:                    346   except BaseException as err:
442     print(f"Exception processing {path}")         347     print(f"Exception processing {path}")
443     raise                                         348     raise
444   metrics: list[Tuple[str, str, metric.Express !! 349   for event in result:
445   for event in events:                         << 
446     event.topic = topic                           350     event.topic = topic
447     if event.metric_name and '-' not in event. !! 351   return result
448       metrics.append((event.pmu, event.metric_ << 
449   updates = metric.RewriteMetricsInTermsOfOthe << 
450   if updates:                                  << 
451     for event in events:                       << 
452       if event.metric_name in updates:         << 
453         # print(f'Updated {event.metric_name}  << 
454         #       f'to\n"{updates[event.metric_n << 
455         event.metric_expr = updates[event.metr << 
456                                                << 
457   return events                                << 
458                                                   352 
459 def preprocess_arch_std_files(archpath: str) -    353 def preprocess_arch_std_files(archpath: str) -> None:
460   """Read in all architecture standard events.    354   """Read in all architecture standard events."""
461   global _arch_std_events                         355   global _arch_std_events
462   for item in os.scandir(archpath):               356   for item in os.scandir(archpath):
463     if item.is_file() and item.name.endswith('    357     if item.is_file() and item.name.endswith('.json'):
464       for event in read_json_events(item.path,    358       for event in read_json_events(item.path, topic=''):
465         if event.name:                            359         if event.name:
466           _arch_std_events[event.name.lower()]    360           _arch_std_events[event.name.lower()] = event
467         if event.metric_name:                  !! 361 
468           _arch_std_events[event.metric_name.l !! 362 
                                                   >> 363 def print_events_table_prefix(tblname: str) -> None:
                                                   >> 364   """Called when a new events table is started."""
                                                   >> 365   global _close_table
                                                   >> 366   if _close_table:
                                                   >> 367     raise IOError('Printing table prefix but last table has no suffix')
                                                   >> 368   _args.output_file.write(f'static const struct compact_pmu_event {tblname}[] = {{\n')
                                                   >> 369   _close_table = True
469                                                   370 
470                                                   371 
471 def add_events_table_entries(item: os.DirEntry    372 def add_events_table_entries(item: os.DirEntry, topic: str) -> None:
472   """Add contents of file to _pending_events t    373   """Add contents of file to _pending_events table."""
                                                   >> 374   if not _close_table:
                                                   >> 375     raise IOError('Table entries missing prefix')
473   for e in read_json_events(item.path, topic):    376   for e in read_json_events(item.path, topic):
474     if e.name:                                 !! 377     _pending_events.append(e)
475       _pending_events.append(e)                << 
476     if e.metric_name:                          << 
477       _pending_metrics.append(e)               << 
478                                                   378 
479                                                   379 
480 def print_pending_events() -> None:            !! 380 def print_events_table_suffix() -> None:
481   """Optionally close events table."""            381   """Optionally close events table."""
482                                                   382 
483   def event_cmp_key(j: JsonEvent) -> Tuple[str !! 383   def event_cmp_key(j: JsonEvent) -> Tuple[bool, str, str, str, str]:
484     def fix_none(s: Optional[str]) -> str:        384     def fix_none(s: Optional[str]) -> str:
485       if s is None:                               385       if s is None:
486         return ''                                 386         return ''
487       return s                                    387       return s
488                                                   388 
489     return (fix_none(j.pmu).replace(',','_'),  !! 389     return (j.desc is not None, fix_none(j.topic), fix_none(j.name), fix_none(j.pmu),
490             fix_none(j.metric_name))              390             fix_none(j.metric_name))
491                                                   391 
492   global _pending_events                       !! 392   global _close_table
493   if not _pending_events:                      !! 393   if not _close_table:
494     return                                        394     return
495                                                   395 
496   global _pending_events_tblname               !! 396   global _pending_events
497   if _pending_events_tblname.endswith('_sys'): << 
498     global _sys_event_tables                   << 
499     _sys_event_tables.append(_pending_events_t << 
500   else:                                        << 
501     global event_tables                        << 
502     _event_tables.append(_pending_events_tblna << 
503                                                << 
504   first = True                                 << 
505   last_pmu = None                              << 
506   last_name = None                             << 
507   pmus = set()                                 << 
508   for event in sorted(_pending_events, key=eve    397   for event in sorted(_pending_events, key=event_cmp_key):
509     if last_pmu and last_pmu == event.pmu:     !! 398     _args.output_file.write(event.to_c_string())
510       assert event.name != last_name, f"Duplic !! 399     _pending_events = []
511     if event.pmu != last_pmu:                  << 
512       if not first:                            << 
513         _args.output_file.write('};\n')        << 
514       pmu_name = event.pmu.replace(',', '_')   << 
515       _args.output_file.write(                 << 
516           f'static const struct compact_pmu_ev << 
517       first = False                            << 
518       last_pmu = event.pmu                     << 
519       pmus.add((event.pmu, pmu_name))          << 
520                                                << 
521     _args.output_file.write(event.to_c_string( << 
522     last_name = event.name                     << 
523   _pending_events = []                         << 
524                                                << 
525   _args.output_file.write(f"""                 << 
526 }};                                            << 
527                                                << 
528 const struct pmu_table_entry {_pending_events_ << 
529 """)                                           << 
530   for (pmu, tbl_pmu) in sorted(pmus):          << 
531     pmu_name = f"{pmu}\\000"                   << 
532     _args.output_file.write(f"""{{             << 
533      .entries = {_pending_events_tblname}_{tbl << 
534      .num_entries = ARRAY_SIZE({_pending_event << 
535      .pmu_name = {{ {_bcs.offsets[pmu_name]} / << 
536 }},                                            << 
537 """)                                           << 
538   _args.output_file.write('};\n\n')            << 
539                                                << 
540 def print_pending_metrics() -> None:           << 
541   """Optionally close metrics table."""        << 
542                                                << 
543   def metric_cmp_key(j: JsonEvent) -> Tuple[bo << 
544     def fix_none(s: Optional[str]) -> str:     << 
545       if s is None:                            << 
546         return ''                              << 
547       return s                                 << 
548                                                << 
549     return (j.desc is not None, fix_none(j.pmu << 
550                                                << 
551   global _pending_metrics                      << 
552   if not _pending_metrics:                     << 
553     return                                     << 
554                                                << 
555   global _pending_metrics_tblname              << 
556   if _pending_metrics_tblname.endswith('_sys') << 
557     global _sys_metric_tables                  << 
558     _sys_metric_tables.append(_pending_metrics << 
559   else:                                        << 
560     global metric_tables                       << 
561     _metric_tables.append(_pending_metrics_tbl << 
562                                                << 
563   first = True                                 << 
564   last_pmu = None                              << 
565   pmus = set()                                 << 
566   for metric in sorted(_pending_metrics, key=m << 
567     if metric.pmu != last_pmu:                 << 
568       if not first:                            << 
569         _args.output_file.write('};\n')        << 
570       pmu_name = metric.pmu.replace(',', '_')  << 
571       _args.output_file.write(                 << 
572           f'static const struct compact_pmu_ev << 
573       first = False                            << 
574       last_pmu = metric.pmu                    << 
575       pmus.add((metric.pmu, pmu_name))         << 
576                                                << 
577     _args.output_file.write(metric.to_c_string << 
578   _pending_metrics = []                        << 
579                                                   400 
580   _args.output_file.write(f"""                 << 
581 }};                                            << 
582                                                << 
583 const struct pmu_table_entry {_pending_metrics << 
584 """)                                           << 
585   for (pmu, tbl_pmu) in sorted(pmus):          << 
586     pmu_name = f"{pmu}\\000"                   << 
587     _args.output_file.write(f"""{{             << 
588      .entries = {_pending_metrics_tblname}_{tb << 
589      .num_entries = ARRAY_SIZE({_pending_metri << 
590      .pmu_name = {{ {_bcs.offsets[pmu_name]} / << 
591 }},                                            << 
592 """)                                           << 
593   _args.output_file.write('};\n\n')               401   _args.output_file.write('};\n\n')
                                                   >> 402   _close_table = False
594                                                   403 
595 def get_topic(topic: str) -> str:                 404 def get_topic(topic: str) -> str:
596   if topic.endswith('metrics.json'):              405   if topic.endswith('metrics.json'):
597     return 'metrics'                              406     return 'metrics'
598   return removesuffix(topic, '.json').replace(    407   return removesuffix(topic, '.json').replace('-', ' ')
599                                                   408 
600 def preprocess_one_file(parents: Sequence[str]    409 def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
601                                                   410 
602   if item.is_dir():                               411   if item.is_dir():
603     return                                        412     return
604                                                   413 
605   # base dir or too deep                          414   # base dir or too deep
606   level = len(parents)                            415   level = len(parents)
607   if level == 0 or level > 4:                     416   if level == 0 or level > 4:
608     return                                        417     return
609                                                   418 
610   # Ignore other directories. If the file name    419   # Ignore other directories. If the file name does not have a .json
611   # extension, ignore it. It could be a readme    420   # extension, ignore it. It could be a readme.txt for instance.
612   if not item.is_file() or not item.name.endsw    421   if not item.is_file() or not item.name.endswith('.json'):
613     return                                        422     return
614                                                   423 
615   if item.name == 'metricgroups.json':         << 
616     metricgroup_descriptions = json.load(open( << 
617     for mgroup in metricgroup_descriptions:    << 
618       assert len(mgroup) > 1, parents          << 
619       description = f"{metricgroup_description << 
620       mgroup = f"{mgroup}\\000"                << 
621       _bcs.add(mgroup, metric=True)            << 
622       _bcs.add(description, metric=True)       << 
623       _metricgroups[mgroup] = description      << 
624     return                                     << 
625                                                << 
626   topic = get_topic(item.name)                    424   topic = get_topic(item.name)
627   for event in read_json_events(item.path, top    425   for event in read_json_events(item.path, topic):
628     pmu_name = f"{event.pmu}\\000"             !! 426     _bcs.add(event.build_c_string())
629     if event.name:                             << 
630       _bcs.add(pmu_name, metric=False)         << 
631       _bcs.add(event.build_c_string(metric=Fal << 
632     if event.metric_name:                      << 
633       _bcs.add(pmu_name, metric=True)          << 
634       _bcs.add(event.build_c_string(metric=Tru << 
635                                                   427 
636 def process_one_file(parents: Sequence[str], i    428 def process_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
637   """Process a JSON file during the main walk.    429   """Process a JSON file during the main walk."""
638   def is_leaf_dir_ignoring_sys(path: str) -> b !! 430   global _sys_event_tables
                                                   >> 431 
                                                   >> 432   def is_leaf_dir(path: str) -> bool:
639     for item in os.scandir(path):                 433     for item in os.scandir(path):
640       if item.is_dir() and item.name != 'sys': !! 434       if item.is_dir():
641         return False                              435         return False
642     return True                                   436     return True
643                                                   437 
644   # Model directories are leaves (ignoring pos !! 438   # model directory, reset topic
645   # directories). The FTW will walk into the d !! 439   if item.is_dir() and is_leaf_dir(item.path):
646   # pending events and metrics and update the  !! 440     print_events_table_suffix()
647   # model directory.                           << 
648   if item.is_dir() and is_leaf_dir_ignoring_sy << 
649     print_pending_events()                     << 
650     print_pending_metrics()                    << 
651                                                << 
652     global _pending_events_tblname             << 
653     _pending_events_tblname = file_name_to_tab << 
654     global _pending_metrics_tblname            << 
655     _pending_metrics_tblname = file_name_to_ta << 
656                                                   441 
                                                   >> 442     tblname = file_name_to_table_name(parents, item.name)
657     if item.name == 'sys':                        443     if item.name == 'sys':
658       _sys_event_table_to_metric_table_mapping !! 444       _sys_event_tables.append(tblname)
                                                   >> 445     print_events_table_prefix(tblname)
659     return                                        446     return
660                                                   447 
661   # base dir or too deep                          448   # base dir or too deep
662   level = len(parents)                            449   level = len(parents)
663   if level == 0 or level > 4:                     450   if level == 0 or level > 4:
664     return                                        451     return
665                                                   452 
666   # Ignore other directories. If the file name    453   # Ignore other directories. If the file name does not have a .json
667   # extension, ignore it. It could be a readme    454   # extension, ignore it. It could be a readme.txt for instance.
668   if not item.is_file() or not item.name.endsw !! 455   if not item.is_file() or not item.name.endswith('.json'):
669     return                                        456     return
670                                                   457 
671   add_events_table_entries(item, get_topic(ite    458   add_events_table_entries(item, get_topic(item.name))
672                                                   459 
673                                                   460 
674 def print_mapping_table(archs: Sequence[str])     461 def print_mapping_table(archs: Sequence[str]) -> None:
675   """Read the mapfile and generate the struct     462   """Read the mapfile and generate the struct from cpuid string to event table."""
676   _args.output_file.write("""                     463   _args.output_file.write("""
677 /* Struct used to make the PMU event table imp    464 /* Struct used to make the PMU event table implementation opaque to callers. */
678 struct pmu_events_table {                         465 struct pmu_events_table {
679         const struct pmu_table_entry *pmus;    !! 466         const struct compact_pmu_event *entries;
680         uint32_t num_pmus;                     !! 467         size_t length;
681 };                                             << 
682                                                << 
683 /* Struct used to make the PMU metric table im << 
684 struct pmu_metrics_table {                     << 
685         const struct pmu_table_entry *pmus;    << 
686         uint32_t num_pmus;                     << 
687 };                                                468 };
688                                                   469 
689 /*                                                470 /*
690  * Map a CPU to its table of PMU events. The C    471  * Map a CPU to its table of PMU events. The CPU is identified by the
691  * cpuid field, which is an arch-specific iden    472  * cpuid field, which is an arch-specific identifier for the CPU.
692  * The identifier specified in tools/perf/pmu-    473  * The identifier specified in tools/perf/pmu-events/arch/xxx/mapfile
693  * must match the get_cpuid_str() in tools/per    474  * must match the get_cpuid_str() in tools/perf/arch/xxx/util/header.c)
694  *                                                475  *
695  * The  cpuid can contain any character other     476  * The  cpuid can contain any character other than the comma.
696  */                                               477  */
697 struct pmu_events_map {                           478 struct pmu_events_map {
698         const char *arch;                         479         const char *arch;
699         const char *cpuid;                        480         const char *cpuid;
700         struct pmu_events_table event_table;   !! 481         struct pmu_events_table table;
701         struct pmu_metrics_table metric_table; << 
702 };                                                482 };
703                                                   483 
704 /*                                                484 /*
705  * Global table mapping each known CPU for the    485  * Global table mapping each known CPU for the architecture to its
706  * table of PMU events.                           486  * table of PMU events.
707  */                                               487  */
708 const struct pmu_events_map pmu_events_map[] =    488 const struct pmu_events_map pmu_events_map[] = {
709 """)                                              489 """)
710   for arch in archs:                              490   for arch in archs:
711     if arch == 'test':                            491     if arch == 'test':
712       _args.output_file.write("""{                492       _args.output_file.write("""{
713 \t.arch = "testarch",                             493 \t.arch = "testarch",
714 \t.cpuid = "testcpu",                             494 \t.cpuid = "testcpu",
715 \t.event_table = {                             !! 495 \t.table = {
716 \t\t.pmus = pmu_events__test_soc_cpu,          !! 496 \t.entries = pme_test_soc_cpu,
717 \t\t.num_pmus = ARRAY_SIZE(pmu_events__test_so !! 497 \t.length = ARRAY_SIZE(pme_test_soc_cpu),
718 \t},                                           << 
719 \t.metric_table = {                            << 
720 \t\t.pmus = pmu_metrics__test_soc_cpu,         << 
721 \t\t.num_pmus = ARRAY_SIZE(pmu_metrics__test_s << 
722 \t}                                               498 \t}
723 },                                                499 },
724 """)                                              500 """)
725     else:                                         501     else:
726       with open(f'{_args.starting_dir}/{arch}/    502       with open(f'{_args.starting_dir}/{arch}/mapfile.csv') as csvfile:
727         table = csv.reader(csvfile)               503         table = csv.reader(csvfile)
728         first = True                              504         first = True
729         for row in table:                         505         for row in table:
730           # Skip the first row or any row begi    506           # Skip the first row or any row beginning with #.
731           if not first and len(row) > 0 and no    507           if not first and len(row) > 0 and not row[0].startswith('#'):
732             event_tblname = file_name_to_table !! 508             tblname = file_name_to_table_name([], row[2].replace('/', '_'))
733             if event_tblname in _event_tables: << 
734               event_size = f'ARRAY_SIZE({event << 
735             else:                              << 
736               event_tblname = 'NULL'           << 
737               event_size = '0'                 << 
738             metric_tblname = file_name_to_tabl << 
739             if metric_tblname in _metric_table << 
740               metric_size = f'ARRAY_SIZE({metr << 
741             else:                              << 
742               metric_tblname = 'NULL'          << 
743               metric_size = '0'                << 
744             if event_size == '0' and metric_si << 
745               continue                         << 
746             cpuid = row[0].replace('\\', '\\\\    509             cpuid = row[0].replace('\\', '\\\\')
747             _args.output_file.write(f"""{{        510             _args.output_file.write(f"""{{
748 \t.arch = "{arch}",                               511 \t.arch = "{arch}",
749 \t.cpuid = "{cpuid}",                             512 \t.cpuid = "{cpuid}",
750 \t.event_table = {{                            !! 513 \t.table = {{
751 \t\t.pmus = {event_tblname},                   !! 514 \t\t.entries = {tblname},
752 \t\t.num_pmus = {event_size}                   !! 515 \t\t.length = ARRAY_SIZE({tblname})
753 \t}},                                          << 
754 \t.metric_table = {{                           << 
755 \t\t.pmus = {metric_tblname},                  << 
756 \t\t.num_pmus = {metric_size}                  << 
757 \t}}                                              516 \t}}
758 }},                                               517 }},
759 """)                                              518 """)
760           first = False                           519           first = False
761                                                   520 
762   _args.output_file.write("""{                    521   _args.output_file.write("""{
763 \t.arch = 0,                                      522 \t.arch = 0,
764 \t.cpuid = 0,                                     523 \t.cpuid = 0,
765 \t.event_table = { 0, 0 },                     !! 524 \t.table = { 0, 0 },
766 \t.metric_table = { 0, 0 },                    << 
767 }                                                 525 }
768 };                                                526 };
769 """)                                              527 """)
770                                                   528 
771                                                   529 
772 def print_system_mapping_table() -> None:         530 def print_system_mapping_table() -> None:
773   """C struct mapping table array for tables f    531   """C struct mapping table array for tables from /sys directories."""
774   _args.output_file.write("""                     532   _args.output_file.write("""
775 struct pmu_sys_events {                           533 struct pmu_sys_events {
776 \tconst char *name;                               534 \tconst char *name;
777 \tstruct pmu_events_table event_table;         !! 535 \tstruct pmu_events_table table;
778 \tstruct pmu_metrics_table metric_table;       << 
779 };                                                536 };
780                                                   537 
781 static const struct pmu_sys_events pmu_sys_eve    538 static const struct pmu_sys_events pmu_sys_event_tables[] = {
782 """)                                              539 """)
783   printed_metric_tables = []                   << 
784   for tblname in _sys_event_tables:               540   for tblname in _sys_event_tables:
785     _args.output_file.write(f"""\t{{              541     _args.output_file.write(f"""\t{{
786 \t\t.event_table = {{                          !! 542 \t\t.table = {{
787 \t\t\t.pmus = {tblname},                       !! 543 \t\t\t.entries = {tblname},
788 \t\t\t.num_pmus = ARRAY_SIZE({tblname})        !! 544 \t\t\t.length = ARRAY_SIZE({tblname})
789 \t\t}},""")                                    << 
790     metric_tblname = _sys_event_table_to_metri << 
791     if metric_tblname in _sys_metric_tables:   << 
792       _args.output_file.write(f"""             << 
793 \t\t.metric_table = {{                         << 
794 \t\t\t.pmus = {metric_tblname},                << 
795 \t\t\t.num_pmus = ARRAY_SIZE({metric_tblname}) << 
796 \t\t}},""")                                    << 
797       printed_metric_tables.append(metric_tbln << 
798     _args.output_file.write(f"""               << 
799 \t\t.name = \"{tblname}\",                     << 
800 \t}},                                          << 
801 """)                                           << 
802   for tblname in _sys_metric_tables:           << 
803     if tblname in printed_metric_tables:       << 
804       continue                                 << 
805     _args.output_file.write(f"""\t{{           << 
806 \t\t.metric_table = {{                         << 
807 \t\t\t.pmus = {tblname},                       << 
808 \t\t\t.num_pmus = ARRAY_SIZE({tblname})        << 
809 \t\t}},                                           545 \t\t}},
810 \t\t.name = \"{tblname}\",                        546 \t\t.name = \"{tblname}\",
811 \t}},                                             547 \t}},
812 """)                                              548 """)
813   _args.output_file.write("""\t{                  549   _args.output_file.write("""\t{
814 \t\t.event_table = { 0, 0 },                   !! 550 \t\t.table = { 0, 0 }
815 \t\t.metric_table = { 0, 0 },                  << 
816 \t},                                              551 \t},
817 };                                                552 };
818                                                   553 
819 static void decompress_event(int offset, struc !! 554 static void decompress(int offset, struct pmu_event *pe)
820 {                                                 555 {
821 \tconst char *p = &big_c_string[offset];          556 \tconst char *p = &big_c_string[offset];
822 """)                                              557 """)
823   for attr in _json_event_attributes:             558   for attr in _json_event_attributes:
824     _args.output_file.write(f'\n\tpe->{attr} = !! 559     _args.output_file.write(f"""
825     if attr in _json_enum_attributes:          !! 560 \tpe->{attr} = (*p == '\\0' ? NULL : p);
826       _args.output_file.write("*p - '0';\n")   << 
827     else:                                      << 
828       _args.output_file.write("(*p == '\\0' ?  << 
829     if attr == _json_event_attributes[-1]:     << 
830       continue                                 << 
831     if attr in _json_enum_attributes:          << 
832       _args.output_file.write('\tp++;')        << 
833     else:                                      << 
834       _args.output_file.write('\twhile (*p++); << 
835   _args.output_file.write("""}                 << 
836                                                << 
837 static void decompress_metric(int offset, stru << 
838 {                                              << 
839 \tconst char *p = &big_c_string[offset];       << 
840 """)                                              561 """)
841   for attr in _json_metric_attributes:         !! 562     if attr == _json_event_attributes[-1]:
842     _args.output_file.write(f'\n\tpm->{attr} = << 
843     if attr in _json_enum_attributes:          << 
844       _args.output_file.write("*p - '0';\n")   << 
845     else:                                      << 
846       _args.output_file.write("(*p == '\\0' ?  << 
847     if attr == _json_metric_attributes[-1]:    << 
848       continue                                    563       continue
849     if attr in _json_enum_attributes:          !! 564     _args.output_file.write('\twhile (*p++);')
850       _args.output_file.write('\tp++;')        << 
851     else:                                      << 
852       _args.output_file.write('\twhile (*p++); << 
853   _args.output_file.write("""}                    565   _args.output_file.write("""}
854                                                   566 
855 static int pmu_events_table__for_each_event_pm !! 567 int pmu_events_table_for_each_event(const struct pmu_events_table *table,
856                                                << 
857                                                << 
858                                                << 
859 {                                              << 
860         int ret;                               << 
861         struct pmu_event pe = {                << 
862                 .pmu = &big_c_string[pmu->pmu_ << 
863         };                                     << 
864                                                << 
865         for (uint32_t i = 0; i < pmu->num_entr << 
866                 decompress_event(pmu->entries[ << 
867                 if (!pe.name)                  << 
868                         continue;              << 
869                 ret = fn(&pe, table, data);    << 
870                 if (ret)                       << 
871                         return ret;            << 
872         }                                      << 
873         return 0;                              << 
874  }                                             << 
875                                                << 
876 static int pmu_events_table__find_event_pmu(co << 
877                                             co << 
878                                             co << 
879                                             pm << 
880                                             vo << 
881 {                                              << 
882         struct pmu_event pe = {                << 
883                 .pmu = &big_c_string[pmu->pmu_ << 
884         };                                     << 
885         int low = 0, high = pmu->num_entries - << 
886                                                << 
887         while (low <= high) {                  << 
888                 int cmp, mid = (low + high) /  << 
889                                                << 
890                 decompress_event(pmu->entries[ << 
891                                                << 
892                 if (!pe.name && !name)         << 
893                         goto do_call;          << 
894                                                << 
895                 if (!pe.name && name) {        << 
896                         low = mid + 1;         << 
897                         continue;              << 
898                 }                              << 
899                 if (pe.name && !name) {        << 
900                         high = mid - 1;        << 
901                         continue;              << 
902                 }                              << 
903                                                << 
904                 cmp = strcasecmp(pe.name, name << 
905                 if (cmp < 0) {                 << 
906                         low = mid + 1;         << 
907                         continue;              << 
908                 }                              << 
909                 if (cmp > 0) {                 << 
910                         high = mid - 1;        << 
911                         continue;              << 
912                 }                              << 
913   do_call:                                     << 
914                 return fn ? fn(&pe, table, dat << 
915         }                                      << 
916         return PMU_EVENTS__NOT_FOUND;          << 
917 }                                              << 
918                                                << 
919 int pmu_events_table__for_each_event(const str << 
920                                     struct per << 
921                                     pmu_event_    568                                     pmu_event_iter_fn fn,
922                                     void *data    569                                     void *data)
923 {                                                 570 {
924         for (size_t i = 0; i < table->num_pmus !! 571         for (size_t i = 0; i < table->length; i++) {
925                 const struct pmu_table_entry * !! 572                 struct pmu_event pe;
926                 const char *pmu_name = &big_c_ << 
927                 int ret;                          573                 int ret;
928                                                   574 
929                 if (pmu && !pmu__name_match(pm !! 575                 decompress(table->entries[i].offset, &pe);
930                         continue;              !! 576                 ret = fn(&pe, table, data);
931                                                << 
932                 ret = pmu_events_table__for_ea << 
933                 if (pmu || ret)                << 
934                         return ret;            << 
935         }                                      << 
936         return 0;                              << 
937 }                                              << 
938                                                << 
939 int pmu_events_table__find_event(const struct  << 
940                                  struct perf_p << 
941                                  const char *n << 
942                                  pmu_event_ite << 
943                                  void *data)   << 
944 {                                              << 
945         for (size_t i = 0; i < table->num_pmus << 
946                 const struct pmu_table_entry * << 
947                 const char *pmu_name = &big_c_ << 
948                 int ret;                       << 
949                                                << 
950                 if (!pmu__name_match(pmu, pmu_ << 
951                         continue;              << 
952                                                << 
953                 ret = pmu_events_table__find_e << 
954                 if (ret != PMU_EVENTS__NOT_FOU << 
955                         return ret;            << 
956         }                                      << 
957         return PMU_EVENTS__NOT_FOUND;          << 
958 }                                              << 
959                                                << 
960 size_t pmu_events_table__num_events(const stru << 
961                                     struct per << 
962 {                                              << 
963         size_t count = 0;                      << 
964                                                << 
965         for (size_t i = 0; i < table->num_pmus << 
966                 const struct pmu_table_entry * << 
967                 const char *pmu_name = &big_c_ << 
968                                                << 
969                 if (pmu__name_match(pmu, pmu_n << 
970                         count += table_pmu->nu << 
971         }                                      << 
972         return count;                          << 
973 }                                              << 
974                                                << 
975 static int pmu_metrics_table__for_each_metric_ << 
976                                                << 
977                                                << 
978                                                << 
979 {                                              << 
980         int ret;                               << 
981         struct pmu_metric pm = {               << 
982                 .pmu = &big_c_string[pmu->pmu_ << 
983         };                                     << 
984                                                << 
985         for (uint32_t i = 0; i < pmu->num_entr << 
986                 decompress_metric(pmu->entries << 
987                 if (!pm.metric_expr)           << 
988                         continue;              << 
989                 ret = fn(&pm, table, data);    << 
990                 if (ret)                       << 
991                         return ret;            << 
992         }                                      << 
993         return 0;                              << 
994 }                                              << 
995                                                << 
996 int pmu_metrics_table__for_each_metric(const s << 
997                                      pmu_metri << 
998                                      void *dat << 
999 {                                              << 
1000         for (size_t i = 0; i < table->num_pmu << 
1001                 int ret = pmu_metrics_table__ << 
1002                                               << 
1003                                               << 
1004                 if (ret)                         577                 if (ret)
1005                         return ret;              578                         return ret;
1006         }                                        579         }
1007         return 0;                                580         return 0;
1008 }                                                581 }
1009                                                  582 
1010 static const struct pmu_events_map *map_for_p !! 583 const struct pmu_events_table *perf_pmu__find_table(struct perf_pmu *pmu)
1011 {                                                584 {
1012         static struct {                       !! 585         const struct pmu_events_table *table = NULL;
1013                 const struct pmu_events_map * !! 586         char *cpuid = perf_pmu__getcpuid(pmu);
1014                 struct perf_pmu *pmu;         !! 587         int i;
1015         } last_result;                        << 
1016         static struct {                       << 
1017                 const struct pmu_events_map * << 
1018                 char *cpuid;                  << 
1019         } last_map_search;                    << 
1020         static bool has_last_result, has_last << 
1021         const struct pmu_events_map *map = NU << 
1022         char *cpuid = NULL;                   << 
1023         size_t i;                             << 
1024                                               << 
1025         if (has_last_result && last_result.pm << 
1026                 return last_result.map;       << 
1027                                               << 
1028         cpuid = perf_pmu__getcpuid(pmu);      << 
1029                                                  588 
1030         /*                                    !! 589         /* on some platforms which uses cpus map, cpuid can be NULL for
1031          * On some platforms which uses cpus  << 
1032          * PMUs other than CORE PMUs.            590          * PMUs other than CORE PMUs.
1033          */                                      591          */
1034         if (!cpuid)                              592         if (!cpuid)
1035                 goto out_update_last_result;  << 
1036                                               << 
1037         if (has_last_map_search && !strcmp(la << 
1038                 map = last_map_search.map;    << 
1039                 free(cpuid);                  << 
1040         } else {                              << 
1041                 i = 0;                        << 
1042                 for (;;) {                    << 
1043                         map = &pmu_events_map << 
1044                                               << 
1045                         if (!map->arch) {     << 
1046                                 map = NULL;   << 
1047                                 break;        << 
1048                         }                     << 
1049                                               << 
1050                         if (!strcmp_cpuid_str << 
1051                                 break;        << 
1052                }                              << 
1053                free(last_map_search.cpuid);   << 
1054                last_map_search.cpuid = cpuid; << 
1055                last_map_search.map = map;     << 
1056                has_last_map_search = true;    << 
1057         }                                     << 
1058 out_update_last_result:                       << 
1059         last_result.pmu = pmu;                << 
1060         last_result.map = map;                << 
1061         has_last_result = true;               << 
1062         return map;                           << 
1063 }                                             << 
1064                                               << 
1065 const struct pmu_events_table *perf_pmu__find << 
1066 {                                             << 
1067         const struct pmu_events_map *map = ma << 
1068                                               << 
1069         if (!map)                             << 
1070                 return NULL;                  << 
1071                                               << 
1072         if (!pmu)                             << 
1073                 return &map->event_table;     << 
1074                                               << 
1075         for (size_t i = 0; i < map->event_tab << 
1076                 const struct pmu_table_entry  << 
1077                 const char *pmu_name = &big_c << 
1078                                               << 
1079                 if (pmu__name_match(pmu, pmu_ << 
1080                          return &map->event_t << 
1081         }                                     << 
1082         return NULL;                          << 
1083 }                                             << 
1084                                               << 
1085 const struct pmu_metrics_table *perf_pmu__fin << 
1086 {                                             << 
1087         const struct pmu_events_map *map = ma << 
1088                                               << 
1089         if (!map)                             << 
1090                 return NULL;                     593                 return NULL;
1091                                                  594 
1092         if (!pmu)                             !! 595         i = 0;
1093                 return &map->metric_table;    !! 596         for (;;) {
1094                                               !! 597                 const struct pmu_events_map *map = &pmu_events_map[i++];
1095         for (size_t i = 0; i < map->metric_ta !! 598                 if (!map->arch)
1096                 const struct pmu_table_entry  !! 599                         break;
1097                 const char *pmu_name = &big_c !! 600 
1098                                               !! 601                 if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
1099                 if (pmu__name_match(pmu, pmu_ !! 602                         table = &map->table;
1100                            return &map->metri !! 603                         break;
                                                   >> 604                 }
1101         }                                        605         }
1102         return NULL;                          !! 606         free(cpuid);
                                                   >> 607         return table;
1103 }                                                608 }
1104                                                  609 
1105 const struct pmu_events_table *find_core_even    610 const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid)
1106 {                                                611 {
1107         for (const struct pmu_events_map *tab    612         for (const struct pmu_events_map *tables = &pmu_events_map[0];
1108              tables->arch;                       613              tables->arch;
1109              tables++) {                         614              tables++) {
1110                 if (!strcmp(tables->arch, arc    615                 if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
1111                         return &tables->event !! 616                         return &tables->table;
1112         }                                     << 
1113         return NULL;                          << 
1114 }                                             << 
1115                                               << 
1116 const struct pmu_metrics_table *find_core_met << 
1117 {                                             << 
1118         for (const struct pmu_events_map *tab << 
1119              tables->arch;                    << 
1120              tables++) {                      << 
1121                 if (!strcmp(tables->arch, arc << 
1122                         return &tables->metri << 
1123         }                                        617         }
1124         return NULL;                             618         return NULL;
1125 }                                                619 }
1126                                                  620 
1127 int pmu_for_each_core_event(pmu_event_iter_fn    621 int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
1128 {                                                622 {
1129         for (const struct pmu_events_map *tab    623         for (const struct pmu_events_map *tables = &pmu_events_map[0];
1130              tables->arch;                       624              tables->arch;
1131              tables++) {                         625              tables++) {
1132                 int ret = pmu_events_table__f !! 626                 int ret = pmu_events_table_for_each_event(&tables->table, fn, data);
1133                                               << 
1134                                               << 
1135                 if (ret)                      << 
1136                         return ret;           << 
1137         }                                     << 
1138         return 0;                             << 
1139 }                                             << 
1140                                               << 
1141 int pmu_for_each_core_metric(pmu_metric_iter_ << 
1142 {                                             << 
1143         for (const struct pmu_events_map *tab << 
1144              tables->arch;                    << 
1145              tables++) {                      << 
1146                 int ret = pmu_metrics_table__ << 
1147                                                  627 
1148                 if (ret)                         628                 if (ret)
1149                         return ret;              629                         return ret;
1150         }                                        630         }
1151         return 0;                                631         return 0;
1152 }                                                632 }
1153                                                  633 
1154 const struct pmu_events_table *find_sys_event    634 const struct pmu_events_table *find_sys_events_table(const char *name)
1155 {                                                635 {
1156         for (const struct pmu_sys_events *tab    636         for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
1157              tables->name;                       637              tables->name;
1158              tables++) {                         638              tables++) {
1159                 if (!strcmp(tables->name, nam    639                 if (!strcmp(tables->name, name))
1160                         return &tables->event !! 640                         return &tables->table;
1161         }                                        641         }
1162         return NULL;                             642         return NULL;
1163 }                                                643 }
1164                                                  644 
1165 int pmu_for_each_sys_event(pmu_event_iter_fn     645 int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
1166 {                                                646 {
1167         for (const struct pmu_sys_events *tab    647         for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
1168              tables->name;                       648              tables->name;
1169              tables++) {                         649              tables++) {
1170                 int ret = pmu_events_table__f !! 650                 int ret = pmu_events_table_for_each_event(&tables->table, fn, data);
1171                                               << 
1172                                               << 
1173                 if (ret)                      << 
1174                         return ret;           << 
1175         }                                     << 
1176         return 0;                             << 
1177 }                                             << 
1178                                               << 
1179 int pmu_for_each_sys_metric(pmu_metric_iter_f << 
1180 {                                             << 
1181         for (const struct pmu_sys_events *tab << 
1182              tables->name;                    << 
1183              tables++) {                      << 
1184                 int ret = pmu_metrics_table__ << 
1185                                                  651 
1186                 if (ret)                         652                 if (ret)
1187                         return ret;              653                         return ret;
1188         }                                        654         }
1189         return 0;                                655         return 0;
1190 }                                                656 }
1191 """)                                             657 """)
1192                                                  658 
1193 def print_metricgroups() -> None:             << 
1194   _args.output_file.write("""                 << 
1195 static const int metricgroups[][2] = {        << 
1196 """)                                          << 
1197   for mgroup in sorted(_metricgroups):        << 
1198     description = _metricgroups[mgroup]       << 
1199     _args.output_file.write(                  << 
1200         f'\t{{ {_bcs.offsets[mgroup]}, {_bcs. << 
1201     )                                         << 
1202   _args.output_file.write("""                 << 
1203 };                                            << 
1204                                               << 
1205 const char *describe_metricgroup(const char * << 
1206 {                                             << 
1207         int low = 0, high = (int)ARRAY_SIZE(m << 
1208                                               << 
1209         while (low <= high) {                 << 
1210                 int mid = (low + high) / 2;   << 
1211                 const char *mgroup = &big_c_s << 
1212                 int cmp = strcmp(mgroup, grou << 
1213                                               << 
1214                 if (cmp == 0) {               << 
1215                         return &big_c_string[ << 
1216                 } else if (cmp < 0) {         << 
1217                         low = mid + 1;        << 
1218                 } else {                      << 
1219                         high = mid - 1;       << 
1220                 }                             << 
1221         }                                     << 
1222         return NULL;                          << 
1223 }                                             << 
1224 """)                                          << 
1225                                                  659 
1226 def main() -> None:                              660 def main() -> None:
1227   global _args                                   661   global _args
1228                                                  662 
1229   def dir_path(path: str) -> str:                663   def dir_path(path: str) -> str:
1230     """Validate path is a directory for argpa    664     """Validate path is a directory for argparse."""
1231     if os.path.isdir(path):                      665     if os.path.isdir(path):
1232       return path                                666       return path
1233     raise argparse.ArgumentTypeError(f'\'{pat    667     raise argparse.ArgumentTypeError(f'\'{path}\' is not a valid directory')
1234                                                  668 
1235   def ftw(path: str, parents: Sequence[str],     669   def ftw(path: str, parents: Sequence[str],
1236           action: Callable[[Sequence[str], os    670           action: Callable[[Sequence[str], os.DirEntry], None]) -> None:
1237     """Replicate the directory/file walking b    671     """Replicate the directory/file walking behavior of C's file tree walk."""
1238     for item in sorted(os.scandir(path), key= !! 672     for item in os.scandir(path):
1239       if _args.model != 'all' and item.is_dir << 
1240         # Check if the model matches one in _ << 
1241         if len(parents) == _args.model.split( << 
1242           # We're testing the correct directo << 
1243           item_path = '/'.join(parents) + ('/ << 
1244           if 'test' not in item_path and item << 
1245             continue                          << 
1246       action(parents, item)                      673       action(parents, item)
1247       if item.is_dir():                          674       if item.is_dir():
1248         ftw(item.path, parents + [item.name],    675         ftw(item.path, parents + [item.name], action)
1249                                                  676 
1250   ap = argparse.ArgumentParser()                 677   ap = argparse.ArgumentParser()
1251   ap.add_argument('arch', help='Architecture     678   ap.add_argument('arch', help='Architecture name like x86')
1252   ap.add_argument('model', help='''Select a m << 
1253 reduce the code size.  Normally set to "all". << 
1254 ARM64 with an implementor/model, the model mu << 
1255 such as "arm/cortex-a34".''',                 << 
1256                   default='all')              << 
1257   ap.add_argument(                               679   ap.add_argument(
1258       'starting_dir',                            680       'starting_dir',
1259       type=dir_path,                             681       type=dir_path,
1260       help='Root of tree containing architect    682       help='Root of tree containing architecture directories containing json files'
1261   )                                              683   )
1262   ap.add_argument(                               684   ap.add_argument(
1263       'output_file', type=argparse.FileType('    685       'output_file', type=argparse.FileType('w', encoding='utf-8'), nargs='?', default=sys.stdout)
1264   _args = ap.parse_args()                        686   _args = ap.parse_args()
1265                                                  687 
1266   _args.output_file.write(f"""                << 
1267 /* SPDX-License-Identifier: GPL-2.0 */        << 
1268 /* THIS FILE WAS AUTOGENERATED BY jevents.py  << 
1269 """)                                          << 
1270   _args.output_file.write("""                    688   _args.output_file.write("""
1271 #include <pmu-events/pmu-events.h>            !! 689 #include "pmu-events/pmu-events.h"
1272 #include "util/header.h"                         690 #include "util/header.h"
1273 #include "util/pmu.h"                            691 #include "util/pmu.h"
1274 #include <string.h>                              692 #include <string.h>
1275 #include <stddef.h>                              693 #include <stddef.h>
1276                                                  694 
1277 struct compact_pmu_event {                       695 struct compact_pmu_event {
1278         int offset;                           !! 696   int offset;
1279 };                                            << 
1280                                               << 
1281 struct pmu_table_entry {                      << 
1282         const struct compact_pmu_event *entri << 
1283         uint32_t num_entries;                 << 
1284         struct compact_pmu_event pmu_name;    << 
1285 };                                               697 };
1286                                                  698 
1287 """)                                             699 """)
1288   archs = []                                     700   archs = []
1289   for item in os.scandir(_args.starting_dir):    701   for item in os.scandir(_args.starting_dir):
1290     if not item.is_dir():                        702     if not item.is_dir():
1291       continue                                   703       continue
1292     if item.name == _args.arch or _args.arch     704     if item.name == _args.arch or _args.arch == 'all' or item.name == 'test':
1293       archs.append(item.name)                    705       archs.append(item.name)
1294                                                  706 
1295   if len(archs) < 2 and _args.arch != 'none': !! 707   if len(archs) < 2:
1296     raise IOError(f'Missing architecture dire    708     raise IOError(f'Missing architecture directory \'{_args.arch}\'')
1297                                                  709 
1298   archs.sort()                                   710   archs.sort()
1299   for arch in archs:                             711   for arch in archs:
1300     arch_path = f'{_args.starting_dir}/{arch}    712     arch_path = f'{_args.starting_dir}/{arch}'
1301     preprocess_arch_std_files(arch_path)         713     preprocess_arch_std_files(arch_path)
1302     ftw(arch_path, [], preprocess_one_file)      714     ftw(arch_path, [], preprocess_one_file)
1303                                                  715 
1304   _bcs.compute()                                 716   _bcs.compute()
1305   _args.output_file.write('static const char     717   _args.output_file.write('static const char *const big_c_string =\n')
1306   for s in _bcs.big_string:                      718   for s in _bcs.big_string:
1307     _args.output_file.write(s)                   719     _args.output_file.write(s)
1308   _args.output_file.write(';\n\n')               720   _args.output_file.write(';\n\n')
1309   for arch in archs:                             721   for arch in archs:
1310     arch_path = f'{_args.starting_dir}/{arch}    722     arch_path = f'{_args.starting_dir}/{arch}'
1311     ftw(arch_path, [], process_one_file)         723     ftw(arch_path, [], process_one_file)
1312     print_pending_events()                    !! 724     print_events_table_suffix()
1313     print_pending_metrics()                   << 
1314                                                  725 
1315   print_mapping_table(archs)                     726   print_mapping_table(archs)
1316   print_system_mapping_table()                   727   print_system_mapping_table()
1317   print_metricgroups()                        !! 728 
1318                                                  729 
1319 if __name__ == '__main__':                       730 if __name__ == '__main__':
1320   main()                                         731   main()
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php