summaryrefslogtreecommitdiffstats
path: root/tools/perf/pmu-events/Build
blob: 63c65788d442838da5636a14883d34e878491935 (plain)
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
EMPTY_PMU_EVENTS_C = pmu-events/empty-pmu-events.c
# pmu-events.c will be generated by jevents.py or copied from EMPTY_PMU_EVENTS_C
PMU_EVENTS_C	=  $(OUTPUT)pmu-events/pmu-events.c
pmu-events-y	+= pmu-events.o

# pmu-events.c file is generated in the OUTPUT directory so it needs a
# separate rule to depend on it properly
$(OUTPUT)pmu-events/pmu-events.o: $(PMU_EVENTS_C)
	$(call rule_mkdir)
	$(call if_changed_dep,cc_o_c)

# Message for $(call echo-cmd,cp), possibly remove the src file from
# the destination to save space in the build log.
quiet_cmd_cp   = COPY    $(patsubst %$<,%,$@) <- $<

# --- NO_JEVENTS=1 build ---
ifeq ($(NO_JEVENTS),1)
$(PMU_EVENTS_C): $(EMPTY_PMU_EVENTS_C)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,cp)cp $< $@
else
# --- Regular build ---

# Setup the JEVENTS_ARCH and JEVENTS_MODEL
ifeq ($(JEVENTS_ARCH),)
JEVENTS_ARCH=$(SRCARCH)
endif
JEVENTS_MODEL ?= all

# The input json/csv files
SRC_DIR		:= pmu-events/arch
ifeq ($(JEVENTS_ARCH),all)
SRC_JSON	:= $(shell find $(SRC_DIR) -name '*.json' -o -name '*.csv')
else
SRC_JSON	:= $(shell find $(SRC_DIR)/common $(SRC_DIR)/test $(SRC_DIR)/$(JEVENTS_ARCH) -name '*.json' -o -name '*.csv')
endif

# Python to build the generic legacy cache events
LEGACY_CACHE_PY	=  pmu-events/make_legacy_cache.py
LEGACY_CACHE_JSON = $(OUTPUT)pmu-events/arch/common/common/legacy-cache.json
GEN_JSON = $(LEGACY_CACHE_JSON)

$(LEGACY_CACHE_JSON): $(LEGACY_CACHE_PY)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,gen)$(PYTHON) $(LEGACY_CACHE_PY) > $@

# Python to generate architectural metrics
GEN_METRIC_DEPS := pmu-events/metric.py pmu-events/common_metrics.py
# Functions to extract the model from an extra-metrics.json or extra-metricgroups.json path.
model_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/extra-metric.*\.json@\1@')
vendor_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/[^/]*/extra-metric.*\.json@\1@')

ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all))
# Generate AMD Json
ZENS = $(shell ls -d pmu-events/arch/x86/amdzen*)
ZEN_METRICS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metrics.json)
ZEN_METRICGROUPS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metricgroups.json)
GEN_JSON += $(ZEN_METRICS) $(ZEN_METRICGROUPS)

$(ZEN_METRICS): pmu-events/amd_metrics.py $(GEN_METRIC_DEPS)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,gen)$(PYTHON) $< $(call model_name,$@) pmu-events/arch > $@

$(ZEN_METRICGROUPS): pmu-events/amd_metrics.py $(GEN_METRIC_DEPS)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call model_name,$@) pmu-events/arch > $@

