Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | |
| 3 | # perf pmu-events sorting tool |
| 4 | # |
| 5 | # Copyright (C) 2021 Bruce Ashfield |
| 6 | # |
| 7 | # SPDX-License-Identifier: MIT |
| 8 | # |
| 9 | |
| 10 | import sys |
| 11 | import os |
| 12 | import re |
| 13 | from collections import OrderedDict |
| 14 | |
| 15 | if len(sys.argv) < 2: |
| 16 | print( "[ERROR]: input and output pmu files missing" ) |
| 17 | sys.exit(1) |
| 18 | |
| 19 | if len(sys.argv) < 3: |
| 20 | print( "[ERROR]: output pmu file missing" ) |
| 21 | sys.exit(1) |
| 22 | |
| 23 | infile = sys.argv[1] |
| 24 | outfile = sys.argv[2] |
| 25 | |
| 26 | if not os.path.exists(infile): |
| 27 | print( "ERROR. input file does not exist: %s" % infile ) |
| 28 | sys.exit(1) |
| 29 | |
| 30 | if os.path.exists(outfile): |
| 31 | print( "WARNING. output file will be overwritten: %s" % infile ) |
| 32 | |
| 33 | with open(infile, 'r') as file: |
| 34 | data = file.read() |
| 35 | |
Andrew Geissler | 595f630 | 2022-01-24 19:11:47 +0000 | [diff] [blame] | 36 | preamble_regex = re.compile( '^(.*?)^(struct|const struct|static struct|static const struct)', re.MULTILINE | re.DOTALL ) |
Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 37 | |
| 38 | preamble = re.search( preamble_regex, data ) |
Andrew Geissler | 595f630 | 2022-01-24 19:11:47 +0000 | [diff] [blame] | 39 | struct_block_regex = re.compile( '^(struct|const struct|static struct|static const struct).*?(\w+) (.*?)\[\] = {(.*?)^};', re.MULTILINE | re.DOTALL ) |
Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 40 | field_regex = re.compile( '{.*?},', re.MULTILINE | re.DOTALL ) |
| 41 | cpuid_regex = re.compile( '\.cpuid = (.*?),', re.MULTILINE | re.DOTALL ) |
| 42 | name_regex = re.compile( '\.name = (.*?),', re.MULTILINE | re.DOTALL ) |
| 43 | |
| 44 | # create a dictionary structure to store all the structs, their |
| 45 | # types and then their fields. |
| 46 | entry_dict = {} |
| 47 | for struct in re.findall( struct_block_regex, data ): |
Andrew Geissler | 595f630 | 2022-01-24 19:11:47 +0000 | [diff] [blame] | 48 | # print( "struct: %s %s %s" % (struct[0],struct[1],struct[2]) ) |
| 49 | entry_dict[struct[2]] = {} |
| 50 | entry_dict[struct[2]]['type_prefix'] = struct[0] |
| 51 | entry_dict[struct[2]]['type'] = struct[1] |
| 52 | entry_dict[struct[2]]['fields'] = {} |
| 53 | for entry in re.findall( field_regex, struct[3] ): |
Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 54 | #print( " entry: %s" % entry ) |
| 55 | cpuid = re.search( cpuid_regex, entry ) |
| 56 | if cpuid: |
| 57 | #print( " cpuid found: %s" % cpuid.group(1) ) |
Andrew Geissler | 595f630 | 2022-01-24 19:11:47 +0000 | [diff] [blame] | 58 | entry_dict[struct[2]]['fields'][cpuid.group(1)] = entry |
| 59 | |
Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 60 | name = re.search( name_regex, entry ) |
| 61 | if name: |
| 62 | #print( " name found: %s" % name.group(1) ) |
Andrew Geissler | 595f630 | 2022-01-24 19:11:47 +0000 | [diff] [blame] | 63 | entry_dict[struct[2]]['fields'][name.group(1)] = entry |
| 64 | |
Andrew Geissler | 615f2f1 | 2022-07-15 14:00:58 -0500 | [diff] [blame^] | 65 | # unmatched entries are most likely array terminators and |
| 66 | # should end up as the last element in the sorted list, which |
| 67 | # is achieved by using '0' as the key |
| 68 | if not cpuid and not name: |
Andrew Geissler | 595f630 | 2022-01-24 19:11:47 +0000 | [diff] [blame] | 69 | entry_dict[struct[2]]['fields']['0'] = entry |
Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 70 | |
| 71 | # created ordered dictionaries from the captured values. These are ordered by |
| 72 | # a sorted() iteration of the keys. We don't care about the order we read |
| 73 | # things, just the sorted order. Hency why we couldn't create these during |
| 74 | # reading. |
| 75 | # |
| 76 | # yes, there's a more concise way to do this, but our nested dictionaries of |
| 77 | # fields make it complex enough that it becomes unreadable. |
| 78 | entry_dict_sorted = OrderedDict() |
| 79 | for i in sorted(entry_dict.keys()): |
| 80 | entry_dict_sorted[i] = {} |
Andrew Geissler | 595f630 | 2022-01-24 19:11:47 +0000 | [diff] [blame] | 81 | entry_dict_sorted[i]['type_prefix'] = entry_dict[i]['type_prefix'] |
Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 82 | entry_dict_sorted[i]['type'] = entry_dict[i]['type'] |
| 83 | entry_dict_sorted[i]['fields'] = {} |
| 84 | for f in sorted(entry_dict[i]['fields'].keys()): |
| 85 | entry_dict_sorted[i]['fields'][f] = entry_dict[i]['fields'][f] |
| 86 | |
| 87 | # dump the sorted elements to the outfile |
| 88 | outf = open( outfile, 'w' ) |
| 89 | |
| 90 | print( preamble.group(1) ) |
| 91 | outf.write( preamble.group(1) ) |
| 92 | for d in entry_dict_sorted: |
Andrew Geissler | 595f630 | 2022-01-24 19:11:47 +0000 | [diff] [blame] | 93 | outf.write( "%s %s %s[] = {\n" % (entry_dict_sorted[d]['type_prefix'], entry_dict_sorted[d]['type'],d) ) |
Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 94 | for f in entry_dict_sorted[d]['fields']: |
| 95 | outf.write( entry_dict_sorted[d]['fields'][f] + '\n' ) |
| 96 | |
| 97 | outf.write( "};\n" ) |
| 98 | |
| 99 | outf.close() |
| 100 | |