summaryrefslogtreecommitdiff
path: root/mk
diff options
context:
space:
mode:
Diffstat (limited to 'mk')
-rw-r--r--mk/build.mk2
-rw-r--r--mk/cores.mk10
-rw-r--r--mk/quartus.mk128
-rw-r--r--mk/tools.mk2
-rw-r--r--mk/top.mk1
-rw-r--r--mk/verilator.mk12
6 files changed, 146 insertions, 9 deletions
diff --git a/mk/build.mk b/mk/build.mk
index 40b2b9e..33bd81b 100644
--- a/mk/build.mk
+++ b/mk/build.mk
@@ -38,7 +38,7 @@ define setup_obj
$$(obj): export CONTENTS := $$(build_id_text)
$$(obj):
- @mkdir -p $$@ && echo -n "$$$$CONTENTS" >$$@/build-vars
+ @mkdir -p $$@ && echo -n "$$$$CONTENTS" >$$@/build-vars && ln -Tsf ../../../ $$@/src
endef
define find_command_lazy
diff --git a/mk/cores.mk b/mk/cores.mk
index 7ce2e47..238ece4 100644
--- a/mk/cores.mk
+++ b/mk/cores.mk
@@ -17,6 +17,16 @@ core_paths = \
$(let prefix,$(core_info/$(1)/workdir), \
$(addprefix /$(if $(prefix),$(prefix)/),$(core_info/$(1)/$(2)))))))
+require_core_paths = \
+ $(strip \
+ $(let val,$(strip $(call core_paths,$(1),$(2))), \
+ $(if $(val),$(val),$(error core '$(1)' must define '$(2)'))))
+
+require_core_var = \
+ $(strip \
+ $(let val,$(core_info/$(1)/$(2)), \
+ $(if $(val),$(val),$(error core '$(1)' must define '$(2)'))))
+
define add_core
this := core_info/$(1)
diff --git a/mk/quartus.mk b/mk/quartus.mk
new file mode 100644
index 0000000..ae26a7d
--- /dev/null
+++ b/mk/quartus.mk
@@ -0,0 +1,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
diff --git a/mk/tools.mk b/mk/tools.mk
index 9f3734e..9df3eff 100644
--- a/mk/tools.mk
+++ b/mk/tools.mk
@@ -2,6 +2,8 @@ define find_tools_lazy
$(call find_command_lazy,cocotb-config,COCOTB_CONFIG)
$(call find_command_lazy,genhtml,GENHTML)
$(call find_command_lazy,pkg-config,PKG_CONFIG)
+ $(call find_command_lazy,qsys-generate,QSYS_GENERATE)
+ $(call find_command_lazy,quartus,QUARTUS)
$(call find_command_lazy,verilator,VERILATOR)
$(call shell_defer,cocotb_share,$$(COCOTB_CONFIG) --share)
diff --git a/mk/top.mk b/mk/top.mk
index 6db6abb..aede1e5 100644
--- a/mk/top.mk
+++ b/mk/top.mk
@@ -31,6 +31,7 @@ include mk/cocotb.mk
include mk/cores.mk
include mk/cov.mk
include mk/output.mk
+include mk/quartus.mk
include mk/target.mk
include mk/tools.mk
include mk/verilator.mk
diff --git a/mk/verilator.mk b/mk/verilator.mk
index 56d8783..2692863 100644
--- a/mk/verilator.mk
+++ b/mk/verilator.mk
@@ -17,10 +17,7 @@ endef
define target/sim/setup
$(setup_verilator_target)
- $$(call target_var,vl_main) := $$(strip $$(call core_paths,$$(rule_top),vl_main))
- ifeq (,$$(vl_main))
- $$(error core '$$(rule_top)' does not define vl_main)
- endif
+ $$(call target_var,vl_main) := $$(strip $$(call require_core_paths,$$(rule_top),vl_main))
endef
define target/sim/rules
@@ -123,8 +120,8 @@ endef
verilator_src_args = \
$(strip \
- $(let rtl_top,$(core_info/$(rule_top)/rtl_top), \
- $(if $(rtl_top),--top $(rtl_top),$(error core '$(rule_top)' must define rtl_top)) \
+ $(let rtl_top,$(call require_core_var,$(rule_top),rtl_top), \
+ --top $(rtl_top) \
$(foreach dep,$(dep_tree/$(rule_top)), \
$(let prefix,$(core_info/$(dep)/workdir)/, \
$(foreach rtl_dir,$(call core_paths,$(dep),rtl_dirs), \
@@ -132,6 +129,5 @@ verilator_src_args = \
$(foreach include_dir,$(call core_paths,$(dep),rtl_include_dirs), \
-I$(include_dir)) \
$(foreach src_file,$(call core_paths,$(dep),rtl_files) $(call core_paths,$(dep),vl_files), \
- $(src_file)))) \
- $(if $(core_info/$(rule_top)/rtl_files),,$(rtl_top))) \
+ $(src_file))))) \
$(if $(vl_main),$(vl_main),$(error $$(vl_main) not defined by target '$(rule_target)')))