#*******************************************************************************
#
# Copyright (C) 2013-2019 MACNICA,Inc. All Rights Reserved.\n
#
# This software is licensed "AS IS".
# Please perform use of this software by a user's own responsibility and expense.
# It cannot guarantee in the maker side about the damage which occurred by the ab-
# ility not to use or use this software, and all damage that occurred secondarily.
#
#*******************************************************************************
include config.mk

######################################
# Include Auto Select Target Options #
######################################
# 
# Select Target Board # {1:helio / 2:atlas / 3:sodia / 4:c5socdk / 5:a10socdk / 6:de10nano} 
# 
ifeq ($(TARGET_BOARD),helio)
  TARGET_BOARD_NO := 1
  ALT_DEVICE_FAMILY := soc_cv_av
  DESIGN_NAME := soc_system
  HPS_MODULE_NAME := hps_0_arm_a9_0
  UART_CH := 0
endif
ifeq ($(TARGET_BOARD),atlas)
  TARGET_BOARD_NO := 2
  ALT_DEVICE_FAMILY := soc_cv_av
  DESIGN_NAME := soc_system
  HPS_MODULE_NAME := hps_0_arm_a9_0
  UART_CH := 0
endif
ifeq ($(TARGET_BOARD),sodia)
  TARGET_BOARD_NO := 3
  ALT_DEVICE_FAMILY := soc_cv_av
  DESIGN_NAME := soc_system
  HPS_MODULE_NAME := hps_0_arm_a9_0
  UART_CH := 0
endif
ifeq ($(TARGET_BOARD),c5socdk)
  TARGET_BOARD_NO := 4
  ALT_DEVICE_FAMILY := soc_cv_av
  DESIGN_NAME := soc_system
  HPS_MODULE_NAME := hps_0_arm_a9_0
  UART_CH := 0
endif
ifeq ($(TARGET_BOARD),a10socdk)
  TARGET_BOARD_NO := 5
  ALT_DEVICE_FAMILY := soc_a10
  DESIGN_NAME := ghrd_10as066n2
  HPS_MODULE_NAME := a10_hps_arm_a9_0
  UART_CH := 1
endif
ifeq ($(TARGET_BOARD),de10nano)
  TARGET_BOARD_NO := 6
  ALT_DEVICE_FAMILY := soc_cv_av
  DESIGN_NAME := soc_system
  HPS_MODULE_NAME := hps_0_arm_a9_0
  UART_CH := 0
endif
	
APP_LOAD_ADDR := 0x00200000

SOCEDS_ROOT ?= $(SOCEDS_DEST_ROOT)
#NEWLIB_ROOT ?= $(SOCEDS_DEST_ROOT)/host_tools/linaro/newlib/usr/local/arm-eabi
NEWLIB_ROOT ?= $(SOCEDS_DEST_ROOT)/tools/newlib/usr/arm-eabi
HWLIBS_ROOT = util/hwlib

INC_PATH := -I$(HWLIBS_ROOT)/include
INC_PATH += -I$(HWLIBS_ROOT)/include/$(ALT_DEVICE_FAMILY)
INC_PATH += -I$(HWLIBS_ROOT)/include/$(ALT_DEVICE_FAMILY)/socal
INC_PATH += -I$(HWLIBS_ROOT)/include/safeclib
ifeq ($(COMPILER),GNU)
  INC_PATH += -I$(NEWLIB_ROOT)/include
endif
INC_PATH += -Iutil
INC_PATH += -Iutil/nios_hal/include
INC_PATH += -I.

#############################
# Build Target Source Files #
#############################
HWLIBS_SRC  := 
HWLIBS_ASM  := 
EXAMPLE_SRC := $(wildcard *.c)
EXAMPLE_ASM := 

# if it is semihosted, printf goes to semihosting console otherwise to UART
ifeq ($(SEMIHOSTED), 1)
  UART_DEFINES ?= -DPRINTF_HOST
else
  UART_DEFINES ?= -DPRINTF_UART
  ifeq ($(COMPILER),GNU)
    HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/utils/alt_retarget_gnu.c
  else
    HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/utils/alt_retarget_armclang.c
  endif
  HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/utils/alt_p2uart.c
  HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/utils/alt_printf.c
endif

ifeq ($(COMPILER),GNU)
  HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/utils/alt_base.c
endif

ifeq ($(ENABLE_EXAMPLE_DMA),1)
  EXAMPLE_SRC	+=	examples/sample_dmac.c
  EXAMPLE_SRC	+=	examples/sample_dma_mem.c
endif
ifeq ($(ENABLE_EXAMPLE_CACHE),1)
  EXAMPLE_SRC	+=	examples/sample_cache_manage.c 
endif
ifeq ($(ENABLE_EXAMPLE_CLK),1)
  EXAMPLE_SRC	+=	examples/sample_clock_manager.c 
