summaryrefslogtreecommitdiff
path: root/mk/quartus.mk
blob: 81ec420def8916e46233dd25dae04dc34c1a64bc (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
# 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))

  explicit_rtl := $$(foreach dep,$$(deps),$$(call core_paths,$$(dep),rtl_files))

  $(call target_var,quartus_rtl) := \
    $$(explicit_rtl) \
    $$(filter-out $$(explicit_rtl), \
      $$(foreach rtl_dir,$$(foreach dep,$$(deps),$$(call core_paths,$$(dep),rtl_dirs)), \
        $$(filter %.v %.sv %.vhd,$$(wildcard $$(rtl_dir)/*))))

  $(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
	$$(if $$(enable_gui),$$(call run,GUI) $$(quartus_run) $$(quartus_top).qpf)

  $$(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 core_objs,$$(rule_top),obj_deps)
	$$(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