Index: openmp/libomptarget/plugins-nextgen/amdgpu/src/rtl.cpp =================================================================== --- openmp/libomptarget/plugins-nextgen/amdgpu/src/rtl.cpp +++ openmp/libomptarget/plugins-nextgen/amdgpu/src/rtl.cpp @@ -2086,8 +2086,253 @@ } /// Print information about the device. - Error printInfoImpl() override { - // TODO: Implement the basic info. + Error printInfoImpl(std::deque &Items) override { + char TmpChar[1000]; + const char *TmpCharPtr; + uint16_t Major, Minor; + uint32_t TmpUInt, TmpUInt2; + uint32_t CacheSize[4]; + bool TmpBool; + uint16_t WorkgroupMaxDim[3]; + hsa_dim3_t GridMaxDim; + hsa_status_t Status, Status2; + + Status = hsa_system_get_info(HSA_SYSTEM_INFO_VERSION_MAJOR, &Major); + Status2 = hsa_system_get_info(HSA_SYSTEM_INFO_VERSION_MINOR, &Minor); + if (Status == HSA_STATUS_SUCCESS && Status2 == HSA_STATUS_SUCCESS) + Items.push_back({"HSA Runtime Version", + std::to_string(Major) + "." + std::to_string(Minor), 1}); + + Items.push_back({"HSA OpenMP Device Number", DeviceId, 1}); + + Status = hsa_agent_get_info( + Agent, (hsa_agent_info_t)HSA_AMD_AGENT_INFO_PRODUCT_NAME, TmpChar); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Product Name", TmpChar, 1}); + + Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_NAME, TmpChar); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Device Name", TmpChar, 1}); + + Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_VENDOR_NAME, TmpChar); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Vendor Name", TmpChar, 1}); + + hsa_device_type_t DevType; + Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_DEVICE, &DevType); + if (Status == HSA_STATUS_SUCCESS) { + switch (DevType) { + case HSA_DEVICE_TYPE_CPU: + TmpCharPtr = "CPU"; + break; + case HSA_DEVICE_TYPE_GPU: + TmpCharPtr = "GPU"; + break; + case HSA_DEVICE_TYPE_DSP: + TmpCharPtr = "DSP"; + break; + default: + TmpCharPtr = "UNKNOWN"; + } + Items.push_back({"Device Type", TmpCharPtr, 1}); + } + + Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_QUEUES_MAX, &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Max Queues", TmpUInt, 1}); + + Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_QUEUE_MIN_SIZE, &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Queue Min Size", TmpUInt, 1}); + + Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_QUEUE_MAX_SIZE, &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Queue Max Size", TmpUInt, 1}); + + // FIXME: This is deprecated according to HSA documentation. But using + // hsa_agent_iterate_caches and hsa_cache_get_info breaks execution during + // runtime. + Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_CACHE_SIZE, CacheSize); + if (Status == HSA_STATUS_SUCCESS) { + Items.push_back({"Cache", "", 1}); + + for (int I = 0; I < 4; I++) + if (CacheSize[I]) + Items.push_back({"L" + std::to_string(I), CacheSize[I], 2}); + } + + Status = hsa_agent_get_info( + Agent, (hsa_agent_info_t)HSA_AMD_AGENT_INFO_CACHELINE_SIZE, &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Cacheline Size", TmpUInt, 1}); + + Status = hsa_agent_get_info( + Agent, (hsa_agent_info_t)HSA_AMD_AGENT_INFO_MAX_CLOCK_FREQUENCY, + &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Max Clock Freq(MHz)", TmpUInt, 1}); + + Status = hsa_agent_get_info( + Agent, (hsa_agent_info_t)HSA_AMD_AGENT_INFO_COMPUTE_UNIT_COUNT, + &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Compute Units", TmpUInt, 1}); + + Status = hsa_agent_get_info( + Agent, (hsa_agent_info_t)HSA_AMD_AGENT_INFO_NUM_SIMDS_PER_CU, &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"SIMD per CU", TmpUInt, 1}); + + Status = + hsa_agent_get_info(Agent, HSA_AGENT_INFO_FAST_F16_OPERATION, &TmpBool); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Fast F16 Operation", (TmpBool ? "TRUE" : "FALSE"), 1}); + + Status = + hsa_agent_get_info(Agent, HSA_AGENT_INFO_WAVEFRONT_SIZE, &TmpUInt2); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Wavefront Size", TmpUInt2, 1}); + + Status = + hsa_agent_get_info(Agent, HSA_AGENT_INFO_WORKGROUP_MAX_SIZE, &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Workgroup Max Size", TmpUInt, 1}); + + Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_WORKGROUP_MAX_DIM, + WorkgroupMaxDim); + if (Status == HSA_STATUS_SUCCESS) { + Items.push_back({"Workgroup Max Size per Dimension", "", 1}); + Items.push_back({"x", WorkgroupMaxDim[0], 2}); + Items.push_back({"y", WorkgroupMaxDim[1], 2}); + Items.push_back({"z", WorkgroupMaxDim[2], 2}); + } + + Status = hsa_agent_get_info( + Agent, (hsa_agent_info_t)HSA_AMD_AGENT_INFO_MAX_WAVES_PER_CU, &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) { + Items.push_back({"Max Waves Per CU", TmpUInt, 1}); + Items.push_back({"Max Work-item Per CU", TmpUInt * TmpUInt2, 1}); + } + + Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_GRID_MAX_SIZE, &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Grid Max Size", TmpUInt, 1}); + + Status = + hsa_agent_get_info(Agent, HSA_AGENT_INFO_GRID_MAX_DIM, &GridMaxDim); + if (Status == HSA_STATUS_SUCCESS) { + Items.push_back({"Grid Max Size per Dimension", "", 1}); + Items.push_back({"x", GridMaxDim.x, 2}); + Items.push_back({"y", GridMaxDim.y, 2}); + Items.push_back({"z", GridMaxDim.z, 2}); + } + + Status = + hsa_agent_get_info(Agent, HSA_AGENT_INFO_FBARRIER_MAX_SIZE, &TmpUInt); + if (Status == HSA_STATUS_SUCCESS) + Items.push_back({"Max fbarriers/Workgrp", TmpUInt, 1}); + + Items.push_back({"Memory Pools", "", 1}); + auto CbMem = [](hsa_amd_memory_pool_t Region, void *Data) -> hsa_status_t { + std::string TmpStr, TmpStr2; + size_t Size; + bool Alloc, Access; + hsa_amd_segment_t Segment; + hsa_amd_memory_pool_global_flag_t GlobalFlags; + hsa_status_t Status; + + std::deque *Items = + static_cast *>(Data); + assert(Items && "Null callback parameter"); + + Status = hsa_amd_memory_pool_get_info( + Region, HSA_AMD_MEMORY_POOL_INFO_SEGMENT, &Segment); + if (Status != HSA_STATUS_SUCCESS) + return HSA_STATUS_SUCCESS; + + switch (Segment) { + case HSA_AMD_SEGMENT_GLOBAL: + TmpStr = "GLOBAL"; + break; + case HSA_AMD_SEGMENT_READONLY: + TmpStr = "READONLY"; + break; + case HSA_AMD_SEGMENT_PRIVATE: + TmpStr = "PRIVATE"; + break; + case HSA_AMD_SEGMENT_GROUP: + TmpStr = "GROUP"; + break; + } + Items->push_back({"Pool " + TmpStr, "", 2}); + + if (Segment == HSA_AMD_SEGMENT_GLOBAL) { + Status = hsa_amd_memory_pool_get_info( + Region, HSA_AMD_MEMORY_POOL_INFO_GLOBAL_FLAGS, &GlobalFlags); + if (Status != HSA_STATUS_SUCCESS) + return HSA_STATUS_SUCCESS; + + if (HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_KERNARG_INIT & GlobalFlags) + TmpStr2 += "KERNARG "; + if (HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED & GlobalFlags) + TmpStr2 += "FINE GRAINED "; + if (HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_COARSE_GRAINED & GlobalFlags) + TmpStr2 += "COARSE GRAINED "; + + Items->push_back({"Flags", TmpStr2, 3}); + } + + Status = hsa_amd_memory_pool_get_info( + Region, HSA_AMD_MEMORY_POOL_INFO_SIZE, &Size); + if (Status == HSA_STATUS_SUCCESS) + Items->push_back({"Size", std::to_string(Size) + " bytes", 3}); + + Status = hsa_amd_memory_pool_get_info( + Region, HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALLOWED, &Alloc); + if (Status == HSA_STATUS_SUCCESS) + Items->push_back({"Allocatable", (Alloc ? "TRUE" : "FALSE"), 3}); + + Status = hsa_amd_memory_pool_get_info( + Region, HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_GRANULE, &Size); + if (Status == HSA_STATUS_SUCCESS) + Items->push_back( + {"Runtime Alloc Granule", std::to_string(Size) + " bytes", 3}); + + Status = hsa_amd_memory_pool_get_info( + Region, HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALIGNMENT, &Size); + if (Status == HSA_STATUS_SUCCESS) + Items->push_back( + {"Runtime Alloc Alignment", std::to_string(Size) + " bytes", 3}); + + Status = hsa_amd_memory_pool_get_info( + Region, HSA_AMD_MEMORY_POOL_INFO_ACCESSIBLE_BY_ALL, &Access); + if (Status == HSA_STATUS_SUCCESS) + Items->push_back({"Accessable by all", (Access ? "TRUE" : "FALSE"), 3}); + + return HSA_STATUS_SUCCESS; + }; + // Iterate over all memory regions for this agent and get their properties. + hsa_amd_agent_iterate_memory_pools(Agent, CbMem, &Items); + + Items.push_back({"ISAs", "", 1}); + auto CBIsas = [](hsa_isa_t Isa, void *Data) -> hsa_status_t { + std::deque *Items = + static_cast *>(Data); + assert(Items && "Null callback parameter"); + + char TmpChar[1000]; + hsa_status_t Status = + hsa_isa_get_info_alt(Isa, HSA_ISA_INFO_NAME, TmpChar); + if (Status == HSA_STATUS_SUCCESS) + Items->push_back({"Name", TmpChar, 2}); + + return HSA_STATUS_SUCCESS; + }; + + // Iterate over all memory regions for this agent. Get the memory region + // type and size. + hsa_agent_iterate_isas(Agent, CBIsas, &Items); + return Plugin::success(); } Index: openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.h =================================================================== --- openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.h +++ openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -84,6 +85,30 @@ __tgt_async_info *AsyncInfoPtr; }; +/// Structure representing a print info item. Each item has a string key, a +/// string value and the item level (starting at 1). The level specifies the +/// indentation of the item when printing its key and value. +struct PrintInfoTy { + std::string Key; + std::string Value; + uint64_t Level; + + PrintInfoTy(const std::string &Key, const std::string &Value, uint64_t Level) + : Key(Key), Value(Value), Level(Level) {} + + PrintInfoTy(const std::string &Key, const char *Value, uint64_t Level) + : Key(Key), Value(Value), Level(Level) {} + + PrintInfoTy(const std::string &Key, char *Value, uint64_t Level) + : Key(Key), Value(Value), Level(Level) {} + + template + PrintInfoTy(const std::string &Key, T Value, uint64_t Level) + : Key(Key), Value(std::to_string(Value)), Level(Level) {} + + PrintInfoTy() {} +}; + /// Class wrapping a __tgt_device_image and its offload entry table on a /// specific device. This class is responsible for storing and managing /// the offload entries for an image on a device. @@ -645,7 +670,7 @@ /// Print information about the device. Error printInfo(); - virtual Error printInfoImpl() = 0; + virtual Error printInfoImpl(std::deque &Items) = 0; /// Getters of the grid values. uint32_t getWarpSize() const { return GridValues.GV_Warp_Size; } Index: openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp =================================================================== --- openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp +++ openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp @@ -992,8 +992,41 @@ } Error GenericDeviceTy::printInfo() { - // TODO: Print generic information here - return printInfoImpl(); + std::deque Items; + + // Get the vendor-specific info items describing the properties of the device. + if (auto Err = printInfoImpl(Items)) + return Err; + + // Each level has four spaces. + constexpr uint64_t IndentLen = 4; + + // Find the maximum key length (level + key) to compute the individual + // indentation of items. + uint64_t MaxKeyLen = 0; + for (const auto &Info : Items) { + if (!Info.Key.empty() && + (Info.Key.size() + Info.Level * IndentLen > MaxKeyLen)) + MaxKeyLen = Info.Key.size() + Info.Level * IndentLen; + } + + // Print all info items. + for (const auto &Info : Items) { + if (Info.Key.empty()) { + fprintf(stdout, "\n"); + } else { + // Compute the indentations for the item. + uint64_t KeyIndentLen = Info.Level * IndentLen; + uint64_t ValueIndentLen = + MaxKeyLen - (Info.Key.size() + Info.Level * IndentLen) + IndentLen; + + fprintf(stdout, "%s%s:%s%s\n", std::string(KeyIndentLen, ' ').data(), + Info.Key.data(), std::string(ValueIndentLen, ' ').data(), + Info.Value.data()); + } + } + + return Plugin::success(); } Error GenericDeviceTy::createEvent(void **EventPtrStorage) { Index: openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp =================================================================== --- openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp +++ openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp @@ -620,7 +620,7 @@ } /// Print information about the device. - Error printInfoImpl() override { + Error printInfoImpl(std::deque &Items) override { char TmpChar[1000]; std::string TmpStr; size_t TmpSt; Index: openmp/libomptarget/plugins-nextgen/generic-elf-64bit/src/rtl.cpp =================================================================== --- openmp/libomptarget/plugins-nextgen/generic-elf-64bit/src/rtl.cpp +++ openmp/libomptarget/plugins-nextgen/generic-elf-64bit/src/rtl.cpp @@ -294,7 +294,7 @@ Error syncEventImpl(void *EventPtr) override { return Plugin::success(); } /// Print information about the device. - Error printInfoImpl() override { + Error printInfoImpl(std::deque &Items) override { printf(" This is a generic-elf-64bit device\n"); return Plugin::success(); }