# <license>
# 
# Controller v2.1
# 
# This software is provided to enhance knowledge and encourage progress in the scientific
# community. It should be used only for research and educational purposes. Any reproduction
# or use for commercial purpose, public redistribution, in source or binary forms, with or 
# without modifications, is NOT ALLOWED without the previous authorization of the copyright 
# holder. The origin of this software must not be misrepresented; you must not claim that you
# wrote the original software. If you use this software for any purpose (e.g. publication),
# a reference to the software package and the authors must be included.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
# THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# 
# Copyright (c) 2007-2020, Trasgo Group, Universidad de Valladolid.
# All rights reserved.
# 
# More information on http://trasgo.infor.uva.es/
# 
# </license>
cmake_minimum_required (VERSION 2.6)

# Common files and include dirs
set(CTRL_INCLUDE_DIRS ${CTRL_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/Ctrl/inc)
set(CTRL_SOURCES ${CTRL_SOURCES} src/Core/Ctrl_Core.c)


# Support for OpenCl Cpu
if (SUPPORT_CPU)
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_ARCH_CPU_ ")
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_ARCH_CPU_ ")
	
	set(CTRL_SOURCES ${CTRL_SOURCES} src/Architectures/Cpu/Ctrl_Cpu.c)
endif (SUPPORT_CPU)


# Support for OpenCl Gpu
if (SUPPORT_OPENCL_GPU)
	if (OPENCL_GPU_ERROR_CHECK)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_OPENCL_GPU_ERROR_CHECK_ ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_OPENCL_GPU_ERROR_CHECK_ ")
	endif (OPENCL_GPU_ERROR_CHECK)

	if (OPENCL_GPU_PERFORMANCE)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_OPENCL_GPU_PERFORMANCE_ ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_OPENCL_GPU_PERFORMANCE_ ")
	endif (OPENCL_GPU_PERFORMANCE)

	if (OPENCL_GPU_DEBUG)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_OPENCL_GPU_DEBUG_ ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_OPENCL_GPU_DEBUG_ ")
	endif (OPENCL_GPU_DEBUG)

	if (OPENCL_GPU_TEST_OUTPUT)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_OPENCL_GPU_TEST_OUTPUT_ ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_OPENCL_GPU_TEST_OUTPUT_ ")
	endif (OPENCL_GPU_TEST_OUTPUT)

	if (OPENCL_GPU_PROFILING)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_OPENCL_GPU_PROFILING_ ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_OPENCL_GPU_PROFILING_ ")

		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_OPENCL_GPU_PROFILING_N_READ_TASKS_=${OPENCL_GPU_PROFILING_N_READ_TASKS} ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_OPENCL_GPU_PROFILING_N_READ_TASKS_=${OPENCL_GPU_PROFILING_N_READ_TASKS} ")

		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_OPENCL_GPU_PROFILING_N_WRITE_TASKS_=${OPENCL_GPU_PROFILING_N_WRITE_TASKS} ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_OPENCL_GPU_PROFILING_N_WRITE_TASKS_=${OPENCL_GPU_PROFILING_N_WRITE_TASKS} ")

		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_OPENCL_GPU_PROFILING_N_KERNEL_TASKS_=${OPENCL_GPU_PROFILING_N_KERNEL_TASKS} ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_OPENCL_GPU_PROFILING_N_KERNEL_TASKS_=${OPENCL_GPU_PROFILING_N_KERNEL_TASKS} ")

		if (OPENCL_GPU_PROFILING_VERBOSE)
			set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_OPENCL_GPU_PROFILING_VERBOSE_ ")
			set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_OPENCL_GPU_PROFILING_VERBOSE_ ")
		endif (OPENCL_GPU_PROFILING_VERBOSE)
	endif (OPENCL_GPU_PROFILING)

	if (SUPPORT_OPENCL_GPU_AMD)
		set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} /opt/amdgpu-pro/lib64/)
		set(CTRL_INCLUDE_DIRS ${CTRL_INCLUDE_DIRS} /opt/amdgpu-pro/include/)
	else (SUPPORT_OPENCL_GPU_AMD)
		set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} /usr/local/cuda/lib64)
		set(CTRL_INCLUDE_DIRS ${CTRL_INCLUDE_DIRS} /usr/local/cuda/include/)
	endif (SUPPORT_OPENCL_GPU_AMD)
	# set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} /opt/amdgpu-pro/lib/x86_64-linux-gnu/)
	# set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} /usr/local/cuda/lib64)
	# set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} /usr/lib/x86_64-linux-gnu)
	
	find_library(OPENCLLIB OpenCL HINTS ${OPENCL_LIB_DIRS})
	
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_ARCH_OPENCL_GPU_ ")
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_ARCH_OPENCL_GPU_ ")

	# set(CTRL_INCLUDE_DIRS ${CTRL_INCLUDE_DIRS} /usr/include/)
	set(CTRL_SOURCES ${CTRL_SOURCES} src/Architectures/OpenCL/Ctrl_OpenCL_Gpu.c)
	set(CTRL_LIBS ${CTRL_LIBS} ${OPENCLLIB})
