################################################
#
# SPDX-License-Identifier: MIT-0
# SPDX-FileCopyrightText: Copyright (C) 2025 Altera Corporation
#
################################################
#
# Makefile to Manage Quartus Prime Pro / QSys Design
#
################################################

SHELL := /bin/bash

.SECONDEXPANSION:
.SUFFIXES:
.DELETE_ON_ERROR:

################################################
# Tools

CAT := cat
CD := cd
CHMOD := chmod
CP := cp -rf
DATE := date
ECHO := echo
FIND := find
GREP := grep
HEAD := head
MKDIR := mkdir -p
MV := mv
RM := rm -rf
SED := sed
TAR := tar
TOUCH := touch
WHICH := which

# Helpful Macros
SPACE := $(empty) $(empty)

# Convert upper case string to lower case string
lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1))))))))))))))))))))))))))

ifndef COMSPEC
ifdef ComSpec
COMSPEC = $(ComSpec)
endif # ComSpec
endif # COMSPEC

ifdef COMSPEC # if Windows OS
IS_WINDOWS_HOST := 1
endif

ifeq ($(IS_WINDOWS_HOST),1)
ifneq ($(shell $(WHICH) cygwin1.dll 2>/dev/null),)
IS_CYGWIN_HOST := 1
endif
endif

ifneq ($(shell $(WHICH) quartus 2>/dev/null),)
HAVE_QUARTUS := 1
endif

ifneq ($(shell $(WHICH) armclang 2>/dev/null),)
HAVE_C_COMPILER := 1
else ifneq ($(shell $(WHICH) aarch64-none-linux-gnu-gcc 2>/dev/null),)
HAVE_C_COMPILER := 1
CROSS_COMPILE ?= "aarch64-none-linux-gnu-"
else ifneq ($(shell $(WHICH) aarch64-linux-gnu-gcc 2>/dev/null),)
HAVE_C_COMPILER := 1
CROSS_COMPILE ?= "aarch64-linux-gnu-"
endif

ifeq ($(HAVE_QUARTUS),1)
HAVE_QSYS := 1
endif

################################################


################### Start of Design Settings ####################################################
#
# Design Settings
#  If you change and design settings, you need
#  to run "make scrub_clean" followed by
#  "make generate_from_tcl_internal" for the settings
#  to be applied
#

####
# Dependency
INTEL_CUSTOM_IP_TARBALL = "intel_custom_ip_20210323_04233.tar.gz"
INTEL_CUSTOM_IP_LINK = "https://releases.rocketboards.org/release/intel_custom_ip/$(INTEL_CUSTOM_IP_TARBALL)"

# Family and Device
# QUARTUS_DEVICE to Board Revision Mapping

####
# User Settings
# Valid BOARD_TYPE: devkit, pcie_devkit, devkit_fp82, devkit_fm87, devkit_fm86
BOARD_TYPE ?= DK-SI-AGF014E

#Loading board configuration
ifeq ($(BOARD_TYPE), DK-DEV-AGM039FES)
BOARD_TYPE = devkit_fp82
else ifeq ($(BOARD_TYPE), DK-SI-AGI027FB)
BOARD_TYPE = devkit_fm87
else ifeq ($(BOARD_TYPE), DK-DEV-AGF027F1ES)
BOARD_TYPE = devkit_fm86
endif

include board/board_$(BOARD_TYPE)_make_config.inc

# System initilization mode: fpga, hps
BOOTS_FIRST ?= hps

# HPS JTAG MODE: combined, separate
HPS_JTAG_MODE ?= combined

# Board Revision: A0, A1
BOARD_REV ?= A1

# H2F F2H Loopback Enable: 0, 1
LOOPBACK_EN ?= 0

# HPS EMIF Enabled: 0, 1
HPS_EMIF_EN ?= 1

# HPS EMIF ECC is not support for REVA Agilex
ENABLE_HPS_EMIF_ECC ?= 1

# Enable Watchdog Reset: 0, 1
ENABLE_WATCHDOG_RST ?= 1

# Supported watchdog reset action: cold, warm, remote_update
WATCHDOG_RST_ACTION ?= cold

# Enable Partial Reconfiguration: 0, 1
# Not applicable to FM6 RevA (AGFB014R24A3E3VR0)
ENABLE_PARTIAL_RECONFIGURATION ?= 0

# Enable JOP for remote debug: 0, 1
ENABLE_JOP ?= 0

# Enable NIOSV Subsystem
ENABLE_NIOSV_SUBSYS ?= 0

####
# Default Assignment (Do not modify)
QUARTUS_DEVICE_FAMILY := Agilex
# Prelimenary Device
#FM68 (cypress)
#QUARTUS_DEVICE ?= AGFB014R17A2E2VR0

#FM67 (lookout, pyramid, mcgowan)
#QUARTUS_DEVICE ?= AGIB014R29C1E2VR0

#FM85 (lookout, pyramid, mcgowan)
#QUARTUS_DEVICE ?= AGIB027R29A1E2VR0

#FM61 (devkit, mUDV1, mUDV2, char)
#QUARTUS_DEVICE ?= AGFB014R24A3E3VR0
#QUARTUS_DEVICE ?= AGFB014R24A2E2VR1
#QUARTUS_DEVICE ?= AGFB014R24B2E2V

#FP82
#QUARTUS_DEVICE ?= AGMF039R47A1E2VR0

# Board Power Management. Support board devkit is supported: linear, enpirion
BOARD_PWRMGT ?= enpirion

# Publicly Available DC: devkit_dc_oobe, devkit_dc_nand, devkit_dc_emmc
ifeq ($(BOARD_TYPE), pcie_devkit)
DAUGHTER_CARD = pcie_devkit
endif

DAUGHTER_CARD ?= devkit_dc_oobe

# Enable ETILE 1588v2 PTP
ENABLE_ETILE_1588 ?= 0

# Enable for Etile 10Gbe or 25Gbe PTP Subsystem
HPS_ETILE_1588_25GBE_EN ?= 0
HPS_ETILE_1588_10GBE_EN ?= 0

# Enable Signal Tap
ENABLE_SIGNALTAP_CROSS_TRIGGER := 0

# Enable PCIe
ENABLE_PCIE ?= 0
PCIE_GEN ?= 4
PCIE_COUNT ?= 4

# Quartus Partial Reconfiguration
ENABLE_PARTIAL_RECONFIGURATION_TESTING ?= 0