endif
ifeq ($(ENABLE_EXAMPLE_ECC),1)
  EXAMPLE_SRC	+=	examples/sample_ecc.c 
endif
ifeq ($(ENABLE_EXAMPLE_GLTMR),1)
  EXAMPLE_SRC	+=	examples/sample_globaltmr.c 
endif
ifeq ($(ENABLE_EXAMPLE_GPIO),1)
  EXAMPLE_SRC	+=	examples/sample_gpio.c 
endif
ifeq ($(ENABLE_EXAMPLE_GPTMR),1)
  EXAMPLE_SRC	+=	examples/sample_gptmr.c
endif
ifeq ($(ENABLE_EXAMPLE_INTCTRL),1)
  EXAMPLE_SRC	+=	examples/sample_interruptctrlSGI.c 
endif
ifeq ($(ENABLE_EXAMPLE_TIME),1)
  EXAMPLE_SRC	+=	examples/sample_time_measurement.c 
endif
ifeq ($(ENABLE_EXAMPLE_WDOG),1)
  EXAMPLE_SRC	+=	examples/sample_watchdog.c 
endif

EXAMPLE_FLAGS := \
 -DENABLE_EXAMPLE_DMA=$(ENABLE_EXAMPLE_DMA) \
 -DENABLE_EXAMPLE_CACHE=$(ENABLE_EXAMPLE_CACHE) \
 -DENABLE_EXAMPLE_CLK=$(ENABLE_EXAMPLE_CLK) \
 -DENABLE_EXAMPLE_ECC=$(ENABLE_EXAMPLE_ECC) \
 -DENABLE_EXAMPLE_GLTMR=$(ENABLE_EXAMPLE_GLTMR) \
 -DENABLE_EXAMPLE_GPIO=$(ENABLE_EXAMPLE_GPIO) \
 -DENABLE_EXAMPLE_GPTMR=$(ENABLE_EXAMPLE_GPTMR) \
 -DENABLE_EXAMPLE_INTCTRL=$(ENABLE_EXAMPLE_INTCTRL) \
 -DENABLE_EXAMPLE_TIME=$(ENABLE_EXAMPLE_TIME) \
 -DENABLE_EXAMPLE_WDOG=$(ENABLE_EXAMPLE_WDOG) 

EXAMPLE_SRC	+=	util/cmd.c
EXAMPLE_SRC	+=	util/mem_util.c
EXAMPLE_SRC	+=	util/usleep_soc.c
EXAMPLE_SRC	+=	util/util_interrupt_log.c
EXAMPLE_SRC	+=	util/util_time_measurement.c

#Common HWLib SRC
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_16550_uart.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_address_space.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_cache.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_can.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_dma_custom.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_dma_program.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_generalpurpose_io.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_globaltmr.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_i2c.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_interrupt.c
ifeq ($(COMPILER),ARM)
  #HWLIBS_ASM	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_interrupt_armclang.s
  HWLIBS_ASM	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_interrupt_armcc.s
