-
Notifications
You must be signed in to change notification settings - Fork 16
/
Makefile
352 lines (269 loc) · 11.3 KB
/
Makefile
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# Top level make file for building PandA FPGA images
TOP := $(CURDIR)
# Need bash for the source command in Xilinx settings64.sh
SHELL = /bin/bash
# The following symbols MUST be defined in the CONFIG file before being used.
PANDA_ROOTFS = $(error Define PANDA_ROOTFS in CONFIG file)
VIVADO = $(error Define VIVADO in CONFIG file)
APP_NAME = $(error Define APP_NAME in CONFIG file)
# Build defaults that can be overwritten by the CONFIG file if required
PYTHON = python3
SPHINX_BUILD = sphinx-build
MAKE_ZPKG = $(PANDA_ROOTFS)/make-zpkg
MAKE_GITHUB_RELEASE = $(PANDA_ROOTFS)/make-github-release.py
BUILD_DIR = $(TOP)/build
VIVADO_VER = 2023.2
DEFAULT_TARGETS = zpkg
# The CONFIG file is required. If not present, create by copying CONFIG.example
# and editing as appropriate.
include CONFIG
# Now we've loaded the CONFIG compute all the appropriate destinations
TGT_BUILD_DIR = $(BUILD_DIR)/targets/$(TARGET)
TEST_DIR = $(TGT_BUILD_DIR)/tests
APP_BUILD_DIR = $(BUILD_DIR)/apps/$(APP_NAME)
AUTOGEN_BUILD_DIR = $(APP_BUILD_DIR)/autogen
FPGA_BUILD_DIR = $(APP_BUILD_DIR)/FPGA
# The TARGET defines the class of application and is extracted from the first
# part of the APP_NAME.
TARGET = $(firstword $(subst -, ,$(APP_NAME)))
TARGET_DIR = $(TOP)/targets/$(TARGET)
# Location of Vivado project files and default run-modes
# Need different MODE variables for TOP and PS/IP as PS/IP are prerequisites of TOP
PS_PROJ = $(TGT_BUILD_DIR)/panda_ps/panda_ps.xpr
IP_PROJ = $(TGT_BUILD_DIR)/ip_repo/managed_ip_project/managed_ip_project.xpr
TOP_PROJ = $(FPGA_BUILD_DIR)/panda_top/carrier_fpga_top.xpr
VIVADO_MODE ?= batch
XSIM_MODE ?= gui
# Store the git hash in top-level build directory
VER = $(BUILD_DIR)/VERSION
default: $(DEFAULT_TARGETS)
all: python_tests python_timing hdl_test default boot
.PHONY: default all
# If ALL_APPS not specified in CONFIG, pick up all valid entries in the apps dir
ifndef ALL_APPS
ALL_APPS := $(wildcard apps/*.app.ini)
# Exclude udpontrig apps as they can't currently be built with our license
ALL_APPS := $(filter-out $(wildcard apps/*udpontrig*),$(ALL_APPS))
ALL_APPS := $(filter-out $(wildcard apps/*eventr*),$(ALL_APPS))
ALL_APPS := $(notdir $(ALL_APPS))
ALL_APPS := $(ALL_APPS:.app.ini=)
endif
# Helper for MAKE_ALL_APPS below. This separate definition is needed so that
# each generate makefile call is a separate command.
define _MAKE_ONE_APP
$(MAKE) APP_NAME=$(1) $(2)
endef
# Helper function for building all apps: invoke
#
# $(call MAKE_ALL_APPS, target)
#
# to build target for all applications in the target directory
MAKE_ALL_APPS = $(foreach app,$(ALL_APPS), $(call _MAKE_ONE_APP,$(app),$(1)))
# ------------------------------------------------------------------------------
# App source autogeneration
APP_FILE = $(TOP)/apps/$(APP_NAME).app.ini
VERSION_FILE = $(AUTOGEN_BUILD_DIR)/hdl/version.vhd
CONSTANT_FILE = $(AUTOGEN_BUILD_DIR)/hdl/panda_constants.vhd
APP_DEPENDS += $(wildcard common/python/*.py)
APP_DEPENDS += $(wildcard common/templates/*)
APP_DEPENDS += $(wildcard includes/*)
APP_DEPENDS += $(wildcard targets/*/*.ini)
APP_DEPENDS += $(wildcard modules/*/const/*.xdc)
APP_DEPENDS += $(wildcard modules/*/*.ini)
AUTOGEN_TARGETS += generate_app_autogen
AUTOGEN_TARGETS += $(VERSION_FILE)
AUTOGEN_TARGETS += $(CONSTANT_FILE)
# Make the built app from the ini file
$(AUTOGEN_BUILD_DIR): $(AUTOGEN_TARGETS)
generate_app_autogen: $(APP_FILE) $(APP_DEPENDS)
rm -rf $(AUTOGEN_BUILD_DIR)
$(PYTHON) -m common.python.generate_app $(AUTOGEN_BUILD_DIR) $<
.PHONY: generate_app_autogen
autogen: $(AUTOGEN_BUILD_DIR)
.PHONY: autogen
all_autogen:
$(call MAKE_ALL_APPS,autogen)
.PHONY: all_autogen
# ------------------------------------------------------------------------------
# Version symbols for FPGA bitstream generation etc
# Something like 0.1-1-g5539563-dirty
GIT_VERSION := $(shell git describe --abbrev=7 --dirty --always --tags)
# Split and append .0 to get 0.1.0, then turn into hex to get 00000100
VERSION := $(shell $(PYTHON) common/python/parse_git_version.py "$(GIT_VERSION)")
# 8 if dirty, 0 if clean
DIRTY_PRE = $(shell \
$(PYTHON) -c "print(8 if '$(GIT_VERSION)'.endswith('dirty') else 0)")
# Something like 85539563
SHA := $(DIRTY_PRE)$(shell git rev-parse --short=7 HEAD)
# Trigger rebuild of FPGA targets based on change in the git hash wrt hash stored in build dir
# If the stored hash value does not exist, or disagrees with the present
# value, or contains the 'dirty' string then the FPGA build will be considered
# out-of-date.
.PHONY: update_VER
update_VER :
ifeq ($(wildcard $(VER)), )
echo $(SHA) > $(VER)
else
if [[ $(SHA) != `cat $(VER)` ]] || [[ $(SHA) == 8* ]]; \
then echo $(SHA) > $(VER); \
fi
endif
#####################################################################
# Create VERSION_FILE
$(VERSION_FILE) : update_VER
rm -f $(VERSION_FILE)
echo 'library ieee;' >> $(VERSION_FILE)
echo 'use ieee.std_logic_1164.all;' >> $(VERSION_FILE)
echo 'package version is' >> $(VERSION_FILE)
echo -n 'constant FPGA_VERSION: std_logic_vector(31 downto 0)' >> $(VERSION_FILE)
echo ' := X"$(VERSION)";' >> $(VERSION_FILE)
echo -n 'constant FPGA_BUILD: std_logic_vector(31 downto 0)' >> $(VERSION_FILE)
echo ' := X"$(SHA)";' >> $(VERSION_FILE)
echo 'end version;' >> $(VERSION_FILE)
$(CONSTANT_FILE) : $(TOP)/common/templates/registers_server
$(PYTHON) $(TOP)/common/python/generate_constants.py "$<" > $@
# ------------------------------------------------------------------------------
# Documentation
# Generated rst sources from modules are put here, unfortunately it has to be in
# the docs dir otherwise matplotlib plot_directive screws up
DOCS_BUILD_DIR = $(TOP)/docs/build
# The html docs are built into this dir
DOCS_HTML_DIR = $(BUILD_DIR)/html
ALL_RST_FILES = $(shell find docs modules -name '*.rst')
BUILD_RST_FILES = $(wildcard docs/build/*.rst)
SRC_RST_FILES = $(filter-out $(BUILD_RST_FILES),$(ALL_RST_FILES))
$(DOCS_HTML_DIR): docs/conf.py $(SRC_RST_FILES)
$(SPHINX_BUILD) -b html docs $@
docs: $(DOCS_HTML_DIR)
.PHONY: docs
# ------------------------------------------------------------------------------
# Tests
# Test just the python framework
python_tests:
$(PYTHON) -m unittest discover -v tests.python
.PHONY: python_tests
# Test just the timing for simulations
python_timing:
$(PYTHON) -m unittest -v tests.test_python_sim_timing
.PHONY: python_timing
# Run a specific testbench using run_sim_<testbench-folder's-name>
run_sim_%: $(TOP)/common/fpga.make
mkdir -p $(FPGA_BUILD_DIR)
$(MAKE) -C $(FPGA_BUILD_DIR) -f $< VIVADO_VER=$(VIVADO_VER) \
TOP=$(TOP) TARGET_DIR=$(TARGET_DIR) APP_BUILD_DIR=$(APP_BUILD_DIR) \
TGT_BUILD_DIR=$(TGT_BUILD_DIR) XSIM_MODE=$(XSIM_MODE) \
$@
# ------------------------------------------------------------------------------
# Timing test benches using vivado to run FPGA simulations
# every modules/MODULE/BLOCK.timing.ini
TIMINGS = $(wildcard modules/*/*.timing.ini)
# MODULE for every modules/MODULE_DIR/BLOCK.timing.ini
MODULE_DIRS = $(sort $(dir $(patsubst modules/%,%,$(TIMINGS))))
# Remove trailing backslash from module directory names
MODULES = $(patsubst %/,%,$(MODULE_DIRS))
# build/hdl_timing/MODULE for every MODULES
TIMING_BUILD_DIRS = $(patsubst %,$(BUILD_DIR)/hdl_timing/%,$(MODULES))
# Make the built app from the ini file
$(BUILD_DIR)/hdl_timing/%: modules/%/*.timing.ini
rm -rf $@_tmp $@
$(PYTHON) -m common.python.generate_hdl_timing $@_tmp $^
mv -f $@_tmp $@
# Make the hdl_timing folders and run all tests, or specific modules by setting
# the MODULES argument
hdl_test: $(TIMING_BUILD_DIRS) $(BUILD_DIR)/hdl_timing/pcap carrier_ip
rm -rf $(TEST_DIR)/regression_tests
rm -rf $(TEST_DIR)/*.jou
rm -rf $(TEST_DIR)/*.log
mkdir -p $(TEST_DIR)
cd $(TEST_DIR) && . $(VIVADO) && vivado -mode batch -notrace \
-source $(TOP)/tests/hdl/regression_tests.tcl \
-tclargs $(TOP) $(TARGET_DIR) $(TGT_BUILD_DIR) $(BUILD_DIR) $(APP_BUILD_DIR) $(MODULES)
# Make the hdl_timing folders and run a single test, set TEST argument
# E.g. make TEST="clock 1" single_hdl_test
single_hdl_test: $(TIMING_BUILD_DIRS) $(BUILD_DIR)/hdl_timing/pcap carrier_ip
rm -rf $(TEST_DIR)/single_test
rm -rf $(TEST_DIR)/*.jou
rm -rf $(TEST_DIR)/*.log
mkdir -p $(TEST_DIR)
cd $(TEST_DIR) && . $(VIVADO) && vivado -mode batch -notrace \
-source $(TOP)/tests/hdl/single_test.tcl -tclargs \
-tclargs $(TOP) $(TARGET_DIR) $(TGT_BUILD_DIR) $(BUILD_DIR) $(APP_BUILD_DIR) $(TEST)
# Make the hdl_timing folders without running tests
hdl_timing: $(TIMING_BUILD_DIRS)
.PHONY: hdl_timing
# ------------------------------------------------------------------------------
# FPGA build
# The following phony targets are passed straight to the FPGA sub-make programme
FPGA_TARGETS = fpga-all fpga-bit carrier_fpga carrier_ip ps_core \
fsbl devicetree boot u-boot dts xsct sw_clean u-boot-src \
dtc atf ip_clean ps_clean
$(FPGA_TARGETS): $(TOP)/common/fpga.make $(AUTOGEN_BUILD_DIR)
mkdir -p $(FPGA_BUILD_DIR)
mkdir -p $(TGT_BUILD_DIR)
ifdef SKIP_FPGA_BUILD
@echo Skipping FPGA build
else
@echo building FPGA
$(MAKE) -C $(FPGA_BUILD_DIR) -f $< VIVADO_VER=$(VIVADO_VER) \
TOP=$(TOP) TARGET_DIR=$(TARGET_DIR) APP_BUILD_DIR=$(APP_BUILD_DIR) \
TGT_BUILD_DIR=$(TGT_BUILD_DIR) VIVADO_MODE=$(VIVADO_MODE) \
VER=$(VER) TARGET=$(TARGET) GIT_VERSION=$(GIT_VERSION) \
ZIP_BUILD_DIR=$(BUILD_DIR) $@
endif
.PHONY: $(FPGA_TARGETS)
# Targets to launch and edit vivado projects in interactive mode
# Targets : edit_ps_bd ; edit_ips ; carrier-fpga_gui
edit_ps_bd: ps_core
cd $(TGT_BUILD_DIR)/panda_ps; \
. $(VIVADO) && vivado -mode gui $(PS_PROJ)
edit_ips: carrier_ip
cd $(TGT_BUILD_DIR)/ip_repo && \
. $(VIVADO) && vivado -mode gui $(IP_PROJ)
carrier-fpga_gui: VIVADO_MODE=gui
ifeq ($(wildcard $(TOP_PROJ)), )
carrier-fpga_gui: carrier_fpga
else
carrier-fpga_gui :
cd $(FPGA_BUILD_DIR); \
. $(VIVADO) && vivado -mode $(VIVADO_MODE) $(TOP_PROJ)
endif
.PHONY: edit_ps_bd edit_ips carrier-fpga_gui
# ------------------------------------------------------------------------------
# Build installation package
ZPKG_LIST = targets/$(TARGET)/etc/panda-fpga.list
ZPKG_VERSION = $(APP_NAME)-$(GIT_VERSION)
ZPKG_FILE = $(BUILD_DIR)/panda-fpga@$(ZPKG_VERSION).zpg
ZPKG_DEPENDS += fpga-bit
ZPKG_DEPENDS += $(APP_BUILD_DIR)/ipmi.ini
ZPKG_DEPENDS += $(APP_BUILD_DIR)/extensions
ZPKG_DEPENDS += $(DOCS_HTML_DIR)
$(APP_BUILD_DIR)/ipmi.ini: $(APP_FILE)
$(PYTHON) -m common.python.copy_file_in_modules \
--fallback $(TOP)/common/templates/default_ipmi.ini \
$(TOP) $< ipmi.ini $@
$(APP_BUILD_DIR)/extensions: $(APP_FILE)
rm -rf $@
mkdir -p $@
$(PYTHON) -m common.python.make_extensions $(TOP) $< $(TARGET) $@
# Unconditionally rebuild the extensions and ipmi.ini files. This is cheap and
# the result is more predictable
.PHONY: $(APP_BUILD_DIR)/ipmi.ini $(APP_BUILD_DIR)/extensions
$(ZPKG_FILE): $(ZPKG_LIST) $(ZPKG_DEPENDS)
$(MAKE_ZPKG) -t $(TOP) -b $(APP_BUILD_DIR) -d $(BUILD_DIR) \
$< $(ZPKG_VERSION)
zpkg: $(ZPKG_FILE)
.PHONY: zpkg
all-zpkg:
$(call MAKE_ALL_APPS, zpkg)
.PHONY: all-zpkg
# ------------------------------------------------------------------------------
# Clean
# Removes the built stuff, but not the built FPGA IP
clean:
rm -rf $(BUILD_DIR)/apps
.PHONY: clean
clean-all:
-chmod -R +w $(BUILD_DIR)/src
rm -rf $(BUILD_DIR) $(DOCS_BUILD_DIR) *.zpg
find -name '*.pyc' -delete
.PHONY: clean-all