# Enable SGMII (HPS EMAC + TSE PHY)
HPS_ENABLE_SGMII ?= 0

# Enable SGMII (HPS EMAC + TSE PHY)
HPS_SGMII_EMAC1_EN ?= 1
HPS_SGMII_EMAC2_EN ?= 0

# Option to enable/disable HPS_F2S_IRQ
HPS_F2S_IRQ_EN ?= 1

# Option to enable/disable HPS_STM
HPS_STM_EN ?= 1

#  Option to enable/disable SGPIO
FPGA_SGPIO_EN ?= 0

# Board Config Scheme
CONFIG_SCHEME ?= ACTIVE\ SERIAL\ X4

# Option to enable/disable HBM subsystem
HBM_EN ?= 0

# Default value for OCM_DATAWIDTH
OCM_DATAWIDTH ?= 128

# Default value for HPS_EMIF_RATE
HPS_EMIF_RATE ?= RATE_QUARTER

###########################################################################################

ifneq ($(OCM_DATAWIDTH),)
QUARTUS_TCL_ARGS += ocm_datawidth $(OCM_DATAWIDTH)
QSYS_TCL_CMDS += set ocm_datawidth $(OCM_DATAWIDTH);
endif

ifneq ($(HBM_EN),)
QUARTUS_TCL_ARGS += hbm_en $(HBM_EN)
QSYS_TCL_CMDS += set hbm_en $(HBM_EN);
endif

ifneq ($(CONFIG_SCHEME),)
QUARTUS_TCL_ARGS += config_scheme $(CONFIG_SCHEME)
QSYS_TCL_CMDS += set config_scheme $(CONFIG_SCHEME);
endif

ifneq ($(QUARTUS_DEVICE_FAMILY),)
QUARTUS_TCL_ARGS += devicefamily $(QUARTUS_DEVICE_FAMILY)
QSYS_TCL_CMDS += set devicefamily $(QUARTUS_DEVICE_FAMILY);

QUARTUS_TCL_ARGS += project_name ghrd_$(call lc,$(QUARTUS_DEVICE))
QSYS_TCL_CMDS += set project_name ghrd_$(call lc,$(QUARTUS_DEVICE));
endif

ifneq ($(QUARTUS_DEVICE),)
QUARTUS_TCL_ARGS += device $(QUARTUS_DEVICE)
QSYS_TCL_CMDS += set device $(QUARTUS_DEVICE);
endif

ifneq ($(BOARD_TYPE),)
QUARTUS_TCL_ARGS += board $(BOARD_TYPE)
QSYS_TCL_CMDS += set board $(BOARD_TYPE);
endif

ifneq ($(BOARD_PWRMGT),)
#   "linear" or "enpirion"
QUARTUS_TCL_ARGS += board_pwrmgt $(BOARD_PWRMGT)
QSYS_TCL_CMDS += set board_pwrmgt $(BOARD_PWRMGT);
endif

ifneq ($(HPS_EMIF_TYPE),)
QUARTUS_TCL_ARGS += hps_emif_type $(HPS_EMIF_TYPE)
QSYS_TCL_CMDS += set hps_emif_type $(HPS_EMIF_TYPE);
endif

ifneq ($(HPS_EMIF_WIDTH),)
QUARTUS_TCL_ARGS += hps_emif_width $(HPS_EMIF_WIDTH)
QSYS_TCL_CMDS += set hps_emif_width $(HPS_EMIF_WIDTH);
endif

ifneq ($(F2H_WIDTH),)
QUARTUS_TCL_ARGS += f2h_width $(F2H_WIDTH)
QSYS_TCL_CMDS += set f2h_width $(F2H_WIDTH);
endif

ifneq ($(HPS_F2S_IRQ_EN),)
QUARTUS_TCL_ARGS += hps_f2s_irq_en $(HPS_F2S_IRQ_EN)
QSYS_TCL_CMDS += set hps_f2s_irq_en $(HPS_F2S_IRQ_EN);
endif

ifneq ($(HPS_STM_EN),)
QUARTUS_TCL_ARGS += hps_stm_en $(HPS_STM_EN)
QSYS_TCL_CMDS += set hps_stm_en $(HPS_STM_EN);
endif

ifneq ($(FPGA_SGPIO_EN),)
QUARTUS_TCL_ARGS += fpga_sgpio_en $(FPGA_SGPIO_EN)
QSYS_TCL_CMDS += set fpga_sgpio_en $(FPGA_SGPIO_EN);
endif

QUARTUS_TCL_ARGS += hps_emif_ecc_en $(ENABLE_HPS_EMIF_ECC)
QSYS_TCL_CMDS += set hps_emif_ecc_en $(ENABLE_HPS_EMIF_ECC);

ifneq ($(HPS_EMIF_REF_CLK_FREQ_MHZ),)
QUARTUS_TCL_ARGS += hps_emif_ref_clk_freq_mhz $(HPS_EMIF_REF_CLK_FREQ_MHZ)
QSYS_TCL_CMDS += set hps_emif_ref_clk_freq_mhz $(HPS_EMIF_REF_CLK_FREQ_MHZ);
endif

ifneq ($(HPS_EMIF_MEM_CLK_FREQ_MHZ),)
QUARTUS_TCL_ARGS += hps_emif_mem_clk_freq_mhz $(HPS_EMIF_MEM_CLK_FREQ_MHZ)
QSYS_TCL_CMDS += set hps_emif_mem_clk_freq_mhz $(HPS_EMIF_MEM_CLK_FREQ_MHZ);
endif

ifneq ($(HPS_EMIF_RATE),)
QUARTUS_TCL_ARGS += hps_emif_rate $(HPS_EMIF_RATE)
QSYS_TCL_CMDS += set hps_emif_rate $(HPS_EMIF_RATE);
endif

ifneq ($(LOOPBACK_EN),)
QUARTUS_TCL_ARGS += h2f_f2h_loopback_en $(LOOPBACK_EN)
QSYS_TCL_CMDS += set h2f_f2h_loopback_en $(LOOPBACK_EN);
endif

ifneq ($(BOARD_REV),)
QUARTUS_TCL_ARGS += board_rev $(BOARD_REV)
QSYS_TCL_CMDS += set board_rev $(BOARD_REV);
endif