endif (SUPPORT_OPENCL_GPU)


if (SUPPORT_FPGA)
	if (OPENCL_GPU_ERROR_CHECK)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_OPENCL_GPU_ERROR_CHECK_ ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_OPENCL_GPU_ERROR_CHECK_ ")
	endif (OPENCL_GPU_ERROR_CHECK)

	if (OPENCL_GPU_PERFORMANCE)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_OPENCL_GPU_PERFORMANCE_ ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_OPENCL_GPU_PERFORMANCE_ ")
	endif (OPENCL_GPU_PERFORMANCE)

	if (OPENCL_GPU_DEBUG)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_OPENCL_GPU_DEBUG_ ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_OPENCL_GPU_DEBUG_ ")
	endif (OPENCL_GPU_DEBUG)

	if (OPENCL_GPU_TEST_OUTPUT)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_OPENCL_GPU_TEST_OUTPUT_ ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_OPENCL_GPU_TEST_OUTPUT_ ")
	endif (OPENCL_GPU_TEST_OUTPUT)

	if (OPENCL_GPU_PROFILING)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_OPENCL_GPU_PROFILING_ ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_OPENCL_GPU_PROFILING_ ")

		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_OPENCL_GPU_PROFILING_N_READ_TASKS_=${OPENCL_GPU_PROFILING_N_READ_TASKS} ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_OPENCL_GPU_PROFILING_N_READ_TASKS_=${OPENCL_GPU_PROFILING_N_READ_TASKS} ")

		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_OPENCL_GPU_PROFILING_N_WRITE_TASKS_=${OPENCL_GPU_PROFILING_N_WRITE_TASKS} ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_OPENCL_GPU_PROFILING_N_WRITE_TASKS_=${OPENCL_GPU_PROFILING_N_WRITE_TASKS} ")

		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_OPENCL_GPU_PROFILING_N_KERNEL_TASKS_=${OPENCL_GPU_PROFILING_N_KERNEL_TASKS} ")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_OPENCL_GPU_PROFILING_N_KERNEL_TASKS_=${OPENCL_GPU_PROFILING_N_KERNEL_TASKS} ")

		if (OPENCL_GPU_PROFILING_VERBOSE)
			set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_OPENCL_GPU_PROFILING_VERBOSE_ ")
			set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_OPENCL_GPU_PROFILING_VERBOSE_ ")
		endif (OPENCL_GPU_PROFILING_VERBOSE)
	endif (OPENCL_GPU_PROFILING)

	set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} /glob/development-tools/versions/fpgasupportstack/a10/1.2/inteldevstack/intelFPGA_pro/hld/linux64/lib)
	set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} ${OPENCL_LIB_DIRS} /opt/intel/inteloneapi/compiler/2021.1-beta04/linux/lib/oclfpga/board/intel_a10gx_pac/linux64/lib)
	set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} ${OPENCL_LIB_DIRS} /glob/development-tools/versions/fpgasupportstack/a10/1.2/inteldevstack/intelFPGA_pro/hld/host/linux64/lib)
	set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} ${OPENCL_LIB_DIRS} -lalteracl)
	set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} ${OPENCL_LIB_DIRS} -lintel_opae_mmd)
	set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} ${OPENCL_LIB_DIRS} -lrtl)
	set(OPENCL_LIB_DIRS ${OPENCL_LIB_DIRS} ${OPENCL_LIB_DIRS} -lelf)
	set(CTRL_INCLUDE_DIRS ${CTRL_INCLUDE_DIRS} /glob/development-tools/versions/fpgasupportstack/a10/1.2/inteldevstack/intelFPGA_pro/hld/host/include)
	
	find_library(OPENCLLIB OpenCL HINTS ${OPENCL_LIB_DIRS})
	
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_ARCH_FPGA_ ")
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_ARCH_FPGA_ ")

	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCTRL_HOST_COMPILE ")
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCTRL_HOST_COMPILE ")

	# set(CTRL_INCLUDE_DIRS ${CTRL_INCLUDE_DIRS} /usr/include/)
	set(CTRL_SOURCES ${CTRL_SOURCES} src/Architectures/FPGA/Ctrl_FPGA.c)
	set(CTRL_LIBS ${CTRL_LIBS} ${OPENCLLIB})
endif (SUPPORT_FPGA)