endif

ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),arm64 all))
# Generate ARM Json
ARMS = $(shell ls -d pmu-events/arch/arm64/arm/*|grep -v cmn)
ARM_METRICS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metrics.json)
ARM_METRICGROUPS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metricgroups.json)
GEN_JSON += $(ARM_METRICS) $(ARM_METRICGROUPS)

$(ARM_METRICS): pmu-events/arm64_metrics.py $(GEN_METRIC_DEPS)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,gen)$(PYTHON) $< $(call vendor_name,$@) $(call model_name,$@) pmu-events/arch > $@

$(ARM_METRICGROUPS): pmu-events/arm64_metrics.py $(GEN_METRIC_DEPS)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call vendor_name,$@) $(call model_name,$@) pmu-events/arch > $@

endif

ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all))
# Generate Intel Json
INTELS = $(shell ls -d pmu-events/arch/x86/*|grep -v amdzen|grep -v mapfile.csv)
INTEL_METRICS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metrics.json)
INTEL_METRICGROUPS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metricgroups.json)
GEN_JSON += $(INTEL_METRICS) $(INTEL_METRICGROUPS)

$(INTEL_METRICS): pmu-events/intel_metrics.py $(GEN_METRIC_DEPS)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,gen)$(PYTHON) $< $(call model_name,$@) pmu-events/arch > $@

$(INTEL_METRICGROUPS): pmu-events/intel_metrics.py $(GEN_METRIC_DEPS)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call model_name,$@) pmu-events/arch > $@

endif

OUT_DIR		:= $(OUTPUT)pmu-events/arch

ifeq ($(OUTPUT),)
OUT_JSON	:= $(SRC_JSON)
ORPHAN_FILES	:=
else
# Things that need to be built in the OUTPUT directory. Note, ensure
# there is a slash after the directory name so that it matches what
# $(dir) gives in COPY_RULE.
OUT_JSON	:= $(patsubst $(SRC_DIR)/%,$(OUT_DIR)/%,$(SRC_JSON))
OUT_DIRS	:= $(sort $(patsubst %/,%,$(dir $(OUT_JSON))))

# Things already in the OUTPUT directory
CUR_OUT_JSON	:= $(shell [ -d $(OUT_DIR) ] && find $(OUT_DIR) -type f)

# Things in the OUTPUT directory but shouldn't be there as computed by
# OUT_JSON and GEN_JSON.
ORPHAN_FILES	:= $(filter-out $(OUT_JSON) $(GEN_JSON),$(CUR_OUT_JSON))

# Message for $(call echo-cmd,mkd). There is already a mkdir message
# but it assumes $@ is a file to mkdir the directory for.
quiet_cmd_mkd  = MKDIR   $@

$(OUT_DIRS):
	$(Q)$(call echo-cmd,mkd)mkdir -p $@

# Explicitly generate rules to copy SRC_JSON files as $(dir) cannot
# apply to $@ in a dependency. Exclude from the copy rules any that
# look like they are copying generated json. This happens as a perf
# build within the tools/perf directory will leave generated json
# files within the tree, these then get picked up by SRC_JSON find.
define COPY_RULE
$(2): $(1) | $(3)
	$$(Q)$$(call echo-cmd,cp)cp $(1) $(2)
endef
$(foreach src,$(SRC_JSON), \
    $(eval dest := $(patsubst $(SRC_DIR)/%,$(OUT_DIR)/%,$(src))) \
    $(eval ddir := $(patsubst %/,%,$(dir $(dest)))) \
    $(if $(filter $(dest),$(GEN_JSON)),, \
        $(eval $(call COPY_RULE,$(src),$(dest),$(ddir))) \
    ) \
)

endif # ifneq ($(OUTPUT),)

JEVENTS_PY	=  pmu-events/jevents.py
METRIC_PY	=  pmu-events/metric.py

# Rule to run the metric test.
METRIC_TEST_PY	=  pmu-events/metric_test.py
METRIC_TEST_LOG	=  $(OUTPUT)pmu-events/metric_test.log

$(METRIC_TEST_LOG): $(METRIC_TEST_PY) $(METRIC_PY)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,test)$(PYTHON) $< 2> $@ || (cat $@ && false)

# Rule to create then ensure the empty-pmu-events.c is in sync.
TEST_EMPTY_PMU_EVENTS_C = $(OUTPUT)pmu-events/test-empty-pmu-events.c
EMPTY_PMU_EVENTS_TEST_LOG = $(OUTPUT)pmu-events/empty-pmu-events.log

$(TEST_EMPTY_PMU_EVENTS_C): $(OUT_JSON) $(GEN_JSON) $(JEVENTS_PY) $(METRIC_PY)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) none none $(OUTPUT)pmu-events/arch $@

$(EMPTY_PMU_EVENTS_TEST_LOG): $(EMPTY_PMU_EVENTS_C) $(TEST_EMPTY_PMU_EVENTS_C)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,test)diff -u $^ 2> $@ || (cat $@ && false)


# Dependencies for jevents.py
JEVENTS_DEPS := $(OUT_JSON) $(GEN_JSON) $(JEVENTS_PY) $(METRIC_PY) $(EMPTY_PMU_EVENTS_TEST_LOG) $(METRIC_TEST_LOG)

# Rules to run mypy if enabled.
ifdef MYPY
define MYPY_RULE
$(2): $(1)
	$$(Q)$$(call echo-cmd,test)mypy $(1) > $(2) || (cat $(2) && rm $(2) && false)
endef
$(foreach src,$(wildcard pmu-events/*.py), \
    $(eval dest := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.mypy_log,$(src))) \
    $(eval $(call MYPY_RULE,$(src),$(dest))) \
)

MYPY_INPUTS := $(wildcard pmu-events/*.py)
MYPY_OUTPUTS := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.mypy_log,$(MYPY_INPUTS))
JEVENTS_DEPS += $(MYPY_OUTPUTS)
endif

# Rules to run pylint if enabled.
ifdef PYLINT
define PYLINT_RULE
$(2): $(1)
	$$(Q)$$(call echo-cmd,test)pylint $(1) > $(2) || (cat $(2) && rm $(2) && false)
endef
$(foreach src,$(wildcard pmu-events/*.py), \
    $(eval dest := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.pylint_log,$(src))) \
    $(eval $(call PYLINT_RULE,$(src),$(dest))) \
)

PYLINT_INPUTS := $(wildcard pmu-events/*.py)
PYLINT_OUTPUTS := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.pylint_log,$(PYLINT_INPUTS))
JEVENTS_DEPS += $(PYLINT_OUTPUTS)
endif

# If there are orphaned files remove them.
ifneq ($(strip $(ORPHAN_FILES)),)
.PHONY: prune_orphans

# Message for $(call echo-cmd,rm). Generally cleaning files isn't part
# of a build step.
quiet_cmd_rm  = RM      $^

prune_orphans: $(ORPHAN_FILES)
	$(Q)$(call echo-cmd,rm)rm -f $^

JEVENTS_DEPS += prune_orphans
endif

# Finally, the rule to build pmu-events.c using jevents.py. All test
# and inputs are dependencies.
$(PMU_EVENTS_C): $(JEVENTS_DEPS)
	$(call rule_mkdir)
	$(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) $(OUT_DIR) $@

endif # ifeq ($(NO_JEVENTS),1)