# Valid BOOTS_FIRST Values: fpga or hps
ifneq ($(BOOTS_FIRST),)
QUARTUS_TCL_ARGS += sys_initialization $(BOOTS_FIRST)
QSYS_TCL_CMDS += set sys_initialization $(BOOTS_FIRST);
endif

ifeq ($(HPS_JTAG_MODE),separate)
QUARTUS_TCL_ARGS += hps_dap_mode 1
endif
ifeq ($(HPS_JTAG_MODE),combined)
QUARTUS_TCL_ARGS += hps_dap_mode 2
endif
ifeq ($(HPS_JTAG_MODE),disabled)
QUARTUS_TCL_ARGS += hps_dap_mode 0
endif

QSYS_TCL_CMDS += set watchdog_rst_en $(ENABLE_WATCHDOG_RST);

ifeq ($(WATCHDOG_RST_ACTION),cold)
QSYS_TCL_CMDS += set watchdog_rst_act 0;
endif
ifeq ($(WATCHDOG_RST_ACTION),warm)
QSYS_TCL_CMDS += set watchdog_rst_act 1;
endif
ifeq ($(WATCHDOG_RST_ACTION),remote_update)
QSYS_TCL_CMDS += set watchdog_rst_act 2;
endif

ifeq ($(ENABLE_SIGNALTAP_CROSS_TRIGGER),1)
QUARTUS_TCL_ARGS += cross_trigger_en 1
QSYS_TCL_CMDS += set cross_trigger_en 1;
endif

ifeq ($(HPS_EMIF_EN),0)
OCM_MEMSIZE := 8388608
else
OCM_MEMSIZE := 262144
endif

ifeq ($(ENABLE_PCIE),1)
QUARTUS_TCL_ARGS += fpga_pcie 1 pcie_f2h 1 pcie_hptxs 1 pcie_gen $(PCIE_GEN) pcie_count $(PCIE_COUNT) ocm_memsize $(OCM_MEMSIZE) f2h_width 128
QSYS_TCL_CMDS += set fpga_pcie 1; set pcie_f2h 1; set pcie_hptxs 1; set pcie_gen $(PCIE_GEN); set pcie_count $(PCIE_COUNT); set ocm_memsize $(OCM_MEMSIZE); set f2h_width 128;
endif

###
ifeq ($(ENABLE_PARTIAL_RECONFIGURATION),1)
ifneq ($(shell echo $(QUARTUS_DEVICE) | grep -E "AGFB014R24A.*VR0"),)
$(warning WARNING: Partial Reconfiguraion is not supported on FM6 REVA. ENABLE_PARTIAL_RECONFIGURATION force to 0)
ENABLE_PARTIAL_RECONFIGURATION = 0
endif

QUARTUS_TCL_ARGS += pr_enable $(ENABLE_PARTIAL_RECONFIGURATION)
QSYS_TCL_CMDS += set pr_enable $(ENABLE_PARTIAL_RECONFIGURATION);
QSYS_TCL_CMDS += set freeze_ack_dly_enable $(ENABLE_PARTIAL_RECONFIGURATION_TESTING);

# Add all named PR partitions
QUARTUS_PARTITIONS += pr_partition_0

endif # ENABLE_PARTIAL_RECONFIGURATION == 1
####

####
ifeq ($(HPS_ENABLE_SGMII),1)
ifneq ($(shell echo $(QUARTUS_DEVICE) | grep -E "AGFB014R24A.*VR0"),)
$(warning WARNING: HPS SGMII is not supported on FM6 REVA. HPS_ENABLE_SGMII force to 0)
HPS_SGMII_EMAC1_EN = 0
HPS_SGMII_EMAC2_EN = 0
HPS_ENABLE_SGMII = 0
endif

QUARTUS_TCL_ARGS += hps_sgmii_emac1_en $(HPS_SGMII_EMAC1_EN) hps_sgmii_emac2_en $(HPS_SGMII_EMAC2_EN)
QSYS_TCL_CMDS += set hps_sgmii_emac1_en $(HPS_SGMII_EMAC1_EN); set hps_sgmii_emac2_en $(HPS_SGMII_EMAC2_EN);
endif
####

ifeq ($(ENABLE_JOP),1)
QUARTUS_TCL_ARGS += jop_en 1
QSYS_TCL_CMDS += set jop_en 1;
endif

ifeq ($(ENABLE_NIOSV_SUBSYS),0)
QUARTUS_TCL_ARGS += niosv_subsys_en 0
QSYS_TCL_CMDS += set niosv_subsys_en 0;
endif

# Enable Etile 1588v2 PTP Subsystem
ifeq ($(ENABLE_ETILE_1588),1)
QUARTUS_TCL_ARGS += hps_etile_1588_en 1
QSYS_TCL_CMDS += set hps_etile_1588_en 1;
endif

ifeq ($(HPS_ETILE_1588_25GBE_EN),1)
QUARTUS_TCL_ARGS += hps_etile_1588_25gbe_en 1
QSYS_TCL_CMDS += set hps_etile_1588_25gbe_en 1;
endif

ifeq ($(HPS_ETILE_1588_10GBE_EN),1)
QUARTUS_TCL_ARGS += hps_etile_1588_10gbe_en 1
QSYS_TCL_CMDS += set hps_etile_1588_10gbe_en 1;
endif

ifneq ($(DAUGHTER_CARD),)
QUARTUS_TCL_ARGS += daughter_card $(DAUGHTER_CARD)
QSYS_TCL_CMDS += set daughter_card $(DAUGHTER_CARD);
endif

QUARTUS_TCL_ARGS += h2f_f2h_loopback_en 0
QSYS_TCL_CMDS += set h2f_f2h_loopback_en 0;
QUARTUS_TCL_ARGS += hps_peri_irq_loopback_en 0
QSYS_TCL_CMDS += set hps_peri_irq_loopback_en 0;
QUARTUS_TCL_ARGS += hps_emif_en $(HPS_EMIF_EN)
QSYS_TCL_CMDS += set hps_emif_en $(HPS_EMIF_EN);
QUARTUS_TCL_ARGS += hps_emif_ecc_en $(ENABLE_HPS_EMIF_ECC)
QSYS_TCL_CMDS += set hps_emif_ecc_en $(ENABLE_HPS_EMIF_ECC);

ifeq ($(HPS_EMIF_EN),0)
QUARTUS_TCL_ARGS += f2h_width 0
QSYS_TCL_CMDS += set f2h_width 0;
endif

