-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgen_driver.py
executable file
·147 lines (134 loc) · 5.09 KB
/
gen_driver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
import plistlib
import sys
def BIT(n):
return 1 << n
PMU_NR_COUNTERS = 10 # Ref: https://lore.kernel.org/lkml/[email protected]/
ONLY_5_6_7 = BIT(5) | BIT(6) | BIT(7)
ONLY_2_4_6 = BIT(2) | BIT(4) | BIT(6)
ONLY_2_TO_7 = BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7)
ANY_BUT_0_1 = sum([BIT(i) for i in range(2, PMU_NR_COUNTERS)])
# Some counters_mask of events are not described in the counters_mask key, just override it here
override_affinity_list = { # Ref: https://lore.kernel.org/lkml/[email protected]/
0x02: ANY_BUT_0_1 | BIT(0), # M1_PMU_PERFCTR_CPU_CYCLES,
0x8c: BIT(7) | BIT(1), # M1_PMU_PERFCTR_INSTRUCTIONS
}
known_affinity_list = { # Ref: https://lore.kernel.org/lkml/[email protected]/
0x01: BIT(7),
0x8d: ONLY_5_6_7,
0x8e: ONLY_5_6_7,
0x8f: ONLY_5_6_7,
0x90: ONLY_5_6_7,
0x93: ONLY_5_6_7,
0x94: ONLY_5_6_7,
0x95: ONLY_5_6_7,
0x96: ONLY_5_6_7,
0x97: BIT(7),
0x98: ONLY_5_6_7,
0x99: ONLY_5_6_7,
0x9a: BIT(7),
0x9b: ONLY_5_6_7,
0x9c: ONLY_5_6_7,
0x9f: BIT(7),
0xbf: ONLY_5_6_7,
0xc0: ONLY_5_6_7,
0xc1: ONLY_5_6_7,
0xc4: ONLY_5_6_7,
0xc5: ONLY_5_6_7,
0xc6: ONLY_5_6_7,
0xc8: ONLY_5_6_7,
0xca: ONLY_5_6_7,
0xcb: ONLY_5_6_7,
0xf5: ONLY_2_4_6,
0xf6: ONLY_2_4_6,
0xf7: ONLY_2_4_6,
0xf8: ONLY_2_TO_7,
0xfd: ONLY_2_4_6,
}
def gen_affinity_str(counters_mask):
if counters_mask == BIT(0):
return "BIT(0)"
elif counters_mask == BIT(1):
return "BIT(1)"
elif counters_mask == ONLY_2_4_6:
return "ONLY_2_4_6"
elif counters_mask == BIT(7):
return "BIT(7)"
elif counters_mask == BIT(7) | BIT(1):
return "BIT(7) | BIT(1)"
elif counters_mask == ONLY_5_6_7:
return "ONLY_5_6_7"
elif counters_mask == ONLY_2_TO_7:
return "ONLY_2_TO_7"
elif counters_mask == ANY_BUT_0_1 | BIT(0):
return "ANY_BUT_0_1 | BIT(0)"
else:
return str(counters_mask)
def gen_tabs(key_str_len, key_string):
# Don't +1 here since the space should be generated by \t
tabs_need = (key_str_len - (8 + len(key_string)) + 7) // 8
return "\t" + key_string + "\t" * tabs_need
def gen_pmu_event_table(pl, chip):
events = pl["system"]["cpu"]["events"]
num_dict = dict()
for key, value in events.items():
if value.get('number') is not None:
num_dict[value['number']] = key
for key in known_affinity_list.keys():
if key not in num_dict.keys():
num_dict[key] = f"UNKNOWN_{str(hex(key))[2:]}"
prefix = chip.capitalize() + "_PMU_PERFCTR_"
# First 8 is \t, last 1 is space, then (... + 7) // 8 to round up
key_str_len = ( (8 + max(map(lambda x: len(prefix) + len(x), num_dict.values())) + 1 + 7) // 8) * 8
inner_str = []
for key in sorted(num_dict.keys()):
key_string = gen_tabs(key_str_len, prefix + num_dict[key])
inner_str.append(f"{key_string}= {hex(key)},")
inner_str = "\n".join(inner_str)
return f'''
enum {chip}_pmu_events {{
{inner_str}
{gen_tabs(key_str_len, f"{chip.capitalize()}_PMU_PERFCTR_LAST")}= {chip.capitalize()}_PMU_CFG_EVENT,
/*
* From this point onwards, these are not actual HW events,
* but attributes that get stored in hw->config_base.
*/
{gen_tabs(key_str_len, f"{chip.capitalize()}_PMU_CFG_COUNT_USER")}= BIT(8),
{gen_tabs(key_str_len, f"{chip.capitalize()}_PMU_CFG_COUNT_KERNEL")}= BIT(9),
}};
'''.strip()
def gen_pmu_affinity_table(pl, chip):
events = pl["system"]["cpu"]["events"]
num_dict = dict()
for key, value in events.items():
if value.get('number') is not None:
if value['number'] in override_affinity_list.keys():
num_dict[value['number']] = (key, override_affinity_list[value['number']])
elif value.get('counters_mask') is not None:
num_dict[value['number']] = (key, value['counters_mask'])
for key in known_affinity_list.keys():
if key not in num_dict.keys():
num_dict[key] = (f"UNKNOWN_{str(hex(key))[2:]}", known_affinity_list[key])
prefix = chip.capitalize() + "_PMU_PERFCTR_"
# First 8 is \t, last 1 is space, then (... + 7) // 8 to round up
key_str_len = ( ( (8 + max(map(lambda x: len(f"[{prefix}{x[0]}]"), num_dict.values())) + 1) + 7) // 8) * 8
inner_str = []
for key in sorted(num_dict.keys()):
key_string = gen_tabs(key_str_len, f"[{prefix}{num_dict[key][0]}]")
inner_str.append(f"{key_string}= {gen_affinity_str(num_dict[key][1])},")
inner_str = "\n".join(inner_str)
return f'''
static const u16 {chip}_pmu_event_affinity[{chip.capitalize()}_PMU_PERFCTR_LAST + 1] = {{
{gen_tabs(key_str_len, f"[0 ... {chip.capitalize()}_PMU_PERFCTR_LAST]")}= ANY_BUT_0_1,
{inner_str}
}};
'''.strip()
if __name__ == "__main__":
filename = sys.argv[1]
chip = sys.argv[2] if len(sys.argv) > 2 else "m1"
pl = {}
with open(filename, 'rb') as f:
pl = plistlib.load(f)
print(gen_pmu_event_table(pl, chip))
print(gen_pmu_affinity_table(pl, chip))