Add 'projects/rocr-runtime/' from commit '72061a9024139fa0a99f73f9d3d4deb275670095'

git-subtree-dir: projects/rocr-runtime
git-subtree-mainline: ad0fb25ed5
git-subtree-split: 72061a9024
This commit is contained in:
systems-assistant[bot]
2025-07-22 22:52:49 +00:00
645 ha cambiato i file con 322673 aggiunte e 0 eliminazioni
@@ -0,0 +1,7 @@
OPENCL_DEPTH = ../../..
include $(OPENCL_DEPTH)/runtimenew/runtimedefs
SUBDIRS = build
include $(OPENCL_DEPTH)/runtimenew/runtimerules
@@ -0,0 +1,8 @@
OPENCL_DEPTH = ../../../..
include $(OPENCL_DEPTH)/hsadefs
BUILD_SUBDIRS = $(DEFAULT_TARGETS)
BUILD_MAKEFILE = Makefile.get_info
include $(OPENCL_DEPTH)/hsarules
@@ -0,0 +1,107 @@
include $(OPENCL_DEPTH)/hsadefs
# Executable containing all the API core tests
EXE_TARGET = HsaGetInfo
#
# Makefile construct to copy executable to Dist folder
#
DIST_BIN_TARGET = $(EXE_TARGET)
ifdef ATI_OS_WINDOWS
DIST_BIN_TARGETS = $(EXE_TARGET)$(EXE_EXT)
endif
ifdef ATI_BITS_64
LIB_SUFFIX=64
BITS=64
CMPILERBITS=64
else
LIB_SUFFIX=
BITS=
ifdef ATI_OS_WINDOWS
CMPILERBITS=
else
CMPILERBITS=32
endif
endif
ifdef ATI_OS_WINDOWS
LFLAGS += /subsystem:console
CORE_LIB=dll
LIB_PREFIX=
DYN_LIB_EXT=$(LIB_EXT)
UTIL_EXT=win
else
LIB_PREFIX=lib
CORE_LIB=so
DYN_LIB_EXT=$(DLL_EXT)
UTIL_EXT=
endif
LCXXDEFS += -DAMD_INTERNAL_BUILD
vpath %.cpp $(COMPONENT_DEPTH)
CPPFILES := $(notdir $(wildcard $(COMPONENT_DEPTH)/*.cpp))
TOOLS_TEST_COMMON=$(COMPONENT_DEPTH)/../common
vpath %.cpp $(TOOLS_TEST_COMMON)
CPPFILES += $(notdir $(wildcard $(TOOLS_TEST_COMMON)/*.cpp))
ifdef ATI_OS_LINUX
GCXXOPTS := $(filter-out -fno-rtti,$(GCXXOPTS))
GCXXOPTS := $(filter-out -fno-exceptions,$(GCXXOPTS))
LFLAGS += -L$(DIST_LIB_DEST) -lpthread $(LIBSTDCXX) -lm -ldl -lrt -lstdc++
#LFLAGS += -L$(DIST_LIB_DEST) -lpthread $(LIBSTDCXX) -lm -ldl -lrt
endif
SC_DIR_NAME ?= finalizer
export HT_DEPTH=$(OPENCL_DEPTH)/compiler/$(SC_DIR_NAME)/HSAIL/hsail-tools
include $(HT_DEPTH)/htlibs
#LCINCS := $(INCSWITCH) "$(OPENCL_DEPTH)/contrib/gtest-1.6.0/include"
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/runtime"
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/runtime/samples"
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/contrib/elftoolchain/libelf"
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/contrib/elftoolchain/common"
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/runtime/inc"
LCINCS += $(LIBHSAIL_INCS) $(LIBHSAIL_AMD_INCS)
LCINCS += $(INCSWITCH) "$(OPENCL_PATH)/compiler/lib/include"
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/runtime/samples/common"
UTIL_BUILD=build/$(OS_TYPE)/util/$(UTIL_EXT)/$(BUILD_DIR)
#LLLIBS += $(OPENCL_DEPTH)/runtime/core/$(UTIL_BUILD)/util$(UTIL_EXT)$(LIB_EXT)
LIBELF_DIR=build/$(OS_TYPE)/$(BUILD_DIR)
RUNTIME_BUILD=build/$(OS_TYPE)/$(CORE_LIB)/$(BUILD_DIR)
ifdef ATI_OS_LINUX
GCXXOPTS := $(filter-out -fno-exceptions,$(GCXXOPTS))
LFLAGS += -L$(DIST_LIB_DEST) -lpthread $(LIBSTDCXX) -lm -ldl -lrt
LFLAGS += -L$(OPENCL_DEPTH)/contrib/elftoolchain/libelf/$(LIBELF_DIR) -lelf
LFLAGS += -L$(OPENCL_DEPTH)/runtime/core/$(RUNTIME_BUILD) -lhsa-runtime$(LIB_SUFFIX)
LFLAGS += -L$(OPENCL_DEPTH)/runtime/tools/$(RUNTIME_BUILD) -lhsa-runtime-tools$(LIB_SUFFIX)
else
# Verify the extension of libelf is valid i.e. is not dll but instead is "lib"
#LLLIBS += -L$(OPENCL_DEPTH)/contrib/elftoolchain/libelf/$(LIBELF_DIR)/libelf
LLLIBS += $(OPENCL_DEPTH)/runtime/core/$(RUNTIME_BUILD)/hsa-runtime$(LIB_SUFFIX)$(LIB_EXT)
LLLIBS += $(OPENCL_DEPTH)/runtime/tools/$(RUNTIME_BUILD)/hsa-runtime-tools$(LIB_SUFFIX)$(LIB_EXT)
endif
LLLIBS += $(LIBHSAIL_USER_LIBS)
#
# Copy the Hsa ample to Hsa distribution folder
#
ifdef ATI_OS_LINUX
LOCAL_TARGETS = inst_sample_copy
endif
inst_sample_copy:
$(MKDIR) $(DIST_BIN_DEST)/../../samples/$(OS_TYPE)
-$(RM) -f $(DIST_BIN_DEST)/../../samples/$(OS_TYPE)/$(EXE_TARGET)
$(CP) $(BUILD_DIR)/$(EXE_TARGET) $(DIST_BIN_DEST)/../../samples/$(OS_TYPE)
include $(OPENCL_DEPTH)/hsarules
@@ -0,0 +1,83 @@
#include "get_info.h"
#include <iostream>
GetInfo::GetInfo() : HsaTest("HSA Info") {}
GetInfo::~GetInfo() {}
void GetInfo::Run() {
std::cout << std::endl;
std::cout << "Num CPUs in platform: " << cpus_.size() << std::endl;
std::cout << "------------------------------------------------\n";
for (size_t i = 0; i < cpus_.size(); ++i) {
hsa_agent_t cpu = cpus_[i];
std::cout << "CPU[" << i << "] properties:" << std::endl;
std::cout << "------------------------------------------------\n";
AgentProps prop(cpu);
PrintAgentInfo(prop);
PrintPeers(cpu);
std::cout << "------------------------------------------------\n";
hsa_amd_memory_pool_t global_fine = global_fine_[cpu.handle];
if (global_fine.handle != 0) {
std::cout << "CPU[" << i << "] system fine grain pool properties:\n";
std::cout << "------------------------------------------------\n";
PoolProps prop(global_fine);
PrintPoolInfo(prop);
std::cout << "------------------------------------------------\n";
}
hsa_amd_memory_pool_t global_coarse = global_coarse_[cpu.handle];
if (global_coarse.handle != 0) {
std::cout << "CPU[" << i << "] system coarse grain pool properties:\n";
std::cout << "------------------------------------------------\n";
PoolProps prop(global_coarse);
PrintPoolInfo(prop);
std::cout << "------------------------------------------------\n";
}
}
std::cout << std::endl;
std::cout << "Num GPUs in platform: " << gpus_.size() << std::endl;
std::cout << "------------------------------------------------\n";
for (size_t i = 0; i < gpus_.size(); ++i) {
hsa_agent_t gpu = gpus_[i];
std::cout << "GPU[" << i << "] properties:" << std::endl;
std::cout << "------------------------------------------------\n";
AgentProps prop(gpu);
PrintAgentInfo(prop);
PrintPeers(gpu);
std::cout << "------------------------------------------------\n";
hsa_amd_memory_pool_t global_coarse = global_coarse_[gpu.handle];
if (global_coarse.handle != 0) {
std::cout << "GPU[" << i << "] local memory pool properties:\n";
std::cout << "------------------------------------------------\n";
PoolProps prop(global_coarse);
PrintPoolInfo(prop);
std::cout << "------------------------------------------------\n";
}
hsa_amd_memory_pool_t group = group_[gpu.handle];
if (group.handle != 0) {
std::cout << "GPU[" << i << "] group memory pool properties:\n";
std::cout << "------------------------------------------------\n";
PoolProps prop(group);
PrintPoolInfo(prop);
std::cout << "------------------------------------------------\n";
}
}
}
int main(int argc, char* argv[]) {
GetInfo get_info;
get_info.Init();
get_info.Run();
get_info.Cleanup();
return 0;
}
@@ -0,0 +1,14 @@
#ifndef GET_INFO_H
#define GET_INFO_H
#include "samples/common/hsa_test.h"
class GetInfo : public HsaTest {
public:
GetInfo();
~GetInfo();
void Run() override;
};
#endif // GET_INFO_H
+17
Vedi File
@@ -0,0 +1,17 @@
OPENCL_DEPTH = ../..
include $(OPENCL_DEPTH)/hsadefs
SUBDIRS = NBody
SUBDIRS += DwtHarr1D
SUBDIRS += BitonicSort
SUBDIRS += BinarySearch
SUBDIRS += BlackScholes
SUBDIRS += FloydWarshall
SUBDIRS += FastWalshTransform
SUBDIRS += MatrixTranspose
SUBDIRS += MatrixMultiplication
SUBDIRS += MonteCarloAsian
SUBDIRS += SimpleConvolution
include $(OPENCL_DEPTH)/hsarules
@@ -0,0 +1,48 @@
#include "common.hpp"
void ErrorCheck(hsa_status_t hsa_error_code) {
if (hsa_error_code != HSA_STATUS_SUCCESS) {
std::cerr << "HSA reported error!" << std::endl;
exit(EXIT_FAILURE);
}
}
hsa_status_t FindGpuDevice(hsa_agent_t agent, void *data) {
if (data == NULL) {
return HSA_STATUS_ERROR_INVALID_ARGUMENT;
}
hsa_device_type_t hsa_device_type;
hsa_status_t hsa_error_code = hsa_agent_get_info(
agent, HSA_AGENT_INFO_DEVICE, &hsa_device_type
);
if (hsa_error_code != HSA_STATUS_SUCCESS) {
return hsa_error_code;
}
if (hsa_device_type == HSA_DEVICE_TYPE_GPU) {
*((hsa_agent_t*)data) = agent;
}
return HSA_STATUS_SUCCESS;
}
hsa_status_t FindHostRegion(hsa_region_t region, void *data) {
if (data == NULL) {
return HSA_STATUS_ERROR_INVALID_ARGUMENT;
}
bool is_host_region = false;
hsa_status_t hsa_error_code = hsa_region_get_info(
region, (hsa_region_info_t)HSA_AMD_REGION_INFO_HOST_ACCESSIBLE,
&is_host_region);
if (hsa_error_code != HSA_STATUS_SUCCESS) {
return hsa_error_code;
}
if (is_host_region) {
*((hsa_region_t*)data) = region;
}
return HSA_STATUS_SUCCESS;
}
@@ -0,0 +1,27 @@
#ifndef COMMON_COMMON_HPP
#define COMMON_COMMON_HPP
#include <cstdlib>
#include <iostream>
#include "hsa.h"
#include "hsa_ext_finalize.h"
#include "hsa_ext_amd.h"
#if defined(_MSC_VER)
#define ALIGNED_(x) __declspec(align(x))
#else
#if defined(__GNUC__)
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif // __GNUC__
#endif // _MSC_VER
#define MULTILINE(...) # __VA_ARGS__
void ErrorCheck(hsa_status_t hsa_error_code);
hsa_status_t FindGpuDevice(hsa_agent_t agent, void *data);
hsa_status_t FindHostRegion(hsa_region_t region, void *data);
#endif // COMMON_COMMON_HPP
@@ -0,0 +1,67 @@
#include "common_utility.h"
double CalcMedian(vector<double> scores)
{
double median;
size_t size = scores.size();
if (size % 2 == 0)
median = (scores[size / 2 - 1] + scores[size / 2]) / 2;
else
median = scores[size / 2];
return median;
}
double CalcMean(vector<double> scores)
{
double mean = 0;
size_t size = scores.size();
for (int i=0; i<size; ++i)
mean += scores[i];
return mean/size;
}
double CalcStdDeviation(vector<double> scores, int score_mean)
{
double ret = 0.0;
for (int i=0; i<scores.size(); ++i)
{
ret += (scores[i] - score_mean) * (scores[i] - score_mean);
}
ret /= scores.size();
return sqrt(ret);
}
int CalcConcurrentQueues(vector<double> scores)
{
int num_of_concurrent_queues = 0;
vector<double>execpted_exec_time_array;
for (int i=0; i<scores.size(); ++i)
{
execpted_exec_time_array.push_back(scores[0]/(1<<i));
}
for (int i=0; i<scores.size(); ++i)
{
cout << "expected exe time = " << execpted_exec_time_array[i] << endl;
}
for (int i=1; i<scores.size(); ++i)
{
if ((execpted_exec_time_array[i] - scores[i]) < 0.1 * execpted_exec_time_array[i])
++num_of_concurrent_queues;
}
return num_of_concurrent_queues;
}
@@ -0,0 +1,13 @@
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
double CalcMean(vector<double> scores);
double CalcMedian(vector<double> scores);
double CalcStdDeviation(vector<double> scores, int score_mean);
int CalcConcurrentQueues(vector<double> scores);
+386
Vedi File
@@ -0,0 +1,386 @@
/**********************************************************************
Copyright ©2013 Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
• Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
• Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
********************************************************************/
#include "helper_funcs.hpp"
#ifndef _WIN32
#include <unistd.h>
#endif
/*
* Prints no more than 256 elements of the given array.
* Prints full array if length is less than 256.
* Prints Array name followed by elements.
*/
template<typename T>
void printArray(
const std::string header,
const T * data,
const int width,
const int height)
{
std::cout<<"\n"<<header<<"\n";
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
std::cout<<data[i*width+j]<<" ";
}
std::cout<<"\n";
}
std::cout<<"\n";
}
template<typename T>
int fillRandom(
T * arrayPtr,
const int width,
const int height,
const T rangeMin,
const T rangeMax,
unsigned int seed)
{
if(!arrayPtr)
{
error("Cannot fill array. NULL pointer.");
return HSA_SDK_FAILURE;
}
if(!seed)
seed = (unsigned int)time(NULL);
srand(seed);
double range = double(rangeMax - rangeMin) + 1.0;
/* random initialisation of input */
for(int i = 0; i < height; i++)
for(int j = 0; j < width; j++)
{
int index = i*width + j;
arrayPtr[index] = rangeMin + T(range*rand()/(RAND_MAX + 1.0));
}
return HSA_SDK_SUCCESS;
}
template<typename T>
int fillPos(
T * arrayPtr,
const int width,
const int height)
{
if(!arrayPtr)
{
error("Cannot fill array. NULL pointer.");
return HSA_SDK_FAILURE;
}
/* initialisation of input with positions*/
for(T i = 0; i < height; i++)
for(T j = 0; j < width; j++)
{
T index = i*width + j;
arrayPtr[index] = index;
}
return HSA_SDK_SUCCESS;
}
template<typename T>
int fillConstant(
T * arrayPtr,
const int width,
const int height,
const T val)
{
if(!arrayPtr)
{
error("Cannot fill array. NULL pointer.");
return HSA_SDK_FAILURE;
}
/* initialisation of input with constant value*/
for(int i = 0; i < height; i++)
for(int j = 0; j < width; j++)
{
int index = i*width + j;
arrayPtr[index] = val;
}
return HSA_SDK_SUCCESS;
}
template<typename T>
T roundToPowerOf2(T val)
{
int bytes = sizeof(T);
val--;
for(int i = 0; i < bytes; i++)
val |= val >> (1<<i);
val++;
return val;
}
template<typename T>
int isPowerOf2(T val)
{
long long _val = val;
if((_val & (-_val))-_val == 0 && _val != 0)
return HSA_SDK_SUCCESS;
else
return HSA_SDK_FAILURE;
}
template<typename T>
bool checkVal(
T input,
T reference,
std::string message,
bool isAPIerror)
{
if(input==reference)
{
return true;
}
else
{
error(message);
return false;
}
}
template<typename T>
std::string toString(T t, std::ios_base &(*r)(std::ios_base&))
{
std::ostringstream output;
output << r << t;
return output.str();
}
bool
compare(const float *refData, const float *data,
const int length, const float epsilon)
{
float error = 0.0f;
float ref = 0.0f;
for(int i = 1; i < length; ++i)
{
float diff = refData[i] - data[i];
error += diff * diff;
ref += refData[i] * refData[i];
}
float normRef =::sqrtf((float) ref);
if (::fabs((float) ref) < 1e-7f) {
return false;
}
float normError = ::sqrtf((float) error);
error = normError / normRef;
return error < epsilon;
}
bool
compare(const double *refData, const double *data,
const int length, const double epsilon)
{
double error = 0.0;
double ref = 0.0;
for(int i = 1; i < length; ++i)
{
double diff = refData[i] - data[i];
error += diff * diff;
ref += refData[i] * refData[i];
}
double normRef =::sqrt((double) ref);
if (::fabs((double) ref) < 1e-7) {
return false;
}
double normError = ::sqrt((double) error);
error = normError / normRef;
return error < epsilon;
}
void
error(const char* errorMsg)
{
std::cout<<"Error: "<<errorMsg<<std::endl;
}
void
error(std::string errorMsg)
{
std::cout<<"Error: "<<errorMsg<<std::endl;
}
void
expectedError(const char* errorMsg)
{
std::cout<<"Expected Error: "<<errorMsg<<std::endl;
}
void
expectedError(std::string errorMsg)
{
std::cout<<"Expected Error: "<<errorMsg<<std::endl;
}
/////////////////////////////////////////////////////////////////
// Template Instantiations
/////////////////////////////////////////////////////////////////
template
void printArray<short>(const std::string,
const short*, int, int);
template
void printArray<unsigned char>(const std::string,
const unsigned char *, int, int);
template
void printArray<unsigned int>(const std::string,
const unsigned int *, int, int);
template
void printArray<int>(const std::string,
const int *, int, int);
template
void printArray<long>(const std::string,
const long*, int, int);
template
void printArray<float>(const std::string,
const float*, int, int);
template
void printArray<double>(const std::string,
const double*, int, int);
template
int fillRandom<unsigned char>(unsigned char* arrayPtr,
const int width, const int height,
unsigned char rangeMin, unsigned char rangeMax, unsigned int seed);
template
int fillRandom<unsigned int>(unsigned int* arrayPtr,
const int width, const int height,
unsigned int rangeMin, unsigned int rangeMax, unsigned int seed);
template
int fillRandom<int>(int* arrayPtr,
const int width, const int height,
int rangeMin, int rangeMax, unsigned int seed);
template
int fillRandom<long>(long* arrayPtr,
const int width, const int height,
long rangeMin, long rangeMax, unsigned int seed);
template
int fillRandom<float>(float* arrayPtr,
const int width, const int height,
float rangeMin, float rangeMax, unsigned int seed);
template
int fillRandom<double>(double* arrayPtr,
const int width, const int height,
double rangeMin, double rangeMax, unsigned int seed);
template
short roundToPowerOf2<short>(short val);
template
unsigned int roundToPowerOf2<unsigned int>(unsigned int val);
template
int roundToPowerOf2<int>(int val);
template
long roundToPowerOf2<long>(long val);
template
int isPowerOf2<short>(short val);
template
int isPowerOf2<unsigned int>(unsigned int val);
template
int isPowerOf2<int>(int val);
template
int isPowerOf2<long>(long val);
template<>
int fillPos<short>(short * arrayPtr, const int width, const int height);
template<>
int fillPos<unsigned int>(unsigned int * arrayPtr, const int width, const int height);
template<>
int fillPos<int>(int * arrayPtr, const int width, const int height);
template<>
int fillPos<long>(long * arrayPtr, const int width, const int height);
template<>
int fillConstant<short>(short * arrayPtr,
const int width, const int height,
const short val);
template<>
int fillConstant(unsigned int * arrayPtr,
const int width, const int height,
const unsigned int val);
template<>
int fillConstant(int * arrayPtr,
const int width, const int height,
const int val);
template<>
int fillConstant(long * arrayPtr,
const int width, const int height,
const long val);
template<>
int fillConstant(long * arrayPtr,
const int width, const int height,
const long val);
template<>
int fillConstant(long * arrayPtr,
const int width, const int height,
const long val);
template
bool checkVal<char>(char input, char reference, std::string message, bool isAPIerror);
template
bool checkVal<bool>(bool input, bool reference, std::string message, bool isAPIerror);
template
bool checkVal<std::string>(std::string input, std::string reference, std::string message, bool isAPIerror);
template
bool checkVal<short>(short input, short reference, std::string message, bool isAPIerror);
template
bool checkVal<unsigned int>(unsigned int input, unsigned int reference, std::string message, bool isAPIerror);
template
bool checkVal<int>(int input, int reference, std::string message, bool isAPIerror);
template
bool checkVal<long>(long input, long reference, std::string message, bool isAPIerror);
template
std::string toString<char>(char t, std::ios_base &(*r)(std::ios_base&));
template
std::string toString<short>(short t, std::ios_base &(*r)(std::ios_base&));
template
std::string toString<unsigned int>(unsigned int t, std::ios_base &(*r)(std::ios_base&));
template
std::string toString<int>(int t, std::ios_base &(*r)(std::ios_base&));
template
std::string toString<long>(long t, std::ios_base &(*r)(std::ios_base&));
template
std::string toString<float>(float t, std::ios_base &(*r)(std::ios_base&));
template
std::string toString<double>(double t, std::ios_base &(*r)(std::ios_base&));
+159
Vedi File
@@ -0,0 +1,159 @@
/**********************************************************************
Copyright ©2013 Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
• Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
• Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
********************************************************************/
#ifndef HELPER_FUNCS_HPP_
#define HELPER_FUNCS_HPP_
#define HSA_SDK_SUCCESS 0
#define HSA_SDK_FAILURE 1
#define HSA_SDK_EXPECTED_FAILURE 2
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#include <ctime>
#include <cmath>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <malloc.h>
/**
* error
* constant function, Prints error messages
* @param errorMsg char* message
*/
void error(const char* errorMsg);
/**
* error
* constant function, Prints error messages
* @param errorMsg std::string message
*/
void error(std::string errorMsg);
/**
* expectedError
* constant function, Prints error messages
* @param errorMsg char* message
*/
void expectedError(const char* errorMsg);
/**
* expectedError
* constant function, Prints error messages
* @param errorMsg string message
*/
void expectedError(std::string errorMsg);
/**
* compare template version
* compare data to check error
* @param refData templated input
* @param data templated input
* @param length number of values to compare
* @param epsilon errorWindow
*/
bool compare(const float *refData, const float *data,
const int length, const float epsilon = 1e-6f);
bool compare(const double *refData, const double *data,
const int length, const double epsilon = 1e-6);
/**
* printArray
* displays a array on std::out
*/
template<typename T>
void printArray(
const std::string header,
const T * data,
const int width,
const int height);
/**
* fillRandom
* fill array with random values
*/
template<typename T>
int fillRandom(
T * arrayPtr,
const int width,
const int height,
const T rangeMin,
const T rangeMax,
unsigned int seed=123);
/**
* fillPos
* fill the specified positions
*/
template<typename T>
int fillPos(
T * arrayPtr,
const int width,
const int height);
/**
* fillConstant
* fill the array with constant value
*/
template<typename T>
int fillConstant(
T * arrayPtr,
const int width,
const int height,
const T val);
/**
* roundToPowerOf2
* rounds to a power of 2
*/
template<typename T>
T roundToPowerOf2(T val);
/**
* isPowerOf2
* checks if input is a power of 2
*/
template<typename T>
int isPowerOf2(T val);
/**
* checkVal
* Set default(isAPIerror) parameter to false
* if checkVaul is used to check otherthan OpenCL API error code
*/
template<typename T>
bool checkVal(
T input,
T reference,
std::string message, bool isAPIerror = true);
/**
* toString
* convert a T type to string
*/
template<typename T>
std::string toString(T t, std::ios_base & (*r)(std::ios_base&));
#endif
@@ -0,0 +1,318 @@
#include "hsa_base_util.h"
#include "HSAILAmdExt.h"
void HSA_UTIL::GetHsailNameAndKernelName(char * file_name_full, char *file_name_base, char *kernel_name)
{
strcpy(hail_file_name_full, file_name_full);
strcpy(hail_file_name_base, file_name_base);
strcpy(hsa_kernel_name, kernel_name);
}
HSA_UTIL::HSA_UTIL()
{
#ifdef TIME
base_kernel_time_idx = base_timer.CreateTimer();
base_setup_time_idx = base_timer.CreateTimer();
#endif
}
HSA_UTIL::~HSA_UTIL()
{
}
bool HSA_UTIL::HsaInit()
{
#ifdef TIME
base_timer.StartTimer(base_setup_time_idx);
#endif
err = hsa_init();
check(Initializing the hsa runtime, err);
/*
* Iterate over the agents and pick the gpu agent using
* the find_gpu callback.
*/
err = hsa_iterate_agents(find_gpu, &device);
check(Calling hsa_iterate_agents, err);
err = (device.handle== 0) ? HSA_STATUS_ERROR : HSA_STATUS_SUCCESS;
check(Checking if the GPU device is non-zero, err);
if (err == HSA_STATUS_ERROR)
return false;
/*
* Query the maximum size of the queue.
*/
err = hsa_agent_get_info(device, HSA_AGENT_INFO_QUEUE_MAX_SIZE, &queue_size);
check(Querying the device maximum queue size, err);
/*
* Create a queue using the maximum size.
*/
err = hsa_queue_create(device, queue_size, HSA_QUEUE_TYPE_MULTI, NULL, NULL, 0, 0, &command_queue);
check(Creating the queue, err);
profile = hsa_profile_t(108);
hsa_agent_get_info(device, HSA_AGENT_INFO_PROFILE, &profile);
if (profile == HSA_PROFILE_BASE)
{
memset(hail_file_name_full, 0, sizeof(char)*128);
cout << "Loading base profile!!!" << endl;
strcpy(hail_file_name_full, hail_file_name_base); //overwrite full hsail file name with base
}
amd::hsail::registerExtensions();
if (!tool.assembleFromFile(hail_file_name_full))
{
std::cout << tool.output();
return false;
}
module = tool.brigModule();
// Create hsail program.
err = hsa_ext_program_create(HSA_MACHINE_MODEL_LARGE, profile, HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO, NULL, &hsa_program);
check("Error in creating program object", err);
// Add hsail module.
//cout << "hsail file name = " << hail_file_name_full << endl;
err = hsa_ext_program_add_module(hsa_program, module);
check("Error in adding module to program object", err);
// Finalize hsail program.
hsa_isa_t isa = {0};
err = hsa_agent_get_info(device, HSA_AGENT_INFO_ISA, &isa);
check("Get hsa agent info isa", err);
hsa_ext_control_directives_t control_directives;
memset(&control_directives, 0, sizeof(hsa_ext_control_directives_t));
err = hsa_ext_program_finalize(hsa_program,
isa,
0,
control_directives,
NULL, //"-g -O0 -dump-isa",
HSA_CODE_OBJECT_TYPE_PROGRAM,
&code_object);
check("Error in finalizing program object", err);
// Create executable.
err = hsa_executable_create(profile, HSA_EXECUTABLE_STATE_UNFROZEN, "", &hsaExecutable);
check("Error in creating executable object", err);
// Load code object.
err = hsa_executable_load_code_object(hsaExecutable, device, code_object, "");
check("Error in loading executable object", err);
// Freeze executable.
err = hsa_executable_freeze(hsaExecutable, "");
check("Error in freezing executable object", err);
// Get symbol handle.
err = hsa_executable_get_symbol(hsaExecutable, NULL, hsa_kernel_name, device, 0, &kernelSymbol);
check("get symbol handle", err);
// Get code handle.
err = hsa_executable_symbol_get_info(kernelSymbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &codeHandle);
check("Get code handle", err);
#ifdef TIME
base_timer.StopTimer(base_setup_time_idx);
#endif
//hsa_region_t local_kernarg_region;
mem_region.kernarg_region.handle = 0;
mem_region.coarse_region.handle = 0;
hsa_agent_iterate_regions(device, get_memory_region, &mem_region);
err = (mem_region.kernarg_region.handle== 0) ? HSA_STATUS_ERROR : HSA_STATUS_SUCCESS;
check(Finding a kernarg memory region, err);
return true;
}
double HSA_UTIL::Run(int dim, int group_x, int group_y, int group_z, int s_size, int grid_x, int grid_y, int grid_z, void* kernel_args, int kernel_args_size)
{
#ifdef TIME
base_timer.StartTimer(base_kernel_time_idx);
#endif
/*
* Create a signal to wait for the dispatch to finish.
*/
hsa_signal_t local_signal;
err=hsa_signal_create(1, 0, NULL, &local_signal);
check(Creating a HSA_UTIL signal, err);
/* Initialize the dispatch packet */
hsa_kernel_dispatch_packet_t local_dispatch_packet;
memset(&local_dispatch_packet, 0, sizeof(hsa_kernel_dispatch_packet_t));
/*
* Setup the dispatch information.
*/
local_dispatch_packet.completion_signal=local_signal;
local_dispatch_packet.setup |= dim<< HSA_KERNEL_DISPATCH_PACKET_SETUP_DIMENSIONS;
local_dispatch_packet.workgroup_size_x = group_x;
local_dispatch_packet.workgroup_size_y = group_y;
local_dispatch_packet.workgroup_size_z = group_z;
local_dispatch_packet.group_segment_size = s_size;
local_dispatch_packet.grid_size_x = grid_x;
local_dispatch_packet.grid_size_y = grid_y;
local_dispatch_packet.grid_size_z = grid_z;
local_dispatch_packet.header |= HSA_PACKET_TYPE_KERNEL_DISPATCH;
//local_dispatch_packet.header |= HSA_FENCE_SCOPE_AGENT << HSA_PACKET_HEADER_ACQUIRE_FENCE_SCOPE;
//local_dispatch_packet.header |= HSA_FENCE_SCOPE_AGENT << HSA_PACKET_HEADER_RELEASE_FENCE_SCOPE;
local_dispatch_packet.header |= HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_ACQUIRE_FENCE_SCOPE;
local_dispatch_packet.header |= HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_RELEASE_FENCE_SCOPE;
local_dispatch_packet.kernel_object = codeHandle;
// Specify amount of private segment size (in bytes) that is needed per work-item
// Retrieve the amount of private memory needed
uint32_t private_mem_size = 0;
hsa_executable_symbol_get_info(kernelSymbol,
HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_PRIVATE_SEGMENT_SIZE, &private_mem_size);
local_dispatch_packet.private_segment_size = private_mem_size;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
* Find a memory region that supports kernel arguments.
*/
/*
kernarg_region.handle = 0;
hsa_agent_iterate_regions(device, get_kernarg, &kernarg_region);
err = (kernarg_region.handle== 0) ? HSA_STATUS_ERROR : HSA_STATUS_SUCCESS;
check(Finding a kernarg memory region, err);
*/
void* local_kernel_arg_buffer = NULL;
/*
* Allocate the kernel argument buffer from the correct region.
*/
err = hsa_memory_allocate(mem_region.kernarg_region, kernel_args_size, &local_kernel_arg_buffer);
check(Allocating kernel argument memory buffer, err);
memcpy(local_kernel_arg_buffer, kernel_args, kernel_args_size);
local_dispatch_packet.kernarg_address = local_kernel_arg_buffer;
/*
* Obtain the current queue write index.
*/
uint64_t index = hsa_queue_load_write_index_relaxed(command_queue);
/*
* Write the aql packet at the calculated queue index address.
*/
const uint32_t queueMask = command_queue->size - 1;
((hsa_kernel_dispatch_packet_t*)(command_queue->base_address))[index&queueMask]=local_dispatch_packet;
/*
* Increment the write index and ring the doorbell to dispatch the kernel.
*/
hsa_queue_store_write_index_relaxed(command_queue, index+1);
hsa_signal_store_release(command_queue->doorbell_signal, index);
/*
* Wait on the dispatch signal until all kernel are finished.
*/
while (hsa_signal_wait_acquire(local_signal, HSA_SIGNAL_CONDITION_EQ, 0, UINT64_MAX, HSA_WAIT_STATE_ACTIVE) != 0);
#ifdef TIME
base_timer.StopTimer(base_kernel_time_idx);
#endif
/*
* Cleanup all allocated resources.
*/
err = hsa_memory_free(local_kernel_arg_buffer);
check(Deallocate memory, err);
err=hsa_signal_destroy(local_signal);
check(Destroying the local_signal, err);
return 0;
}
double HSA_UTIL::GetKernelTime()
{
return base_timer.ReadTimer(base_kernel_time_idx);
}
double HSA_UTIL::GetSetupTime()
{
return base_timer.ReadTimer(base_setup_time_idx);
}
void HSA_UTIL::Close()
{
err = hsa_executable_destroy(hsaExecutable);
check(Destroying the hsaExecutable, err)
err = hsa_code_object_destroy(code_object);
check(Destroying the code_object, err);
err=hsa_queue_destroy(command_queue);
check(Destroying the queue, err);
err=hsa_shut_down();
check(Shutting down the runtime, err);
}
void* HSA_UTIL::AllocateLocalMemory(size_t size)
{
void *buffer = NULL;
// Allocate in local memory only if it is available
if (mem_region.coarse_region.handle != 0)
{
cout << "Allocating in local memory" << endl;
err = hsa_memory_allocate(mem_region.coarse_region, size, (void **)&buffer);
check(hsa memory allocation in local memory, err);
// register agent
err = hsa_memory_assign_agent(buffer, device, HSA_ACCESS_PERMISSION_RW);
return (err == HSA_STATUS_SUCCESS) ? buffer : NULL;
}
// Allocate in system memory if local memory is not available
cout << "Allocating in system memory" << endl;
err = hsa_memory_allocate(mem_region.kernarg_region, size, (void **)&buffer);
return (err == HSA_STATUS_SUCCESS) ? buffer : NULL;
}
void* HSA_UTIL::AllocateSysMemory( size_t size)
{
void *buffer = NULL;
err = hsa_memory_allocate(mem_region.kernarg_region, size, (void **)&buffer);
return (err == HSA_STATUS_SUCCESS) ? buffer : NULL;
}
bool HSA_UTIL::TransferData(void *dest, void *src, uint length, bool host_to_dev)
{
hsa_status_t status;
void *buffer = (host_to_dev) ? dest : src;
err = hsa_memory_assign_agent(buffer, device, HSA_ACCESS_PERMISSION_RW);
if (err != HSA_STATUS_SUCCESS)
{
return false;
}
err = hsa_memory_copy(dest, src, length); // first is dest, second is src
return (err == HSA_STATUS_SUCCESS);
}
@@ -0,0 +1,65 @@
#ifndef __HSA_BASE__
#define __HSA_BASE__
#include <vector>
#include "hsa.h"
#include "hsa_ext_finalize.h"
#include "hsa_ext_amd.h"
#include "hsatimer.h"
#include "utilities.h"
#include "common.hpp"
#include "HSAILTool.h"
class HSA_UTIL{
public:
HSA_UTIL();
~HSA_UTIL();
public:
void GetHsailNameAndKernelName(char *hail_file_name_full, char *hail_file_name_base, char *kernel_name);
bool HsaInit();
void Close();
double GetKernelTime();
double GetSetupTime();
void* AllocateLocalMemory(size_t size) ;
void* AllocateSysMemory(size_t size);
bool TransferData(void *dest, void *src, uint length, bool host_to_dev) ;
double Run(int dim, int group_x, int group_y, int group_z, int s_size, int grid_x, int grid_y, int grid_z, void* kernel_args, int kernel_args_size);
public:
hsa_status_t err;
uint32_t queue_size;
hsa_agent_t device;
MemRegion mem_region;
//hsa_region_t kernarg_region;
// Memory region supporting kernel parameters
// hsa_region_t coarse_region;
// Hsail profile supported by agent
hsa_profile_t profile;
char hail_file_name_full[128];
char hail_file_name_base[128];
char hsa_kernel_name[128];
hsa_queue_t* command_queue;
HSAIL_ASM::Tool tool;
hsa_ext_module_t module;
hsa_ext_program_t hsa_program;
hsa_executable_t hsaExecutable;
hsa_executable_symbol_t kernelSymbol;
hsa_code_object_t code_object;
uint64_t codeHandle;
hsa_signal_t hsa_signal;
hsa_kernel_dispatch_packet_t dispatch_packet;
hsa_region_t hsa_kernarg_region;
PerfTimer base_timer;
int base_kernel_time_idx;
int base_setup_time_idx;
};
#endif
@@ -0,0 +1,184 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <cassert>
#include <iostream>
#include <vector>
#include <string>
#include <stdlib.h>
#include "hsa.h"
#include "tools/inc/hsa_ext_profiler.h"
#include "tools/inc/amd_hsa_tools_interfaces.h"
#include "hsa_perf_cntrs.hpp"
using namespace std;
void PreDispatchCallback(const hsa_dispatch_callback_t* dispParam, void* usrArg) {
assert((dispParam->pre_dispatch) && "Pre Dispatch Callback Param is Malformed");
hsa_ext_tools_pmu_t* perfMgr = reinterpret_cast<hsa_ext_tools_pmu_t*>(usrArg);
hsa_status_t status = hsa_ext_tools_pmu_begin(*perfMgr, dispParam->queue,
dispParam->aql_translation_handle, true);
assert((status == HSA_STATUS_SUCCESS) && "Error in beginning Perf Cntr Session");
}
void PostDispatchCallback(const hsa_dispatch_callback_t* dispParam, void* usrArg) {
assert((!dispParam->pre_dispatch) && "Post Dispatch Callback Param is Malformed");
hsa_ext_tools_pmu_t* perfMgr = reinterpret_cast<hsa_ext_tools_pmu_t*>(usrArg);
hsa_status_t status = hsa_ext_tools_pmu_end(*perfMgr, dispParam->queue,
dispParam->aql_translation_handle);
assert((status == HSA_STATUS_SUCCESS) && "Error in endning Perf Cntr Session");
}
// Constructor of the class
RocrPerfCntrApp::RocrPerfCntrApp( ) : perfMgr_(NULL) {
}
// Destructor of the class. Ideally it should delete the
// PMU and its counters
RocrPerfCntrApp::~RocrPerfCntrApp( ) {
}
// Return the number of perf counters
uint32_t RocrPerfCntrApp::GetNumPerfCntrs( ) {
return uint32_t(cntrList_.size());
}
// Return the handle of perf counter at specified index
CntrInfo* RocrPerfCntrApp::GetPerfCntr(uint32_t idx) {
return cntrList_[idx];
}
// Print the various fields of Perf Cntrs being programmed
bool RocrPerfCntrApp::PrintCntrs( ) {
CntrInfo *info;
int size = uint32_t(cntrList_.size());
for (int idx = 0; idx < size; idx++) {
info = cntrList_[idx];
std::cout << std::endl;
std::cout << "Rocr Perf Cntr Id: " << info->cntrId << std::endl;
std::cout << "Rocr Perf Cntr Name: " << info->cntrName << std::endl;
std::cout << "Rocr Perf Cntr Blk Id: " << info->blkId << std::endl;
std::cout << "Rocr Perf Cntr Value: " << info->cntrResult << std::endl;
std::cout << "Rocr Perf Cntr Validation: " << info->cnfType << std::endl;
std::cout << std::endl;
}
return true;
}
// Initialize the list of perf counters
// block id of kHsaAiCounterBlockSQ = 14 == 0x0E
hsa_status_t RocrPerfCntrApp::Init(hsa_agent_t agent) {
// Initialize the list of Perf Cntrs
// Add SQ counter for number of waves
CntrInfo* info = NULL;
cntrList_.reserve(23);
char *cntrChoice = getenv("IOMMU");
if (cntrChoice == NULL) {
// Event for number of Waves
info = new CntrInfo(0x4, "SQ_SQ_PERF_SEL_WAVES", NULL,
0x0E, NULL, 0x00, 0xFFFFFFFF, CntrValCnf_Exact);
cntrList_.push_back(info);
// Event for number of Threads
info = new CntrInfo(0xE, "SQ_SQ_PERF_SEL_ITEMS", NULL,
0x0E, NULL, 0x00, 0xFFFFFFFF, CntrValCnf_Exact);
cntrList_.push_back(info);
} else {
// Program to collect event number 4
info = new CntrInfo(0x4, "Iommu_Cntr_4", NULL,
0x63, NULL, 0x00, 0xFFFFFFFF, CntrValCnf_None);
cntrList_.push_back(info);
// Program to collect event number 6
info = new CntrInfo(0x6, "Iommu_Cntr_6", NULL,
0x63, NULL, 0x00, 0xFFFFFFFF, CntrValCnf_None);
cntrList_.push_back(info);
}
// Create an instance of Perf Mgr
hsa_status_t status;
status = hsa_ext_tools_create_pmu(agent, &perfMgr_);
assert((status == HSA_STATUS_SUCCESS) && "Error in creating Perf Cntr Mgr");
// Process each counter from the list as necessary
// each counter descriptor with its perf block handle
// and create an instance of counter in that block
uint32_t size = GetNumPerfCntrs();
for (uint32_t idx = 0; idx < size; idx++) {
info = GetPerfCntr(idx);
// Obtain the handle of perf block
if (info->blkHndl == NULL) {
status = hsa_ext_tools_get_counter_block_by_id(perfMgr_, info->blkId, &info->blkHndl);
assert((status == HSA_STATUS_SUCCESS) && "Error in getting Perf Cntr Blk Hndl");
}
// Create an instance of counter in the perf block
status = hsa_ext_tools_create_counter(info->blkHndl, &info->cntrHndl);
assert((status == HSA_STATUS_SUCCESS) && "Error in creating Perf Cntr in Perf Blk");
// Update the Event Index property of counter
uint32_t cntrProp = HSA_EXT_TOOLS_COUNTER_PARAMETER_EVENT_INDEX;
status = hsa_ext_tools_set_counter_parameter(info->cntrHndl, cntrProp,
sizeof(uint32_t), (void*)&info->cntrId);
assert((status == HSA_STATUS_SUCCESS) && "Error in updating Perf Cntr Property Event Index");
// Enable the updated perf counter
status = hsa_ext_tools_set_counter_enabled(info->cntrHndl, true);
assert((status == HSA_STATUS_SUCCESS) && "Error in enabing Perf Cntr");
}
return status;
}
// Register Pre and Post dispatch callbacks
void RocrPerfCntrApp::RegisterCallbacks(hsa_queue_t *queue){
hsa_status_t status;
status = hsa_ext_tools_set_callback_functions(queue, PreDispatchCallback, PostDispatchCallback);
assert((status == HSA_STATUS_SUCCESS) && "Error in registering Pre & Post Dispatch Callbacks");
status = hsa_ext_tools_set_callback_arguments(queue, &perfMgr_, &perfMgr_);
assert((status == HSA_STATUS_SUCCESS) && "Error in registering Pre & Post Dispatch Callback Params");
return;
}
// Wait for perf counter collection to complete
hsa_status_t RocrPerfCntrApp::Wait() {
hsa_status_t status;
status = hsa_ext_tools_pmu_wait_for_completion(perfMgr_, 5000);
assert((status == HSA_STATUS_SUCCESS) && "Error in Waiting for Perf Cntr Completion");
return status;
}
// Validate perf counter values
hsa_status_t RocrPerfCntrApp::Validate() {
// Retrieve the results of the different Perf Cntrs
// and validate them as configured
CntrInfo* info = NULL;
hsa_status_t status = HSA_STATUS_SUCCESS;
uint32_t size = GetNumPerfCntrs();
for (uint32_t idx = 0; idx < size; idx++) {
info = GetPerfCntr(idx);
status = hsa_ext_tools_get_counter_result(info->cntrHndl, &info->cntrResult);
std::cout << "Value of Perf Cntr is: " << info->cntrResult << std::endl;
}
return status;
}
@@ -0,0 +1,115 @@
#ifndef ROCR_PERF_CNTR_APP_H_
#define ROCR_PERF_CNTR_APP_H_
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <iostream>
#include <vector>
#include <string>
#include "hsa.h"
#include "tools/inc/hsa_ext_profiler.h"
typedef enum CntrValCnfType {
///< no counter value validation should be performed
CntrValCnf_None,
///< counter value should be an exact match to expectedResult
CntrValCnf_Exact,
///< counter value should be greater than expectedResult
CntrValCnf_GreaterThan,
///< counter value should be less than expectedResult
CntrValCnf_LessThan
} CntrValCnfType;
/// Struct used to encapsulate Counter Info
typedef struct CntrInfo {
///< Id of counter in hardware block
uint32_t cntrId;
///< Name of counter
char cntrName[72];
///< Handle of perf counter
hsa_ext_tools_counter_t cntrHndl;
///< Id of hardware block containing the counter
uint32_t blkId;
///< Handle of counter block
hsa_ext_tools_counter_block_t blkHndl;
///< Expected value of perf counte
uint64_t expectedResult;
///< Value of perf counter expected
uint64_t cntrResult;
///< Type of validation upon completion of dispatch
CntrValCnfType cnfType;
CntrInfo(uint32_t cntrId, char* cntrName, void* cntrHndl,
uint32_t blkId, void* blkHndl,
uint64_t expResult, uint64_t result, CntrValCnfType cnfType) {
this->cntrId = cntrId;
this->cntrHndl = cntrHndl;
this->blkId = blkId;
this->blkHndl = blkHndl;
this->expectedResult = expResult;
this->cntrResult = result;
this->cnfType = cnfType;
memcpy(this->cntrName, cntrName, strlen(cntrName));
}
} CntrInfo;
class RocrPerfCntrApp {
public:
// Constructor of the class. Will initialize the list of perf counters
// that will be used to program the device
RocrPerfCntrApp( );
// Destructor of the class
~RocrPerfCntrApp( );
// Return the number of perf counters
uint32_t GetNumPerfCntrs();
// Return the handle of perf counter at specified index
CntrInfo* GetPerfCntr(uint32_t idx);
// Print the list of perf counters
bool PrintCntrs();
// Initialize the list of perf counters
hsa_status_t Init(hsa_agent_t agent);
// Register Pre and Post dispatch callbacks
void RegisterCallbacks(hsa_queue_t *queue);
// Wait for perf counter collection to complete
hsa_status_t Wait();
// Validate perf counter values
hsa_status_t Validate();
private:
// Number of queues to create
std::vector<CntrInfo *> cntrList_;
// Handle of Perf Cntr Manager
hsa_ext_tools_pmu_t perfMgr_;
};
#endif // ROCR_PERF_CNTR_APP_H_
@@ -0,0 +1,582 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <cassert>
#include <iostream>
#include <vector>
#include <string>
#include "hsa.h"
#include "hsa_rsrc_factory.hpp"
#include "hsa_ext_finalize.h"
#include "tools/inc/hsa_ext_profiler.h"
#include "HSAILAmdExt.h"
#include "common.hpp"
using namespace std;
// Provide access to command line arguments passed in by user
uint32_t hsa_cmdline_arg_cnt;
char **hsa_cmdline_arg_list;
// Callback function to find and bind kernarg region of an agent
static hsa_status_t find_memregions(hsa_region_t region, void *data) {
hsa_region_global_flag_t flags;
hsa_region_segment_t segment_id;
hsa_region_get_info(region, HSA_REGION_INFO_SEGMENT, &segment_id);
if (segment_id != HSA_REGION_SEGMENT_GLOBAL) {
return HSA_STATUS_SUCCESS;
}
AgentInfo *agent_info = (AgentInfo *)data;
hsa_region_get_info(region, HSA_REGION_INFO_GLOBAL_FLAGS, &flags);
if (flags & HSA_REGION_GLOBAL_FLAG_COARSE_GRAINED) {
agent_info->coarse_region = region;
}
if (flags & HSA_REGION_GLOBAL_FLAG_KERNARG) {
agent_info->kernarg_region = region;
}
return HSA_STATUS_SUCCESS;
}
// Callback function to get the number of agents
static hsa_status_t get_hsa_agents(hsa_agent_t agent, void *data) {
// Copy handle of agent and increment number of agents reported
HsaRsrcFactory *rsrcFactory = reinterpret_cast<HsaRsrcFactory *>(data);
// Determine if device is a Gpu agent
hsa_status_t status;
hsa_device_type_t type;
status = hsa_agent_get_info(agent, HSA_AGENT_INFO_DEVICE, &type);
if (type == HSA_DEVICE_TYPE_DSP) {
return HSA_STATUS_SUCCESS;
}
if (type == HSA_DEVICE_TYPE_CPU) {
AgentInfo *agent_info = reinterpret_cast<AgentInfo *>(malloc(sizeof(AgentInfo)));
agent_info->dev_id = agent;
agent_info->dev_type = HSA_DEVICE_TYPE_CPU;
rsrcFactory->AddAgentInfo(agent_info, false);
return HSA_STATUS_SUCCESS;
}
// Device is a Gpu agent, build an instance of AgentInfo
AgentInfo *agent_info = reinterpret_cast<AgentInfo *>(malloc(sizeof(AgentInfo)));
agent_info->dev_id = agent;
agent_info->dev_type = HSA_DEVICE_TYPE_GPU;
hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, agent_info->name);
agent_info->max_wave_size = 0;
hsa_agent_get_info(agent, HSA_AGENT_INFO_WAVEFRONT_SIZE, &agent_info->max_wave_size);
agent_info->max_queue_size = 0;
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUE_MAX_SIZE, &agent_info->max_queue_size);
agent_info->profile = hsa_profile_t(108);
hsa_agent_get_info(agent, HSA_AGENT_INFO_PROFILE, &agent_info->profile);
// Initialize memory regions to zero
agent_info->kernarg_region.handle = 0;
agent_info->coarse_region.handle = 0;
// Find and Bind Memory regions of the Gpu agent
hsa_agent_iterate_regions(agent, find_memregions, agent_info);
// Save the instance of AgentInfo
rsrcFactory->AddAgentInfo(agent_info, true);
return HSA_STATUS_SUCCESS;
}
// Definitions for Static Data members of the class
char* HsaRsrcFactory::brig_path_ = NULL;
uint32_t HsaRsrcFactory::num_cus_;
uint32_t HsaRsrcFactory::num_waves_;
uint32_t HsaRsrcFactory::num_workitems_;
uint32_t HsaRsrcFactory::kernel_loop_count_;
bool HsaRsrcFactory::print_debug_info_ = false;
char* HsaRsrcFactory::num_cus_key_ = "num_cus";
char* HsaRsrcFactory::brig_path_key_ = "brig_path";
char* HsaRsrcFactory::num_waves_key_ = "waves_per_cu";
char* HsaRsrcFactory::num_workitems_key_ = "workitems_per_wave";
char* HsaRsrcFactory::print_debug_key_ = "print_debug";
char* HsaRsrcFactory::kernel_loop_count_key_ = "kernel_loop_count";
// Constructor of the class
HsaRsrcFactory::HsaRsrcFactory( ) {
// Initialize the Hsa Runtime
hsa_status_t status = hsa_init();
assert(status == HSA_STATUS_SUCCESS);
// Discover the set of Gpu devices available on the platform
status = hsa_iterate_agents(get_hsa_agents, this);
check("Error Calling hsa_iterate_agents", status);
// Process command line arguments
ProcessCmdline( );
}
// Destructor of the class
HsaRsrcFactory::~HsaRsrcFactory( ) {
}
// Get the count of Hsa Gpu Agents available on the platform
//
// @return uint32_t Number of Gpu agents on platform
//
uint32_t HsaRsrcFactory::GetCountOfGpuAgents( ) {
return uint32_t(gpu_list_.size());
}
// Get the count of Hsa Cpu Agents available on the platform
//
// @return uint32_t Number of Cpu agents on platform
//
uint32_t HsaRsrcFactory::GetCountOfCpuAgents( ) {
return uint32_t(cpu_list_.size());
}
// Get the AgentInfo handle of a Gpu device
//
// @param idx Gpu Agent at specified index
//
// @param agent_info Output parameter updated with AgentInfo
//
// @return bool true if successful, false otherwise
//
bool HsaRsrcFactory::GetGpuAgentInfo(uint32_t idx, AgentInfo **agent_info) {
// Determine if request is valid
uint32_t size = uint32_t(gpu_list_.size());
if (idx >= size) {
return false;
}
// Copy AgentInfo from specified index
*agent_info = gpu_list_[idx];
return true;
}
// Get the AgentInfo handle of a Cpu device
//
// @param idx Cpu Agent at specified index
//
// @param agent_info Output parameter updated with AgentInfo
//
// @return bool true if successful, false otherwise
//
bool HsaRsrcFactory::GetCpuAgentInfo(uint32_t idx, AgentInfo **agent_info) {
// Determine if request is valid
uint32_t size = uint32_t(cpu_list_.size());
if (idx >= size) {
return false;
}
// Copy AgentInfo from specified index
*agent_info = cpu_list_[idx];
return true;
}
// Create a Queue object and return its handle. The queue object is expected
// to support user requested number of Aql dispatch packets.
//
// @param agent_info Gpu Agent on which to create a queue object
//
// @param num_Pkts Number of packets to be held by queue
//
// @param queue Output parameter updated with handle of queue object
//
// @return bool true if successful, false otherwise
//
bool HsaRsrcFactory::CreateQueue(AgentInfo *agent_info,
uint32_t num_pkts, hsa_queue_t **queue) {
hsa_status_t status;
// Code to create a Profile Queue object
if (num_pkts == UINT32_MAX) {
status = hsa_ext_tools_queue_create_profiled(agent_info->dev_id,
512, HSA_QUEUE_TYPE_SINGLE, NULL,
NULL, UINT32_MAX, UINT32_MAX, queue);
return (status == HSA_STATUS_SUCCESS);
}
status = hsa_queue_create(agent_info->dev_id, num_pkts,
HSA_QUEUE_TYPE_MULTI, NULL, NULL,
UINT32_MAX, UINT32_MAX, queue);
return (status == HSA_STATUS_SUCCESS);
}
// Create a Signal object and return its handle.
//
// @param value Initial value of signal object
//
// @param signal Output parameter updated with handle of signal object
//
// @return bool true if successful, false otherwise
//
bool HsaRsrcFactory::CreateSignal(uint32_t value, hsa_signal_t *signal) {
hsa_status_t status;
status = hsa_signal_create(value, 0, NULL, signal);
return (status == HSA_STATUS_SUCCESS);
}
// Allocate memory for use by a kernel of specified size in specified
// agent's memory region. Currently supports Global segment whose Kernarg
// flag set.
//
// @param agent_info Agent from whose memory region to allocate
//
// @param size Size of memory in terms of bytes
//
// @return uint8_t* Pointer to buffer, null if allocation fails.
//
uint8_t* HsaRsrcFactory::AllocateLocalMemory(AgentInfo *agent_info, size_t size) {
hsa_status_t status;
uint8_t *buffer = NULL;
// Allocate in local memory only if it is available
if (agent_info->coarse_region.handle != 0) {
std::cout << "Allocating in local memory" << std::endl;
status = hsa_memory_allocate(agent_info->coarse_region, size, (void **)&buffer);
if (status == HSA_STATUS_SUCCESS) {
status = hsa_memory_assign_agent(buffer, agent_info->dev_id, HSA_ACCESS_PERMISSION_RW);
return (status == HSA_STATUS_SUCCESS) ? buffer : NULL;
}
return NULL;
}
// Allocate in system memory if local memory is not available
std::cout << "Allocating in system memory" << std::endl;
status = hsa_memory_allocate(agent_info->kernarg_region, size, (void **)&buffer);
return (status == HSA_STATUS_SUCCESS) ? buffer : NULL;
}
// Allocate memory tp pass kernel parameters.
//
// @param agent_info Agent from whose memory region to allocate
//
// @param size Size of memory in terms of bytes
//
// @return uint8_t* Pointer to buffer, null if allocation fails.
//
uint8_t* HsaRsrcFactory::AllocateSysMemory(AgentInfo *agent_info, size_t size) {
hsa_status_t status;
uint8_t *buffer = NULL;
status = hsa_memory_allocate(agent_info->kernarg_region, size, (void **)&buffer);
return (status == HSA_STATUS_SUCCESS) ? buffer : NULL;
}
bool HsaRsrcFactory::TransferData(uint8_t *dest_buff, uint8_t *src_buff,
uint32_t length, bool host_to_dev) {
hsa_status_t status;
status = hsa_memory_copy(dest_buff, src_buff, length);
return (status == HSA_STATUS_SUCCESS);
}
// Fake method for compilation steps only
uint8_t* HsaRsrcFactory::AllocateMemory(AgentInfo *agent_info, size_t size) {
hsa_status_t status;
uint8_t *buffer = NULL;
status = hsa_memory_allocate(agent_info->kernarg_region, size, (void **)&buffer);
return (status == HSA_STATUS_SUCCESS) ? buffer : NULL;
}
// Loads an Assembled Brig file and Finalizes it into Device Isa
//
// @param agent_info Gpu device for which to finalize
//
// @param brig_path File path of the Assembled Brig file
//
// @param kernel_name Name of the kernel to finalize
//
// @param code_desc Handle of finalized Code Descriptor that could
// be used to submit for execution
//
// @return bool true if successful, false otherwise
//
bool HsaRsrcFactory::LoadAndFinalize(AgentInfo *agent_info,
const char *brig_path, char *kernel_name,
hsa_executable_symbol_t *code_desc) {
hsa_status_t status;
// Load BRIG, encapsulated in an ELF container, into a BRIG module.
/*
status_t build_err;
hsa_ext_brig_module_t *brig_obj;
build_err = (status_t)create_brig_module_from_brig_file(brig_path, &brig_obj);
check_build("Error in creating the brig module from brig file", build_err);
// Determine the Brig module has the kernel symbol
hsa_status_t status;
hsa_ext_brig_code_section_offset32_t kernel_symbol;
status = hsa_find_symbol_offset(brig_obj, kernel_name, &kernel_symbol);
check("Error in Finding the Symbol Offset for the Kernel", status);
*/
amd::hsail::registerExtensions();
// Copy handle of Brig object
hsa_ext_module_t brig_module_v3;
if (!tool.assembleFromFile(brig_path)) {
std::cout << tool.output();
return false;
}
brig_module_v3 = tool.brigModule();
// Create hsail program.
hsa_ext_program_t hsailProgram;
status = hsa_ext_program_create(HSA_MACHINE_MODEL_LARGE,
agent_info->profile,
HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO,
NULL, &hsailProgram);
check("Error in creating program object", status);
// Add hsail module.
status = hsa_ext_program_add_module(hsailProgram, brig_module_v3);
check("Error in adding module to program object", status);
// Finalize hsail program.
hsa_isa_t isa = {0};
status = hsa_agent_get_info(agent_info->dev_id, HSA_AGENT_INFO_ISA, &isa);
check("Error in getting Id of Isa supported by agent", status);
hsa_ext_control_directives_t control_directives;
memset(&control_directives, 0, sizeof(hsa_ext_control_directives_t));
hsa_code_object_t code_object;
status = hsa_ext_program_finalize(hsailProgram,
isa,
0,
control_directives,
NULL, //"-g -O0 -dump-isa",
HSA_CODE_OBJECT_TYPE_PROGRAM,
&code_object);
check("Error in finalizing program object", status);
//status = hsa_ext_program_destroy(hsailProgram);
//check("Error in destroying program object", status);
// Create executable.
hsa_executable_t hsaExecutable;
status = hsa_executable_create(agent_info->profile,
HSA_EXECUTABLE_STATE_UNFROZEN,
"", &hsaExecutable);
check("Error in creating executable object", status);
// Load code object.
status = hsa_executable_load_code_object(hsaExecutable, agent_info->dev_id, code_object, "");
check("Error in loading executable object", status);
// Freeze executable.
status = hsa_executable_freeze(hsaExecutable, "");
check("Error in freezing executable object", status);
// Get symbol handle.
hsa_executable_symbol_t kernelSymbol;
status = hsa_executable_get_symbol(hsaExecutable, NULL,
kernel_name, agent_info->dev_id, 0, &kernelSymbol);
// Update output parameter
*code_desc = kernelSymbol;
return true;
/**
// Create Hsa Program
hsa_ext_program_handle_t program;
status = hsa_ext_program_create(&agent_info->dev_id, 1,
HSA_EXT_BRIG_MACHINE_LARGE,
HSA_EXT_BRIG_PROFILE_FULL, &program);
check("Error in Creating Hsa Program", status);
// Add the BRIG module to hsa program.
hsa_ext_brig_module_handle_t brig_handle;
status = hsa_ext_add_module(program, brig_obj, &brig_handle);
check("Error in Adding Brig Module to the Program", status);
// Construct finalization request list.
hsa_ext_finalization_request_t finalize_request;
finalize_request.module = brig_handle;
finalize_request.symbol = kernel_symbol;
finalize_request.program_call_convention = 0;
// Finalize the Hsa Program.
status = hsa_ext_finalize_program(program, agent_info->dev_id,
1, &finalize_request, NULL, NULL, 0, NULL, 0);
check("Error in Finalizing the Hsa Program", status);
// Destroy the brig module. The program was successfully created the kernel
// symbol was found and the program was finalized, so it is no longer needed.
destroy_brig_module(brig_obj);
// Get the hsa code descriptor address.
status = hsa_ext_query_kernel_descriptor_address(program, brig_handle, kernel_symbol, code_desc);
check("Error Querying the Kernel Descriptor Address", status);
return true;
**/
}
// Add an instance of AgentInfo representing a Hsa Gpu agent
void HsaRsrcFactory::AddAgentInfo(AgentInfo *agent_info, bool gpu) {
// Add input to Gpu list
if (gpu) {
gpu_list_.push_back(agent_info);
return;
}
// Add input to Cpu list
cpu_list_.push_back(agent_info);
}
// Print the various fields of Hsa Gpu Agents
bool HsaRsrcFactory::PrintGpuAgents( ) {
AgentInfo *agent_info;
int size = uint32_t(gpu_list_.size());
for (int idx = 0; idx < size; idx++) {
agent_info = gpu_list_[idx];
std::cout << std::endl;
std::cout << "Hsa Gpu Agent Id: " << agent_info->dev_id.handle << std::endl;
std::cout << "Hsa Gpu Agent Name: " << agent_info->name << std::endl;
std::cout << "Hsa Gpu Agent Max Wave Size: " << agent_info->max_wave_size << std::endl;
std::cout << "Hsa Gpu Agent Max Queue Size: " << agent_info->max_queue_size << std::endl;
std::cout << "Hsa Gpu Agent Kernarg Region Id: " << agent_info->coarse_region.handle << std::endl;
std::cout << std::endl;
}
return true;
}
// Returns the file path where brig files is located. Value is
// available only after an instance has been built.
char* HsaRsrcFactory::GetBrigPath( ) {
return HsaRsrcFactory::brig_path_;
}
// Returns the number of compute units present on platform
// Value is available only after an instance has been built.
uint32_t HsaRsrcFactory::GetNumOfCUs( ) {
return HsaRsrcFactory::num_cus_;
}
// Returns the maximum number of waves that can be launched
// per compute unit. The actual number that can be launched
// is affected by resource availability
//
// Value is available only after an instance has been built.
uint32_t HsaRsrcFactory::GetNumOfWavesPerCU( ) {
return HsaRsrcFactory::num_waves_;
}
// Returns the number of work-items that can execute per wave
// Value is available only after an instance has been built.
uint32_t HsaRsrcFactory::GetNumOfWorkItemsPerWave( ) {
return HsaRsrcFactory::num_workitems_;
}
// Returns the number of times kernel loop body should execute.
// Value is available only after an instance has been built.
uint32_t HsaRsrcFactory::GetKernelLoopCount() {
return HsaRsrcFactory::kernel_loop_count_;
}
// Returns boolean flag to indicate if debug info should be printed
// Value is available only after an instance has been built.
uint32_t HsaRsrcFactory::GetPrintDebugInfo() {
return HsaRsrcFactory::print_debug_info_;
}
// Process command line arguments. The method will capture
// various user command line parameters for tests to use
void HsaRsrcFactory::ProcessCmdline( ) {
// Command line arguments are given
uint32_t idx;
uint32_t arg_idx;
for (idx = 1; idx < hsa_cmdline_arg_cnt; idx += 2) {
arg_idx = GetArgIndex((char *)hsa_cmdline_arg_list[idx]);
switch(arg_idx) {
case 0:
HsaRsrcFactory::brig_path_ = hsa_cmdline_arg_list[idx + 1];
break;
case 1:
HsaRsrcFactory::num_cus_ = atoi(hsa_cmdline_arg_list[idx + 1]);
break;
case 2:
HsaRsrcFactory::num_waves_ = atoi(hsa_cmdline_arg_list[idx + 1]);
break;
case 3:
HsaRsrcFactory::num_workitems_ = atoi(hsa_cmdline_arg_list[idx + 1]);
break;
case 4:
HsaRsrcFactory::kernel_loop_count_ = atoi(hsa_cmdline_arg_list[idx + 1]);
break;
case 5:
HsaRsrcFactory::print_debug_info_ = true;
break;
}
}
}
uint32_t HsaRsrcFactory::GetArgIndex(char *arg_value ) {
// Map Brig file path to index zero
if (!strcmp(HsaRsrcFactory::brig_path_key_, arg_value)) {
return 0;
}
// Map Number of Compute Units to index one
if (!strcmp(HsaRsrcFactory::num_cus_key_, arg_value)) {
return 1;
}
// Map Number of Waves per CU to index two
if (!strcmp(HsaRsrcFactory::num_waves_key_, arg_value)) {
return 2;
}
// Map Number of Workitems per Wave to index three
if (!strcmp(HsaRsrcFactory::num_workitems_key_, arg_value)) {
return 3;
}
// Map Kernel Loop Count to index four
if (!strcmp(HsaRsrcFactory::kernel_loop_count_key_, arg_value)) {
return 4;
}
// Map print debug info parameter
if (!strcmp(HsaRsrcFactory::print_debug_key_, arg_value)) {
return 5;
}
return 108;
}
void HsaRsrcFactory::PrintHelpMsg( ) {
std::cout << "Key for passing Brig filepath: " << HsaRsrcFactory::brig_path_key_ << std::endl;
std::cout << "Key for passing Number of Compute Units: " << HsaRsrcFactory::num_cus_key_ << std::endl;
std::cout << "Key for passing Number of Waves per CU: " << HsaRsrcFactory::num_waves_key_ << std::endl;
std::cout << "Key for passing Number of Workitems per Wave: " << HsaRsrcFactory::num_workitems_key_ << std::endl;
std::cout << "Key for passing Kernel Loop Count: " << HsaRsrcFactory::kernel_loop_count_key_ << std::endl;
}
@@ -0,0 +1,322 @@
#ifndef HSA_RSRC_FACTORY_H_
#define HSA_RSRC_FACTORY_H_
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <iostream>
#include <vector>
#include <string>
#include "hsatimer.h"
#include "hsa.h"
#include "hsa_ext_finalize.h"
#include "HSAILTool.h"
#define HSA_ARGUMENT_ALIGN_BYTES 16
#define HSA_QUEUE_ALIGN_BYTES 64
#define HSA_PACKET_ALIGN_BYTES 64
#define check(msg, status) \
if (status != HSA_STATUS_SUCCESS) { \
const char *emsg = 0; \
hsa_status_string(status, &emsg); \
printf("%s: %s\n", msg, emsg ? emsg : "<unknown error>"); \
exit(1); \
}
#define check_build(msg, status) \
if (status != STATUS_SUCCESS) { \
printf("%s\n", msg); \
exit(1); \
}
// Define required BRIG data structures.
typedef uint32_t BrigCodeOffset32_t;
typedef uint32_t BrigDataOffset32_t;
typedef uint16_t BrigKinds16_t;
typedef uint8_t BrigLinkage8_t;
typedef uint8_t BrigExecutableModifier8_t;
typedef BrigDataOffset32_t BrigDataOffsetString32_t;
/*
enum BrigKinds {
BRIG_KIND_NONE = 0x0000,
BRIG_KIND_DIRECTIVE_BEGIN = 0x1000,
BRIG_KIND_DIRECTIVE_KERNEL = 0x1008,
};
typedef struct BrigBase BrigBase;
struct BrigBase {
uint16_t byteCount;
BrigKinds16_t kind;
};
typedef struct BrigExecutableModifier BrigExecutableModifier;
struct BrigExecutableModifier {
BrigExecutableModifier8_t allBits;
};
typedef struct BrigDirectiveExecutable BrigDirectiveExecutable;
struct BrigDirectiveExecutable {
uint16_t byteCount;
BrigKinds16_t kind;
BrigDataOffsetString32_t name;
uint16_t outArgCount;
uint16_t inArgCount;
BrigCodeOffset32_t firstInArg;
BrigCodeOffset32_t firstCodeBlockEntry;
BrigCodeOffset32_t nextModuleEntry;
uint32_t codeBlockEntryCount;
BrigExecutableModifier modifier;
BrigLinkage8_t linkage;
uint16_t reserved;
};
typedef struct BrigData BrigData;
struct BrigData {
uint32_t byteCount;
uint8_t bytes[1];
};
*/
// Provide access to command line arguments passed in by user
extern uint32_t hsa_cmdline_arg_cnt;
extern char **hsa_cmdline_arg_list;
// Encapsulates information about a Hsa Agent such as its
// handle, name, max queue size, max wavefront size, etc.
typedef struct {
// Handle of Agent
hsa_agent_t dev_id;
// Agent type - Cpu = 0, Gpu = 1 or Dsp = 2
uint32_t dev_type;
// Name of Agent whose length is less than 64
char name[64];
// Max size of Wavefront size
uint32_t max_wave_size;
// Max size of Queue buffer
uint32_t max_queue_size;
// Hsail profile supported by agent
hsa_profile_t profile;
// Memory region supporting kernel parameters
hsa_region_t coarse_region;
// Memory region supporting kernel arguments
hsa_region_t kernarg_region;
} AgentInfo;
class HsaRsrcFactory {
public:
// Constructor of the class. Will initialize the Hsa Runtime and
// query the system topology to get the list of Cpu and Gpu devices
HsaRsrcFactory( );
// Destructor of the class
~HsaRsrcFactory( );
// Get the count of Hsa Gpu Agents available on the platform
//
// @return uint32_t Number of Gpu agents on platform
//
uint32_t GetCountOfGpuAgents( );
// Get the count of Hsa Cpu Agents available on the platform
//
// @return uint32_t Number of Cpu agents on platform
//
uint32_t GetCountOfCpuAgents( );
// Get the AgentInfo handle of a Gpu device
//
// @param idx Gpu Agent at specified index
//
// @param agent_info Output parameter updated with AgentInfo
//
// @return bool true if successful, false otherwise
//
bool GetGpuAgentInfo(uint32_t idx, AgentInfo **agent_info);
// Get the AgentInfo handle of a Cpu device
//
// @param idx Cpu Agent at specified index
//
// @param agent_info Output parameter updated with AgentInfo
//
// @return bool true if successful, false otherwise
//
bool GetCpuAgentInfo(uint32_t idx, AgentInfo **agent_info);
// Create a Queue object and return its handle. The queue object is expected
// to support user requested number of Aql dispatch packets.
//
// @param agent_info Gpu Agent on which to create a queue object
//
// @param num_Pkts Number of packets to be held by queue
//
// @param queue Output parameter updated with handle of queue object
//
// @return bool true if successful, false otherwise
//
bool CreateQueue(AgentInfo *agent_info,
uint32_t num_pkts, hsa_queue_t **queue);
// Create a Signal object and return its handle.
//
// @param value Initial value of signal object
//
// @param signal Output parameter updated with handle of signal object
//
// @return bool true if successful, false otherwise
//
bool CreateSignal(uint32_t value, hsa_signal_t *signal);
// Allocate memory for use by a kernel of specified size in specified
// agent's memory region. Currently supports Global segment whose Kernarg
// flag set.
//
// @param agent_info Agent from whose memory region to allocate
//
// @param size Size of memory in terms of bytes
//
// @return uint8_t* Pointer to buffer, null if allocation fails.
//
uint8_t* AllocateLocalMemory(AgentInfo *agent_info, size_t size);
uint8_t* AllocateMemory(AgentInfo *agent_info, size_t size);
bool TransferData(uint8_t *dest_buff, uint8_t *src_buff,
uint32_t length, bool host_to_dev);
// Allocate memory tp pass kernel parameters.
//
// @param agent_info Agent from whose memory region to allocate
//
// @param size Size of memory in terms of bytes
//
// @return uint8_t* Pointer to buffer, null if allocation fails.
//
uint8_t* AllocateSysMemory(AgentInfo *agent_info, size_t size);
// Loads an Assembled Brig file and Finalizes it into Device Isa
//
// @param agent_info Gpu device for which to finalize
//
// @param brig_path File path of the Assembled Brig file
//
// @param kernel_name Name of the kernel to finalize
//
// @param code_desc Handle of finalized Code Descriptor that could
// be used to submit for execution
//
// @return bool true if successful, false otherwise
//
bool LoadAndFinalize(AgentInfo *agent_info,
const char *brig_path, char *kernel_name,
hsa_executable_symbol_t *code_desc);
// Add an instance of AgentInfo representing a Hsa Gpu agent
void AddAgentInfo(AgentInfo *agent_info, bool gpu);
// Returns the file path where brig files is located
static char* GetBrigPath( );
// Returns the number of compute units present on platform
static uint32_t GetNumOfCUs( );
// Returns the maximum number of waves that can be launched
// per compute unit. The actual number that can be launched
// is affected by resource availability
static uint32_t GetNumOfWavesPerCU( );
// Returns the number of work-items that can execute per wave
static uint32_t GetNumOfWorkItemsPerWave( );
// Returns the number of times kernel loop body should execute.
static uint32_t GetKernelLoopCount();
// Returns boolean flag to indicate if debug info should be printed
static uint32_t GetPrintDebugInfo();
private:
// Number of queues to create
uint32_t num_queues_;
// Used to maintain a list of Hsa Queue handles
std::vector<hsa_queue_t *> queue_list_;
// Number of Signals to create
uint32_t num_signals_;
// Used to maintain a list of Hsa Signal handles
std::vector<hsa_signal_t *> signal_list_;
// Number of agents reported by platform
uint32_t num_agents_;
// Used to maintain a list of Hsa Gpu Agent Info
std::vector<AgentInfo *> gpu_list_;
// Used to maintain a list of Hsa Cpu Agent Info
std::vector<AgentInfo *> cpu_list_;
// Records the file path where Brig file is located.
// Value is available only after an instance has been built.
static char* brig_path_;
static char* brig_path_key_;
// Records the number of Compute units present on system.
// Value is available only after an instance has been built.
static uint32_t num_cus_;
static char* num_cus_key_;
// Records the number of waves that can be launched per Compute unit
// Value is available only after an instance has been built.
static uint32_t num_waves_;
static char* num_waves_key_;
// Records the number of work-items that can be packed into a wave
// Value is available only after an instance has been built.
static uint32_t num_workitems_;
static char* num_workitems_key_;
// Records the number of times kernel loop body should run. Value
// is available only after an instance has been built.
static uint32_t kernel_loop_count_;
static char* kernel_loop_count_key_;
// Records the number of times kernel loop body should run. Value
// is available only after an instance has been built.
static bool print_debug_info_;
static char* print_debug_key_;
// Print the various fields of Hsa Gpu Agents
bool PrintGpuAgents( );
// Process command line arguments. The method will capture
// various user command line parameters for tests to use
static void ProcessCmdline( );
// Prints the help banner on user arg keys
static void PrintHelpMsg( );
// Maps an index for the user argument
static uint32_t GetArgIndex(char *arg_value);
HSAIL_ASM::Tool tool;
};
#endif // HSA_RSRC_FACTORY_H_
@@ -0,0 +1,516 @@
#include "hsa_test.h"
#include <atomic>
#include <iostream>
#define PRINT_ATTRIBUTE(attribute, value, metric) \
std::cout << #attribute " = " << value << " " << metric << std::endl;
static size_t ToMB(size_t size) { return (size / (1024 * 1024)); }
HsaTest::HsaTest(const char* test_name) : test_name_(test_name) {
std::cout << "Running " << test_name_ << std::endl;
std::cout << "------------------------------------------------\n";
}
HsaTest::~HsaTest() {}
void HsaTest::Init() {
hsa_status_t stat = hsa_init();
if (stat != HSA_STATUS_SUCCESS) {
std::cerr << "hsa_init fail with status " << stat << std::endl;
}
stat = hsa_iterate_agents(IterateAgents, (void*)this);
}
void HsaTest::Cleanup() { hsa_shut_down(); }
hsa_status_t HsaTest::IterateAgents(hsa_agent_t agent, void* data) {
HsaTest* hsatest = (HsaTest*)data;
AgentProps prop(agent);
if (prop.device_type == HSA_DEVICE_TYPE_CPU) {
hsatest->cpus_.push_back(agent);
} else if (prop.device_type == HSA_DEVICE_TYPE_GPU) {
hsatest->gpus_.push_back(agent);
}
hsa_amd_memory_pool_t pools[3] = {{0}, {0}, {0}};
hsa_status_t stat =
hsa_amd_agent_iterate_memory_pools(agent, IteratePools, pools);
hsatest->global_fine_[agent.handle] = pools[0];
hsatest->global_coarse_[agent.handle] = pools[1];
hsatest->group_[agent.handle] = pools[2];
return HSA_STATUS_SUCCESS;
}
hsa_status_t HsaTest::IteratePools(hsa_amd_memory_pool_t pool, void* data) {
hsa_amd_memory_pool_t* pools = (hsa_amd_memory_pool_t*)data;
PoolProps prop(pool);
if (prop.segment == HSA_AMD_SEGMENT_GLOBAL) {
if (prop.global_flag & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED) {
pools[0].handle = pool.handle;
} else {
pools[1].handle = pool.handle;
}
} else if (prop.segment == HSA_AMD_SEGMENT_GROUP) {
pools[2].handle = pool.handle;
}
return HSA_STATUS_SUCCESS;
}
HsaTest::AgentProps::AgentProps(hsa_agent_t agent) {
if (agent.handle == 0) {
return;
}
hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, (void*)name);
hsa_agent_get_info(agent, HSA_AGENT_INFO_VENDOR_NAME, (void*)vendor_name);
hsa_agent_get_info(agent, HSA_AGENT_INFO_FEATURE, (void*)&feature);
hsa_agent_get_info(agent, HSA_AGENT_INFO_MACHINE_MODEL,
(void*)&machine_model);
hsa_agent_get_info(agent, HSA_AGENT_INFO_PROFILE, (void*)&profile);
hsa_agent_get_info(agent, HSA_AGENT_INFO_DEFAULT_FLOAT_ROUNDING_MODE,
(void*)&default_float_rounding_mode);
hsa_agent_get_info(agent,
HSA_AGENT_INFO_BASE_PROFILE_DEFAULT_FLOAT_ROUNDING_MODES,
(void*)&base_profile_float_rounding_mode);
hsa_agent_get_info(agent, HSA_AGENT_INFO_FAST_F16_OPERATION,
(void*)&fast_f16_operation);
hsa_agent_get_info(agent, HSA_AGENT_INFO_WAVEFRONT_SIZE,
(void*)&wavefront_size);
hsa_agent_get_info(agent, HSA_AGENT_INFO_WORKGROUP_MAX_DIM,
(void*)workgroup_max_dim);
hsa_agent_get_info(agent, HSA_AGENT_INFO_WORKGROUP_MAX_SIZE,
(void*)&workgroup_max_size);
hsa_agent_get_info(agent, HSA_AGENT_INFO_GRID_MAX_DIM, (void*)&grid_max_dim);
hsa_agent_get_info(agent, HSA_AGENT_INFO_GRID_MAX_SIZE,
(void*)&grid_max_size);
hsa_agent_get_info(agent, HSA_AGENT_INFO_FBARRIER_MAX_SIZE,
(void*)&fbarrier_max_size);
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUES_MAX, (void*)&queue_max);
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUE_MIN_SIZE,
(void*)&queue_min_size);
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUE_MAX_SIZE,
(void*)&queue_max_size);
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUE_TYPE, (void*)&queue_type);
hsa_agent_get_info(agent, HSA_AGENT_INFO_NODE, (void*)&node);
hsa_agent_get_info(agent, HSA_AGENT_INFO_DEVICE, (void*)&device_type);
hsa_agent_get_info(agent, HSA_AGENT_INFO_CACHE_SIZE, (void*)cache_size);
hsa_agent_get_info(agent, HSA_AGENT_INFO_ISA, (void*)&isa);
hsa_agent_get_info(agent, HSA_AGENT_INFO_EXTENSIONS, (void*)extensions);
hsa_agent_get_info(agent, HSA_AGENT_INFO_VERSION_MAJOR,
(void*)&version_major);
hsa_agent_get_info(agent, HSA_AGENT_INFO_VERSION_MINOR,
(void*)&version_minor);
}
HsaTest::PoolProps::PoolProps(hsa_amd_memory_pool_t pool) {
if (pool.handle == 0) {
return;
}
hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_SEGMENT,
(void*)&segment);
hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_GLOBAL_FLAGS,
(void*)&global_flag);
hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_SIZE,
(void*)&size);
hsa_amd_memory_pool_get_info(pool,
HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALLOWED,
(void*)&alloc_allowed);
hsa_amd_memory_pool_get_info(pool,
HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_GRANULE,
(void*)&alloc_granule);
hsa_amd_memory_pool_get_info(pool,
HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALIGNMENT,
(void*)&alloc_alignment);
hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_ACCESSIBLE_BY_ALL,
(void*)&all_accessible);
}
HsaTest::Kernel::Kernel(hsa_agent_t agent, std::string hsail_text)
: agent_(agent), hsail_file_(hsail_text) {
program_.handle = 0;
code_object_.handle = 0;
executable_.handle = 0;
AgentProps prop(agent_);
profile_ = prop.profile;
Initialize();
}
HsaTest::Kernel::~Kernel() { Cleanup(); }
uint64_t HsaTest::Kernel::GetCodeHandle(const char* kernel_name) {
kernel_symbol_ = {0};
if (HSA_STATUS_SUCCESS != hsa_executable_get_symbol(executable_, NULL,
kernel_name, agent_, 0,
&kernel_symbol_)) {
return 0;
}
uint64_t code_handle = 0;
if (HSA_STATUS_SUCCESS !=
hsa_executable_symbol_get_info(kernel_symbol_,
HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT,
&code_handle)) {
return 0;
}
return code_handle;
}
hsa_status_t HsaTest::Kernel::GetScratchSize(uint32_t* size) {
hsa_status_t status;
status = hsa_executable_symbol_get_info(kernel_symbol_,
HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_PRIVATE_SEGMENT_SIZE, size);
return status;
}
void HsaTest::Kernel::Initialize() {
CreateProgramFromHsailFile();
CreateCodeObjectAndExecutable();
}
void HsaTest::Kernel::Cleanup() {
if (executable_.handle != 0) {
hsa_executable_destroy(executable_);
executable_.handle = 0;
}
if (code_object_.handle != 0) {
hsa_code_object_destroy(code_object_);
code_object_.handle = 0;
}
if (program_.handle != 0) {
hsa_ext_program_destroy(program_);
program_.handle = 0;
}
}
bool HsaTest::Kernel::CreateProgramFromHsailFile() {
if (HSA_STATUS_SUCCESS !=
hsa_ext_program_create(HSA_MACHINE_MODEL_LARGE, profile_,
HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO, NULL,
&program_)) {
return false;
}
if (!tool_.assembleFromFile(hsail_file_.c_str())) {
return false;
}
hsa_ext_module_t module = tool_.brigModule();
if (HSA_STATUS_SUCCESS != hsa_ext_program_add_module(program_, module)) {
return false;
}
return true;
}
bool HsaTest::Kernel::CreateCodeObjectAndExecutable() {
hsa_isa_t isa = {0};
if (HSA_STATUS_SUCCESS !=
hsa_agent_get_info(agent_, HSA_AGENT_INFO_ISA, &isa)) {
return false;
}
hsa_ext_control_directives_t control_directives = {0};
if (HSA_STATUS_SUCCESS !=
hsa_ext_program_finalize(program_, isa, 0, control_directives, "",
HSA_CODE_OBJECT_TYPE_PROGRAM, &code_object_)) {
return false;
}
if (HSA_STATUS_SUCCESS != hsa_executable_create(profile_,
HSA_EXECUTABLE_STATE_UNFROZEN,
"", &executable_)) {
return false;
}
if (HSA_STATUS_SUCCESS !=
hsa_executable_load_code_object(executable_, agent_, code_object_, "")) {
return false;
}
if (HSA_STATUS_SUCCESS != hsa_executable_freeze(executable_, "")) {
return false;
}
return true;
}
void HsaTest::GetGpuPeer(hsa_agent_t master,
std::vector<hsa_agent_t>& gpu_peers) {
AgentProps master_prop(master);
for (hsa_agent_t agent : gpus_) {
AgentProps agent_prop(agent);
if (master.handle == agent.handle ||
agent_prop.device_type != HSA_DEVICE_TYPE_GPU) {
continue;
}
hsa_amd_memory_pool_t peer_local_pool = global_coarse_[agent.handle];
hsa_amd_memory_pool_access_t access =
HSA_AMD_MEMORY_POOL_ACCESS_NEVER_ALLOWED;
if (HSA_STATUS_SUCCESS == hsa_amd_agent_memory_pool_get_info(
master, peer_local_pool,
HSA_AMD_AGENT_MEMORY_POOL_INFO_ACCESS,
(void*)&access) &&
access != HSA_AMD_MEMORY_POOL_ACCESS_NEVER_ALLOWED) {
gpu_peers.push_back(agent);
}
}
}
void* HsaTest::AllocateSystemMemory(bool fine_grain, size_t size) {
if (cpus_.size() == 0) {
return NULL;
}
hsa_amd_memory_pool_t pool = (fine_grain) ? global_fine_[cpus_[0].handle]
: global_coarse_[cpus_[0].handle];
void* ptr = NULL;
if (HSA_STATUS_SUCCESS != hsa_amd_memory_pool_allocate(pool, size, 0, &ptr)) {
return NULL;
}
return ptr;
}
void* HsaTest::AllocateLocalMemory(hsa_agent_t agent, size_t size) {
if (gpus_.size() == 0) {
return NULL;
}
hsa_amd_memory_pool_t pool = global_coarse_[agent.handle];
void* ptr = NULL;
if (HSA_STATUS_SUCCESS != hsa_amd_memory_pool_allocate(pool, size, 0, &ptr)) {
return NULL;
}
return ptr;
}
void HsaTest::FreeMemory(void* ptr) { hsa_amd_memory_pool_free(ptr); }
void HsaTest::LaunchPacket(hsa_queue_t& queue, hsa_packet_type_t type,
void* packet) {
uint32_t queue_bitmask = queue.size - 1;
const uint64_t write_index = hsa_queue_add_write_index_acq_rel(&queue, 1);
static const uint16_t kInvalidPacketHeader = HSA_PACKET_TYPE_INVALID;
if (type == HSA_PACKET_TYPE_KERNEL_DISPATCH) {
hsa_kernel_dispatch_packet_t* dispatch_packet =
reinterpret_cast<hsa_kernel_dispatch_packet_t*>(packet);
const uint16_t temp_header = dispatch_packet->header;
dispatch_packet->header = kInvalidPacketHeader;
// Populate queue buffer.
hsa_kernel_dispatch_packet_t* queue_buffer =
reinterpret_cast<hsa_kernel_dispatch_packet_t*>(queue.base_address);
queue_buffer[write_index & queue_bitmask] = *dispatch_packet;
// Enable packet.
std::atomic_thread_fence(std::memory_order_release);
queue_buffer[write_index & queue_bitmask].header = temp_header;
dispatch_packet->header = temp_header;
} else if (type == HSA_PACKET_TYPE_BARRIER_AND) {
hsa_barrier_and_packet_t* barrier_and_packet =
reinterpret_cast<hsa_barrier_and_packet_t*>(packet);
const uint16_t temp_header = barrier_and_packet->header;
barrier_and_packet->header = kInvalidPacketHeader;
// Populate queue buffer.
hsa_barrier_and_packet_t* queue_buffer =
reinterpret_cast<hsa_barrier_and_packet_t*>(queue.base_address);
queue_buffer[write_index & queue_bitmask] = *barrier_and_packet;
// Enable packet.
std::atomic_thread_fence(std::memory_order_release);
queue_buffer[write_index & queue_bitmask].header = temp_header;
barrier_and_packet->header = temp_header;
} else if (type == HSA_PACKET_TYPE_BARRIER_OR) {
hsa_barrier_or_packet_t* barrier_or_packet =
reinterpret_cast<hsa_barrier_or_packet_t*>(packet);
const uint16_t temp_header = barrier_or_packet->header;
barrier_or_packet->header = kInvalidPacketHeader;
// Populate queue buffer.
hsa_barrier_or_packet_t* queue_buffer =
reinterpret_cast<hsa_barrier_or_packet_t*>(queue.base_address);
queue_buffer[write_index & queue_bitmask] = *barrier_or_packet;
// Enable packet.
std::atomic_thread_fence(std::memory_order_release);
queue_buffer[write_index & queue_bitmask].header = temp_header;
barrier_or_packet->header = temp_header;
}
hsa_signal_store_release(queue.doorbell_signal, write_index);
}
void HsaTest::PrintAgentInfo(AgentProps& prop) {
PRINT_ATTRIBUTE(HSA_AGENT_INFO_NAME, prop.name, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_VENDOR_NAME, prop.vendor_name, "");
const char* feature_strings[] = {"NONE", "HSA_AGENT_FEATURE_DISPATCH",
"HSA_AGENT_FEATURE_AGENT_DISPATCH"};
PRINT_ATTRIBUTE(HSA_AGENT_INFO_FEATURE, feature_strings[prop.feature], "");
const char* model_strings[] = {"HSA_MACHINE_MODEL_SMALL",
"HSA_MACHINE_MODEL_LARGE"};
PRINT_ATTRIBUTE(HSA_AGENT_INFO_MACHINE_MODEL,
model_strings[prop.machine_model], "");
const char* profile_strings[] = {"HSA_PROFILE_BASE", "HSA_PROFILE_FULL"};
PRINT_ATTRIBUTE(HSA_AGENT_INFO_PROFILE, profile_strings[prop.profile], "");
const char* default_float_rounding_strings[] = {
"HSA_DEFAULT_FLOAT_ROUNDING_MODE_DEFAULT",
"HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO",
"HSA_DEFAULT_FLOAT_ROUNDING_MODE_NEAR"};
PRINT_ATTRIBUTE(
HSA_AGENT_INFO_DEFAULT_FLOAT_ROUNDING_MODE,
default_float_rounding_strings[prop.default_float_rounding_mode], "");
PRINT_ATTRIBUTE(
HSA_AGENT_INFO_BASE_PROFILE_DEFAULT_FLOAT_ROUNDING_MODES,
default_float_rounding_strings[prop.base_profile_float_rounding_mode],
"");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_FAST_F16_OPERATION, prop.fast_f16_operation,
"");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_WAVEFRONT_SIZE, prop.wavefront_size, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_WORKGROUP_MAX_DIM[0],
prop.workgroup_max_dim[0], "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_WORKGROUP_MAX_DIM[1],
prop.workgroup_max_dim[1], "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_WORKGROUP_MAX_DIM[2],
prop.workgroup_max_dim[2], "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_WORKGROUP_MAX_SIZE, prop.workgroup_max_size,
"");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_GRID_MAX_DIM.x, prop.grid_max_dim.x, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_GRID_MAX_DIM.y, prop.grid_max_dim.y, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_GRID_MAX_DIM.z, prop.grid_max_dim.z, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_GRID_MAX_SIZE, prop.grid_max_size, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_FBARRIER_MAX_SIZE, prop.fbarrier_max_size, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_QUEUES_MAX, prop.queue_max, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_QUEUE_MIN_SIZE, prop.queue_min_size, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_QUEUE_MAX_SIZE, prop.queue_max_size, "");
const char* queue_type_strings[] = {"HSA_QUEUE_TYPE_MULTI",
"HSA_QUEUE_TYPE_SINGLE"};
PRINT_ATTRIBUTE(HSA_AGENT_INFO_QUEUE_TYPE,
queue_type_strings[prop.queue_type], "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_NODE, prop.node, "");
const char* device_type_strings[] = {
"HSA_DEVICE_TYPE_CPU", "HSA_DEVICE_TYPE_GPU", "HSA_DEVICE_TYPE_DSP"};
PRINT_ATTRIBUTE(HSA_AGENT_INFO_DEVICE, device_type_strings[prop.device_type],
"");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_CACHE_SIZE[0], prop.cache_size[0], "bytes");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_CACHE_SIZE[1], prop.cache_size[1], "bytes");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_CACHE_SIZE[2], prop.cache_size[2], "bytes");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_CACHE_SIZE[3], prop.cache_size[3], "bytes");
std::string extensions = "";
extensions += (prop.extensions[HSA_EXTENSION_FINALIZER])
? "HSA_EXTENSION_FINALIZER | "
: "";
extensions +=
(prop.extensions[HSA_EXTENSION_IMAGES]) ? "HSA_EXTENSION_IMAGES | " : "";
extensions += (prop.extensions[HSA_EXTENSION_AMD_PROFILER])
? "HSA_EXTENSION_AMD_PROFILER "
: "";
PRINT_ATTRIBUTE(HSA_AGENT_INFO_EXTENSIONS, extensions, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_VERSION_MAJOR, prop.version_major, "");
PRINT_ATTRIBUTE(HSA_AGENT_INFO_VERSION_MINOR, prop.version_minor, "");
}
void HsaTest::PrintPeers(hsa_agent_t agent) {
std::cout << "Peer GPUs: ";
std::vector<hsa_agent_t> gpu_peers;
GetGpuPeer(agent, gpu_peers);
if (gpu_peers.size() > 0) {
for (hsa_agent_t peer_agent : gpu_peers) {
// Get the index of the peer in gpus_.
size_t peer_idx = 0;
for (; peer_idx < gpus_.size(); ++peer_idx) {
if (peer_agent.handle == gpus_[peer_idx].handle) {
std::cout << "GPU[" << peer_idx << "] ";
break;
}
}
}
std::cout << std::endl;
} else {
std::cout << "No peer GPUs\n";
}
}
void HsaTest::PrintPoolInfo(PoolProps& prop) {
const char* segment_strings[] = {
"HSA_SEGMENT_GLOBAL", "HSA_AMD_SEGMENT_READONLY",
"HSA_AMD_SEGMENT_PRIVATE", "HSA_AMD_SEGMENT_GROUP"};
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_SEGMENT,
segment_strings[prop.segment], "");
std::string global_flag = "";
global_flag +=
(prop.global_flag & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_KERNARG_INIT)
? "HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_KERNARG_INIT | "
: "";
global_flag +=
(prop.global_flag & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED)
? "HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED | "
: "";
global_flag +=
(prop.global_flag & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_COARSE_GRAINED)
? "HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_COARSE_GRAINED "
: "";
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_GLOBAL_FLAGS, global_flag, "");
static const size_t kMb = 1024 * 1024;
if (prop.size >= kMb) {
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_SIZE, ToMB(prop.size), "MB");
} else {
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_SIZE, prop.size, "bytes");
}
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALLOWED,
prop.alloc_allowed, "");
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_GRANULE,
prop.alloc_granule, "bytes");
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALIGNMENT,
prop.alloc_alignment, "bytes");
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_ACCESSIBLE_BY_ALL,
prop.all_accessible, "");
}
@@ -0,0 +1,124 @@
#ifndef HSA_TEST_H
#define HSA_TEST_H
#include <map>
#include <string>
#include <vector>
#include "hsa.h"
#include "hsa_ext_amd.h"
#include "hsa_ext_finalize.h"
#include "HSAILTool.h"
class HsaTest {
public:
HsaTest(const char* test_name);
virtual ~HsaTest();
void Init();
void Cleanup();
virtual void Run() = 0;
protected:
static hsa_status_t IterateAgents(hsa_agent_t agent, void* data);
static hsa_status_t IteratePools(hsa_amd_memory_pool_t pool, void* data);
typedef struct AgentProps {
AgentProps(hsa_agent_t);
char name[64];
char vendor_name[64];
hsa_agent_feature_t feature;
hsa_machine_model_t machine_model;
hsa_profile_t profile;
hsa_default_float_rounding_mode_t default_float_rounding_mode;
hsa_default_float_rounding_mode_t base_profile_float_rounding_mode;
bool fast_f16_operation;
uint32_t wavefront_size;
uint16_t workgroup_max_dim[3];
uint32_t workgroup_max_size;
hsa_dim3_t grid_max_dim;
uint32_t grid_max_size;
uint32_t fbarrier_max_size;
uint32_t queue_max;
uint32_t queue_min_size;
uint32_t queue_max_size;
hsa_queue_type_t queue_type;
uint32_t node;
hsa_device_type_t device_type;
uint32_t cache_size[4];
hsa_isa_t isa;
uint8_t extensions[128];
uint16_t version_major;
uint16_t version_minor;
} AgentProps;
typedef struct PoolProps {
PoolProps(hsa_amd_memory_pool_t pool);
hsa_amd_segment_t segment;
hsa_amd_memory_pool_global_flag_t global_flag;
size_t size;
bool alloc_allowed;
size_t alloc_granule;
size_t alloc_alignment;
bool all_accessible;
} PoolProps;
class Kernel {
public:
Kernel(hsa_agent_t agent, std::string hsail_file);
virtual ~Kernel();
uint64_t GetCodeHandle(const char* kernel_name);
hsa_status_t GetScratchSize(uint32_t* size);
protected:
virtual void Initialize();
virtual void Cleanup();
bool CreateProgramFromHsailFile();
bool CreateCodeObjectAndExecutable();
HSAIL_ASM::Tool tool_;
hsa_agent_t agent_;
hsa_profile_t profile_;
hsa_ext_program_t program_;
hsa_code_object_t code_object_;
hsa_executable_t executable_;
hsa_executable_symbol_t kernel_symbol_;
std::string hsail_file_;
};
virtual void GetGpuPeer(hsa_agent_t master,
std::vector<hsa_agent_t>& gpu_peers);
virtual void* AllocateSystemMemory(bool fine_grain, size_t size);
virtual void* AllocateLocalMemory(hsa_agent_t agent, size_t size);
virtual void FreeMemory(void* ptr);
virtual void LaunchPacket(hsa_queue_t& queue, hsa_packet_type_t type,
void* packet);
virtual void PrintAgentInfo(AgentProps& prop);
virtual void PrintPeers(hsa_agent_t agent);
virtual void PrintPoolInfo(PoolProps& prop);
std::string test_name_;
std::vector<hsa_agent_t> cpus_;
std::vector<hsa_agent_t> gpus_;
std::map<uint64_t, hsa_amd_memory_pool_t> global_fine_;
std::map<uint64_t, hsa_amd_memory_pool_t> global_coarse_;
std::map<uint64_t, hsa_amd_memory_pool_t> group_;
};
#endif // HSA_TEST_H
@@ -0,0 +1,190 @@
#include "hsatimer.h"
PerfTimer::PerfTimer()
{
freq_in_100mhz = MeasureTSCFreqHz();
}
PerfTimer::~PerfTimer()
{
while(!_timers.empty())
{
Timer *temp = _timers.back();
_timers.pop_back();
delete temp;
}
}
//a new cretaed timer instantance index will be returned
int PerfTimer::CreateTimer()
{
Timer *newTimer = new Timer;
newTimer->_start = 0;
newTimer->_clocks = 0;
#ifdef _WIN32
QueryPerformanceFrequency((LARGE_INTEGER*)&newTimer->_freq);
#else
newTimer->_freq = (long long)1.0E3;
#endif
/* Push back the address of new Timer instance created */
_timers.push_back(newTimer);
return (int)(_timers.size() - 1);
}
int PerfTimer::StartTimer(int index)
{
if(index >= (int)_timers.size())
{
Error("Cannot reset timer. Invalid handle.");
return HSA_FAILURE;
}
#ifdef _WIN32
// General Windows timing method
#ifndef _AMD
long long tmpStart;
QueryPerformanceCounter((LARGE_INTEGER*)&(tmpStart));
_timers[index]->_start = (double)tmpStart;
#else
// AMD Windows timing method
#endif
#else
// General Linux timing method
#ifndef _AMD
struct timeval s;
gettimeofday(&s, 0);
_timers[index]->_start = s.tv_sec * 1.0E3 + ((double)(s.tv_usec / 1.0E3));
#else
// AMD timing method
unsigned int unused;
_timers[index]->_start = __rdtscp(&unused);
#endif
#endif
return HSA_SUCCESS;
}
int PerfTimer::StopTimer(int index)
{
double n=0;
if(index >= (int)_timers.size())
{
Error("Cannot reset timer. Invalid handle.");
return HSA_FAILURE;
}
#ifdef _WIN32
#ifndef _AMD
long long n1;
QueryPerformanceCounter((LARGE_INTEGER*)&(n1));
n = (double) n1;
#else
// AMD Window Timing
#endif
#else
// General Linux timing method
#ifndef _AMD
struct timeval s;
gettimeofday(&s, 0);
n = s.tv_sec * 1.0E3+ (double)(s.tv_usec/1.0E3);
#else
// AMD Linux timing
unsigned int unused;
n = __rdtscp(&unused);
#endif
#endif
n -= _timers[index]->_start;
_timers[index]->_start = 0;
#ifndef _AMD
_timers[index]->_clocks += n;
#else
//_timers[index]->_clocks += 10 * n /freq_in_100mhz; // unit is ns
_timers[index]->_clocks += 1.0E-6 * 10 * n /freq_in_100mhz; // convert to ms
cout << "_AMD is enabled!!!" << endl;
#endif
return HSA_SUCCESS;
}
void PerfTimer::Error(string str)
{
cout << str << endl;
}
double PerfTimer::ReadTimer(int index)
{
if(index >= (int)_timers.size())
{
Error("Cannot read timer. Invalid handle.");
return HSA_FAILURE;
}
double reading = double(_timers[index]->_clocks);
reading = double(reading / _timers[index]->_freq);
return reading;
}
uint64_t PerfTimer::CoarseTimestampUs()
{
#ifdef _WIN32
uint64_t freqHz, ticks;
QueryPerformanceFrequency((LARGE_INTEGER *)&freqHz);
QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
// Scale numerator and divisor until (ticks * 1000000) fits in uint64_t.
while (ticks > (1ULL << 44)) {
ticks /= 16;
freqHz /= 16;
}
return (ticks * 1000000) / freqHz;
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
return uint64_t(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000;
#endif
}
uint64_t PerfTimer::MeasureTSCFreqHz()
{
// Make a coarse interval measurement of TSC ticks for 1 gigacycles.
unsigned int unused;
uint64_t tscTicksEnd;
uint64_t coarseBeginUs = CoarseTimestampUs();
uint64_t tscTicksBegin = __rdtscp(&unused);
do
{
tscTicksEnd = __rdtscp(&unused);
}
while (tscTicksEnd - tscTicksBegin < 1000000000);
uint64_t coarseEndUs = CoarseTimestampUs();
// Compute the TSC frequency and round to nearest 100MHz.
uint64_t coarseIntervalNs = (coarseEndUs - coarseBeginUs) * 1000;
uint64_t tscIntervalTicks = tscTicksEnd - tscTicksBegin;
return (tscIntervalTicks * 10 + (coarseIntervalNs / 2)) / coarseIntervalNs;
}
@@ -0,0 +1,70 @@
#ifndef __MYTIME__
#define __MYTIME__
// Will use AMD timer and general Linux timer based on users' need --> compilation flag
// need to consider platform is Windows or Linux
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
#if defined(_MSC_VER)
#include <time.h>
#include <windows.h>
#include <intrin.h>
#else
#if defined(__GNUC__)
#include <sys/time.h>
#include <x86intrin.h>
#endif // __GNUC__
#endif //_MSC_VER
#define HSA_FAILURE 1
#define HSA_SUCCESS 0
class PerfTimer {
private:
struct Timer
{
string name; /* < name name of time object*/
long long _freq; /* < _freq frequency*/
double _clocks; /* < _clocks number of ticks at end*/
double _start; /* < _start start point ticks*/
};
std::vector<Timer*> _timers; /*< _timers vector to Timer objects */
double freq_in_100mhz;
public:
PerfTimer();
~PerfTimer();
private:
//AMD timing method
uint64_t CoarseTimestampUs();
uint64_t MeasureTSCFreqHz();
//General Linux timing method
public:
int CreateTimer();
int StartTimer(int index);
int StopTimer(int index);
public:
// retrieve time
double ReadTimer(int index);
// write into a file
double WriteTimer(int index);
public:
void Error(string str);
};
#endif
+45
Vedi File
@@ -0,0 +1,45 @@
#ifdef _WIN32 // Compiling for Windows Platform
#include <stdlib.h>
#include <Windows.h>
#include "os.h"
#include <stdio.h>
void SetEnv(const char* env_var_name, const char* env_var_value) {
BOOL err = SetEnvironmentVariable(env_var_name, env_var_value);
if(FALSE == err){
printf("Set environment variable failed!\n");
exit(1);
}
return;
}
char* GetEnv(const char* env_var_name){
char* buff;
DWORD char_count = GetEnvironmentVariable(env_var_name, NULL, 0);
if (char_count == 0) return NULL;
buff = (char*)malloc(sizeof(char) * char_count);
GetEnvironmentVariable(env_var_name, buff, char_count);
buff[char_count - 1] = '\0';
return buff;
}
#elif defined(__linux__)
#include "os.h"
#include <stdlib.h>
void SetEnv(const char* env_var_name, const char* env_var_value){
int err = setenv(env_var_name, env_var_value, 1);
if(0 != err){
printf("Set environment variable failed!\n");
exit(1);
}
return;
}
char* GetEnv(const char* env_var_name) {
return getenv(env_var_name);
}
#endif
+12
Vedi File
@@ -0,0 +1,12 @@
#ifndef HSA_PERF_SRC_UTILS_OS_H_
#define HSA_PERF_SRC_UTILS_OS_H_
#include <stdio.h>
// Set envriroment variable
void SetEnv(const char* env_var_name, const char* env_var_value);
// Get the value of enviroment
char* GetEnv(const char* env_var_name);
#endif
@@ -0,0 +1,193 @@
#include "utilities.h"
/*
* Prints no more than 256 elements of the given array.
* Prints full array if length is less than 256.
* Prints Array name followed by elements.
*/
template<typename T>
void PrintArray(
string header,
const T * data,
const int width,
const int height)
{
cout<<"\n"<<header<<"\n";
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
cout<<data[i*width+j]<<" ";
}
cout<<"\n";
}
cout<<"\n";
}
template<typename T>
int IsPowerOf2(T val)
{
long long _val = val;
if((_val & (-_val))-_val == 0 && _val != 0)
return 0;
else
return -1;
}
template<typename T>
T RoundToPowerOf2(T val)
{
int bytes = sizeof(T);
val--;
for(int i = 0; i < bytes; i++)
val |= val >> (1<<i);
val++;
return val;
}
template<typename T>
int FillRandom(
T * arrayPtr,
const int width,
const int height,
const T rangeMin,
const T rangeMax,
unsigned int seed)
{
if(!arrayPtr)
{
printf("Cannot fill array. NULL pointer.");
return -1;
}
if(!seed)
seed = (unsigned int)time(NULL);
srand(seed);
double range = double(rangeMax - rangeMin) + 1.0;
/* random initialisation of input */
for(int i = 0; i < height; i++)
for(int j = 0; j < width; j++)
{
int index = i*width + j;
arrayPtr[index] = rangeMin + T(range*rand()/(RAND_MAX + 1.0));
}
return 0;
}
#if 0
//get a memory region that can be used for global memory allocations.
hsa_status_t get_global_region(hsa_region_t region, void* data)
{
hsa_region_segment_t segment;
hsa_region_get_info(region, HSA_REGION_INFO_SEGMENT, &segment);
if (HSA_REGION_SEGMENT_GLOBAL == segment)
{
hsa_region_t* ret = (hsa_region_t*) data;
*ret = region;
}
return HSA_STATUS_SUCCESS;
}
/*
* Finds the specified symbols offset in the specified brig_module.
* If the symbol is found the function returns HSA_STATUS_SUCCESS,
* otherwise it returns HSA_STATUS_ERROR.
*/
hsa_status_t find_symbol_offset(hsa_ext_brig_module_t* brig_module,
char* symbol_name,
hsa_ext_brig_code_section_offset32_t* offset)
{
/*
* Get the data section
*/
hsa_ext_brig_section_header_t* data_section_header =
brig_module->section[HSA_EXT_BRIG_SECTION_DATA];
/*
* Get the code section
*/
hsa_ext_brig_section_header_t* code_section_header =
brig_module->section[HSA_EXT_BRIG_SECTION_CODE];
/*
* First entry into the BRIG code section
*/
BrigCodeOffset32_t code_offset = code_section_header->header_byte_count;
BrigBase* code_entry = (BrigBase*) ((char*)code_section_header + code_offset);
while (code_offset != code_section_header->byte_count)
{
if (code_entry->kind == BRIG_KIND_DIRECTIVE_KERNEL)
{
/*
* Now find the data in the data section
*/
BrigDirectiveExecutable* directive_kernel = (BrigDirectiveExecutable*) (code_entry);
BrigDataOffsetString32_t data_name_offset = directive_kernel->name;
BrigData* data_entry = (BrigData*)((char*) data_section_header + data_name_offset);
if (!strncmp(symbol_name, (char*) data_entry->bytes, strlen(symbol_name)))
{
*offset = code_offset;
return HSA_STATUS_SUCCESS;
}
}
code_offset += code_entry->byteCount;
code_entry = (BrigBase*) ((char*)code_section_header + code_offset);
}
return HSA_STATUS_ERROR;
}
#endif
/*
* Determines if the given agent is of type HSA_DEVICE_TYPE_GPU
* and sets the value of data to the agent handle if it is.
*/
hsa_status_t find_gpu(hsa_agent_t agent, void *data)
{
if (data == NULL)
{
return HSA_STATUS_ERROR_INVALID_ARGUMENT;
}
hsa_device_type_t device_type;
hsa_status_t stat = hsa_agent_get_info(agent, HSA_AGENT_INFO_DEVICE, &device_type);
if (stat != HSA_STATUS_SUCCESS)
{
return stat;
}
if (device_type == HSA_DEVICE_TYPE_GPU)
{
*((hsa_agent_t *)data) = agent;
}
return HSA_STATUS_SUCCESS;
}
/*
* Determines if a memory region can be used for kernarg
* allocations.
*/
hsa_status_t get_memory_region(hsa_region_t region, void* data)
{
hsa_region_global_flag_t flags;
hsa_region_get_info(region, HSA_REGION_INFO_GLOBAL_FLAGS, &flags);
MemRegion *my_mem_region = (MemRegion *)data;
if (flags & HSA_REGION_GLOBAL_FLAG_COARSE_GRAINED) {
my_mem_region->coarse_region = region;
}
if (flags & HSA_REGION_GLOBAL_FLAG_KERNARG)
{
my_mem_region->kernarg_region= region;
}
return HSA_STATUS_SUCCESS;
}
@@ -0,0 +1,236 @@
#ifndef __HSA_UTILITY__
#define __HSA_UTILITY__
#include <vector>
#include <thread>
#include "hsa.h"
#include "hsa_ext_finalize.h"
#include <string.h>
#include<iostream>
using namespace std;
#define HSA_ARGUMENT_ALIGN_BYTES 16
#if defined(_MSC_VER)
#define ALIGNED_(x) __declspec(align(x))
#pragma warning(disable: 4800)
#pragma warning(disable: 4305) // truncation from 'double' to 'const float'
#pragma warning(disable: 4267) // conversion from 'size_t' to 'int', possible loss of data
typedef unsigned int uint;
#else
#if defined(__GNUC__)
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif // __GNUC__
#endif // _MSC_VER
#define SDK_FAILURE 1
#define SDK_SUCCESS 0
/*
#define check(msg, status) \
if (status != HSA_STATUS_SUCCESS) { \
printf("%s failed.\n", #msg); \
exit(1); \
} else { \
printf("%s succeeded.\n", #msg); \
}
*/
#define check(msg, status) \
if (status != HSA_STATUS_SUCCESS) { \
printf("%s failed.\n", #msg); \
exit(1); \
} else { \
; \
}
/*
* Define required BRIG data structures.
*/
typedef uint32_t BrigCodeOffset32_t;
typedef uint32_t BrigDataOffset32_t;
typedef uint16_t BrigKinds16_t;
typedef uint8_t BrigLinkage8_t;
typedef uint8_t BrigExecutableModifier8_t;
typedef BrigDataOffset32_t BrigDataOffsetString32_t;
typedef struct {
// memory region accessed by GPU only
hsa_region_t coarse_region;
// system memory access by gpu and cpu
hsa_region_t kernarg_region;
} MemRegion;
/*
enum BrigKinds {
BRIG_KIND_NONE = 0x0000,
BRIG_KIND_DIRECTIVE_BEGIN = 0x1000,
BRIG_KIND_DIRECTIVE_KERNEL = 0x1008,
};
typedef struct BrigBase BrigBase;
struct BrigBase {
uint16_t byteCount;
BrigKinds16_t kind;
};
typedef struct BrigExecutableModifier BrigExecutableModifier;
struct BrigExecutableModifier {
BrigExecutableModifier8_t allBits;
};
typedef struct BrigDirectiveExecutable BrigDirectiveExecutable;
struct BrigDirectiveExecutable {
uint16_t byteCount;
BrigKinds16_t kind;
BrigDataOffsetString32_t name;
uint16_t outArgCount;
uint16_t inArgCount;
BrigCodeOffset32_t firstInArg;
BrigCodeOffset32_t firstCodeBlockEntry;
BrigCodeOffset32_t nextModuleEntry;
uint32_t codeBlockEntryCount;
BrigExecutableModifier modifier;
BrigLinkage8_t linkage;
uint16_t reserved;
};
typedef struct BrigData BrigData;
struct BrigData {
uint32_t byteCount;
uint8_t bytes[1];
};
*/
struct float2
{
float s0;
float s1;
float2 operator * (float2 &fl)
{
float2 temp;
temp.s0 = (this->s0) * fl.s0;
temp.s1 = (this->s1) * fl.s1;
return temp;
}
float2 operator * (float scalar)
{
float2 temp;
temp.s0 = (this->s0) * scalar;
temp.s1 = (this->s1) * scalar;
return temp;
}
float2 operator + (float2 &fl)
{
float2 temp;
temp.s0 = (this->s0) + fl.s0;
temp.s1 = (this->s1) + fl.s1;
return temp;
}
float2 operator - (float2 fl)
{
float2 temp;
temp.s0 = (this->s0) - fl.s0;
temp.s1 = (this->s1) - fl.s1;
return temp;
}
};
struct uint2
{
uint s0;
uint s1;
uint2 operator * (uint2 &fl)
{
uint2 temp;
temp.s0 = (this->s0) * fl.s0;
temp.s1 = (this->s1) * fl.s1;
return temp;
}
uint2 operator * (float scalar)
{
uint2 temp;
temp.s0 = (this->s0) * scalar;
temp.s1 = (this->s1) * scalar;
return temp;
}
uint2 operator + (uint2 &fl)
{
uint2 temp;
temp.s0 = (this->s0) + fl.s0;
temp.s1 = (this->s1) + fl.s1;
return temp;
}
uint2 operator - (uint2 fl)
{
uint2 temp;
temp.s0 = (this->s0) - fl.s0;
temp.s1 = (this->s1) - fl.s1;
return temp;
}
};
/*
* Prints no more than 256 elements of the given array.
* Prints full array if length is less than 256.
* Prints Array name followed by elements.
*/
template<typename T> void PrintArray(string header, const T * data, const int width, const int height);
template<typename T> int IsPowerOf2(T val);
template<typename T> T RoundToPowerOf2(T val);
template<typename T> int FillRandom(T * arrayPtr, const int width, const int height, const T rangeMin, const T rangeMax, unsigned int seed=123);
//get a memory region that can be used for global memory allocations.
hsa_status_t get_global_region(hsa_region_t region, void* data);
/*
* Finds the specified symbols offset in the specified brig_module.
* If the symbol is found the function returns HSA_STATUS_SUCCESS,
* otherwise it returns HSA_STATUS_ERROR.
*/
//hsa_status_t find_symbol_offset(hsa_ext_brig_module_t* brig_module, char* symbol_name, hsa_ext_brig_code_section_offset32_t* offset);
/*
* Determines if the given agent is of type HSA_DEVICE_TYPE_GPU
* and sets the value of data to the agent handle if it is.
*/
hsa_status_t find_gpu(hsa_agent_t agent, void *data);
/*
* Determines if a memory region can be used for kernarg
* allocations.
*/
hsa_status_t get_memory_region(hsa_region_t region, void* data);
#endif