# Support for CUDA
if (SUPPORT_CUDA)
	find_package(CUDA REQUIRED)

	if (CUDA_DEBUG)
		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_CUDA_DEBUG_ ")
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_CUDA_DEBUG_ ")
	endif (CUDA_DEBUG)

	if (CUDA_EVENT_DEBUG)
		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_CUDA_EVENT_DEBUG_ ")
		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_CUDA_EVENT_DEBUG_ ")
	endif (CUDA_EVENT_DEBUG)
	
	if (SUPPORT_CUDA_9)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_ARCH_CUDA_LEGACY_")
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_ARCH_CUDA_LEGACY_")
	endif (SUPPORT_CUDA_9)

	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CTRL_ARCH_CUDA_")
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CTRL_ARCH_CUDA_")
	set (NVCC_FLAGS "-lcuda")

	set(CUDA_LIB_DIRS ${CUDA_LIB_DIRS} /usr/local/cuda/lib64/stubs)
	find_library(CUDALIBS cuda HINTS ${CUDA_LIB_DIRS})
	
	set(CTRL_INCLUDE_DIRS ${CTRL_INCLUDE_DIRS} /usr/local/cuda/samples/common/inc)
	set(CTRL_INCLUDE_DIRS ${CTRL_INCLUDE_DIRS} ${CUDA_INCLUDE_DIRS})
	
	# TODO: Add conditional selection of CTRL_SOURCES -@ismael at 6/2/2019 17:59:19
	# Depending on Cuda architecture major version, the controller' source code has 
	# to be changed to the legacy one
	if (CUDA_VERSION_MAJOR LESS 10)
		set(SUPPORT_CUDA_9 ON)
	endif (CUDA_VERSION_MAJOR LESS 10)

	if (SUPPORT_CUDA_9)
		set(CTRL_SOURCES ${CTRL_SOURCES} src/Architectures/Cuda/Legacy/Ctrl_Cuda.c)
	else (SUPPORT_CUDA_9)
		set(CTRL_SOURCES ${CTRL_SOURCES} src/Architectures/Cuda/Ctrl_Cuda.c)
	endif (SUPPORT_CUDA_9)
	
	# set(CTRL_SOURCES ${CTRL_SOURCES} src/Architectures/Cuda/Ctrl_Cuda.c)
	set(CTRL_LIBS ${CTRL_LIBS} ${CUDA_LIBRARIES})
	set(CTRL_LIBS ${CTRL_LIBS} ${CUDALIBS})
	# set(CUDA_HOST_COMPILATION_CPP OFF)
	set(CUDA_USE_STATIC_CUDA_RUNTIME OFF)
	# set(CUDA_SEPARABLE_COMPILATION ON)
endif (SUPPORT_CUDA)


if (CTRL_CMAKE_VERBOSE_CTRL)
	message(STATUS "CTRL_CPU = ${SUPPORT_CPU}")
	message(STATUS "CTRL_CUDA = ${SUPPORT_CUDA}")
	message(STATUS "CTRL_OPENCL_GPU = ${SUPPORT_OPENCL_GPU}")
	message(STATUS "CTRL_OPENCL_GPU = ${SUPPORT_FPGA}")
	message(STATUS "CTRL_C vars = ${CMAKE_C_FLAGS}")
	message(STATUS "CTRL_CXX vars = ${CMAKE_CXX_FLAGS}")
	message(STATUS "CTRL_HEADERS = ${CTRL_HEADERS}")
	message(STATUS "CTRL_INCLUDE DIRS = ${CTRL_INCLUDE_DIRS}")
	message(STATUS "CTRL_SOURCES = ${CTRL_SOURCES}")
	message(STATUS "CTRL_LIBS = ${CTRL_LIBS}")
endif(CTRL_CMAKE_VERBOSE_CTRL)

# Include all directories
include_directories(${CTRL_INCLUDE_DIRS})

add_library(Ctrl SHARED ${CTRL_SOURCES})
target_link_libraries(Ctrl ${CTRL_LIBS})
set_target_properties(Ctrl PROPERTIES VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION} SOVERSION ${VERSION_MAJOR})

# Update parent vars
set(CTRL_LIBS ${CTRL_LIBS} PARENT_SCOPE)
set(CTRL_INCLUDE_DIRS ${CTRL_INCLUDE_DIRS} PARENT_SCOPE)
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} PARENT_SCOPE)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} PARENT_SCOPE)

set(CUDA_USE_STATIC_CUDA_RUNTIME OFF PARENT_SCOPE)

if(SUPPORT_CUDA)
	# set(CUDA_HOST_COMPILATION_CPP OFF PARENT_SCOPE)
	set(CUDA_USE_STATIC_CUDA_RUNTIME OFF PARENT_SCOPE)
endif(SUPPORT_CUDA)
