Skip to content

Commit 0417651

Browse files
[SYCL] Add new SYCL 2020 style FPGA selectors (#7136)
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 <[email protected]>
1 parent 6725863 commit 0417651

File tree

8 files changed

+271
-26
lines changed

8 files changed

+271
-26
lines changed

sycl/doc/extensions/supported/sycl_ext_intel_fpga_device_selector.asciidoc

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,25 @@ supports.
9090

9191
|2
9292
|fpga_simulator_selector added.
93+
94+
|3
95+
|SYCL 2020 selector variants `fpga_selector_v`, `fpga_simulator_selector_v`, and
96+
`fpga_emulator_selector_v` added. Old selectors `fpga_selector`,
97+
`fpga_simulator_selector`, and `fpga_emulator_selector` deprecated.
9398
|===
9499

95100
=== Select FPGA hardware device
96101
....
97102
// select FPGA hardware device
98-
sycl::queue deviceQueue{sycl::ext::intel::fpga_selector{}};
103+
sycl::queue deviceQueue1{sycl::ext::intel::fpga_selector{}}; // Deprecated
104+
sycl::queue deviceQueue2{sycl::ext::intel::fpga_selector_v};
99105
....
100106

101107
=== Select FPGA simulator device
102108
....
103109
// select FPGA simulator device
104-
sycl::queue deviceQueue{sycl::ext::intel::fpga_simulator_selector{}};
110+
sycl::queue deviceQueue1{sycl::ext::intel::fpga_simulator_selector{}}; // Deprecated
111+
sycl::queue deviceQueue2{sycl::ext::intel::fpga_simulator_selector_v};
105112
....
106113

107114
[NOTE]
@@ -112,14 +119,16 @@ Added in version 2 of this extension.
112119
=== Select FPGA emulator device
113120
....
114121
// select FPGA emulator device
115-
sycl::queue deviceQueue{sycl::ext::intel::fpga_emulator_selector{}};
122+
sycl::queue deviceQueue1{sycl::ext::intel::fpga_emulator_selector{}}; // Deprecated
123+
sycl::queue deviceQueue2{sycl::ext::intel::fpga_emulator_selector_v};
116124
....
117125

118126
== Implementation notes
119127

120128
The current implementation has a restriction on the use of
121-
`fpga_simulator_selector`. If an object of `fpga_simulator_selector` is
122-
defined in the application, FPGA hardware devices selected using
123-
`fpga_selector` will select a simulator device. This behaviour is expected to
129+
`fpga_simulator_selector` and `fpga_simulator_selector_v`. If an object of
130+
`fpga_simulator_selector` is defined or `fpga_simulator_selector_v` is used in
131+
the application, FPGA hardware devices selected using fpga_selector` and
132+
`fpga_selector_v` will select a simulator device. This behaviour is expected to
124133
be eliminated in the future.
125134

sycl/include/sycl/ext/intel/fpga_device_selector.hpp

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <sycl/device_selector.hpp>
1313

1414
#include <string>
15+
#include <string_view>
1516

1617
namespace sycl {
1718
__SYCL_INLINE_VER_NAMESPACE(_V1) {
@@ -22,6 +23,26 @@ class platform;
2223
namespace ext {
2324
namespace intel {
2425

26+
namespace detail {
27+
// Scores a device by platform name.
28+
inline int selectDeviceByPlatform(std::string_view required_platform_name,
29+
const device &device) {
30+
if (device.get_platform().get_info<sycl::info::platform::name>() ==
31+
required_platform_name)
32+
return 10000;
33+
return -1;
34+
}
35+
36+
// Enables an environment variable required by the FPGA simulator.
37+
inline void enableFPGASimulator() {
38+
#ifdef _WIN32
39+
_putenv_s("CL_CONTEXT_MPSIM_DEVICE_INTELFPGA", "1");
40+
#else
41+
setenv("CL_CONTEXT_MPSIM_DEVICE_INTELFPGA", "1", 0);
42+
#endif
43+
}
44+
} // namespace detail
45+
2546
class platform_selector : public device_selector {
2647
private:
2748
std::string device_platform_name;
@@ -31,13 +52,7 @@ class platform_selector : public device_selector {
3152
: device_platform_name(platform_name) {}
3253

3354
int operator()(const device &device) const override {
34-
const platform &pf = device.get_platform();
35-
const std::string &platform_name =
36-
pf.get_info<sycl::info::platform::name>();
37-
if (platform_name == device_platform_name) {
38-
return 10000;
39-
}
40-
return -1;
55+
return detail::selectDeviceByPlatform(device_platform_name, device);
4156
}
4257
};
4358

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

49-
class fpga_selector : public platform_selector {
64+
int fpga_selector_v(const device &device) {
65+
return detail::selectDeviceByPlatform(HARDWARE_PLATFORM_NAME, device);
66+
}
67+
68+
int fpga_emulator_selector_v(const device &device) {
69+
return detail::selectDeviceByPlatform(EMULATION_PLATFORM_NAME, device);
70+
}
71+
72+
int fpga_simulator_selector_v(const device &device) {
73+
static bool IsFirstCall = true;
74+
if (IsFirstCall) {
75+
detail::enableFPGASimulator();
76+
IsFirstCall = false;
77+
}
78+
return fpga_selector_v(device);
79+
}
80+
81+
class __SYCL2020_DEPRECATED(
82+
"Use the callable sycl::ext::intel::fpga_selector_v instead.") fpga_selector
83+
: public platform_selector {
5084
public:
5185
fpga_selector() : platform_selector(HARDWARE_PLATFORM_NAME) {}
5286
};
5387

54-
class fpga_emulator_selector : public platform_selector {
88+
class __SYCL2020_DEPRECATED(
89+
"Use the callable sycl::ext::intel::fpga_emulator_selector_v instead.")
90+
fpga_emulator_selector : public platform_selector {
5591
public:
5692
fpga_emulator_selector() : platform_selector(EMULATION_PLATFORM_NAME) {}
5793
};
5894

59-
class fpga_simulator_selector : public fpga_selector {
95+
class __SYCL2020_DEPRECATED(
96+
"Use the callable sycl::ext::intel::fpga_simulator_selector_v instead.")
97+
fpga_simulator_selector : public fpga_selector {
6098
public:
6199
fpga_simulator_selector() {
62100
// Tell the runtime to use a simulator device rather than hardware
63-
#ifdef _WIN32
64-
_putenv_s("CL_CONTEXT_MPSIM_DEVICE_INTELFPGA", "1");
65-
#else
66-
setenv("CL_CONTEXT_MPSIM_DEVICE_INTELFPGA", "1", 0);
67-
#endif
101+
detail::enableFPGASimulator();
68102
}
69103
};
70104

sycl/include/sycl/ext/intel/fpga_utils.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ template <template <int32_t> class _Type, class... _T> struct _GetValue {
2727
template <template <int32_t> class _Type, class _T1, class... _T>
2828
struct _GetValue<_Type, _T1, _T...> {
2929
static constexpr auto value =
30-
detail::conditional_t<_MatchType<_Type, _T1>::value, _T1,
31-
_GetValue<_Type, _T...>>::value;
30+
std::conditional_t<_MatchType<_Type, _T1>::value, _T1,
31+
_GetValue<_Type, _T...>>::value;
3232
};
3333
} // namespace intel
3434
} // namespace ext

sycl/include/sycl/feature_test.hpp.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ __SYCL_INLINE_VER_NAMESPACE(_V1) {
5656
#define SYCL_EXT_INTEL_EXTENDED_ATOMICS 1
5757
#endif
5858
#endif
59-
#define SYCL_EXT_INTEL_FPGA_DEVICE_SELECTOR 2
59+
#define SYCL_EXT_INTEL_FPGA_DEVICE_SELECTOR 3
6060
#define SYCL_EXT_INTEL_FPGA_LSU 1
6161
#define SYCL_EXT_INTEL_FPGA_REG 1
6262
#define SYCL_EXT_INTEL_KERNEL_ARGS_RESTRICT 1

sycl/unittests/Extensions/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
22

33
add_sycl_unittest(ExtensionsTests OBJECT
44
DefaultContext.cpp
5+
FPGADeviceSelectors.cpp
56
DeviceArchitecture.cpp
67
)
78

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
//==------------------- FPGADeviceSelectors.cpp ----------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <sycl/ext/intel/fpga_device_selector.hpp>
10+
#include <sycl/sycl.hpp>
11+
12+
#include <detail/config.hpp>
13+
#include <helpers/PiMock.hpp>
14+
#include <helpers/ScopedEnvVar.hpp>
15+
16+
#include <gtest/gtest.h>
17+
18+
static constexpr char EMULATION_PLATFORM_NAME[] =
19+
"Intel(R) FPGA Emulation Platform for OpenCL(TM)";
20+
static constexpr char HARDWARE_PLATFORM_NAME[] =
21+
"Intel(R) FPGA SDK for OpenCL(TM)";
22+
23+
template <const char PlatformName[]> struct RedefTemplatedWrapper {
24+
static pi_result redefinedPlatformGetInfo(pi_platform platform,
25+
pi_platform_info param_name,
26+
size_t param_value_size,
27+
void *param_value,
28+
size_t *param_value_size_ret) {
29+
switch (param_name) {
30+
case PI_PLATFORM_INFO_NAME: {
31+
size_t PlatformNameLen = strlen(PlatformName) + 1;
32+
if (param_value) {
33+
assert(param_value_size == PlatformNameLen);
34+
std::memcpy(param_value, PlatformName, PlatformNameLen);
35+
}
36+
if (param_value_size_ret)
37+
*param_value_size_ret = PlatformNameLen;
38+
return PI_SUCCESS;
39+
}
40+
default:
41+
return PI_SUCCESS;
42+
}
43+
}
44+
};
45+
46+
static pi_result redefinedDeviceGetInfo(pi_device device,
47+
pi_device_info param_name,
48+
size_t param_value_size,
49+
void *param_value,
50+
size_t *param_value_size_ret) {
51+
constexpr char MockDeviceName[] = "Mock FPGA device";
52+
switch (param_name) {
53+
case PI_DEVICE_INFO_TYPE: {
54+
if (param_value)
55+
*static_cast<_pi_device_type *>(param_value) = PI_DEVICE_TYPE_ACC;
56+
if (param_value_size_ret)
57+
*param_value_size_ret = sizeof(PI_DEVICE_TYPE_ACC);
58+
return PI_SUCCESS;
59+
}
60+
case PI_DEVICE_INFO_NAME: {
61+
if (param_value) {
62+
assert(param_value_size == sizeof(MockDeviceName));
63+
std::memcpy(param_value, MockDeviceName, sizeof(MockDeviceName));
64+
}
65+
if (param_value_size_ret)
66+
*param_value_size_ret = sizeof(MockDeviceName);
67+
return PI_SUCCESS;
68+
}
69+
default:
70+
return PI_SUCCESS;
71+
}
72+
}
73+
74+
TEST(FPGADeviceSelectorsTest, FPGASelectorTest) {
75+
using namespace sycl::detail;
76+
using namespace sycl::unittest;
77+
78+
sycl::unittest::PiMock Mock;
79+
Mock.redefine<detail::PiApiKind::piDeviceGetInfo>(redefinedDeviceGetInfo);
80+
Mock.redefine<detail::PiApiKind::piPlatformGetInfo>(
81+
RedefTemplatedWrapper<HARDWARE_PLATFORM_NAME>::redefinedPlatformGetInfo);
82+
sycl::platform Plt = Mock.getPlatform();
83+
sycl::context Ctx{Plt.get_devices()};
84+
85+
sycl::queue FPGAQueue{Ctx, sycl::ext::intel::fpga_selector_v};
86+
EXPECT_EQ(FPGAQueue.get_device(), Plt.get_devices()[0])
87+
<< "Queue did not contain the expected device";
88+
89+
try {
90+
sycl::queue EmuFPGAQueue{Ctx, sycl::ext::intel::fpga_emulator_selector_v};
91+
FAIL() << "Unexpectedly selected emulator device.";
92+
} catch (sycl::exception &E) {
93+
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
94+
<< "Unexpected exception errc.";
95+
}
96+
}
97+
98+
TEST(FPGADeviceSelectorsTest, FPGAEmulatorSelectorTest) {
99+
using namespace sycl::detail;
100+
using namespace sycl::unittest;
101+
102+
sycl::unittest::PiMock Mock;
103+
Mock.redefine<detail::PiApiKind::piDeviceGetInfo>(redefinedDeviceGetInfo);
104+
Mock.redefine<detail::PiApiKind::piPlatformGetInfo>(
105+
RedefTemplatedWrapper<EMULATION_PLATFORM_NAME>::redefinedPlatformGetInfo);
106+
sycl::platform Plt = Mock.getPlatform();
107+
sycl::context Ctx{Plt.get_devices()};
108+
109+
sycl::queue EmuFPGAQueue{Ctx, sycl::ext::intel::fpga_emulator_selector_v};
110+
EXPECT_EQ(EmuFPGAQueue.get_device(), Plt.get_devices()[0])
111+
<< "Queue did not contain the expected device";
112+
113+
try {
114+
sycl::queue FPGAQueue{Ctx, sycl::ext::intel::fpga_selector_v};
115+
FAIL() << "Unexpectedly selected non-emulator device.";
116+
} catch (sycl::exception &E) {
117+
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
118+
<< "Unexpected exception errc.";
119+
}
120+
}
121+
122+
TEST(FPGADeviceSelectorsTest, FPGASimulatorSelectorTest) {
123+
using namespace sycl::detail;
124+
using namespace sycl::unittest;
125+
126+
constexpr char INTELFPGA_ENV[] = "CL_CONTEXT_MPSIM_DEVICE_INTELFPGA";
127+
ScopedEnvVar EnvVar(INTELFPGA_ENV, nullptr, []() {});
128+
129+
sycl::unittest::PiMock Mock;
130+
Mock.redefine<detail::PiApiKind::piDeviceGetInfo>(redefinedDeviceGetInfo);
131+
Mock.redefine<detail::PiApiKind::piPlatformGetInfo>(
132+
RedefTemplatedWrapper<HARDWARE_PLATFORM_NAME>::redefinedPlatformGetInfo);
133+
sycl::platform Plt = Mock.getPlatform();
134+
sycl::context Ctx{Plt.get_devices()};
135+
136+
sycl::queue SimuFPGAQueue{Ctx, sycl::ext::intel::fpga_simulator_selector_v};
137+
EXPECT_EQ(SimuFPGAQueue.get_device(), Plt.get_devices()[0])
138+
<< "Queue did not contain the expected device";
139+
140+
const char *ReadEnv = getenv(INTELFPGA_ENV);
141+
EXPECT_NE(ReadEnv, nullptr) << "Environment was unset after call.";
142+
EXPECT_EQ(std::string(ReadEnv), "1") << "Environment value was not 1";
143+
144+
try {
145+
sycl::queue EmuFPGAQueue{Ctx, sycl::ext::intel::fpga_emulator_selector_v};
146+
FAIL() << "Unexpectedly selected emulator device.";
147+
} catch (sycl::exception &E) {
148+
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
149+
<< "Unexpected exception errc.";
150+
}
151+
}
152+
153+
TEST(FPGADeviceSelectorsTest, NegativeFPGASelectorTest) {
154+
using namespace sycl::detail;
155+
using namespace sycl::unittest;
156+
157+
constexpr char INTELFPGA_ENV[] = "CL_CONTEXT_MPSIM_DEVICE_INTELFPGA";
158+
ScopedEnvVar EnvVar(INTELFPGA_ENV, nullptr, []() {});
159+
160+
// Do not redefine any APIs. We want it to fail for all.
161+
sycl::unittest::PiMock Mock;
162+
sycl::platform Plt = Mock.getPlatform();
163+
sycl::context Ctx{Plt.get_devices()};
164+
165+
try {
166+
sycl::queue FPGAQueue{Ctx, sycl::ext::intel::fpga_selector_v};
167+
FAIL() << "Unexpectedly selected non-emulator device.";
168+
} catch (sycl::exception &E) {
169+
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
170+
<< "Unexpected exception errc.";
171+
}
172+
173+
try {
174+
sycl::queue EmuFPGAQueue{Ctx, sycl::ext::intel::fpga_emulator_selector_v};
175+
FAIL() << "Unexpectedly selected emulator device.";
176+
} catch (sycl::exception &E) {
177+
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
178+
<< "Unexpected exception errc.";
179+
}
180+
181+
try {
182+
sycl::queue SimuFPGAQueue{Ctx, sycl::ext::intel::fpga_simulator_selector_v};
183+
FAIL() << "Unexpectedly selected simulator device.";
184+
} catch (sycl::exception &E) {
185+
EXPECT_EQ(E.code(), sycl::make_error_code(sycl::errc::runtime))
186+
<< "Unexpected exception errc.";
187+
}
188+
}

sycl/unittests/helpers/PiMockPlugin.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,20 @@ inline pi_result mock_piPlatformGetInfo(pi_platform platform,
3434
size_t param_value_size,
3535
void *param_value,
3636
size_t *param_value_size_ret) {
37+
constexpr char MockPlatformName[] = "Mock platform";
3738
constexpr char MockSupportedExtensions[] =
3839
"cl_khr_il_program cl_khr_subgroups cl_intel_subgroups "
3940
"cl_intel_subgroups_short cl_intel_required_subgroup_size ";
4041
switch (param_name) {
42+
case PI_PLATFORM_INFO_NAME: {
43+
if (param_value) {
44+
assert(param_value_size == sizeof(MockPlatformName));
45+
std::memcpy(param_value, MockPlatformName, sizeof(MockPlatformName));
46+
}
47+
if (param_value_size_ret)
48+
*param_value_size_ret = sizeof(MockPlatformName);
49+
return PI_SUCCESS;
50+
}
4151
case PI_PLATFORM_INFO_EXTENSIONS: {
4252
if (param_value) {
4353
assert(param_value_size == sizeof(MockSupportedExtensions));

0 commit comments

Comments
 (0)