ifeq ($(LOOPBACK_EN),1)
QUARTUS_TCL_ARGS += f2h_width 128 h2f_width 128 h2f_f2h_loopback_cct_en 1 ocm_datawidth 128 h2f_f2h_loopback_en 1
QSYS_TCL_CMDS += set f2h_width 128; set h2f_width 128; set h2f_f2h_loopback_cct_en 1; set ocm_datawidth 128; set h2f_f2h_loopback_en 1;
endif

#
############ End of Design Settings ################################################
#


# Merge QSYS_TCL_CMDS into a single QSys arg
ifneq ($(QSYS_TCL_CMDS),)
QSYS_TCL_ARGS += --cmd="$(QSYS_TCL_CMDS)"
endif
################################################



################################################
.PHONY: default
default: help
################################################

################################################
.PHONY: all
all:

ifeq ($(HAVE_QUARTUS),1)
all: sof
ifeq ($(ENABLE_PARTIAL_RECONFIGURATION),1)
all: pr_rbf
endif
endif
################################################


################################################
# Target Stamping

ifeq ($(QUARTUS_ROOTDIR),)
$(warning WARNING: QUARTUS_ROOTDIR not set)
endif

QUARTUS_VERSION = $(if $(wildcard $(QUARTUS_ROOTDIR)/version.txt),$(shell $(CAT) $(QUARTUS_ROOTDIR)/version.txt 2>/dev/null | $(GREP) Version | $(HEAD) -n1 | $(SED) -e 's,^Version[: \t=]*\([0-9.]*\).*,\1,g' 2>/dev/null))

define get_stamp_dir
stamp$(if $(QUARTUS_VERSION),/$(QUARTUS_VERSION))
endef

define get_stamp_target
$(get_stamp_dir)$(if $1,/$1.stamp,$(error ERROR: Arg 1 missing to $0 function))
endef

define stamp_target
@$(MKDIR) $(@D)
@$(TOUCH) $@
endef

.PHONY: clean
clean:
	@$(ECHO) "Cleaning stamp files (which will trigger rebuild)"
	@$(RM) $(get_stamp_dir)
	@$(ECHO) " TIP: Use 'make scrub_clean' to get a deeper clean"
################################################

################################################
# Checking for the existence of intel custom ip
INTEL_CUSTOM_IP_DIR = intel_custom_ip
INTEL_CUSTOM_IP_DIR_TARGET = $(INTEL_CUSTOM_IP_DIR)-$(wildcard $(INTEL_CUSTOM_IP_DIR))
INTEL_CUSTOM_IP_DIR_PRESENT = $(INTEL_CUSTOM_IP_DIR)-$(INTEL_CUSTOM_IP_DIR)
INTEL_CUSTOM_IP_DIR_ABSENT = $(INTEL_CUSTOM_IP_DIR)-

$(INTEL_CUSTOM_IP_DIR_PRESENT):
	@echo "Folder $(INTEL_CUSTOM_IP_DIR) exists. Compilation will proceed with local directory"

$(INTEL_CUSTOM_IP_DIR_ABSENT):
	@echo "Folder $(INTEL_CUSTOM_IP_DIR) does not exist."
	@echo "Proceed to copy for link $(INTEL_CUSTOM_IP_LINK)"
#if `wget $ -O $(INTEL_CUSTOM_IP_TARBALL) --tries=5 $(INTEL_CUSTOM_IP_LINK)`; then echo "Success"; else echo "Failed" && exit 1; fi
	if `curl $ -o $(INTEL_CUSTOM_IP_TARBALL) --retry 5 -m 60 -L $(INTEL_CUSTOM_IP_LINK)`; then echo "Success"; else echo "Failed to download $(INTEL_CUSTOM_IP_TARBALL)" && exit 1; fi
	@echo "$(INTEL_CUSTOM_IP_TARBALL) copied"
#Untar $(INTEL_CUSTOM_IP_TARBALL)
	tar -xzf $(INTEL_CUSTOM_IP_TARBALL)

################################################

################################################
# Archiving & Cleaning your QuartusII/QSys Project

AR_TIMESTAMP := $(if $(QUARTUS_VERSION),$(subst .,_,$(QUARTUS_VERSION))_)$(subst $(SPACE),,$(shell $(DATE) +%m%d%Y_%k%M%S))

AR_DIR := tgz
AR_FILE := $(AR_DIR)/$(basename $(firstword $(wildcard *.qpf)))_$(AR_TIMESTAMP).tar.gz

SOFTWARE_DIR := software

