Skip to content

Commit b8b6566

Browse files
[SYCL][ESIMD] Software-emulation preparation
* This PR adds new Plug-In module for ESIMD Software-emulation, ESIMD_CPU * The new feature will use CM emulation library for runtime support and ESIMD intrinsics such as Software-multithreaded kernel launching and buffer management/access * pi* functions are filled with dummy codes as placeholder * Steps for importing CM and enumerating/enabling pi_esimd_cpu will be added later * New PI_API is added - piextPluginGetOpaqueData * New API is added - getPluginOpaqueData
1 parent ce7177d commit b8b6566

File tree

16 files changed

+1604
-3
lines changed

16 files changed

+1604
-3
lines changed

buildbot/configure.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def do_configure(args):
2525
llvm_enable_projects = 'clang;' + llvm_external_projects
2626
libclc_targets_to_build = ''
2727
sycl_build_pi_cuda = 'OFF'
28+
sycl_build_pi_esimd_cpu = 'ON'
2829
sycl_werror = 'ON'
2930
llvm_enable_assertions = 'ON'
3031
llvm_enable_doxygen = 'OFF'
@@ -44,6 +45,9 @@ def do_configure(args):
4445
libclc_targets_to_build = 'nvptx64--;nvptx64--nvidiacl'
4546
sycl_build_pi_cuda = 'ON'
4647

48+
if args.disable_esimd_cpu:
49+
sycl_build_pi_esimd_cpu = 'OFF'
50+
4751
if args.no_werror:
4852
sycl_werror = 'OFF'
4953

@@ -86,7 +90,8 @@ def do_configure(args):
8690
"-DLLVM_ENABLE_SPHINX={}".format(llvm_enable_sphinx),
8791
"-DBUILD_SHARED_LIBS={}".format(llvm_build_shared_libs),
8892
"-DSYCL_ENABLE_XPTI_TRACING={}".format(sycl_enable_xpti_tracing),
89-
"-DLLVM_ENABLE_LLD={}".format(llvm_enable_lld)
93+
"-DLLVM_ENABLE_LLD={}".format(llvm_enable_lld),
94+
"-DSYCL_BUILD_PI_ESIMD_CPU={}".format(sycl_build_pi_esimd_cpu)
9095
]
9196

9297
if args.l0_headers and args.l0_loader:
@@ -147,6 +152,7 @@ def main():
147152
metavar="BUILD_TYPE", default="Release", help="build type: Debug, Release")
148153
parser.add_argument("--cuda", action='store_true', help="switch from OpenCL to CUDA")
149154
parser.add_argument("--arm", action='store_true', help="build ARM support rather than x86")
155+
parser.add_argument("--disable-esimd-cpu", action='store_true', help="build without ESIMD_CPU support")
150156
parser.add_argument("--no-assertions", action='store_true', help="build without assertions")
151157
parser.add_argument("--docs", action='store_true', help="build Doxygen documentation")
152158
parser.add_argument("--no-werror", action='store_true', help="Don't treat warnings as errors")

