summaryrefslogtreecommitdiff
path: root/mk/quartus.mk
blob: ae26a7d641e8e9ca3d9a720161dff80cfd4604c9 (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
# Based on github:alexforencich/verilog-ethernet:example/DE2-115/fpga/common/quartus.mk

targets += syn

quartus_qsf = $(obj)/$(quartus_top).qsf
quartus_qpf = $(obj)/$(quartus_top).qpf
quartus_run = cd $(obj) && $(QUARTUS)

quartus_top = $(call per_target,quartus_top)
quartus_device = $(call per_target,quartus_device)
quartus_family = "$(call per_target,quartus_family)"

quartus_rtl = $(call per_target,quartus_rtl)
quartus_sdc = $(call per_target,quartus_sdc)
quartus_tcl = $(call per_target,quartus_tcl)
quartus_qip = $(call per_target,quartus_qip)
quartus_qsys = $(call per_target,quartus_qsys)
quartus_rtl_include = $(call per_target,quartus_rtl_include)

quartus_platforms = $(call per_target,quartus_platforms)
quartus_src_files = $(quartus_rtl) $(quartus_sdc) $(quartus_qip) $(quartus_qsys) $(quartus_tcl)

quartus_plat_qip = $(foreach plat,$(quartus_platforms),$(call quartus_plat_path,$(plat)))
quartus_plat_path = qsys/$(1)/synthesis/$(basename $(notdir $(core_info/$(1)/qsys_platform))).qip

define target/syn/prepare
  flow/type := syn
endef

define target/syn/setup
  $(call target_var,quartus_top) := $$(call require_core_var,$$(rule_top),rtl_top)
  $(call target_var,quartus_device) := $$(call require_core_var,$$(rule_top),altera_device)
  $(call target_var,quartus_family) := $$(call require_core_var,$$(rule_top),altera_family)
endef

define target/syn/rules
  deps := $$(dep_tree/$$(rule_top))

  $(call target_var,quartus_rtl) := \
    $$(foreach dep,$$(deps),$$(call core_paths,$$(dep),rtl_files))

  $(call target_var,quartus_rtl_include) := \
    $$(foreach dep,$$(deps),$$(call core_paths,$$(dep),rtl_include_dirs))

  $(call target_var,quartus_sdc) := \
    $$(foreach dep,$$(deps),$$(call core_paths,$$(dep),sdc_files))

  $(call target_var,quartus_qip) := \
    $$(foreach dep,$$(deps),$$(call core_paths,$$(dep),qip_files))

  $(call target_var,quartus_tcl) := \
    $$(foreach dep,$$(deps),$$(call core_paths,$$(dep),qsf_files))

  $(call target_var,quartus_platforms) := \
    $$(foreach dep,$$(deps),$$(if $$(core_info/$$(dep)/qsys_platform),$$(dep)))

  $(call target_var,quartus_qsys) := \
	$$(foreach dep,$$(quartus_platforms),$$(call core_paths,$$(dep),qsys_platform))

  .PHONY: $$(rule_top_path)/syn

  $$(rule_top_path)/syn: $$(obj)/asm.stamp

  $$(obj)/asm.stamp: $$(obj)/sta.stamp
	$$(call run,ASM) $$(quartus_run)_asm $$(quartus_top)
	@touch $$@

  $$(obj)/sta.stamp: $$(obj)/fit.stamp
	$$(call run,STA) $$(quartus_run)_sta $$(quartus_top)
	@touch $$@

  $$(obj)/fit.stamp: $$(obj)/map.stamp
	$$(call run,FIT) $$(quartus_run)_fit --part=$$(quartus_device) $$(quartus_top)
	@touch $$@

  $$(obj)/map.stamp: $$(quartus_qpf)
	$$(call run,MAP) $$(quartus_run)_map --family=$(quartus_family) $$(quartus_top)
	@touch $$@

  $$(quartus_qsf) $$(quartus_qpf) &: \
    $$(top_stamp) $$(quartus_src_files) \
    $$(addprefix $$(obj)/,$$(quartus_plat_qip))
	$$(call run,QSF) \
	rm -f $$(quartus_qsf) $$(quartus_qpf) && \
	cd $$(obj) && \
	$$(QUARTUS)_sh \
		--prepare -f $$(quartus_family) -d $$(quartus_device) \
		-t $$(quartus_top) $$(quartus_top) && \
	exec >>$$(quartus_top).qsf && \
	echo -e "\n\n# Source files" && \
	assignment() { echo set_global_assignment -name $$$$1 $$$$2; } && \
	assignment_list() { \
		title="$$$$1"; \
		name="$$$$2"; \
		shift 2; \
		echo -e "\n# $$$$title" && \
		for x in $$$$@; do assignment "$$$${name}" "$$$$x"; done \
	} && \
	for x in $$(quartus_rtl); do \
		case $$$${x##*.} in \
			[Vv])         name=VERILOG_FILE ;; \
			[Ss][Vv])     name=SYSTEMVERILOG_FILE ;; \
			[Vv][Hh][Dd]) name=VHDL_FILE ;; \
			*)            name=SOURCE_FILE ;; \
		esac; \
		assignment "$$$$name" "src/$$$$x"; \
	done && \
	assignment_list "Search paths" SEARCH_PATH $$(addprefix src/,$$(quartus_rtl_include)) && \
	assignment_list "Constraint files" SDC_FILE $$(addprefix src/,$$(quartus_sdc)) && \
	assignment_list "IPs" QIP_FILE $$(addprefix src/,$$(quartus_qip)) && \
	assignment_list "Platform IPs" QIP_FILE $$(quartus_plat_qip) && \
	assignment_list "Platforms" QSYS_FILE $$(addprefix src/,$$(quartus_qsys)) && \
	for x in $$(quartus_tcl); do printf "\n#\n# TCL file %s\n#\n" "$$$$x"; cat "src/$$$$x"; done

  $(call target_entrypoint,$(patsubst %,$$(obj)/%.stamp,map fit sta asm))

  $$(foreach plat,$$(quartus_platforms),$$(eval $$(call quartus_qsys_rules,$$(plat))))
endef

define quartus_qsys_rules
  qip_file := $$(obj)/$$(call quartus_plat_path,$(1))
  qsys_file := $$(call core_paths,$(1),qsys_platform)

  $$(qip_file): qsys_file := $$(qsys_file)
  $$(qip_file): $$(call core_stamp,$(1)) $$(qsys_file)
	$$(call run,QSYS,$$(qsys_file)) $$(QSYS_GENERATE) \
		-syn --part=$$(quartus_device) --output-directory=$$(obj)/qsys/$(1) $$(qsys_file)
endef