AR_REGEX += \
	Makefile custom_ip $(INTEL_CUSTOM_IP_DIR) ip/*/*.ip *.txt ds5 software README.md license.txt \
	altera_avalon* *.sdc *.v *.sv *.vhd *.qsys *.tcl *.terp *.stp *.mk board \
	*.hex *.sed quartus.ini output_files/*.sof output_files/*.rbf output_files/*.pmsf output_files/*handoff* *.sopcinfo */*.sopcinfo *.jdi \
	hps_isw_handoff handoff.bin */*.svd */synthesis/*.svd */synth/*.svd *.dts *.dtb *.xml \
	patches

AR_FILTER_OUT += %_tb.qsys
################################################



################################################
# Build QuartusII/QSys Project
#

#############
# QSys
QSYS_FILE_TOP := qsys_top.qsys
QSYS_FILE_TOP ?= $(firstword $(wildcard *top*.qsys) $(wildcard ghrd*.qsys) $(wildcard *main*.qsys) $(wildcard *soc*.qsys) $(wildcard *.qsys))

OTHER_QSYS_FILES :=

QSYS_FILES += $(QSYS_FILE_TOP) $(OTHER_QSYS_FILES)

ifeq ($(QSYS_FILE_TOP),)
$(error ERROR: QSYS_FILE_TOP *.qsys file not set and could not be discovered)
endif

QSYS_DEPS += $(sort $(QSYS_FILES) $(filter-out pr_%.qsys,$(wildcard *.qsys)))

QSYS_BASE_TOP := $(basename $(QSYS_FILE_TOP))
QSYS_GEN_DIRS := $(foreach qsys_file,$(QSYS_FILES),$(dir $(qsys_file))$(notdir $(basename $(qsys_file))))

QSYS_QIP_FILES := $(foreach qsys_file,$(QSYS_FILES),$(dir $(qsys_file))$(notdir $(basename $(qsys_file)))/$(basename $(notdir $(qsys_file))).qip)

QSYS_SOPCINFO := $(QSYS_BASE_TOP)/$(QSYS_BASE_TOP).sopcinfo
QSYS_STAMP := $(foreach qsys_file,$(QSYS_FILES),$(call get_stamp_target,$(qsys_file).qsys_gen))

# Under cygwin, ensure TMP env variable is not a cygwin style path
# before calling qsys-generate
ifeq ($(IS_CYGWIN_HOST),1)
ifneq ($(shell $(WHICH) cygpath 2>/dev/null),)
SET_QSYS_GENERATE_ENV = TMP="$(shell cygpath -m "$(TMP)")"
endif
endif

.PHONY: qsys_compile
qsys_compile: $(QSYS_STAMP)

ifeq ($(HAVE_QSYS),1)
$(QSYS_SOPCINFO) $(QSYS_QIP_FILES): $(QSYS_STAMP)
	@if [ ! -f "$@" ]; then echo "ERROR: $@ not generated" && false; fi
	$(stamp_target)
endif

QSYS_ARGS += --quartus-project=$(QUARTUS_QPF)
QSYS_ARGS += --rev=$(QUARTUS_BASE_REVISION)
#QSYS_GENERATE_ARGS = $(QSYS_ARGS)
QSYS_GENERATE_ARGS = --quartus-project=$(QUARTUS_QPF)
QSYS_GENERATE_ARGS += --clear-output-directory

$(QSYS_STAMP): $(get_stamp_dir)/%.qsys_gen.stamp: % $(QSYS_DEPS) $(INTEL_CUSTOM_IP_DIR_TARGET)
	$(SET_QSYS_GENERATE_ENV) qsys-generate $(QSYS_GENERATE_ARGS) --rev=$(QUARTUS_BASE_REVISION) $< --upgrade-ip-cores
	$(SET_QSYS_GENERATE_ENV) qsys-script --qpf=none --script=update_sysid.tcl --system-file=$<
ifeq ($(ENABLE_PARTIAL_RECONFIGURATION),1)
	$(SET_QSYS_GENERATE_ENV) qsys-script --qpf=none --script=update_sysid.tcl --system-file=pr_region_0.qsys
endif
	$(SET_QSYS_GENERATE_ENV) qsys-generate $(QSYS_GENERATE_ARGS) --rev=$(QUARTUS_BASE_REVISION) $< --synthesis=VERILOG
	$(stamp_target)

HELP_TARGETS += qsys_edit

qsys_edit.HELP := Launch Platform Designer GUI
ifneq ($(HAVE_QSYS),1)
qsys_edit.HELP := $(qsys_edit.HELP) (Install Quartus Prime Software to enable)
endif

.PHONY: qsys_edit
qsys_edit:
	qsys-edit $(QSYS_ARGS) $(QSYS_FILE_TOP) &

SCRUB_CLEAN_FILES += $(wildcard .qsys_edit)

ifeq ($(HAVE_QSYS),1)
SCRUB_CLEAN_FILES += $(QSYS_QIP_FILES) $(QSYS_SOPCINFO) $(QSYS_GEN_DIRS)
endif

#############
# Quartus Prime

QUARTUS_QPF := ghrd_$(call lc,$(QUARTUS_DEVICE)).qpf

ifeq ($(QUARTUS_QPF),)
$(error ERROR: QUARTUS_QPF *.qpf file not set and could not be discovered)
endif
QUARTUS_BASE := $(basename $(QUARTUS_QPF))
QUARTUS_HDL_SOURCE := $(wildcard *.v *.sv *.vhd)
QUARTUS_MISC_SOURCE := $(wildcard *.stp *.sdc)
QUARTUS_BASE_REVISION := $(QUARTUS_BASE)
QUARTUS_QSF := $(QUARTUS_BASE_REVISION).qsf

AR_REGEX += $(QUARTUS_QPF) $(QUARTUS_QSF)

QUARTUS_DEPS += $(QUARTUS_QSF) $(QUARTUS_HDL_SOURCE) $(QUARTUS_MISC_SOURCE) $(QSYS_STAMP) $(QSYS_QIP_FILES)

QUARTUS_OUTPUT_DIR := output_files
QUARTUS_SOF := $(QUARTUS_OUTPUT_DIR)/$(QUARTUS_BASE).sof
QUARTUS_SOF_WITH_HPS_DEBUG := $(patsubst %.sof,%_hps_debug.sof,$(QUARTUS_SOF))
QUARTUS_RBF := $(patsubst %.sof,%.rbf,$(QUARTUS_SOF_WITH_HPS))
QUARTUS_STAMP := $(call get_stamp_target,quartus)

.PHONY: quartus_compile
quartus_compile: $(QUARTUS_STAMP) $(INTEL_CUSTOM_IP_DIR_TARGET)

ifeq ($(HAVE_QUARTUS),1)
$(QUARTUS_SOF): $(QUARTUS_STAMP)
endif

$(QUARTUS_STAMP): $(QUARTUS_DEPS)
	quartus_stp $(QUARTUS_BASE) -c $(QUARTUS_BASE_REVISION)
	quartus_sh --flow compile $(QUARTUS_QPF) -c $(QUARTUS_BASE_REVISION)
	$(stamp_target)

HELP_TARGETS += quartus_edit
quartus_edit.HELP := Launch Quartus Prime GUI

ifneq ($(HAVE_QUARTUS),1)
quartus_edit.HELP := $(quartus_edit.HELP) (Install Quartus Prime Software to enable)
endif

.PHONY: quartus_edit
quartus_edit:
	quartus $(QUARTUS_QPF) &

HELP_TARGETS += sof
sof.HELP := QSys generate & Quartus compile this design
ifneq ($(HAVE_QUARTUS),1)
sof.HELP := $(sof.HELP) (Install Quartus Prime Software to enable)
endif

BATCH_TARGETS += sof

.PHONY: sof
sof: $(QUARTUS_SOF)

ifeq ($(HAVE_C_COMPILER),1)
sof:  $(QUARTUS_SOF_WITH_HPS_DEBUG)
endif


# Partial Reconfig RBF build flow
ifeq ($(ENABLE_PARTIAL_RECONFIGURATION),1)

QUARTUS_PR_REVISIONS += alternate_persona

QUARTUS_PR_RBF := $(strip \
   $(foreach revision,$(QUARTUS_BASE_REVISION) $(QUARTUS_PR_REVISIONS),\
      $(foreach partition,$(QUARTUS_PARTITIONS),\
          $(QUARTUS_OUTPUT_DIR)/$(revision).$(partition).rbf)))

QUARTUS_PMSF := $(patsubst %.rbf,%.pmsf,$(QUARTUS_PR_RBF))

QUARTUS_BASE_QDB := base_static.qdb
SCRUB_CLEAN_FILES += $(QUARTUS_BASE_QDB)
endif

#####################


#####################

.PHONY: qdb
qdb: $(QUARTUS_BASE_QDB)

$(QUARTUS_BASE_QDB): $(QUARTUS_STAMP)
	quartus_cdb $(QUARTUS_QPF) -c $(QUARTUS_BASE_REVISION) --export_partition root_partition --snapshot final --file $@

QSYS_SUBSYS_PR := pr_r0_per
QUARTUS_PR_REVISION := alternate_persona
AR_REGEX += $(QUARTUS_PR_REVISION).qsf
ifeq ($(ENABLE_PARTIAL_RECONFIGURATION),1)
PARTITION_NAME := pr_partition_0
PARTITION_REGION_HIER := "soc_inst|pr_region_0"


.PHONY: quartus_generate_pr_qsf
quartus_generate_pr_qsf: create_pr_revision.tcl
	quartus_sh --script=$< -projectname $(QUARTUS_BASE) -revision $(QUARTUS_BASE_REVISION) -pr_revision $(QUARTUS_PR_REVISION) -pr_partition $(QSYS_SUBSYS_PR) -pr_hierarchy $(PARTITION_REGION_HIER)

.PHONY: qsys_generate_pr_qsys
qsys_generate_pr_qsys: $(QSYS_SUBSYS_PR).qsys

$(QSYS_SUBSYS_PR).qsys: %.qsys: construct_subsys_pr_region.tcl $(QUARTUS_PR_REVISION).qsf
	qsys-script --script=$< --quartus-project=$(QUARTUS_BASE) --rev=$(QUARTUS_PR_REVISION) --cmd="set device $(QUARTUS_DEVICE); set sub_qsys_pr $(QSYS_SUBSYS_PR); set pr_persona 1"
	$(stamp_target)

$(QSYS_SUBSYS_PR)/$(QSYS_SUBSYS_PR).qip: $(QSYS_SUBSYS_PR).qsys
	$(SET_QSYS_GENERATE_ENV) qsys-generate $(QSYS_GENERATE_ARGS) --rev=$(QUARTUS_PR_REVISION) $< --upgrade-ip-cores
	$(SET_QSYS_GENERATE_ENV) qsys-script --qpf=none --script=update_sysid.tcl --system-file=$<
	$(SET_QSYS_GENERATE_ENV) qsys-generate $(QSYS_GENERATE_ARGS) --rev=$(QUARTUS_PR_REVISION) $< --synthesis=VERILOG
	@if [ ! -f "$@" ]; then echo "ERROR: $@ not generated"; false; fi

$(QUARTUS_OUTPUT_DIR)/$(QUARTUS_PR_REVISION).$(PARTITION_NAME).pmsf: %.pmsf: $(QUARTUS_BASE_QDB) $(QSYS_SUBSYS_PR)/$(QSYS_SUBSYS_PR).qip
	quartus_sh --flow compile $(QUARTUS_QPF) -c $(QUARTUS_PR_REVISION)
	@if [ ! -f "$@" ]; then echo "ERROR: $@ not generated"; false; fi

$(QUARTUS_OUTPUT_DIR)/$(QUARTUS_BASE_REVISION).$(PARTITION_NAME).pmsf: $(QUARTUS_SOF)

endif

#####################
# SGMII 1GbE Constraint
ifeq ($(HPS_ENABLE_SGMII),1)
.PHONY: quartus_add_post_sgmii_sdc
quartus_add_post_sgmii_sdc: $(QSYS_FILE_TOP)
	$(SET_QSYS_GENERATE_ENV) quartus_sh --script=add_sdc_post_qsys.tcl -projectname $(QUARTUS_BASE) -hps_enable_sgmii $(HPS_ENABLE_SGMII)
endif

#####################
SPL_DEBUG_GEN_HEX_DEPS += software/hps_debug/hps_debug.S software/hps_debug/Makefile software/hps_debug/Makefile_ARMCLANG.inc software/hps_debug/Makefile_GCC.inc software/hps_debug/scatter.scat

software/hps_debug/hps_debug.ihex: $(SPL_DEBUG_GEN_HEX_DEPS)
	$(MAKE) -C software/hps_debug

$(QUARTUS_SOF_WITH_HPS_DEBUG): $(QUARTUS_SOF) software/hps_debug/hps_debug.ihex
	@$(MKDIR) $(@D)
	quartus_pfg -c -o hps_path=software/hps_debug/hps_debug.ihex $< $@

.PHONY: debug_sof
debug_sof: software/hps_debug/hps_debug.ihex
ifneq ("$(wildcard $(QUARTUS_OUTPUT_DIR)/$(QUARTUS_BASE)*.sof)", "")
	$(info Generating debug version of $(QUARTUS_BASE).sof as $(QUARTUS_BASE)_hps_debug.sof)
	quartus_pfg -c -o hps_path=software/hps_debug/hps_debug.ihex $(QUARTUS_SOF) $(QUARTUS_SOF_WITH_HPS_DEBUG)
else
	$(error ERROR: Please run "make sof" to create $(QUARTUS_SOF))
endif

HELP_TARGETS += debug_sof
debug_sof.HELP := Generate debug version sof to boot with arm debugger

.PHONY: pr_rbf
pr_rbf: $(QUARTUS_PR_RBF)

$(QUARTUS_PR_RBF): %.rbf: %.pmsf
	quartus_pfg -c $< $@


ifeq ($(HAVE_QUARTUS),1)
SCRUB_CLEAN_FILES += $(QUARTUS_SOF) $(QUARTUS_SOF_WITH_HPS) $(QUARTUS_SOF_WITH_HPS_DEBUG) $(QUARTUS_RBF) $(QUARTUS_JIC) $(QUARTUS_OUTPUT_DIR)
endif

################################################


################################################
# QSYS/Quartus Project Generation
#  - we don't run this generation step automatically because
#    it will destroy any changes and/or customizations that
#    you've made to your qsys, top level hdl or your quartus
#    project
#
QSYS_QSYS_GEN := $(firstword $(wildcard create_*_qsys.tcl))
QUARTUS_TOP_GEN := $(firstword $(wildcard create_*_top.tcl))
QUARTUS_QSF_QPF_GEN := $(firstword $(wildcard create_*_quartus.tcl))

.PHONY: quartus_generate_qsf_qpf
ifneq ($(QUARTUS_QSF_QPF_GEN),)
quartus_generate_qsf_qpf: $(QUARTUS_QSF_QPF_GEN)
	@$(RM) $(QUARTUS_QSF) $(QUARTUS_QPF)
	quartus_sh --script=$< $(QUARTUS_TCL_ARGS)
else
quartus_generate_qsf_qpf:
	@$(ECHO) "Make target '$@' is not supported for this design"
endif

QUARTUS_TCL_ARGS += qsys_name $(patsubst %.qsys,%,$(QSYS_FILE_TOP))

.PHONY: quartus_generate_top
ifneq ($(QUARTUS_TOP_GEN),)
quartus_generate_top: $(QUARTUS_TOP_GEN)
	@$(RM) *_top.v
	quartus_sh --script=$< $(QUARTUS_TCL_ARGS)
else
quartus_generate_top:
	@$(ECHO) "Make target '$@' is not supported for this design"
endif

QSYS_GEN_QSYS_DEPS += quartus_generate_qsf_qpf

.PHONY: qsys_generate_qsys
ifneq ($(QSYS_QSYS_GEN),)
qsys_generate_qsys: $(QSYS_QSYS_GEN) $(QSYS_GEN_QSYS_DEPS) $(INTEL_CUSTOM_IP_DIR_TARGET)
	@$(RM) $(QSYS_FILE_TOP)
	qsys-script $(QSYS_ARGS) --script=$< $(QSYS_TCL_ARGS)
ifeq ($(HPS_ENABLE_SGMII),1)
	$(MAKE) quartus_add_post_sgmii_sdc
endif
	$(stamp_target)
else
qsys_generate_qsys:
	@$(ECHO) "Make target '$@' is not supported for this design"
endif

.PHONY: generate_from_tcl_internal
generate_from_tcl_internal: $(INTEL_CUSTOM_IP_DIR_TARGET)
	$(MAKE) -s scrub_clean_all
	$(MAKE) quartus_generate_qsf_qpf quartus_generate_top qsys_generate_qsys
ifeq ($(ENABLE_PARTIAL_RECONFIGURATION),1)
	$(MAKE) quartus_generate_pr_qsf qsys_generate_pr_qsys
endif
################################################


################################################
# Quartus Programming
QUARTUS_PGM_STAMP := $(call get_stamp_target,quartus_pgm)

# set this correctly for your board. If not set, assume the first board
# is your board
CLOSE_PARENTHESIS = )
BOARD_CABLE ?= $(shell jtagconfig | head -n1 | sed -e 's,[0-9]*[$(CLOSE_PARENTHESIS)][ \t]*,,')

# Default to 1 since this is the most common setting
BOARD_DEVICE_INDEX ?= 1


# issp_reset.tcl is required because of the issue described in CASE:487915
define quartus_pgm_sof
jtagconfig
quartus_pgm --mode=jtag $(if $(BOARD_CABLE),--cable="$(BOARD_CABLE)") --operation=p\;$1$(if $(BOARD_DEVICE_INDEX),"@$(BOARD_DEVICE_INDEX)")
jtagconfig $(if $(BOARD_CABLE),-c "$(BOARD_CABLE)") -n
system-console --script=issp_reset.tcl
endef

################################################


################################################
# Clean-up and Archive

AR_FILES += $(filter-out $(AR_FILTER_OUT),$(wildcard $(AR_REGEX)))

ifeq ($(ENABLE_PARTIAL_RECONFIGURATION),1)
AR_FILES += $(QUARTUS_BASE_QDB)
endif

CLEAN_FILES += $(filter-out $(AR_DIR) $(AR_FILES) ip,$(wildcard *))

HELP_TARGETS += tgz
tgz.HELP := Create a tarball with the barebones source files that comprise this design

.PHONY: tarball tgz
tarball tgz: $(AR_FILE)

$(AR_FILE):
	@$(MKDIR) $(@D)
	@$(if $(wildcard $(@D)/*.tar.gz),$(MKDIR) $(@D)/.archive;$(MV) $(@D)/*.tar.gz $(@D)/.archive)
	@$(ECHO) "Generating $@..."
	@$(TAR) -czf $@ $(AR_FILES)

SCRUB_CLEAN_FILES += $(CLEAN_FILES)
QSYS_GEN_FILES += $(filter-out $(wildcard ip/*/*.ip), $(wildcard ip/*/*))
SCRUB_CLEAN_FILES += $(QSYS_GEN_FILES)

HELP_TARGETS += scrub_clean
scrub_clean.HELP := Restore design to its barebones state

.PHONY: scrub scrub_clean
scrub scrub_clean:
	$(FIND) $(SOFTWARE_DIR) \( -name '*.o' -o -name '.depend*' -o -name '*.d' -o -name '*.dep' -o -name '*.objdump' -o -name '*.axf' \) -delete || true
	$(if $(strip $(wildcard $(SCRUB_CLEAN_FILES))),$(RM) $(wildcard $(SCRUB_CLEAN_FILES)),@$(ECHO) "You're already as clean as it gets!")

##scrub_clean_all -> clean all included qpf, qsf and qsys
.PHONY: scrub_clean_all
SCRUB_CLEAN_ALL_FILES += $(SCRUB_CLEAN_FILES)
SCRUB_CLEAN_ALL_FILES += ip/ *.qpf *.qsf *.qsys *.v *.sv
scrub_clean_all:
	$(FIND) $(SOFTWARE_DIR) \( -name '*.o' -o -name '.depend*' -o -name '*.d' -o -name '*.dep' \) -delete || true
	$(if $(strip $(wildcard $(SCRUB_CLEAN_ALL_FILES))),$(RM) $(wildcard $(SCRUB_CLEAN_ALL_FILES)),@$(ECHO) "You're already as clean as it gets!")

.PHONY: tgz_scrub_clean
tgz_scrub_clean:
	$(FIND) $(SOFTWARE_DIR) \( -name '*.o' -o -name '.depend*' -o -name '*.d' -o -name '*.dep' \) -delete || true
	$(MAKE) tgz AR_FILE=$(AR_FILE)
	$(MAKE) -s scrub_clean
	$(TAR) -xzf $(AR_FILE)

################################################


################################################
# Running Batch Jobs
ifneq ($(BATCH_TARGETS),)

BATCH_DIR := $(if $(TMP),$(TMP)/)batch/$(AR_TIMESTAMP)

.PHONY: $(patsubst %,batch-%,$(BATCH_TARGETS))
$(patsubst %,batch-%,$(BATCH_TARGETS)): batch-%: $(AR_FILE)
	@$(RM) $(BATCH_DIR)
	@$(MKDIR) $(BATCH_DIR)
	$(CP) $< $(BATCH_DIR)
	$(CD) $(BATCH_DIR) && $(TAR) -xzf $(notdir $<) && $(CHMOD) -R 755 *
	$(MAKE) -C $(BATCH_DIR) $*

endif # BATCH_TARGETS != <empty>
################################################

################################################
# Design generation targets


generate-agf027f1es-soc-devkit-oobe-baseline:
	make generate_from_tcl_internal BOARD_TYPE=devkit_fm86 BOARD_PWRMGT=linear

generate-agi027fc-si-devkit-oobe-baseline:
	make generate_from_tcl_internal BOARD_TYPE=devkit_fm87 BOARD_PWRMGT=linear ENABLE_HPS_EMIF_ECC=1 FPGA_SGPIO_EN=1

generate-agi027fa-si-devkit-oobe-baseline:
	make generate_from_tcl_internal BOARD_TYPE=devkit_fm87 BOARD_PWRMGT=linear QUARTUS_DEVICE=AGIB027R31B1E1V ENABLE_HPS_EMIF_ECC=1 FPGA_SGPIO_EN=1

generate-agi027fb-si-devkit-oobe-baseline:
	make generate_from_tcl_internal BOARD_TYPE=devkit_fm87 QUARTUS_DEVICE=AGIB027R31B1E1VAA ENABLE_HPS_EMIF_ECC=1 FPGA_SGPIO_EN=1

generate-agf014eb-si-devkit-oobe-baseline:
	make generate_from_tcl_internal BOARD_TYPE=DK-SI-AGF014E BOARD_PWRMGT=linear

generate-agf014eb-si-devkit-nand-baseline:
	make generate_from_tcl_internal BOARD_TYPE=DK-SI-AGF014E BOARD_PWRMGT=linear DAUGHTER_CARD=devkit_dc_nand

generate-agf014eb-si-devkit-oobe-pr:
	make generate_from_tcl_internal BOARD_TYPE=DK-SI-AGF014E BOARD_PWRMGT=linear ENABLE_HPS_EMIF_ECC=1 ENABLE_PARTIAL_RECONFIGURATION=1

build-agf014eb-si-devkit-oobe-pr_alternate-rbf:
	quartus_cdb ghrd_agfb014r24b2e2v.qpf -c ghrd_agfb014r24b2e2v --export_partition root_partition --snapshot final --file base_static.qdb
	qsys-generate --quartus-project=ghrd_agfb014r24b2e2v.qpf --clear-output-directory --rev=alternate_persona pr_r0_per.qsys --upgrade-ip-cores
	qsys-generate --quartus-project=ghrd_agfb014r24b2e2v.qpf --clear-output-directory --rev=alternate_persona pr_r0_per.qsys --synthesis=VERILOG
	quartus_sh --flow compile ghrd_agfb014r24b2e2v.qpf -c alternate_persona

generate-agm039fes-soc-devkit-oobe-baseline:
	make generate_from_tcl_internal BOARD_TYPE=devkit_fp82 CONFIG_SCHEME="AVST\ X8" BOARD_PWRMGT=linear ENABLE_HPS_EMIF_ECC=0 ENABLE_WATCHDOG_RST=0

generate-agf023fa-soc-devkit-oobe-baseline:
	make generate_from_tcl_internal BOARD_TYPE=DK-DEV-AGF023FA BOARD_PWRMGT=linear

generate-agm039ea-soc-devkit-oobe-baseline:
	make generate_from_tcl_internal QUARTUS_DEVICE=AGMF039R47A1E1VC BOARD_TYPE=devkit_fp82 CONFIG_SCHEME="AVST\ X8" BOARD_PWRMGT=linear ENABLE_HPS_EMIF_ECC=0 ENABLE_WATCHDOG_RST=0 OCM_DATAWIDTH=32 HBM_EN=1 HPS_F2S_IRQ_EN=0 HPS_STM_EN=0 HPS_EMIF_EN=0
	
generate-fpga_first_revb_linear:
	make generate_from_tcl_internal BOOTS_FIRST=fpga BOARD_TYPE=DK-SI-AGF014E BOARD_PWRMGT=linear ENABLE_HPS_EMIF_ECC=1
	
generate-fpga_first_pr_linear: 
	make generate_from_tcl_internal BOOTS_FIRST=fpga BOARD_TYPE=DK-SI-AGF014E BOARD_PWRMGT=linear ENABLE_HPS_EMIF_ECC=1 ENABLE_PARTIAL_RECONFIGURATION=1

################################################


################################################
# Help system

HELP_TARGETS += help
help.HELP := Displays this info (i.e. the available targets)

.PHONY: help
help: help-init help-targets help-fini

HELP_TARGETS_X := $(patsubst %,help-%,$(sort $(HELP_TARGETS)))
.PHONY: $(HELP_TARGETS_X)
help-targets: $(HELP_TARGETS_X)
$(HELP_TARGETS_X): help-%:
	@$(ECHO) "*********************"
	@$(ECHO) "* Target: $*"
	@$(ECHO) "*   $($*.HELP)"

.PHONY: help-init
help-init:
	@$(ECHO) "******************************************************"
	@$(ECHO) "*                                                    *"
	@$(ECHO) "* Manage Quartus Prime / Platform Designer Design    *"
	@$(ECHO) "*                                                    *"
	@$(ECHO) "*     Copyright (c) 2017                             *"
	@$(ECHO) "*     All Rights Reserved                            *"
	@$(ECHO) "*                                                    *"
	@$(ECHO) "******************************************************"
	@$(ECHO) ""

.PHONY: help-fini
help-fini:
	@$(ECHO) "*********************"

################################################
