/******************************************************************************* * * MIT License * * Copyright (c) 2023 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * *******************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include #include #include "../driver.hpp" #include "../lib_env_var.hpp" template class ScopedEnvironment { public: explicit ScopedEnvironment(lib_env::LibEnvVar ename, T val) : env_name(ename) { restore = SetValue(val); } explicit ScopedEnvironment(lib_env::LibEnvVar ename) : env_name(ename) { restore = ClearValue(); } ScopedEnvironment() = delete; ScopedEnvironment(const ScopedEnvironment&) = delete; ScopedEnvironment(ScopedEnvironment&&) = delete; ScopedEnvironment& operator=(const ScopedEnvironment&) = delete; ScopedEnvironment& operator=(ScopedEnvironment&&) = delete; ~ScopedEnvironment() { if(!restore) return; if(prev_env) { lib_env::update(env_name, prev_val); } else { lib_env::clear(env_name); } } private: lib_env::LibEnvVar env_name; std::optional prev_env; T prev_val; bool restore = false; bool ClearValue() { prev_env = miopen::debug::env::GetEnvVariable(env_name.name); if(prev_env) { lib_env::clear(env_name); } return prev_env.has_value(); } bool SetValue(T value) { prev_env = miopen::debug::env::GetEnvVariable(env_name.name); if(prev_env) { prev_val = lib_env::value(env_name); if(prev_val == value) { return false; } } lib_env::update(env_name, value); return true; } }; inline void default_check(const std::string& err) { std::cout << err; } inline void tuning_check(const std::string& err) { // TEST_TUNING - the test should fail if output contains "Error" or "failed". EXPECT_FALSE(err.find("Error") != std::string::npos || err.find("failed") != std::string::npos); default_check(err); } inline void compiler_check(const std::string& err) { // the test should fail if kernel build failed. EXPECT_FALSE(err.find("Error") != std::string::npos || err.find("Code object build failed") != std::string::npos); default_check(err); } inline void db_check(const std::string& err) { EXPECT_FALSE(err.find("Perf Db: record not found") != std::string::npos); default_check(err); }; enum class Gpu : int { Default = 0, // \todo remove None = 0, gfx900 = 1 << 0, gfx906 = 1 << 1, gfx908 = 1 << 2, gfx90A = 1 << 3, gfx94X = 1 << 4, gfx950 = 1 << 5, gfx103X = 1 << 6, gfx110X = 1 << 7, gfx115X = 1 << 8, gfx120X = 1 << 9, gfx125X = 1 << 10, gfxLast = Gpu::gfx125X, // \note Change the value when adding a new device All = -1 }; inline Gpu operator~(Gpu lhs) { using T = std::underlying_type_t; return static_cast(~static_cast(lhs)); } inline Gpu operator|(Gpu lhs, Gpu rhs) { using T = std::underlying_type_t; return static_cast(static_cast(lhs) | static_cast(rhs)); } inline Gpu operator&(Gpu lhs, Gpu rhs) { using T = std::underlying_type_t; return static_cast(static_cast(lhs) & static_cast(rhs)); } template struct enabled { using T = std::underlying_type_t; static constexpr T val = (static_cast(bits) | ...); static constexpr bool enabling = true; }; template struct disabled { using T = std::underlying_type_t; static constexpr T val = ~((static_cast(bits) | ...)); static constexpr bool enabling = false; }; struct DevDescription { std::string_view name; unsigned cu_cnt; // CU for gfx9, WGP for gfx10, 11, ... unsigned wavefront_size; // Default wavefront size friend std::ostream& operator<<(std::ostream& os, const DevDescription& dd); }; class MockTargetProperties final : public miopen::TargetProperties { public: MockTargetProperties(const TargetProperties& target_properties, const DevDescription& dev_description, bool disable_xnack); // Add additional methods here if needed const std::string& Name() const override; bool isXnackEnabled() const override; private: std::string name; bool xnack_disabled; }; class MockHandle final : public miopen::Handle { public: MockHandle(const DevDescription& dev_description, bool disable_xnack); // Add additional methods here if needed const miopen::TargetProperties& GetTargetProperties() const override; std::size_t GetMaxComputeUnits() const override; std::size_t GetWavefrontWidth() const override; std::size_t GetMaxMemoryAllocSize() const override; bool CooperativeLaunchSupported() const override; private: DevDescription dev_descr; MockTargetProperties target_properties; }; Gpu GetDevGpuType(); std::string_view GetBaseDeviceName(std::string_view dev_name); Gpu GetGpuType(const std::string& dev_name); const std::multimap& GetAllKnownDevices(); bool IsTestSupportedByDevice(Gpu supported_devs); template bool IsTestSupportedForDevMask() { static_assert((~disabled_mask::val & enabled_mask::val) == 0, "Enabled and Disabled GPUs are overlapped"); static_assert(disabled_mask::enabling == false, "Wrong disabled mask, probably it has to be switched with enabled_mask"); static_assert(enabled_mask::enabling == true, "Wrong enabled mask, probably it has to be switched with disabled_mask"); constexpr int def_val = enabled::val; constexpr int mask = (def_val & disabled_mask::val) | enabled_mask::val; return IsTestSupportedByDevice(static_cast(mask)); } template struct FloatTestCase : public testing::TestWithParam { static constexpr std::string_view fp_args{"--float"}; }; template struct HalfTestCase : public testing::TestWithParam { static constexpr std::string_view fp_args{"--half"}; }; template struct Bf16TestCase : public testing::TestWithParam { static constexpr std::string_view fp_args{"--bfloat16"}; }; template struct Int8TestCase : public testing::TestWithParam { static constexpr std::string_view fp_args{"--int8"}; }; template std::vector get_args(const Case& param) { const auto& [env_tuple, cmd] = param; std::apply([](const auto&... env) { (lib_env::update(env.first, env.second), ...); }, env_tuple); std::stringstream ss(cmd); std::istream_iterator begin(ss); std::istream_iterator end; return {begin, end}; } template