Skip to content

Commit

Permalink
[SYCL] Add new SYCL 2020 style FPGA selectors (#7136)
Browse files Browse the repository at this point in the history
Adds SYCL 2020 style FPGA selectors to the
sycl_ext_intel_fpga_device_selector and implements them. Additionally it
deprecates the old selectors.

Signed-off-by: Larsen, Steffen <steffen.larsen@intel.com>
  • Loading branch information
steffenlarsen authored Oct 24, 2022
1 parent 6725863 commit 0417651
Show file tree
Hide file tree
Showing 8 changed files with 271 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,25 @@ supports.

|2
|fpga_simulator_selector added.

|3
|SYCL 2020 selector variants `fpga_selector_v`, `fpga_simulator_selector_v`, and
`fpga_emulator_selector_v` added. Old selectors `fpga_selector`,
`fpga_simulator_selector`, and `fpga_emulator_selector` deprecated.
|===

=== Select FPGA hardware device
....
// select FPGA hardware device
sycl::queue deviceQueue{sycl::ext::intel::fpga_selector{}};
sycl::queue deviceQueue1{sycl::ext::intel::fpga_selector{}}; // Deprecated
sycl::queue deviceQueue2{sycl::ext::intel::fpga_selector_v};
....

=== Select FPGA simulator device
....
// select FPGA simulator device
sycl::queue deviceQueue{sycl::ext::intel::fpga_simulator_selector{}};
sycl::queue deviceQueue1{sycl::ext::intel::fpga_simulator_selector{}}; // Deprecated
sycl::queue deviceQueue2{sycl::ext::intel::fpga_simulator_selector_v};
....

[NOTE]
Expand All @@ -112,14 +119,16 @@ Added in version 2 of this extension.
=== Select FPGA emulator device
....
// select FPGA emulator device
sycl::queue deviceQueue{sycl::ext::intel::fpga_emulator_selector{}};
sycl::queue deviceQueue1{sycl::ext::intel::fpga_emulator_selector{}}; // Deprecated
sycl::queue deviceQueue2{sycl::ext::intel::fpga_emulator_selector_v};
....

== Implementation notes

The current implementation has a restriction on the use of
`fpga_simulator_selector`. If an object of `fpga_simulator_selector` is
defined in the application, FPGA hardware devices selected using
`fpga_selector` will select a simulator device. This behaviour is expected to
`fpga_simulator_selector` and `fpga_simulator_selector_v`. If an object of
`fpga_simulator_selector` is defined or `fpga_simulator_selector_v` is used in
the application, FPGA hardware devices selected using fpga_selector` and
`fpga_selector_v` will select a simulator device. This behaviour is expected to
be eliminated in the future.

64 changes: 49 additions & 15 deletions sycl/include/sycl/ext/intel/fpga_device_selector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <sycl/device_selector.hpp>

#include <string>
#include <string_view>

namespace sycl {
__SYCL_INLINE_VER_NAMESPACE(_V1) {
Expand All @@ -22,6 +23,26 @@ class platform;
namespace ext {
namespace intel {

namespace detail {
// Scores a device by platform name.
inline int selectDeviceByPlatform(std::string_view required_platform_name,
const device &device) {
if (device.get_platform().get_info<sycl::info::platform::name>() ==
required_platform_name)
return 10000;
return -1;
}

// Enables an environment variable required by the FPGA simulator.
inline void enableFPGASimulator() {
#ifdef _WIN32
_putenv_s("CL_CONTEXT_MPSIM_DEVICE_INTELFPGA", "1");
#else
setenv("CL_CONTEXT_MPSIM_DEVICE_INTELFPGA", "1", 0);
#endif
}
} // namespace detail

class platform_selector : public device_selector {
private:
std::string device_platform_name;
Expand All @@ -31,13 +52,7 @@ class platform_selector : public device_selector {
: device_platform_name(platform_name) {}

int operator()(const device &device) const override {
const platform &pf = device.get_platform();
const std::string &platform_name =
pf.get_info<sycl::info::platform::name>();
if (platform_name == device_platform_name) {
return 10000;
}
return -1;
return detail::selectDeviceByPlatform(device_platform_name, device);
}
};

Expand All @@ -46,25 +61,44 @@ static constexpr auto EMULATION_PLATFORM_NAME =
static constexpr auto HARDWARE_PLATFORM_NAME =
"Intel(R) FPGA SDK for OpenCL(TM)";

class fpga_selector : public platform_selector {
int fpga_selector_v(const device &device) {
return detail::selectDeviceByPlatform(HARDWARE_PLATFORM_NAME, device);
}

int fpga_emulator_selector_v(const device &device) {
return detail::selectDeviceByPlatform(EMULATION_PLATFORM_NAME, device);
}

int fpga_simulator_selector_v(const device &device) {
static bool IsFirstCall = true;
if (IsFirstCall) {
detail::enableFPGASimulator();
IsFirstCall = false;
}
return fpga_selector_v(device);
}

class __SYCL2020_DEPRECATED(
"Use the callable sycl::ext::intel::fpga_selector_v instead.") fpga_selector
: public platform_selector {
public:
fpga_selector() : platform_selector(HARDWARE_PLATFORM_NAME) {}
};

class fpga_emulator_selector : public platform_selector {
class __SYCL2020_DEPRECATED(
"Use the callable sycl::ext::intel::fpga_emulator_selector_v instead.")
fpga_emulator_selector : public platform_selector {
public:
fpga_emulator_selector() : platform_selector(EMULATION_PLATFORM_NAME) {}
};

class fpga_simulator_selector : public fpga_selector {
class __SYCL2020_DEPRECATED(
"Use the callable sycl::ext::intel::fpga_simulator_selector_v instead.")
fpga_simulator_selector : public fpga_selector {
public:
fpga_simulator_selector() {
// Tell the runtime to use a simulator device rather than hardware
#ifdef _WIN32
_putenv_s("CL_CONTEXT_MPSIM_DEVICE_INTELFPGA", "1");
#else
setenv("CL_CONTEXT_MPSIM_DEVICE_INTELFPGA", "1", 0);
#endif
detail::enableFPGASimulator();
}
};

Expand Down
4 changes: 2 additions & 2 deletions sycl/include/sycl/ext/intel/fpga_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ template <template <int32_t> class _Type, class... _T> struct _GetValue {
template <template <int32_t> class _Type, class _T1, class... _T>
struct _GetValue<_Type, _T1, _T...> {
static constexpr auto value =
detail::conditional_t<_MatchType<_Type, _T1>::value, _T1,
_GetValue<_Type, _T...>>::value;
std::conditional_t<_MatchType<_Type, _T1>::value, _T1,
_GetValue<_Type, _T...>>::value;
};
} // namespace intel
} // namespace ext
Expand Down
2 changes: 1 addition & 1 deletion sycl/include/sycl/feature_test.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ __SYCL_INLINE_VER_NAMESPACE(_V1) {
#define SYCL_EXT_INTEL_EXTENDED_ATOMICS 1
#endif
#endif
#define SYCL_EXT_INTEL_FPGA_DEVICE_SELECTOR 2
#define SYCL_EXT_INTEL_FPGA_DEVICE_SELECTOR 3
#define SYCL_EXT_INTEL_FPGA_LSU 1
#define SYCL_EXT_INTEL_FPGA_REG 1
#define SYCL_EXT_INTEL_KERNEL_ARGS_RESTRICT 1
Expand Down
1 change: 1 addition & 0 deletions sycl/unittests/Extensions/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)

add_sycl_unittest(ExtensionsTests OBJECT
DefaultContext.cpp
FPGADeviceSelectors.cpp
DeviceArchitecture.cpp
)

188 changes: 188 additions & 0 deletions sycl/unittests/Extensions/FPGADeviceSelectors.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
//==------------------- FPGADeviceSelectors.cpp ----------------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <sycl/ext/intel/fpga_device_selector.hpp>
#include <sycl/sycl.hpp>

#include <detail/config.hpp>
#include <helpers/PiMock.hpp>
#include <helpers/ScopedEnvVar.hpp>

#include <gtest/gtest.h>

static constexpr char EMULATION_PLATFORM_NAME[] =
"Intel(R) FPGA Emulation Platform for OpenCL(TM)";
static constexpr char HARDWARE_PLATFORM_NAME[] =
"Intel(R) FPGA SDK for OpenCL(TM)";

template <const char PlatformName[]> struct RedefTemplatedWrapper {
static pi_result redefinedPlatformGetInfo(pi_platform platform,
pi_platform_info param_name,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret) {
switch (param_name) {
case PI_PLATFORM_INFO_NAME: {
size_t PlatformNameLen = strlen(PlatformName) + 1;
if (param_value) {
assert(param_value_size == PlatformNameLen);
std::memcpy(param_value, PlatformName, PlatformNameLen);
}
if (param_value_size_ret)
*param_value_size_ret = PlatformNameLen;
return PI_SUCCESS;
}
default:
return PI_SUCCESS;
}
}
};

static pi_result redefinedDeviceGetInfo(pi_device device,
pi_device_info param_name,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret) {
constexpr char MockDeviceName[] = "Mock FPGA device";
switch (param_name) {
case PI_DEVICE_INFO_TYPE: {
if (param_value)
*static_cast<_pi_device_type *>(param_value) = PI_DEVICE_TYPE_ACC;
if (param_value_size_ret)
*param_value_size_ret = sizeof(PI_DEVICE_TYPE_ACC);
return PI_SUCCESS;
}
case PI_DEVICE_INFO_NAME: {
if (param_value) {
assert(param_value_size == sizeof(MockDeviceName));
std::memcpy(param_value, MockDeviceName, sizeof(MockDeviceName));
}
if (param_value_size_ret)
*param_value_size_ret = sizeof(MockDeviceName);
return PI_SUCCESS;
}
default:
return PI_SUCCESS;
}
}

TEST(FPGADeviceSelectorsTest, FPGASelectorTest) {
using namespace sycl::detail;
using namespace sycl::unittest;

sycl::unittest::PiMock Mock;
Mock.redefine<detail::PiApiKind::piDeviceGetInfo>(redefinedDeviceGetInfo);
Mock.redefine<detail::PiApiKind::piPlatformGetInfo>(
RedefTemplatedWrapper<HARDWARE_PLATFORM_NAME>::redefinedPlatformGetInfo);
sycl::platform Plt = Mock.getPlatform();
sycl::context Ctx{Plt.get_devices()};

sycl::queue FPGAQueue{Ctx, sycl::ext::intel::fpga_selector_v};
EXPECT_EQ(FPGAQueue.get_device(), Plt.get_devices()[0])
<< "Queue did not contain the expected device";

try {
sycl::queue EmuFPGAQueue{Ctx, sycl::ext::intel::fpga_emulator_selector_v};
FAIL() << "Unexpectedly selected emulator device.";
} catch (sycl::exception &E) {
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
<< "Unexpected exception errc.";
}
}

TEST(FPGADeviceSelectorsTest, FPGAEmulatorSelectorTest) {
using namespace sycl::detail;
using namespace sycl::unittest;

sycl::unittest::PiMock Mock;
Mock.redefine<detail::PiApiKind::piDeviceGetInfo>(redefinedDeviceGetInfo);
Mock.redefine<detail::PiApiKind::piPlatformGetInfo>(
RedefTemplatedWrapper<EMULATION_PLATFORM_NAME>::redefinedPlatformGetInfo);
sycl::platform Plt = Mock.getPlatform();
sycl::context Ctx{Plt.get_devices()};

sycl::queue EmuFPGAQueue{Ctx, sycl::ext::intel::fpga_emulator_selector_v};
EXPECT_EQ(EmuFPGAQueue.get_device(), Plt.get_devices()[0])
<< "Queue did not contain the expected device";

try {
sycl::queue FPGAQueue{Ctx, sycl::ext::intel::fpga_selector_v};
FAIL() << "Unexpectedly selected non-emulator device.";
} catch (sycl::exception &E) {
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
<< "Unexpected exception errc.";
}
}

TEST(FPGADeviceSelectorsTest, FPGASimulatorSelectorTest) {
using namespace sycl::detail;
using namespace sycl::unittest;

constexpr char INTELFPGA_ENV[] = "CL_CONTEXT_MPSIM_DEVICE_INTELFPGA";
ScopedEnvVar EnvVar(INTELFPGA_ENV, nullptr, []() {});

sycl::unittest::PiMock Mock;
Mock.redefine<detail::PiApiKind::piDeviceGetInfo>(redefinedDeviceGetInfo);
Mock.redefine<detail::PiApiKind::piPlatformGetInfo>(
RedefTemplatedWrapper<HARDWARE_PLATFORM_NAME>::redefinedPlatformGetInfo);
sycl::platform Plt = Mock.getPlatform();
sycl::context Ctx{Plt.get_devices()};

sycl::queue SimuFPGAQueue{Ctx, sycl::ext::intel::fpga_simulator_selector_v};
EXPECT_EQ(SimuFPGAQueue.get_device(), Plt.get_devices()[0])
<< "Queue did not contain the expected device";

const char *ReadEnv = getenv(INTELFPGA_ENV);
EXPECT_NE(ReadEnv, nullptr) << "Environment was unset after call.";
EXPECT_EQ(std::string(ReadEnv), "1") << "Environment value was not 1";

try {
sycl::queue EmuFPGAQueue{Ctx, sycl::ext::intel::fpga_emulator_selector_v};
FAIL() << "Unexpectedly selected emulator device.";
} catch (sycl::exception &E) {
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
<< "Unexpected exception errc.";
}
}

TEST(FPGADeviceSelectorsTest, NegativeFPGASelectorTest) {
using namespace sycl::detail;
using namespace sycl::unittest;

constexpr char INTELFPGA_ENV[] = "CL_CONTEXT_MPSIM_DEVICE_INTELFPGA";
ScopedEnvVar EnvVar(INTELFPGA_ENV, nullptr, []() {});

// Do not redefine any APIs. We want it to fail for all.
sycl::unittest::PiMock Mock;
sycl::platform Plt = Mock.getPlatform();
sycl::context Ctx{Plt.get_devices()};

try {
sycl::queue FPGAQueue{Ctx, sycl::ext::intel::fpga_selector_v};
FAIL() << "Unexpectedly selected non-emulator device.";
} catch (sycl::exception &E) {
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
<< "Unexpected exception errc.";
}

try {
sycl::queue EmuFPGAQueue{Ctx, sycl::ext::intel::fpga_emulator_selector_v};
FAIL() << "Unexpectedly selected emulator device.";
} catch (sycl::exception &E) {
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
<< "Unexpected exception errc.";
}

try {
sycl::queue SimuFPGAQueue{Ctx, sycl::ext::intel::fpga_simulator_selector_v};
FAIL() << "Unexpectedly selected simulator device.";
} catch (sycl::exception &E) {
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
<< "Unexpected exception errc.";
}
}
10 changes: 10 additions & 0 deletions sycl/unittests/helpers/PiMockPlugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,20 @@ inline pi_result mock_piPlatformGetInfo(pi_platform platform,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret) {
constexpr char MockPlatformName[] = "Mock platform";
constexpr char MockSupportedExtensions[] =
"cl_khr_il_program cl_khr_subgroups cl_intel_subgroups "
"cl_intel_subgroups_short cl_intel_required_subgroup_size ";
switch (param_name) {
case PI_PLATFORM_INFO_NAME: {
if (param_value) {
assert(param_value_size == sizeof(MockPlatformName));
std::memcpy(param_value, MockPlatformName, sizeof(MockPlatformName));
}
if (param_value_size_ret)
*param_value_size_ret = sizeof(MockPlatformName);
return PI_SUCCESS;
}
case PI_PLATFORM_INFO_EXTENSIONS: {
if (param_value) {
assert(param_value_size == sizeof(MockSupportedExtensions));
Expand Down
Loading

0 comments on commit 0417651

Please sign in to comment.