sycl/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ set( SYCL_TOOLCHAIN_DEPLOY_COMPONENTS
250250
sycl
251251
pi_opencl
252252
pi_level_zero
253+
pi_esimd_cpu
253254
libsycldevice
254255
${XPTIFW_LIBS}
255256
)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//==----- esimd_emu_functions_v1.h - DPC++ Explicit SIMD API ---------==//
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+
/// \file esimd_emu_functions_v1.h
10+
///
11+
/// \ingroup sycl_pi_esimd_cpu
12+
13+
#pragma once
14+
15+
// <cstdint> for 'uint32_t' type is included in upper-level device
16+
// interface file ('esimdcpu_device_interface.hpp')
17+
18+
// This file defines function interfaces for ESIMD CPU Emulation
19+
// (ESIMD_CPU) to access LibCM CPU emulation functionalities from
20+
// kernel applications running under emulation
21+
22+
// CM CPU Emulation Info :
23+
// https://github.com/intel/cm-cpu-emulation
24+
25+
// Function pointers (*_ptr) with 'cm/__cm' prefixes correspond to
26+
// LibCM functions with same name
27+
// e.g.: cm_fence_ptr -> cm_fence() in LibCM
28+
29+
// Function pointers (*_ptr) with 'sycl_' prefix correspond to LibCM
30+
// functions dedicated to SYCL support
31+
// e.g.: sycl_get_surface_base_addr_ptr
32+
// -> get_surface_base_addr(int) in LibCM
33+
34+
/****** DO NOT MODIFY following function pointers ******/
35+
/****** No reordering, No renaming, No removal ******/
36+
37+
// Intrinsics
38+
void (*cm_barrier_ptr)(void);
39+
void (*cm_sbarrier_ptr)(uint32_t);
40+
void (*cm_fence_ptr)(void);
41+
42+
// libcm functionalities used for intrinsics such as
43+
// surface/buffer/slm access
44+
char *(*sycl_get_surface_base_addr_ptr)(int);
45+
char *(*__cm_emu_get_slm_ptr)(void);
46+
void (*cm_slm_init_ptr)(size_t);
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//==----- esimdcpu_device_interface.hpp - DPC++ Explicit SIMD API ---------==//
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+
/// \file esimdcpu_device_interface.hpp
10+
/// Declarations for ESIMD_CPU-device specific definitions.
11+
/// ESIMD intrinsic and LibCM functionalities required by intrinsic defined
12+
///
13+
/// This interface is for ESIMD intrinsic emulation implementations
14+
/// such as slm_access to access ESIMD_CPU specific-support therefore
15+
/// it has to be defined and shared as include directory
16+
///
17+
/// \ingroup sycl_pi_esimd_cpu
18+
19+
#pragma once
20+
21+
#include <CL/sycl/detail/pi.hpp>
22+
23+
// cstdint-type fields such as 'uint32_t' are to be used in funtion
24+
// pointer table file ('esimd_emu_functions_v1.h') included in 'struct
25+
// ESIMDDeviceInterface' definition.
26+
#include <cstdint>
27+
28+
__SYCL_INLINE_NAMESPACE(cl) {
29+
namespace sycl {
30+
namespace detail {
31+
32+
/// This is the device interface version required (and used) by this
33+
/// implementation of the ESIMD CPU emulator.
34+
#define ESIMD_DEVICE_INTERFACE_VERSION 1
35+
36+
// 'ESIMDDeviceInterface' structure defines interface for ESIMD CPU
37+
// emulation (ESIMD_CPU) to access LibCM CPU emulation functionalities
38+
// from kernel application under emulation.
39+
40+
// Header files included in the structure contains only function
41+
// pointers to access CM functionalities. Only new function can be
42+
// added - reordering, changing, or removing existing function pointer
43+
// is not allowed.
44+
45+
// Whenever a new function(s) is added to this interface, a new header
46+
// file must be added following naming convention that contains
47+
// version number such as 'v1' from 'ESIMD_DEVICE_INTERFACE_VERSION'.
48+
struct ESIMDDeviceInterface {
49+
uintptr_t version;
50+
void *reserved;
51+
52+
ESIMDDeviceInterface();
53+
#include "esimd_emu_functions_v1.h"
54+
};
55+
56+
// Denotes the data version used by the implementation.
57+
// Increment whenever the 'data' field interpretation within PluginOpaqueData is
58+
// changed.
59+
#define ESIMD_EMU_PLUGIN_OPAQUE_DATA_VERSION 0
60+
/// This structure denotes a ESIMD EMU plugin-specific data returned via the
61+
/// piextPluginGetOpaqueData PI call. Depending on the \c version field, the
62+
/// second \c data field can be interpreted differently.
63+
struct ESIMDEmuPluginOpaqueData {
64+
uintptr_t version;
65+
void *data;
66+
};
67+
// The table below shows the correspondence between the \c version
68+
// and the contents of the \c data field:
69+
// version == 0, data is ESIMDDeviceInterface*
70+
71+
ESIMDDeviceInterface *getESIMDDeviceInterface() {
72+
// TODO (performance) cache the interface pointer, can make a difference
73+
// when calling fine-grained libCM APIs through it (like memory access in a
74+
// tight loop)
75+
void *PIOpaqueData = nullptr;
76+
77+
PIOpaqueData = getPluginOpaqueData<cl::sycl::backend::esimd_cpu>(nullptr);
78+
79+
ESIMDEmuPluginOpaqueData *OpaqueData =
80+
reinterpret_cast<ESIMDEmuPluginOpaqueData *>(PIOpaqueData);
81+
82+
// First check if opaque data version is compatible.
83+
if (OpaqueData->version != ESIMD_EMU_PLUGIN_OPAQUE_DATA_VERSION) {
84+
// NOTE: the version check should always be '!=' as layouts of different
85+
// versions of PluginOpaqueData is not backward compatible, unlike
86+
// layout of the ESIMDDeviceInterface.
87+
88+
std::cerr << __FUNCTION__ << std::endl
89+
<< "Opaque data returned by ESIMD Emu plugin is incompatible with"
90+
<< "the one used in current implementation." << std::endl
91+
<< "Returned version : " << OpaqueData->version << std::endl
92+
<< "Required version : " << ESIMD_EMU_PLUGIN_OPAQUE_DATA_VERSION
93+
<< std::endl;
94+
throw cl::sycl::feature_not_supported();
95+
}
96+
// Opaque data version is OK, can cast the 'data' field.
97+
ESIMDDeviceInterface *Interface =
98+
reinterpret_cast<ESIMDDeviceInterface *>(OpaqueData->data);
99+
100+
// Now check that device interface version is compatible.
101+
if (Interface->version < ESIMD_DEVICE_INTERFACE_VERSION) {
102+
std::cerr << __FUNCTION__ << std::endl
103+
<< "The device interface version provided from plug-in "
104+
<< "library is behind required device interface version"
105+
<< std::endl
106+
<< "Found version : " << Interface->version << std::endl
107+
<< "Required version :" << ESIMD_DEVICE_INTERFACE_VERSION
108+
<< std::endl;
109+
throw cl::sycl::feature_not_supported();
110+
}
111+
return Interface;
112+
}
113+
114+
#undef ESIMD_DEVICE_INTERFACE_VERSION
115+
#undef ESIMD_EMU_PLUGIN_OPAQUE_DATA_VERSION
116+
117+
} // namespace detail
118+
} // namespace sycl
119+
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/include/CL/sycl/backend_types.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ enum class backend : char {
2323
opencl = 1,
2424
level_zero = 2,
2525
cuda = 3,
26-
all = 4
26+
esimd_cpu = 4,
27+
all = 5
2728
};
2829

2930
template <backend Backend, typename SYCLObjectT> struct interop;
@@ -51,6 +52,9 @@ inline std::ostream &operator<<(std::ostream &Out, backend be) {
5152
case backend::cuda:
5253
Out << "cuda";
5354
break;
55+
case backend::esimd_cpu:
56+
Out << "esimd_cpu";
57+
break;
5458
case backend::all:
5559
Out << "all";
5660
}

sycl/include/CL/sycl/detail/pi.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ _PI_API(piextUSMGetMemAllocInfo)
128128

129129
_PI_API(piextKernelSetArgMemObj)
130130
_PI_API(piextKernelSetArgSampler)
131+
132+
_PI_API(piextPluginGetOpaqueData)
133+
131134
_PI_API(piTearDown)
132135

133136
#undef _PI_API

sycl/include/CL/sycl/detail/pi.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,6 +1634,15 @@ __SYCL_EXPORT pi_result piextUSMGetMemAllocInfo(
16341634
pi_context context, const void *ptr, pi_mem_info param_name,
16351635
size_t param_value_size, void *param_value, size_t *param_value_size_ret);
16361636

1637+
/// API to get Plugin internal data, opaque to SYCL RT. Some devices whose
1638+
/// device code is compiled by the host compiler (e.g. CPU emulators) may use it
1639+
/// to access some device code functionality implemented in/behind the plugin.
1640+
/// \param opaque_data_param - unspecified argument, interpretation is specific
1641+
/// to a plugin \param opaque_data_return - placeholder for the returned opaque
1642+
/// data.
1643+
__SYCL_EXPORT pi_result piextPluginGetOpaqueData(void *opaque_data_param,
1644+
void **opaque_data_return);
1645+
16371646
/// API to notify that the plugin should clean up its resources.
16381647
/// No PI calls should be made until the next piPluginInit call.
16391648
/// \param PluginParameter placeholder for future use, currenly not used.

sycl/include/CL/sycl/detail/pi.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ enum class PiApiKind {
4444
#include <CL/sycl/detail/pi.def>
4545
};
4646
class plugin;
47+
48+
template <cl::sycl::backend BE>
49+
__SYCL_EXPORT void *getPluginOpaqueData(void *opaquedata_arg);
50+
4751
namespace pi {
4852

4953
// The SYCL_PI_TRACE sets what we will trace.
@@ -61,10 +65,12 @@ bool trace(TraceLevel level);
6165
#define __SYCL_OPENCL_PLUGIN_NAME "pi_opencl.dll"
6266
#define __SYCL_LEVEL_ZERO_PLUGIN_NAME "pi_level_zero.dll"
6367
#define __SYCL_CUDA_PLUGIN_NAME "pi_cuda.dll"
68+
#define __SYCL_ESIMD_CPU_PLUGIN_NAME "pi_esimd_cpu.dll"
6469
#else
6570
#define __SYCL_OPENCL_PLUGIN_NAME "libpi_opencl.so"
6671
#define __SYCL_LEVEL_ZERO_PLUGIN_NAME "libpi_level_zero.so"
6772
#define __SYCL_CUDA_PLUGIN_NAME "libpi_cuda.so"
73+
#define __SYCL_ESIMD_CPU_PLUGIN_NAME "libpi_esimd_cpu.so"
6874
#endif
6975

7076
// Report error and no return (keeps compiler happy about no return statements).
@@ -149,7 +155,7 @@ extern std::shared_ptr<plugin> GlobalPlugin;
149155
const vector_class<plugin> &initialize();
150156

151157
// Get the plugin serving given backend.
152-
template <backend BE> const plugin &getPlugin();
158+
template <backend BE> __SYCL_EXPORT const plugin &getPlugin();
153159

154160
// Utility Functions to get Function Name for a PI Api.
155161
template <PiApiKind PiApiOffset> struct PiFuncInfo {};

sycl/plugins/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ endif()
1010

1111
add_subdirectory(opencl)
1212
add_subdirectory(level_zero)
13+
14+
if (SYCL_BUILD_PI_ESIMD_CPU)
15+
add_subdirectory(esimd_cpu)
16+
endif()

sycl/plugins/esimd_cpu/CMakeLists.txt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
# PI Esimd CPU library
3+
# Create Shared library for libpi_esimd_cpu.so.
4+
5+
include_directories("${sycl_inc_dir}")
6+
include_directories(${OpenCL_INCLUDE_DIR})
7+
include_directories(${LIBCMRT_INCLUDE})
8+
9+
add_library(pi_esimd_cpu SHARED
10+
"${sycl_inc_dir}/CL/sycl/detail/pi.h"
11+
"pi_esimd_cpu.cpp"
12+
)
13+
14+
if (MSVC)
15+
# by defining __SYCL_BUILD_SYCL_DLL, we can use __declspec(dllexport)
16+
# which are individually tagged for all pi* symbols in pi.h
17+
target_compile_definitions(pi_esimd_cpu PRIVATE __SYCL_BUILD_SYCL_DLL)
18+
else()
19+
# we set the visibility of all symbols 'hidden' by default.
20+
# In pi.h file, we set exported symbols with visibility==default individually
21+
target_compile_options(pi_esimd_cpu PUBLIC -fvisibility=hidden)
22+
23+
# This script file is used to allow exporting pi* symbols only.
24+
# All other symbols are regarded as local (hidden)
25+
set(linker_script "${CMAKE_CURRENT_SOURCE_DIR}/../ld-version-script.txt")
26+
27+
# Filter symbols based on the scope defined in the script file,
28+
# and export pi* function symbols in the library.
29+
target_link_libraries( pi_esimd_cpu
30+
PRIVATE "-Wl,--version-script=${linker_script}"
31+
)
32+
endif()
33+
34+
add_dependencies(sycl-toolchain pi_esimd_cpu)
35+
36+
add_dependencies(pi_esimd_cpu
37+
OpenCL-Headers)
38+
39+
target_link_libraries(pi_esimd_cpu PRIVATE sycl)
40+
set_target_properties(pi_esimd_cpu PROPERTIES LINKER_LANGUAGE CXX)
41+
42+
add_common_options(pi_esimd_cpu)
43+
44+
install(TARGETS pi_esimd_cpu
45+
LIBRARY DESTINATION "lib${LLVM_LIBDIR_SUFFIX}" COMPONENT pi_esimd_cpu
46+
RUNTIME DESTINATION "bin" COMPONENT pi_esimd_cpu)

0 commit comments

Comments
 (0)