// Copyright (C) 2013-2018 Altera Corporation, San Jose, California, USA. All rights reserved.
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to
// whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// This agreement shall be governed in all respects by the laws of the State of California and
// by the laws of the United States of America.
#include "AOCLUtils/aocl_utils.h"
#include <algorithm>
#include <stdarg.h>
#ifdef _WIN32 // Windows
#include <windows.h>
#else // Linux
#include <stdio.h>
#include <unistd.h> // readlink, chdir
#endif
namespace aocl_utils {
static const char *const VERSION_STR = "161";
//////////////////////////////////////////
// Host allocation functions for alignment
//////////////////////////////////////////
// This is the minimum alignment requirement to ensure DMA can be used.
const unsigned AOCL_ALIGNMENT = 64;
#ifdef _WIN32 // Windows
void *alignedMalloc(size_t size) {
return _aligned_malloc (size, AOCL_ALIGNMENT);
}
void alignedFree(void * ptr) {
_aligned_free(ptr);
}
#else // Linux
void *alignedMalloc(size_t size) {
void *result = NULL;
int rc;
rc = posix_memalign (&result, AOCL_ALIGNMENT, size);
return result;
}
void alignedFree(void * ptr) {
free (ptr);
}
#endif
///////////////////////////////
// Error functions
///////////////////////////////
// Print the error associciated with an error code
void printError(cl_int error) {
// Print error message
switch(error)
{
case -1:
printf("CL_DEVICE_NOT_FOUND ");
break;
case -2:
printf("CL_DEVICE_NOT_AVAILABLE ");
break;
case -3:
printf("CL_COMPILER_NOT_AVAILABLE ");
break;
case -4:
printf("CL_MEM_OBJECT_ALLOCATION_FAILURE ");
break;
case -5:
printf("CL_OUT_OF_RESOURCES ");
break;
case -6:
printf("CL_OUT_OF_HOST_MEMORY ");
break;
case -7:
printf("CL_PROFILING_INFO_NOT_AVAILABLE ");
break;
case -8:
printf("CL_MEM_COPY_OVERLAP ");
break;
case -9:
printf("CL_IMAGE_FORMAT_MISMATCH ");
break;
case -10:
printf("CL_IMAGE_FORMAT_NOT_SUPPORTED ");
break;
case -11:
printf("CL_BUILD_PROGRAM_FAILURE ");
break;
case -12:
printf("CL_MAP_FAILURE ");
break;
case -13:
printf("CL_MISALIGNED_SUB_BUFFER_OFFSET ");
break;
case -14:
printf("CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST ");
break;
case -30:
printf("CL_INVALID_VALUE ");
break;
case -31:
printf("CL_INVALID_DEVICE_TYPE ");
break;
case -32:
printf("CL_INVALID_PLATFORM ");
break;
case -33:
printf("CL_INVALID_DEVICE ");
break;
case -34:
printf("CL_INVALID_CONTEXT ");
break;
case -35:
printf("CL_INVALID_QUEUE_PROPERTIES ");
break;
case -36:
printf("CL_INVALID_COMMAND_QUEUE ");
break;
case -37:
printf("CL_INVALID_HOST_PTR ");
break;
case -38:
printf("CL_INVALID_MEM_OBJECT ");
break;
case -39:
printf("CL_INVALID_IMAGE_FORMAT_DESCRIPTOR ");
break;
case -40:
printf("CL_INVALID_IMAGE_SIZE ");
break;
case -41:
printf("CL_INVALID_SAMPLER ");
break;
case -42:
printf("CL_INVALID_BINARY ");
break;
case -43:
printf("CL_INVALID_BUILD_OPTIONS ");
break;
case -44:
printf("CL_INVALID_PROGRAM ");
break;
case -45:
printf("CL_INVALID_PROGRAM_EXECUTABLE ");
break;
case -46:
printf("CL_INVALID_KERNEL_NAME ");
break;
case -47:
printf("CL_INVALID_KERNEL_DEFINITION ");
break;
case -48:
printf("CL_INVALID_KERNEL ");
break;
case -49:
printf("CL_INVALID_ARG_INDEX ");
break;
case -50:
printf("CL_INVALID_ARG_VALUE ");
break;
case -51:
printf("CL_INVALID_ARG_SIZE ");
break;
case -52:
printf("CL_INVALID_KERNEL_ARGS ");
break;
case -53:
printf("CL_INVALID_WORK_DIMENSION ");
break;
case -54:
printf("CL_INVALID_WORK_GROUP_SIZE ");
break;
case -55:
printf("CL_INVALID_WORK_ITEM_SIZE ");
break;
case -56:
printf("CL_INVALID_GLOBAL_OFFSET ");
break;
case -57:
printf("CL_INVALID_EVENT_WAIT_LIST ");
break;
case -58:
printf("CL_INVALID_EVENT ");
break;
case -59:
printf("CL_INVALID_OPERATION ");
break;
case -60:
printf("CL_INVALID_GL_OBJECT ");
break;
case -61:
printf("CL_INVALID_BUFFER_SIZE ");
break;
case -62:
printf("CL_INVALID_MIP_LEVEL ");
break;
case -63:
printf("CL_INVALID_GLOBAL_WORK_SIZE ");
break;
default:
printf("UNRECOGNIZED ERROR CODE (%d)", error);
}
}
// Print line, file name, and error code if there is an error. Exits the
// application upon error.
void _checkError(int line,
const char *file,
cl_int error,
const char *msg,
...) {
// If not successful
if(error != CL_SUCCESS) {
// Print line and file
printf("ERROR: ");
printError(error);
printf("\nLocation: %s:%d\n", file, line);
// Print custom message.
va_list vl;
va_start(vl, msg);
vprintf(msg, vl);
printf("\n");
va_end(vl);
// Cleanup and bail.
cleanup();
exit(error);
}
}
// Sets the current working directory to be the same as the directory
// containing the running executable.
bool setCwdToExeDir() {
#ifdef _WIN32 // Windows
HMODULE hMod = GetModuleHandle(NULL);
char path[MAX_PATH];
GetModuleFileNameA(hMod, path, MAX_PATH);
#else // Linux
// Get path of executable.
char path[300];
ssize_t n = readlink("/proc/self/exe", path, sizeof(path)/sizeof(path[0]) - 1);
if(n == -1) {
return false;
}
path[n] = 0;
#endif
// Find the last '\' or '/' and terminate the path there; it is now
// the directory containing the executable.
size_t i;
for(i = strlen(path) - 1; i > 0 && path[i] != '/' && path[i] != '\\'; --i);
path[i] = '\0';
// Change the current directory.
#ifdef _WIN32 // Windows
SetCurrentDirectoryA(path);
#else // Linux
int rc;
rc = chdir(path);
#endif
return true;
}
// Searches all platforms for the first platform whose name
// contains the search string (case-insensitive).
cl_platform_id findPlatform(const char *platform_name_search) {
cl_int status;
std::string search = platform_name_search;
std::transform(search.begin(), search.end(), search.begin(), tolower);
// Get number of platforms.
cl_uint num_platforms;
status = clGetPlatformIDs(0, NULL, &num_platforms);
checkError(status, "Query for number of platforms failed");
// Get a list of all platform ids.
scoped_array<cl_platform_id> pids(num_platforms);
status = clGetPlatformIDs(num_platforms, pids, NULL);
checkError(status, "Query for all platform ids failed");
// For each platform