-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMakefile
More file actions
360 lines (313 loc) · 13.9 KB
/
Copy pathMakefile
File metadata and controls
360 lines (313 loc) · 13.9 KB
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
352
353
354
355
356
357
358
359
360
# =============================================================================
# ADMM FPGA - Top-Level Makefile
# =============================================================================
# Targets:
# all - Build everything (traj -> headers -> HLS -> Vivado -> bitstream)
# traj - Generate deterministic trajectory references
# headers - Generate data.h from Python script
# hls - Build HLS IP
# vivado - Run Vivado synthesis + implementation
# bit - Generate bitstream only (assumes impl done)
# program - Program FPGA via JTAG
# flash - Write to SPI flash
# program-file - Program FPGA from explicit BITSTREAM_FILE
# flash-file - Write explicit BITSTREAM_FILE to SPI flash
# sync - Rsync build/ from remote (for build-on-server, program-local workflow)
# sim - Run Vitis HLS C simulation (quick)
# sim-csim - Run Vitis HLS C simulation
# sim-cosim - Run Vitis HLS C/RTL co-simulation
# hls_closed_loop_sim - Run one HLS closed-loop simulation + plots
# clean - Clean Vivado build artifacts
# clean-hls - Clean HLS build artifacts
# clean-all - Clean everything
# =============================================================================
# Configuration
SUPPORTED_MAKE_OVERRIDE_VARS := BOARD REMOTE SSH_PORT VIVADO VITIS_HLS PYTHON HLS_CLOSED_LOOP_ARGS BITSTREAM_FILE
CMDLINE_OVERRIDE_VARS := $(sort $(foreach tok,$(MAKEOVERRIDES),$(if $(findstring =,$(tok)),$(word 1,$(subst =, ,$(tok))),)))
UNKNOWN_CMDLINE_OVERRIDE_VARS := $(filter-out $(SUPPORTED_MAKE_OVERRIDE_VARS),$(CMDLINE_OVERRIDE_VARS))
ifneq ($(strip $(UNKNOWN_CMDLINE_OVERRIDE_VARS)),)
$(error Unsupported make variable override(s): $(UNKNOWN_CMDLINE_OVERRIDE_VARS). Supported overrides: $(SUPPORTED_MAKE_OVERRIDE_VARS))
endif
BOARD ?= custom
PART := xc7a100tcsg324-1
ifeq ($(BOARD),arty)
TOP_MODULE := top_uart
else ifeq ($(BOARD),custom)
TOP_MODULE := top_spi
else
$(error Unsupported BOARD='$(BOARD)'. Use BOARD=arty or BOARD=custom)
endif
# For sync: remote repo path, e.g. user@host:~/ADMM_FPGA (path must exist on server)
REMOTE ?=
# Optional SSH port for sync (default 22): make sync REMOTE=... SSH_PORT=2222
SSH_PORT ?=
RSYNC_SSH := $(if $(SSH_PORT),-e "ssh -p $(SSH_PORT)",)
VIVADO := vivado
VITIS_HLS := v++
PYTHON := python3
BITSTREAM_FILE ?=
# Directories
PROJ_ROOT := $(shell pwd)
SCRIPTS_DIR := $(PROJ_ROOT)/scripts
BUILD_DIR := $(PROJ_ROOT)/build
HLS_DIR := $(PROJ_ROOT)/vitis_projects/ADMM
HLS_WORK_DIR := $(HLS_DIR)/ADMM
RTL_DIR := $(PROJ_ROOT)/vivado_project/vivado_project.srcs/sources_1/new
XDC_DIR := $(PROJ_ROOT)/vivado_project/vivado_project.srcs/constrs_1/new
IP_DIR := $(PROJ_ROOT)/vivado_project/vivado_project.gen/sources_1/ip/ADMM_solver_0
# Source files
HLS_SOURCES := $(HLS_DIR)/ADMM.cpp $(HLS_DIR)/ADMM.h $(HLS_DIR)/data_types.h $(HLS_DIR)/admm_runtime_config.h
RTL_SOURCES := $(wildcard $(RTL_DIR)/*.v) $(wildcard $(RTL_DIR)/*.vh)
ifeq ($(BOARD),arty)
XDC_SOURCES := $(XDC_DIR)/constraints_arty_a7.xdc
else
XDC_SOURCES := $(XDC_DIR)/constraints.xdc
endif
HEADER_SCRIPT := $(SCRIPTS_DIR)/header_generator.py
TRAJ_SCRIPT := $(SCRIPTS_DIR)/trajectory_generator.py
PARAMS_SCRIPT := $(SCRIPTS_DIR)/parameters.py
HLS_CLOSED_LOOP_SCRIPT := $(SCRIPTS_DIR)/run_hls_closed_loop_once.py
HLS_CLOSED_LOOP_ARGS ?=
# Generated files
DATA_HEADER := $(HLS_DIR)/data.h
RUNTIME_CONFIG_HEADER := $(HLS_DIR)/admm_runtime_config.h
TRAJ_REFS := $(HLS_DIR)/trajectory_refs.csv
TRAJ_HEADER := $(HLS_DIR)/traj_data.h
HLS_IP_MARKER := $(HLS_WORK_DIR)/.export_done
BITSTREAM := $(BUILD_DIR)/$(TOP_MODULE).bit
FLASH_BIN := $(BUILD_DIR)/$(TOP_MODULE).bin
BUILD_TAG := $(TOP_MODULE)_$(BOARD)
SYNTH_DCP := $(BUILD_DIR)/post_synth_$(BUILD_TAG).dcp
ROUTE_DCP := $(BUILD_DIR)/post_route_$(BUILD_TAG).dcp
# =============================================================================
# Main Targets
# =============================================================================
.PHONY: all traj headers hls vivado bit program flash program-file flash-file sync sim sim-csim sim-cosim hls_closed_loop_sim clean clean-hls clean-all help
all: $(BITSTREAM)
@echo "========================================="
@echo "Build complete!"
@echo "BOARD: $(BOARD)"
@echo "TOP: $(TOP_MODULE)"
@echo "Bitstream: $(BITSTREAM)"
@echo "Flash bin: $(FLASH_BIN)"
@echo "========================================="
help:
@echo "ADMM FPGA Build System"
@echo ""
@echo "Targets:"
@echo " all - Build everything (default)"
@echo " traj - Generate deterministic trajectory references"
@echo " headers - Generate data.h"
@echo " hls - Build HLS IP"
@echo " vivado - Synthesis + Implementation"
@echo " bit - Generate bitstream"
@echo " program - Program FPGA via JTAG"
@echo " flash - Write to SPI flash"
@echo " program-file - Program FPGA from explicit BITSTREAM_FILE"
@echo " flash-file - Write explicit BITSTREAM_FILE to SPI flash"
@echo " sim - Vitis HLS C simulation (quick)"
@echo " sim-csim - Vitis HLS C simulation"
@echo " sim-cosim - Vitis HLS C/RTL co-simulation (requires HLS build)"
@echo " hls_closed_loop_sim - One HLS closed-loop simulation + plots"
@echo " sync - Rsync build/ from remote (e.g. make sync REMOTE=user@host:~/ADMM_FPGA [SSH_PORT=2222])"
@echo " clean - Clean Vivado build"
@echo " clean-hls - Clean HLS build"
@echo " clean-all - Clean everything"
@echo ""
@echo "Examples:"
@echo " make # Full build"
@echo " make hls # Rebuild HLS only"
@echo " make vivado # Rebuild Vivado only"
@echo " make sim # Vitis HLS C simulation"
@echo " make sim-cosim # Vitis HLS C/RTL co-simulation"
@echo " make hls_closed_loop_sim"
@echo " make hls_closed_loop_sim HLS_CLOSED_LOOP_ARGS='--sim-duration-s 8 --traj-start-step 60'"
@echo " make program # Program FPGA"
@echo " make flash-file BITSTREAM_FILE=/path/to/top_spi.bit"
@echo " make sync REMOTE=user@host:~/ADMM_FPGA [SSH_PORT=2222] # Fetch build from server"
# =============================================================================
# Trajectory Generation
# =============================================================================
traj: $(TRAJ_HEADER)
$(TRAJ_REFS) $(TRAJ_HEADER): $(TRAJ_SCRIPT) $(SCRIPTS_DIR)/crazyloihimodel.py $(PARAMS_SCRIPT)
@echo "========================================="
@echo "Generating trajectory references..."
@echo "========================================="
cd $(SCRIPTS_DIR) && $(PYTHON) trajectory_generator.py
# =============================================================================
# Header Generation
# =============================================================================
headers: $(DATA_HEADER) $(RUNTIME_CONFIG_HEADER)
$(DATA_HEADER) $(RUNTIME_CONFIG_HEADER): $(HEADER_SCRIPT) $(SCRIPTS_DIR)/crazyloihimodel.py $(PARAMS_SCRIPT) $(TRAJ_HEADER)
@echo "========================================="
@echo "Generating headers..."
@echo "========================================="
cd $(SCRIPTS_DIR) && $(PYTHON) header_generator.py
@touch $(DATA_HEADER)
@touch $(RUNTIME_CONFIG_HEADER)
# =============================================================================
# HLS Build
# =============================================================================
hls: $(HLS_IP_MARKER)
$(HLS_IP_MARKER): $(HLS_SOURCES) $(DATA_HEADER)
@echo "========================================="
@echo "Building HLS IP..."
@echo "========================================="
cd $(HLS_DIR) && $(MAKE) build
cd $(HLS_DIR) && $(MAKE) export
@mkdir -p $(dir $(HLS_IP_MARKER))
@touch $(HLS_IP_MARKER)
# =============================================================================
# Vivado Build
# =============================================================================
vivado: $(ROUTE_DCP)
# Synthesis
$(SYNTH_DCP): $(RTL_SOURCES) $(XDC_SOURCES) $(HLS_IP_MARKER)
@echo "========================================="
@echo "Running Vivado Synthesis (BOARD=$(BOARD), TOP=$(TOP_MODULE))..."
@echo "========================================="
@mkdir -p $(BUILD_DIR)/logs $(BUILD_DIR)/reports
$(VIVADO) -mode batch \
-notrace \
-log $(BUILD_DIR)/logs/synth.log \
-journal $(BUILD_DIR)/logs/synth.jou \
-source $(SCRIPTS_DIR)/synth.tcl \
-tclargs $(TOP_MODULE) $(notdir $(XDC_SOURCES)) $(notdir $(SYNTH_DCP))
# Implementation (Place & Route)
$(ROUTE_DCP): $(SYNTH_DCP)
@echo "========================================="
@echo "Running Vivado Implementation..."
@echo "========================================="
$(VIVADO) -mode batch \
-notrace \
-log $(BUILD_DIR)/logs/impl.log \
-journal $(BUILD_DIR)/logs/impl.jou \
-source $(SCRIPTS_DIR)/impl.tcl \
-tclargs $(notdir $(SYNTH_DCP)) $(notdir $(ROUTE_DCP))
# =============================================================================
# Bitstream Generation
# =============================================================================
bit: $(BITSTREAM)
$(BITSTREAM): $(ROUTE_DCP)
@echo "========================================="
@echo "Generating Bitstream ($(TOP_MODULE))..."
@echo "========================================="
$(VIVADO) -mode batch \
-notrace \
-log $(BUILD_DIR)/logs/bitstream.log \
-journal $(BUILD_DIR)/logs/bitstream.jou \
-source $(SCRIPTS_DIR)/bitstream.tcl \
-tclargs $(TOP_MODULE) $(notdir $(ROUTE_DCP))
# =============================================================================
# Vitis HLS Simulation
# =============================================================================
sim: sim-csim
sim-csim: $(DATA_HEADER)
@echo "========================================="
@echo "Running Vitis HLS C simulation..."
@echo "========================================="
cd $(HLS_DIR) && $(MAKE) csim
sim-cosim: $(HLS_IP_MARKER)
@echo "========================================="
@echo "Running Vitis HLS C/RTL co-simulation..."
@echo "========================================="
cd $(HLS_DIR) && $(MAKE) cosim
hls_closed_loop_sim: $(DATA_HEADER)
@echo "========================================="
@echo "Running HLS closed-loop simulation..."
@echo "========================================="
cd $(PROJ_ROOT) && $(PYTHON) $(HLS_CLOSED_LOOP_SCRIPT) $(HLS_CLOSED_LOOP_ARGS)
# =============================================================================
# Programming (no build dependency: use existing bitstream, e.g. after 'make sync')
# =============================================================================
program:
@if [ ! -f $(BITSTREAM) ]; then \
echo "Error: $(BITSTREAM) not found. Run 'make' or 'make sync' first."; exit 1; \
fi
@echo "========================================="
@echo "Programming FPGA (BOARD=$(BOARD), TOP=$(TOP_MODULE))..."
@echo "========================================="
$(VIVADO) -mode batch \
-notrace \
-source $(SCRIPTS_DIR)/program.tcl \
-tclargs $(TOP_MODULE)
flash:
@if [ ! -f $(BITSTREAM) ]; then \
echo "Error: $(BITSTREAM) not found. Run 'make' or 'make sync' first."; exit 1; \
fi
@echo "========================================="
@echo "Writing to SPI Flash (BOARD=$(BOARD), TOP=$(TOP_MODULE))..."
@echo "========================================="
$(VIVADO) -mode batch \
-notrace \
-source $(SCRIPTS_DIR)/program_flash.tcl \
-tclargs $(TOP_MODULE)
program-file:
@if [ -z "$(BITSTREAM_FILE)" ]; then \
echo "Usage: make program-file BITSTREAM_FILE=/path/to/bitstream.bit"; exit 1; \
fi
@if [ ! -f "$(BITSTREAM_FILE)" ]; then \
echo "Error: $(BITSTREAM_FILE) not found."; exit 1; \
fi
@echo "========================================="
@echo "Programming FPGA from $(BITSTREAM_FILE)"
@echo "========================================="
$(VIVADO) -mode batch \
-notrace \
-source $(SCRIPTS_DIR)/program_file.tcl \
-tclargs "$(BITSTREAM_FILE)"
flash-file:
@if [ -z "$(BITSTREAM_FILE)" ]; then \
echo "Usage: make flash-file BITSTREAM_FILE=/path/to/bitstream.bit"; exit 1; \
fi
@if [ ! -f "$(BITSTREAM_FILE)" ]; then \
echo "Error: $(BITSTREAM_FILE) not found."; exit 1; \
fi
@echo "========================================="
@echo "Writing $(BITSTREAM_FILE) to SPI Flash (BOARD=$(BOARD), TOP=$(TOP_MODULE))..."
@echo "========================================="
$(VIVADO) -mode batch \
-notrace \
-source $(SCRIPTS_DIR)/program_flash.tcl \
-tclargs $(TOP_MODULE) "$(BITSTREAM_FILE)"
$(FLASH_BIN): $(BITSTREAM)
@echo "Flash binary already generated: $(FLASH_BIN)"
# =============================================================================
# Sync from remote (build on server, program locally)
# =============================================================================
sync:
@if [ -z "$(REMOTE)" ]; then \
echo "Usage: make sync REMOTE=user@hostname:path/to/ADMM_FPGA"; \
echo "Example: make sync REMOTE=me@buildserver:~/ADMM_FPGA"; \
exit 1; \
fi
@echo "========================================="
@echo "Syncing build/ from $(REMOTE)..."
@echo "========================================="
@mkdir -p $(BUILD_DIR)
rsync -avz --progress $(RSYNC_SSH) $(REMOTE)/build/ $(BUILD_DIR)/
# =============================================================================
# Clean Targets
# =============================================================================
clean:
@echo "Cleaning Vivado build..."
rm -rf $(BUILD_DIR)
rm -rf $(PROJ_ROOT)/.Xil
rm -rf $(PROJ_ROOT)/*.log $(PROJ_ROOT)/*.jou
rm -rf $(SCRIPTS_DIR)/*.log $(SCRIPTS_DIR)/*.jou
clean-hls:
@echo "Cleaning HLS build..."
cd $(HLS_DIR) && $(MAKE) clean
rm -f $(HLS_IP_MARKER)
clean-all: clean clean-hls
@echo "All build artifacts cleaned."
# =============================================================================
# Utility
# =============================================================================
.PHONY: report
report:
@echo "=== Utilization Report ==="
@cat $(BUILD_DIR)/reports/post_route_utilization.rpt 2>/dev/null || echo "No report found"
@echo ""
@echo "=== Timing Summary ==="
@cat $(BUILD_DIR)/reports/post_route_timing.rpt 2>/dev/null | head -50 || echo "No report found"