endif
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_mmu.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_nand.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_qspi.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_safec.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_sdmmc.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_spi.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_timers.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/alt_watchdog.c
# Device Specific SRC
ifeq ($(ALT_DEVICE_FAMILY),soc_cv_av)
  ifeq ($(COMPILER),ARM)
    HWLIBS_ASM	+=	$(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/alt_bridge_f2s_armcc.s
  else
    HWLIBS_ASM	+=	$(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/alt_bridge_f2s_gnu.s
  endif
endif
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/alt_bridge_manager.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/alt_clock_manager.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/alt_ecc.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/alt_fpga_manager.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/alt_reset_manager.c
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/alt_sdram.c 
HWLIBS_SRC	+=	$(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/alt_system_manager.c 


C_SRC       := $(EXAMPLE_SRC) $(HWLIBS_SRC)
ASM_SRC     := $(EXAMPLE_ASM) $(HWLIBS_ASM)


################################
# Include Compile Instructions #
################################
#/*!
# * This preprocessor definition determines the size of the program buffer
# * within the ALT_DMA_PROGRAM_t structure. This size should provide adequate
# * size for most DMA microcode programs. If calls within this API are
# * reporting out of memory response codes, consider increasing the provisioned
# * program buffersize.
# *
# * To specify another DMA microcode program buffer size, redefine the macro
# * below by defining ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE to another size in
# * your Makefile. It is recommended that the size be a multiple of the
# * microcode engine cache line size. See ALT_DMA_PROGRAM_CACHE_LINE_SIZE for
# * more information. The largest supported buffer size is 65536 bytes.
# */
HWLIBDMAOPT := -DALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE=65536

############################################################################################
# Indirect build for HWLib (0:Direct Build/1:Indirect(Copy&BUild)) < Support 0:Direct only #
############################################################################################
HWLIB_INDIRECT_BUILD := 0

OBJ := $(patsubst %.c,%.o,$(C_SRC)) $(patsubst %.s,%.o,$(ASM_SRC))
ELF = $(TARGET).axf
BIN = $(TARGET).bin
MAP = $(TARGET).map
IMG = $(TARGET)-mkimage.bin

# 
# Select Linker Command File 
# 
# ================ COMPILER ==================== 
ifeq ($(COMPILER),GNU)
# ---------------- GNU Compiler ---------------- 
ifeq ($(ALT_DEVICE_FAMILY),soc_cv_av)
  LINKER_SCRIPT := linkerscripts/cycloneV-dk-ram.ld
endif
ifeq ($(ALT_DEVICE_FAMILY),soc_a10)
  LINKER_SCRIPT := linkerscripts/arria10-dk-ram.ld
endif

MULTILIBFLAGS := -march=armv7-a -mtune=cortex-a9 -mfloat-abi=softfp -mfpu=neon
CFLAGS  := -g -O0 -Wall -Werror -std=c99 -fdata-sections -ffunction-sections $(MULTILIBFLAGS) \
           $(INC_PATH) -D$(COMPILER)_COMPILER -D__$(COMPILER)_VERSION -D$(ALT_DEVICE_FAMILY) $(UART_DEFINES) -DTARGET_BOARD=$(TARGET_BOARD) -DTARGET_BOARD_NO=$(TARGET_BOARD_NO) \
           $(EXAMPLE_FLAGS) $(HWLIBDMAOPT) -DUART_CH=$(UART_CH) -DSOC_SUPPORT -DUSED_DMA=$(USED_DMA) -DAPP_LOAD_ADDR=$(APP_LOAD_ADDR) \
           -DALT_BRIDGE_PROVISION_F2S_SUPPORT
ASFLAGS :=  -g -march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=neon
ifeq ($(SEMIHOSTED), 1)
  LDFLAGS := -T$(LINKER_SCRIPT) $(MULTILIBFLAGS) '-Wl,-Map=$(MAP)' '-Wl,--gc-sections' -Xlinker --require-defined=__auto_semihosting
else
  LDFLAGS := -T$(LINKER_SCRIPT) $(MULTILIBFLAGS) -B$(NEWLIB_ROOT)/lib --sysroot=$(NEWLIB_ROOT)/lib --specs=nosys.specs '-Wl,-Map=$(MAP)' '-Wl,--gc-sections'
endif
ODFLAGS := -dr

CROSS_COMPILE ?= arm-eabi-
AS := $(CROSS_COMPILE)as
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)g++
NM := $(CROSS_COMPILE)nm
OC := $(CROSS_COMPILE)objcopy
OD := $(CROSS_COMPILE)objdump
else
# ---------------- ARM Compiler ---------------- 
ifeq ($(ALT_DEVICE_FAMILY),soc_cv_av)
  LINKER_SCRIPT := linkerscripts/soc_cv_av-scatter.scat
endif
ifeq ($(ALT_DEVICE_FAMILY),soc_a10)
  LINKER_SCRIPT := linkerscripts/soc_a10-scatter.scat
endif

MULTILIBFLAGS := -Wno-gnu -Wno-format-pedantic -Wno-logical-not-parentheses -Wno-strict-prototypes -Wno-extra -Wno-arm-interrupt-vfp-clobber \
                 -mcpu=cortex-a9 --target=arm-arm-none-eabi -mno-unaligned-access
MULTILIBFLAGS_OLD := --diag_suppress=9931 --cpu=Cortex-A9 --no_unaligned_access
CFLAGS   := -g -O0 -xc -std=c99 -pedantic-errors $(MULTILIBFLAGS) \
            $(INC_PATH) -D$(COMPILER)_COMPILER -D__$(COMPILER)_VERSION -D$(ALT_DEVICE_FAMILY) $(UART_DEFINES) -DTARGET_BOARD=$(TARGET_BOARD) \
            -DTARGET_BOARD_NO=$(TARGET_BOARD_NO) $(EXAMPLE_FLAGS) $(HWLIBDMAOPT) -DUART_CH=$(UART_CH) -DSOC_SUPPORT \
            -DUSED_DMA=$(USED_DMA) -DAPP_LOAD_ADDR=$(APP_LOAD_ADDR) -D_USE_STDLIB \
            -DALT_BRIDGE_PROVISION_F2S_SUPPORT
ASFLAGS := -g $(MULTILIBFLAGS_OLD)
LDFLAGS  := --strict $(MULTILIBFLAGS_OLD) --entry=alt_interrupt_vector --scatter=$(LINKER_SCRIPT) --load_addr_map_info --map --info=sizes,stack,summarysizes,summarystack --list=$(MAP)
ifeq ($(SEMIHOSTED), 1)
  LDFLAGS += --keep=__auto_semihosting
endif
ODFLAGS  := --cpu=Cortex-A9 --text -s -v -z

#AS := armclang
AS := armasm
CC := armclang
LD := armlink
AR := armar
OD := fromelf
OC := fromelf
endif
# ================ COMPILER ==================== 

ifeq ($(OS), Windows_NT)
 MKIMAGE := tools/mkimage.exe
else
 MKIMAGE := tools/mkimage
endif
RM := rm -rf
CP := cp -fp

SPL_AXF := u-boot-spl.axf
SPL_DTB := u-boot-spl.dtb
SYSH := hps_system.h
SOPCINFO_FILE := ./target_board/$(TARGET_BOARD)/$(DESIGN_NAME).sopcinfo

.PHONY: all
ifeq ($(GEN_SYS_HEADER),1)
  all:  $(SYSH) $(ELF) $(IMG) $(SPL_AXF) $(SPL_DTB)
else
  all:  $(ELF) $(IMG) $(SPL_AXF) $(SPL_DTB)
endif

.PHONY: clean
ifeq ($(HWLIB_INDIRECT_BUILD),0)
  clean:
	$(RM) $(SYSH) $(ELF) $(SPL_AXF) $(SPL_DTB) $(OBJ) *.axf *.objdump *.map *.bin *.sopcinfo
else
  clean:
	$(RM) $(SYSH) $(ELF) $(SPL_AXF) $(SPL_DTB) $(OBJ) *.axf *.objdump *.map *.bin *.sopcinfo $(HWLIBS_SRC) $(HWLIBS_ASM)
endif

define SET_HWLIBS_DEPENDENCIES
$(1): $(2)
	$(CP) $(2) $(1)
endef

ifeq ($(HWLIB_INDIRECT_BUILD),1)
ALL_HWLIBS_SRC = $(wildcard $(HWLIBS_ROOT)/src/hwmgr/*.c) $(wildcard $(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/*.c)

$(foreach file,$(ALL_HWLIBS_SRC),$(eval $(call SET_HWLIBS_DEPENDENCIES,$(notdir $(file)),$(file))))

ALL_HWLIBS_ASM = $(wildcard $(HWLIBS_ROOT)/src/hwmgr/*.s) $(wildcard $(HWLIBS_ROOT)/src/hwmgr/$(ALT_DEVICE_FAMILY)/*.s)

$(foreach file,$(ALL_HWLIBS_ASM),$(eval $(call SET_HWLIBS_DEPENDENCIES,$(notdir $(file)),$(file))))
endif

ifeq ($(OS),Windows_NT)
  CREATE_HEADER_PATH := $(shell cygpath "$(QUARTUS_ROOTDIR)/sopc_builder/bin")
  CREATE_HEADER := $(CREATE_HEADER_PATH)/sopc-create-header-files
else
  CREATE_HEADER := sopc-create-header-files
endif

ifeq ($(OS),Windows_NT)
$(SYSH): $(SOPCINFO_FILE)
	$(CREATE_HEADER) $(SOPCINFO_FILE) --single $(SYSH) --module $(HPS_MODULE_NAME)
	$(CP) $(SYSH) "./target_board/$(TARGET_BOARD)/$(SYSH)"
else
$(SYSH): $(SOPCINFO_FILE)
	$(CREATE_HEADER) $(SOPCINFO_FILE) --single $(SYSH) --module $(HPS_MODULE_NAME)
endif

%.o: %.c Makefile
	$(CC) $(CFLAGS) -c $< -o $@

%.o: %.s Makefile
	$(AS) $(ASFLAGS) $< -o $@
	
$(ELF): $(OBJ)
	$(LD) $(LDFLAGS) $(OBJ) -o $@ 
ifeq ($(COMPILER),GNU)
	$(OD) $(ODFLAGS) $@ > $@.objdump
else
	$(OD) $(ODFLAGS) $@ --output=$@.objdump
endif

$(BIN): $(ELF)
ifeq ($(COMPILER),GNU)
	$(OC) -O binary $(ELF) $(BIN)
else
	$(OC) --bin --output=$@ $<
endif

$(IMG): $(BIN)
	$(MKIMAGE) -A arm -O u-boot -T standalone -C none -a $(APP_LOAD_ADDR) -e 0 -n "baremetal image" -d $(BIN) $(IMG)

$(SPL_AXF): ./target_board/$(TARGET_BOARD)/u-boot-spl
	$(CP) $< $@	
	$(OD) $(ODFLAGS) $@ > $@.objdump

$(SPL_DTB): ./target_board/$(TARGET_BOARD)/u-boot-spl.dtb
	$(CP) $< $@
