# Check for the required nios2-download command
# The command is only available in nios2_command_shell
ifeq (, $(shell which nios2-download))
$(error "This makefile must be executed within the nios2_command_shell")
endif

uname = $(shell uname -r)
ifneq (,$(findstring Microsoft,${uname}))
exe_suffix=.exe
endif

# Programm pathes
quartus_root ?= ${QUARTUS_ROOTDIR}
intel_root ?= $(quartus_root)/..
sopc_root = $(quartus_root)/sopc_builder

# Tools
qsys_generate = $(sopc_root)/bin/qsys-generate$(exe_suffix)
niosii_bsp = $(intel_root)/nios2eds/sdk2/bin/nios2-bsp
quartus_map = quartus_map$(exe_suffix)
quartus_fit = quartus_fit$(exe_suffix)
quartus_asm = quartus_asm$(exe_suffix)
quartus_sta = quartus_sta$(exe_suffix)
nios2_bsp_generate_files = nios2-bsp-generate-files$(exe_suffix)
quartus_pgm = quartus_pgm$(exe_suffix)
nios2_download = nios2-download$(exe_suffix)
nios2_terminal = nios2-terminal$(exe_suffix)

# Directories
niosii_dir = niosII
bsp_dir = software/signal_processing_bsp
app_dir = software/signal_processing
hw_test_dir = tests/hardware
sw_test_dir = tests/software

# Settings
quartus_project = signal_processing
signal_processing_qsf = signal_processing.qsf

# Sources
niosii_qsys = niosII.qsys

# Targets
niosii_qip = $(niosii_dir)/synthesis/niosII.qip
niosii_info = niosII.sopcinfo

bsp_settings = $(bsp_dir)/settings.bsp
bsp_makefile = $(bsp_dir)/Makefile

# VHDL source files
hdl_src += \
    hardware/system/sync_ff.vhd \
    hardware/system/sync_rst.vhd \
    hardware/system/pll/pll_main.vhd \
    hardware/system/reg32.vhd \
    hardware/system/avalon_slave_transitions.vhd \
    hardware/system/avalon_slave.vhd \
    hardware/system/data_sink_mux.vhd \
    hardware/system/fifo.vhd \
    hardware/system/data_source_mux.vhd \
    hardware/system/data_channel_control.vhd \
    hardware/system/data_channel.vhd \
    hardware/system/hardware_timestamp.vhd \
    hardware/system/task.vhd \
    hardware/system/float.vhd \
    hardware/system/hardware_task_control.vhd \
    hardware/system/hardware_task.vhd \
    hardware/system/float_add.vhd \
    hardware/signal_processing/add.vhd \
    hardware/system/task_add.vhd \
    hardware/signal_processing/rand.vhd \
    hardware/system/task_rand.vhd \
    hardware/system/cordic_pkg.vhd \
    hardware/system/cordic.vhd \
    hardware/system/fixed_sine.vhd \
    hardware/system/float_sine.vhd \
    hardware/signal_processing/sine.vhd \
    hardware/system/task_sine.vhd \
    hardware/system/Butterfly.v \
    hardware/system/DelayBuffer.v \
    hardware/system/FFT1024_32B.v \
    hardware/system/Multiply.v \
    hardware/system/SdfUnit2.v \
    hardware/system/SdfUnit.v \
    hardware/system/Twiddle1024_32B.v \
    hardware/system/squareRoot_pipe.vhd \
    hardware/system/fft_magnitude_calc.vhd \
    hardware/signal_processing/fft.vhd \
    hardware/system/task_fft.vhd \
    hardware/signal_processing/crc.vhd \
    hardware/system/task_crc.vhd \
    hardware/signal_processing/signal_processing.vhd \

#
clean_items += \
    $(niosii_dir) \
    $(niosii_info) \
    .map \
    .fitter \
    .assembler \
    .sta \
    .qsys_edit/ \
    db/ \
    incremental_db/ \
    output_files/ \

.PHONY: all \
        niosII \
        fpga \
        program \
        clean \
        app \
        download \
        run \
		tests \

all: run

#------------------------------------------------------------------------------
# Create the NiosII system from the description file
niosII: $(niosii_info)

# Create the NiosII sources from the description file
$(niosii_qip): $(niosii_qsys)
	@echo Generating the NiosII system from $< ...
	@$(qsys_generate) -syn=VHDL $<

# The NiosII system information file is created in parallel to the .qip file.
$(niosii_info): $(niosii_qip)

#------------------------------------------------------------------------------
# Quartus FPGA toolchain contains the mapper, fitter, assembler and static
# timing analysis (sta).
#
fpga: .sta

# Anaylze and synthesis of the QuartusII project
.map: $(hdl_src) $(niosii_info) $(signal_processing_qsf)
	@rm -f $@
	@$(quartus_map) --read_settings_files=on --write_settings_files=off $(quartus_project) -c $(quartus_project) && date > $@

# Run the quartus fitter on the project
.fitter: .map $(sdc_src) $(signal_processing_qsf)
	@rm -f $@
	@$(quartus_fit) --read_settings_files=on --write_settings_files=off $(quartus_project) -c $(quartus_project) && date > $@

.assembler: .fitter
	@rm -f $@
	@$(quartus_asm) --read_settings_files=off --write_settings_files=off $(quartus_project) -c $(quartus_project)&& date > $@

.sta: .assembler
	@rm -f $@
	@$(quartus_sta) $(quartus_project) -c $(quartus_project) && date > $@

output_files/signal_processing_time_limited.sof: .sta

# Create the BSP from the sopc description
bsp: ${bsp_makefile}

$(bsp_settings): $(niosii_info)
	@echo Generating the NiosII BSP from $< ...
	@$(niosii_bsp) hal $(bsp_dir) $<

$(bsp_makefile): $(bsp_settings)
	@$(nios2_bsp_generate_files) --settings software/signal_processing_bsp/settings.bsp --bsp-dir software/signal_processing_bsp/

app: $(bsp_makefile)
	${MAKE} -C $(app_dir)

# Programme the FPGA design
program: output_files/signal_processing_time_limited.sof
	@$(quartus_pgm) signal_processing.cdf

# Programme the NiosII software design
download: app
	@$(nios2-download) $(app_dir)/signal_processing.elf -g

# Programme the NiosII software design
run: fpga download
	@$(nios2-terminal)

sw_tests:
	@${MAKE} -C tests/software

hw_tests:
	@${MAKE} -C tests/hardware

device_tests:
	@${MAKE} -C tests/device

tests: sw_tests hw_tests device_tests

clean:
	@rm -rf $(clean_items)
	@${MAKE} -C ${hw_test_dir} clean
	@${MAKE} -C ${sw_test_dir} clean
	@${MAKE} -C ${app_dir} clean
	@${MAKE} -C ${bsp_dir} clean